← All field notes
AI Engineering

Coding Agents on a Server: The Afternoon Setup, and the Eight Walls That Come After

Running Claude Code on a VPS takes an afternoon. Running a fleet of coding agents that ships while you are away takes months of solving the same eight problems everyone hits, in order. Here is that order, and how I solved each one.

Matthew TurleyJuly 31, 202615 min read

Everyone found out last week that you can rent a cheap box and run Claude Code on it from your phone. Pieter Levels posted about it, then a dozen people wrote up their setups, and now half my timeline is coding from the toilet. It is genuinely a big unlock and you should do it.

I have been running this way for about six months. Not one session on a box. A fleet of them, all day, building and shipping across a handful of products, most of it while I am away from my desk. So I want to give you the honest version: the setup takes an afternoon, and then you spend the next few months hitting the same wall everyone hits and solving problems in roughly the same order. Here is that order, and how I solved each one, so you can skip ahead.

Part 1: the basic setup (do this first, it really is an afternoon)

The stack almost everyone lands on, and it is the right one to start with:

  1. A cheap VPS. Hetzner or DigitalOcean, 5 to 10 dollars a month, Ubuntu. Setup automatic backups. If you are going to run more than a couple of sessions, get more RAM than you think, each agent plus its tooling eats a surprising amount. A 16GB box is a good starting point once you are serious.

  2. Install Claude Code on it. Log in once. That is the whole "AI" part.

  3. Lock it down before you do anything else. This is the part people skip and regret. Put the box on Tailscale so only your devices can reach it. Add a firewall that blocks all inbound by default. Add fail2ban. If you expose anything to the public internet, do it through a Cloudflare Tunnel, not an open port. You are about to give an AI a shell on this machine with your credentials on it. Treat it like it matters, because it does.

  4. Run inside tmux. Start Claude Code inside a tmux session, not a bare shell. This is what lets the work keep running when you close your phone, and lets you reattach later from any device. This one habit is the difference between "my agent stopped when my screen locked" and "it kept going."

  5. Get on it from your phone. Termius is the SSH app most people use. Install it, add your key, connect, attach to your tmux session. You are now coding from anywhere.

That is it. That is the setup the whole timeline is celebrating. Go do it.

Then, over the next few weeks, in about this order, you will hit the following.

Part 2: the problems you are going to hit, from first to worst

Problem 1: the terminal on your phone is miserable

This is the first wall, and it is universal. You cannot paste properly. You cannot drop in a screenshot. The text is tiny, the scrollback is a nightmare, and one fat-fingered tap kills your session. Someone on X put it perfectly this week: "it works, it's just miserable to use."

Everyone finds the same workarounds. Upload a screenshot to Google Drive and tell the agent to go fetch it. Keep a notes file open to paste through. It is all friction, and friction is what stops you from actually using it.

What worked for me, and it was the biggest shift, was to stop trying to live in the terminal at all. For me the terminal turned out to be the wrong tool for maybe 90 percent of what I do on my phone, which is reading what the agent did and saying yes or no. I started treating a raw SSH terminal as the floor, not the ceiling. Your mileage may vary, but that reframe is what unstuck me.

The way there was gradual, and it followed the problems, not a plan. I started in Termius like everyone else. Then I put a responsive web interface in front of the box so I could actually read and steer from a browser, on the desktop and on my phone. Then I added a chat interface, then a docs view, and each thing I bolted on was just me fixing the next annoyance in my own workflow. Eventually it became a native mobile app with real notifications and voice, so the agents could reach me instead of me sitting there watching them. None of it was a grand design. Each piece was the cheapest way past whatever was slowing me down that week, which is also why it fits the way I work and a copy of someone else's setup probably would not.

The point is not my particular stack, it is the direction. Use the Claude Code mobile app for the on-the-go stuff, it handles paste and images far better than a terminal ever will. And build or adopt a real interface on top of your box, a page you open on your phone that shows what each agent is doing and lets you approve or redirect it, then grow it toward whatever keeps annoying you. The terminal is where the agent lives, not where you live. If there is one thing I would pass on, it is that, at least for me, the way past a miserable terminal was not a better terminal.

Problem 2: your session dies and you lose your place

You will reboot the box, or hit a rate limit, or your login will expire, and you will come back to find your session gone or your agent sitting dead. tmux gets you most of the way, the session survives a disconnect, but it does not survive everything, and "most of the way" is exactly where you lose an hour of context at the worst moment.

What helped me, roughly in order of how much it mattered:

  • Name your sessions and keep a list of them. One tmux pane per project. Know what is running.
  • Resume, do not restart. This is a real trap. When a session dies and you bring it back, there is a difference between continuing the exact conversation and starting a fresh one that happens to be in the same folder. Bring back the actual session with its history, or you lose everything it knew. I keep a small record of each session's real resume ID so recovery brings back the true session, not a blank one wearing its name.
  • Keep it awake. Sessions get killed by inactivity and by expired logins. A keep-alive and an auto-relogin on a 401 save you from babysitting.
  • Automate the recovery. I have a small watchdog that notices when a session has died or gone unresponsive and brings it back, in the right state, on its own.

This is the first hint of the real theme: running one agent is a toy, running many agents reliably is an operations problem.

Problem 3: you cannot actually review the work, so you either rubber-stamp or you slow down

Now that it is easy to fire off work from your phone, you hit the trust problem. The agent pauses and asks to run a command or make a change. You are at dinner. In a terminal, on a phone, you cannot really see the diff, so you either tap yes blindly or you tell yourself you will look later. Blind yes is how bad code ships and how money gets burned. "Later" is how review work piles up.

What I ended up building for myself was a review surface, not a chat box. I wanted to actually see the diff, see a screenshot of the thing it built, and approve with context in about two taps. And I wanted it to come find me, a notification for the moments that genuinely need a decision, instead of me sitting there watching a terminal wait. There are surely other ways to skin this, but that was the shape that worked.

The reframe that helped me: your job stopped being "write the code" a while ago. Now it is not even "watch the code get written." It is "decide the handful of things only you can decide, fast, from wherever you are." Design your setup around making those decisions cheap.

Problem 4: you burn a pile of money on one bad setting

Someone on X this week admitted to torching $4,700 because he did not set a workspace limit. I believe him, because I did a smaller version of the same thing last week: a loop I wrote to keep my agents busy went sideways and quietly ate a chunk of my usage overnight before I caught it. It is the most common expensive mistake in this whole game and nobody's getting-started post mentions it.

The instant you let an agent run unattended, and especially the instant you let a loop trigger agents, you have built a machine that can spend money and make changes while you sleep. That is what makes it worth doing. It is also what makes it dangerous.

What I learned the hard way: put the guardrails in before you let anything run unsupervised, not after.

  • Set hard workspace and spend limits. Know your ceiling and enforce it in code, not in your own vigilance.
  • Any loop that launches work needs a kill switch and a cap on how many times it can fire. A loop with no off-ramp will find a way to run forever. Mine did.
  • Log what got spent and on what, so a runaway shows up as a number you can see, not a surprise on your bill.

Problem 5: one box, one session stops being enough, and now you are running a fleet

This is the fork in the road. Most people stay at one or two sessions and that is fine. But if this clicks for you, you will want ten. Different projects, different jobs, some building while others review. And now the whole thing is chaos: which session is which, which account is each one burning, which model, which one is stuck.

The way I keep it sane: treat the sessions as a fleet with an operator, not a pile of terminals.

  • One session per project or per job, clearly labeled, on a board you can see at a glance.
  • Route accounts and models deliberately. When you run many sessions you will run into usage limits, so you need to know which session is drawing from which pool and be able to switch. A cheaper, faster model for the grunt work, your best model for the hard reviews. I open-sourced the little router I use for exactly this, it sends each request to the right model and account and falls back when one gets capped. It is free and MIT (RelayPlane), use it or read it for the pattern.
  • Give each session its own identity and its own guardrails, so one going wrong cannot take the others down with it.

The people shipping half-built browser UIs and PWAs for this right now, muxboard, the various "control Claude from a phone" tools, are all circling the same realization: the unit of work is no longer the session, it is the fleet, and a fleet needs a console.

Problem 6: the agents produce more than you can review, and you become the bottleneck

You solved reviewing on your phone. Then you scaled up, and now the problem is not that reviewing is awkward, it is that there is simply too much of it. Ten agents shipping all day produce more diffs than one human can look at. You are now the slowest part of your own system.

What worked for me: stop being the only gate. Put a review step between the agent and your main branch that is not you. An automated reviewer that checks the work, runs the tests, and either clears the safe, boring changes on its own or escalates the ones that actually need your eyes. The goal is that the only things reaching you are the things that genuinely need a human, and everything else just lands.

This is the single biggest-payoff thing I built, and it is the part nobody running Termius on a phone has. Running the agent was never the hard part; what actually matters is the process around many of them, a real pipeline with gates, so throughput is not capped by your attention.

Problem 7: something breaks and it silently blocks everything

At fleet scale you hit a failure mode that does not exist with one session: one bad change lands, the build goes red, and now every agent working on that project is stuck behind it. You do not notice for hours because you are not staring at it. You come back to find nothing shipped all day and no one told you.

Where I landed: the thing that breaks should heal itself, or at least name whoever broke it and get out of the way. Most of these breaks are not even real bugs, they are junk: a stale lockfile, leftover test files, an environment mismatch. That class should be auto-detected and auto-fixed without you ever hearing about it. The genuine regressions should be pinned on the specific change that caused them and kicked back automatically, not left to block the whole line. What you do not want is a dumb janitor that keeps retrying blindly, I had one of those loop over a hundred times "fixing" a break it had itself caused. The rule that works: whoever broke it fixes it, and the system tries the known-safe repairs on its own first.

Problem 8: you stop managing loops and start managing graphs

The real thing here is simple, even if the vocabulary around it is not. Early on your agent runs as a loop: it goes around on its own, plan, act, check, repeat, holding its whole plan in its own head, so it loses the thread, retries forever, and you cannot see what it is doing. At some point you get tired of that and start pulling the plan out of the agent's head into something you can actually see: named steps, real state, control flow that does not live inside one agent's context. That is the thing that lets work run without you and lets you debug it when it breaks.

This came out of not being able to see what a looping agent was doing when it stalled, and not being able to gate or resume it. What my pipeline turned into is roughly what people are now drawing as graphs: a task moves through defined stages (build, review, verify, merge), one piece hands off to the next on its own, and the state lives in a database I can look at, not a chat log I have to scroll. People are calling it "loops to graphs" this month; the name will change again, the problem it points at will not.

The bigger shift, and where this leaves you

Somewhere in here the job quietly changed, and this is the part I find most worth sitting with. I am not really coding anymore, I am building the machine that codes. The names for this keep cycling, prompt engineering, context engineering, loop engineering, graph engineering, but the part underneath is steady: the work moves up a level, from writing the lines to designing the system that writes them, and from reviewing every diff to setting the constraints and watching the metrics. It came one problem at a time, until this is what was left.

That is a genuinely different kind of thinking, and honestly a different kind of hard. The old hard was "can I write this function." The new hard is "what should run without me, where does a mistake get expensive, which decisions are actually mine, and how do I keep the number of those flat while the number of agents grows." It feels closer to running a small team than to programming. Some days I miss the old kind. Most days I get more done with my own hours than I ever have, and I would not go back.

So, for what it is worth: do the setup, it is easy and worth it. Then treat the terminal as a starting point you will outgrow, because everything past it is the same lesson in different clothes, your attention is the scarce thing, so build the system that protects it. Get off the terminal onto a real interface, let sessions recover on their own, build a review surface you can trust, put money guards in before you get burned, treat many sessions as a fleet with a console, gate the agents so you are not the bottleneck, let breakage heal itself, and pull the control flow out of the agent's head into something you can actually see. Call that last one whatever you like; the names will have changed again by the time you finish reading this, and the problems will not.

Everyone is at step one this week. It is the part after that got me, the most fun I have had building in years. Nowhere near the end of it. Go build the machine.


This guide kicked off real discussions worth reading: the LinkedIn article and the r/ClaudeAI thread, where people shared setups better than mine on several of these walls. That is the point of writing it down.

M
Matthew Turley, Continuum

Technical co-founder for hire. 20+ years shipping production software.

Run a free Leak Check →