at play · case study
The Hub
An AI coding agent on my own server, driven from my phone — Claude Code today, any provider by design. I type an idea from anywhere; the agent works on the VPS; a prototype is waiting before the walk is over. No third party in the path, and every request billed to the right meter.
hover to inspect- role
- design & code · ops
- stack
- FastAPI · Claude Agent SDK · xterm.js · Tailscale
- runs on
- a self-managed VPS — systemd, isolated users
- status
- private build, in daily use
Born on a walk
The need: ask an LLM something from the phone, mid-walk, without a third-party service reading the traffic and without a fragile SSH-over-mobile ritual. So the agent lives where it should — on a server I run — and the phone carries only a thin, installable PWA. It's a personal idea tester in the OpenClaw family of self-hosted agents: a thought typed on the street becomes a running experiment on the VPS before the walk is over. The instrument panel is provider-agnostic — today it speaks Claude, both the Agent SDK and the first-party CLI; another provider is a lane in the diagram, not a rewrite. Three tabs:chat (streaming, voice input, per-session spend cap), a real terminal (a PTY with the first-party Claude Code CLI and thumb-sized keys), and a dash— CPU, RAM, disk, systemd and docker status, per-project CI and last commits.
The path
There is exactly one road to the server: the tailnet. hub binds to localhost and is published only through Tailscale's private HTTPS — it does not exist on the public internet, there is no relay, no vendor bridge, no one in the middle.
Two bills, kept honest
Anthropic's terms draw a hard line: the Agent SDK must run on a metered API key; subscription OAuth belongs to the first-party CLI only. hub is architected around that line instead of near it. The chat tab and every scheduled cron job run headless on the API key and pay per token. The terminal's claude runs as the real CLI on the Pro/Max subscription — and its PTY deliberately stripsANTHROPIC_API_KEY from the environment, so the two paths cannot cross even by accident.
Reading the compliance page before drawing the architecture is the whole trick — the billing split isn't a setting, it's the shape of the system.
A server of one's own
Everything under hub is handled solo, and repeatably: one install script provisions a full instance — its own linux user, its own systemd unit, venv, env file, and ACL-protected agent state — so a second hub (different project, different model, different system prompt) is one command on any box. The dash closes the loop: the same screen that talks to the agent watches the machine it lives on. Ops isn't outsourced here; it's part of the build.
Anthropic has since shipped the mainstream version of this idea — Remote Control, bridging a laptop session to the phone. hub still runs where that can't: on a server that never sleeps, over a network nobody else can see.