
Tuesday afternoon. I'd kicked off a refactor with Claude Code around 2pm, and at 2:30 I needed to leave for a call, here in Tulum. The old me would have either stayed put with the lid up like a hostage, or killed the run and started over later that night.
Instead I closed the lid, put the laptop in my bag, walked to the café, and reopened Blink on my phone. Three keystrokes. The session was right where I left it. The agent was still working on the /goal I'd defined earlier. As if nothing had happened.
That was the moment.
The bottleneck was me
For nine months my coding setup had a stupid bottleneck. Or more precisely, my laptop. Claude Code and Codex ran locally, which meant the work was anchored to whatever room my MacBook happened to be in. A long task became a commitment to a chair.
I'd also been running three or four worktrees on the same repo at once, each with its own agent. My machine sounded like a hairdryer. Memory at 97% swap. Battery half-dead by lunch.
I'm not a traditional dev. I never SSHed into a server for fun. The "just run it on a VPS" instinct is something engineers have in their bones and I don't. So even though the idea kept floating in the back of my head, I never moved on it. It felt like a thing other people did.

Then Pieter Levels posted this and something clicked. If he runs his whole company off a handful of cheap boxes, I can run a coding agent off one.
The afternoon
I rented a Hetzner VPS. Installed Node, Claude Code, Codex, tmux, mosh, ripgrep. Cloned a few repos. Symlinked the .env files in. Wrote three tiny shell helpers so I don't have to remember paths.
That's the whole setup.
The daily flow is three commands:
> $ mosh devbox
$ dev marvins-personal-website
$ claudemosh devbox connects to the VPS. dev <repo> attaches to a tmux session named after the repo, creating it on first use. claude runs the agent. The agent reads the project's CLAUDE.md, loads the skills, and we're off.
For parallel work on a different branch of the same repo, swap dev for wt (worktree):
> $ mosh devbox
$ wt marvins-personal-website fix-onboarding
$ claudeThat gives me a fresh checkout on a new branch, with env files symlinked in and its own tmux session, in one command. Three terminals, three branches, three agents, none of them stepping on each other.
The dev helper lives at ~/dev/bin/dev and is ten lines of bash that attach (or create) a tmux session per repo:
dev() {
local repo="$1"
local path="$HOME/dev/repos/$repo"
[[ -d "$path" ]] || { echo "no repo: $repo"; return 1; }
if tmux has-session -t "$repo" 2>/dev/null; then
tmux attach -t "$repo"
else
tmux new-session -s "$repo" -c "$path"
fi
}
The whole thing took an afternoon. I had been picturing weeks.
What's actually running
Once the box is up, the picture is simple:
laptop / phone Hetzner VPS
┌──────────────┐ mosh (UDP) ┌─────────────────────────┐
│ Blink / iTerm├───────────────► tmux session "lindy" │
│ │ │ └─ claude (agent) │
│ │ ssh (TCP) │ tmux session "site" │
│ ├───────────────►│ └─ codex (agent) │
│ browser │ forwarded │ └─ next dev :3000 │
│ localhost:3000◄──────────────│ │
└──────────────┘ └─────────────────────────┘
The agent lives in tmux. tmux lives on the box. The box doesn't sleep.
I like to keep btm open while coding to see how many worktrees the VPS can survive. Roughly four agents working in parallel hasn't strained it yet, depending on what they're each doing:

The box isn't more powerful than my MacBook. It's a little less capable, honestly. But it's the right place for the work I want to run async, and a coding agent grinding for two hours is exactly that kind of work.
The lid-close test
The first real test was unglamorous. I gave Claude a non-trivial refactor, watched it start, closed the laptop, and walked downstairs to make coffee. Ten minutes later I opened my phone, tapped into Blink, typed mosh devbox, then dev marvins-personal-website, and there it was. Same session. Same conversation. Mid-tool-call.
Mosh is the unsung piece here. SSH disconnects the second your wifi blinks; you come back to a frozen terminal spewing escape codes. Mosh runs over UDP, reconciles state on reconnect, and survives laptop sleep, wifi-to-cellular handoffs, and brief outages. Combined with tmux holding the agent in place, the session is never tied to a device. It's tied to the box.
That was the moment. Not the install, not the helpers, not the port-forwarding. That.
Two things I didn't expect
Local previews still work. When the agent runs npm run dev, the dev server binds to localhost:3000 on the VPS, not on my Mac. I assumed that meant I'd be stuck previewing UI changes through screenshots or curl. I was wrong. A few lines in ~/.ssh/config forward the ports I actually use, and http://localhost:3000 in my Mac browser hits the VPS:
Host devbox
HostName <vps-ip>
User dev
LocalForward 3000 localhost:3000 # Next.js
LocalForward 5173 localhost:5173 # Vite
LocalForward 4321 localhost:4321 # Astro
LocalForward 8000 localhost:8000 # FastAPI / Django
LocalForward 8501 localhost:8501 # Streamlit
ExitOnForwardFailure no
From my phone I just hit the VPS's Tailscale IP. Same result. Opening a dev preview is identical to running it locally, except the laptop fans aren't on.
Parallel work got easier. I run two or three worktreesA git feature that gives you parallel checkouts of the same repo on different branches. I wrote about how I use them in the four-layers post. per repo, each on its own branch, each with its own Claude session. On my laptop that meant fans roaring and the machine audibly suffering. On the VPS they run side by side and the box doesn't care.
The laptop went from being the work machine to being a window into the work machine. That's a different relationship.

Why it matters
I kept telling myself this was a "nice to have." It isn't. It's the difference between an agent that helps me when I'm at my desk and an agent that helps me, full stop. For €30 a month, less than my ElevenLabs bill, less than a single nice dinner, I bought back the property that long-running work doesn't require my physical presence.
A long-running task used to be a commitment. Now it's just a thing that's happening somewhere. I start a refactor before bed and check it from my phone in the morning. I kick off a content pipeline before lunch and read the output on the walk back. I ship alongside the engineers on my team without being chained to a desk to do it.
The new /goal modes in Codex and Claude Code make this even cleaner. You set a goal, walk away, the agent grinds. Last night I gave Codex a static HTML prototype and told it to turn it into a fully end-to-end-tested Next.js app. It opened 64 PRs by morning. My laptop was closed the whole time.
One of me walks out the door. The other one keeps working. That's the whole sentence.
If you've been putting this off because it sounds like a sysadmin project, it isn't. It's an afternoon. The hardest part is deciding to do it.