Memention

A lab in the closet

A couple of weeks ago I upgraded one of my old main Raspberry Pis at home, a Pi 3 that had been chugging along for years, to a Pi 5 with SSDs. No more tired SD cards, and the little thing is really fast. Mostly idle too, of course. A machine like that is just asking for a job.

The thing that had started to bother me is that Claude Code lives in a terminal on my laptop. Close the lid and everything stops. The model doesn’t get tired, but the laptop goes where I go, and the agent goes with it. A bit wasteful, having a colleague that only works while I hold the door open.

So, the idea: move the agent to a machine that is always on. The new Pi 5 in my case, behind an Apache proxy. It should run uninterrupted, do real work on git repos, and let me steer it from a browser. How hard can it be?

System design: browser and platform clients connected to the always-on dev lab

The result is claude-agent-team. The heart of it is a little Python service built on the Claude Agent SDK. A web console with login and a project list, and each project is its own git clone with its own resumed agent session, so follow-ups build on earlier work instead of starting over. The agent works on chat branches, the lab owns the commits, and there is a merge button when the work looks good. And since the console is just a web page, one can steer the whole thing from the phone in the sofa. It works, but it is just the desktop page squeezed onto a small screen, so a dedicated mobile design is on the list.

How about auth then? Pretty clean, it turned out: there is no API key anywhere. You log in once with the claude CLI on the Pi, and the SDK picks up the credentials from ~/.claude where they sit and auto-refresh. Subscription, not metered API. The lab even refuses to start if it sees ANTHROPIC_API_KEY in the environment, because that would quietly switch the billing over without telling you.

Is a Raspberry Pi really enough to run an AI agent? Well, none of the AI runs on the Pi. All the model work happens on Anthropic’s servers, and what the Claude Code CLI does locally is mostly reading and editing files and running the odd command. Not heavy at all. The heavy, platform-specific part is building and testing - and that is exactly the part I wanted to distribute.

But, a Pi can’t build an iOS app. So the lab borrows capabilities it doesn’t have from machines that do. My first version had this the wrong way around - the Mac ran a little MCP server and the lab connected out to it. Felt right for about a day. Then reality: the Mac is a laptop. It sleeps, it changes networks, it sits behind NAT. The Pi is the one machine in the house with a stable address.

So I flipped it. Clients dial the lab over a WebSocket, announce what they can do (“build”, “run_tests”), and stay connected. The working tree syncs over with content-hash manifests, so the agent can test uncommitted work without a round-trip through GitHub. From the agent’s side it’s just tools: list_clients, run_on_client. On the Mac side it is one command:

platform-client connect --lab ws://<lab-host>:8770/ws/client --name mac \
  --capability run_tests --capability build

The Mac shows up when it’s awake, and the lab uses it while it’s there.

Now, the part that made me smile. I wrote almost none of this. The milestones in the project plan literally say “owner: agent”, and 96 commits landed in five days. My job was the plan, the decisions file (each line “a settled choice no agent should reopen”), and saying no a few times. It’s the cards setup from the other week, just pointed at a bigger target. Well, mostly saying no - the plan said “no web GUI in the initial scope”, and that decision survived less than a day.

Feel free to grab it at github: claude-agent-team. The QUICKSTART covers both running it locally and the full Pi deployment.

So the new Pi has its job now. I haven’t put much real work through the lab yet, mostly testing, but it looks good, I must say. We’ll see how much of my development quietly moves into the closet…

· · ·