Claude Code in my pocket
I wanted to be able to try an idea the moment I had it. Not “when I get back to my laptop”, but on the bus, in a queue, at 11pm on the couch. So I set up a few cheap cloud machines that run Claude Code around the clock, and I talk to them from Telegram on my phone.
It turned out to be one of the most fun setups I’ve built. This post covers the idea and the architecture. There’s nothing here you couldn’t rebuild in a weekend.
What it looks like day to day
I open a Telegram group called “Agents”. It’s a forum group, so it’s split into topics:
- General is the switchboard. I can ask which agents are running, or how much room each machine has left.
- One topic per machine “lobby”. I tell the lobby “start a new project called world-ideas, it’s a research notebook about X”. It creates a private GitHub repo, clones it, and starts a new Claude session for it.
- One topic per project. A new topic appears automatically for every project, and everything I write in it goes to that project’s Claude session. Replies come back in the same topic.
So a typical exchange is: idea pops up, I type (or dictate) two sentences into the lobby, and a few minutes later there’s a repo with a first draft, a prototype, or a research summary in it. Claude replies in the topic with what it did and what it suggests next. When I’m back at a real computer, the work is already on GitHub.
The architecture
Phone (Telegram)
│
▼
Telegram group with topics
│ (one bot, long-polled)
▼
┌──────────────────────────┐ private network ┌────────────────────────────┐
│ control machine │ ◀───────── WebSocket ───────▶ │ agent machine (many) │
│ relay │ │ claude session: lobby │
│ - owns the bot │ ◀──── stats every minute ──── │ claude session: project A │
│ - topic ⇄ session map │ │ claude session: project B │
│ - offline queue, alerts │ │ ... │
└──────────────────────────┘ └────────────────────────────┘
│
▼
GitHub (private repos)
Four ideas hold it together.
1. Cheap, throwaway machines
The agent machines are the smallest ARM VMs at Hetzner (2 vCPU, 4 GB RAM, about €6/month). Claude Code itself is light; the model runs at Anthropic, so the VM only runs the CLI, git, and whatever the project builds. One small machine comfortably holds several projects.
Every machine is treated as disposable. Each project lives in its own private GitHub repo, and the agents are told to commit and push often. If a machine dies or I want a different region, I delete it, create a new one from the setup scripts, and the projects carry on from GitHub. Nothing important lives only on a disk.
Because the machines are throwaway and hold nothing but repos, I run Claude in bypass-permissions mode. That’s a deliberate trade: I give up the per-command approval prompts (which I couldn’t answer from my phone anyway) in exchange for agents that actually get work done while I’m away. To limit the damage a confused agent can do, its GitHub token can create and push to repos but can’t delete them.
2. One Claude session per project, not per machine
My first instinct was “one machine = one agent”. That’s wasteful and it doesn’t match how I work. Now each project gets its own long-running Claude session:
- a systemd user service per project (
claude@<project>), so sessions start at boot and restart if they crash, - each inside its own tmux server, so I can SSH in and attach to exactly what the agent sees, then detach and leave it running,
claude --continueon restart, so a session picks up its previous conversation.
Each machine also runs a lobby session. Its job is housekeeping: creating projects, starting and stopping sessions, answering “what’s running here?”.
3. The switchboard: one bot, many agents
Claude Code has a feature called channels (in research preview): an MCP server that can push messages into a running session, plus a tool Claude uses to reply. The official Telegram channel works great for one session. It breaks down with many, because a Telegram bot can only have one process polling it. Two sessions on the same bot fight over the updates.
So I split it in two:
- A relay on a separate small “control” VM. It’s the only thing holding the bot token. It long-polls Telegram, maps forum topics to sessions, and creates a new topic the first time a session connects. If a session is offline, messages are queued and delivered when it reconnects. A 👀 reaction tells me a message was delivered, and 🟢/🔴 notices tell me when a session goes down or comes back.
- A tiny channel process inside every Claude session. It connects to the relay over the machines’ private network, introduces itself by project name, injects incoming messages into the session, and gives Claude a reply tool that posts back into the right topic.
Topics are keyed by project name, not machine. If I move a project to another machine, its topic and history in Telegram stay the same.
Security is simple: the relay only forwards messages from my Telegram user ID, only one group is bound, agents authenticate to the relay with a shared secret, and the relay only listens on the private network.
4. Knowing when a machine is full
With several projects per machine, I need to know when a machine has run out of room. Every minute each agent machine reports load, memory, swap, disk, Linux pressure stall info (PSI), and memory used per Claude session. The relay keeps the latest numbers:
/machinesin Telegram shows each machine at a glance, including a rough “room for N more sessions” estimate.- If a threshold is crossed for several minutes in a row (memory pressure, swap, disk), the relay posts an alert in General. Short spikes are ignored.
When an alert shows up, I either stop an idle project or spin up another machine.
Rough edges
It isn’t all smooth, and some of these are worth knowing before you try it.
- Custom channels need a development flag. During the research preview, only allowlisted channel plugins load normally. A self-built channel needs
--dangerously-load-development-channels, which shows a confirmation dialog on every start. A new folder also asks whether you trust it. Out of the box, that means attaching over SSH after every restart. I scripted my way around it on my own machines, but expect this part to change as channels mature. - Long-running sessions need babysitting tools. Being able to
sshin andtmux attachto the exact session is what makes debugging bearable. Without that you’re guessing from Telegram replies. - Typing on a phone is the bottleneck. The keyboard’s dictation button helps a lot. Native Telegram voice notes (transcribed on the control machine) are next on my list.
- Login expiry. The Claude subscription login eventually expires and needs a manual
/loginin one session.
What it costs
Two of the smallest ARM VMs (one agent machine, one control machine) come to roughly €12/month, plus the Claude subscription I was paying for anyway. Adding capacity is one more €6 machine.
What’s next
- Voice messages from Telegram, transcribed locally with whisper.cpp.
- An autosave timer that pushes uncommitted work to
wip/<machine>branches, so a dead machine never loses more than a few minutes. - A “new machine” command that does create → base setup → Claude → GitHub → switchboard → lobby in one go.
- A proper dashboard with history graphs.
- Moving the control side from my laptop to a small VM, so the whole thing runs without my laptop.
Why I like it
The best part isn’t the tech. It’s that the gap between “huh, I wonder if…” and “let’s find out” is now a Telegram message. I can kick off a piece of research or a throwaway prototype from anywhere, put the phone away, and come back to a repo with real work in it. Claude Code was already good at that work. Having it in my pocket all the time made it a habit.