I Hired an AI Chief of Staff. His Name Is Bleu.
He lives on a Mac mini, listens on Telegram, sweeps GitHub and Vercel, and opens PRs against himself overnight.
A few weeks ago I wrote about Austin Lau, the one-person growth team at Anthropic. One marketer plus the right toolkit, beating teams that didn’t have the toolkit. I keep coming back to that idea, because I’m a solo founder who can’t hire a team but can hire software that acts like one. So I hired Bleu.
He has a name, a job description in a text file, a schedule in a markdown file, and a Mac mini for a desk. His logins are separate from mine and scoped narrower, the same reason a real employee gets their own accounts.
He shows up every morning, sweeps the repos and dashboards, pings me on Telegram when something needs a human, and otherwise stays out of my way. The whole “AI chief of staff” is a markdown file, a bash script, and a long-running Claude Code session on a Mac mini under my desk, with no SaaS or infra in front of it.
The System
A handful of files do the work.
bleu/
├── bootstrap.sh ← kills old sessions, pulls main, launches tmux
├── schedule.md ← one heading per recurring job
└── .bleu/
├── bleu-prompt.txt ← the job description
└── run-bleu.sh ← invokes the claude CLI with Telegram enabled
A macOS LaunchAgent (Apple’s cron equivalent — runs scripts on a schedule or at login) fires bootstrap.sh at login and again at 3am every day. The script keeps the Mac awake, pulls latest, kills any old sessions, and launches a fresh one:
# Prevent macOS from sleeping — keeps tmux sessions alive
if ! tmux has-session -t bleu-caffeinate 2>/dev/null; then
tmux new-session -d -s bleu-caffeinate 'caffeinate -i -s'
fi
# Kill old sessions, launch the unified Bleu session
for session in bleu bleu-scheduler bleu-telegram; do
tmux has-session -t "$session" 2>/dev/null && tmux kill-session -t "$session"
done
tmux new-session -d -s bleu "bash $BLEU_DIR/.bleu/run-bleu.sh"
(tmux is what lets the claude process keep running after I close the terminal — Bleu lives inside one of these sessions all day.)
run-bleu.sh is where Bleu actually starts up. Anthropic ships an official Telegram channel plugin that turns a Telegram chat into a first-class input for Claude Code. One CLI flag — enableRemoteControl — and the long-running session is listening on my phone:
claude \
--settings '{"enabledPlugins":{"telegram@claude-plugins-official":true},"enableRemoteControl":true}' \
--channels 'plugin:telegram@claude-plugins-official' \
--name bleu \
"$(cat .bleu/bleu-prompt.txt)"
That flag makes Telegram a two-way channel: Bleu’s input and his permission prompts. When he wants to do something destructive, he asks me on my phone first and I tap yes or no. Routine reads and writes don’t ping.
The kick-off prompt tells the session who it is (“you are Bleu, the unified session, both Telegram listener and scheduler”) and points it at schedule.md. One heading per recurring job, with a cron expression and a prompt. Here’s how Morning Update opens:
## Morning Update
- **Cron:** `3 8 * * 1-5` (weekdays 8:03am CT)
- **Prompt:**
You are Bleu, AI Chief of Staff for WorkHoodie. Send Sean a morning update.
Check across every repo: open issues assigned to Bleu, PRs awaiting
review, Vercel deployments, PostHog errors and feature flags, blog
readership, Meta campaign performance, Supabase health, competitor news.
On boot, the kick-off prompt sends Bleu through schedule.md, where he registers each job with CronCreate (Claude Code’s built-in scheduler) before he says hello.
Every job inherits the same default rule: stay silent if nothing’s wrong. The schedule pages me when there’s signal, not when there’s a check.
Two Ways In
One on the schedule, one from me.
Scheduled
When a cron fires, the work falls into three buckets, all the kind a solo dev keeps meaning to do but never gets around to.
- Code in flight. Sweep stale PRs and unaddressed review comments. Triage new issues into “now” versus “later.”
- Production health. Watch deploys for errors and rollbacks. Scan product analytics for spikes or regressions. Audit dependencies for security advisories.
- The big picture. Skim competitor and industry news. Review the day’s commits and codify patterns worth keeping.
Two jobs are worth pulling out.
Morning Update. At 8:03am every weekday, Bleu does his rounds across every repo and dashboard, then lands a summary on my phone before I open the laptop. If everything’s clean I get one line, otherwise a paragraph.
Nightly Reflection. At 10:03pm, Bleu looks back through the day’s commits and review comments, and if he spots a pattern worth keeping, he opens a PR against his own setup. I merge it in the morning. The agent updates the agent.
Inbound
Me texting Bleu. He decides whether to handle it inline or spawn a background agent. The agent works, opens a PR, and pings me on Telegram when it’s done.
Try It Yourself
A few things worth knowing before you copy this.
Claude Code’s CronCreate is session-scoped and recurring tasks expire after seven days, which is why the LaunchAgent re-fires bootstrap.sh every morning at 3am. The daily restart is what keeps the schedule alive. It looked like a workaround the first time I set it up, but after a week of running it, it’s the cleanest part of the design. The schedule lives in cron, the source of truth lives in schedule.md, and the daily restart reconciles them.
The Telegram plugin needs a bot token. The Bot API is free and the setup is a five-minute chat with @BotFather. Bleu pulls the token from ~/.claude/channels/telegram/.env so scheduled jobs can also send messages directly via curl.
The bigger risk than any single tool call is the kick-off prompt and schedule.md themselves. They’re the job description, and a sloppy line gets run unattended hundreds of times. Be deliberate about what you tell him to do, and keep the schedule in version control so every change goes through a PR.
If you want to set up your own version, paste this into Claude Code from an empty directory. It’ll ask you what to call your agent, inspect your stack, scaffold the bootstrap script, run script, kick-off prompt, a starter schedule.md, and the LaunchAgent plist, then walk you through launchctl load.
A few weeks in, the wins are quieter than I expected, and most of them start on Telegram. I’ll text Bleu a half-formed idea — “we should add X to the changelog” or “the pricing FAQ is stale” — and he turns it into a scoped GitHub issue with acceptance criteria. The small ones he picks off himself: spawn a background agent, push a branch, open a PR. By the time I’m back at my laptop the work is waiting for review.
The morning sweeps catch the rest — competitor moves and traffic shifts I wouldn’t have thought to check that day. Bleu has his own scoped credentials and his own opinions about my codebase by the time he reflects on it at night. He’s the always-online employee I never managed to hire.
The reflection PRs show up overnight, and I keep forgetting he’s there until he pings me.