Writing · June 4, 2026
An AI Agent Was Never a Terminal Program
A first-principles walk through how terminal processes work, how Claude Code used to live inside one, and why the supervisor architecture quietly moved agent work off the terminal — and what that says about where value accrues in agent tooling.
Some architecture changes look clever when you first see them and obvious once you understand them. Claude Code moving its background work out of the terminal and under a supervisor is one of those, and the only way I have found to make it feel obvious is to start one level below where most explanations begin, with what the operating system actually does when you run a program.
So I am going to follow a single task the whole way through, "fix the login bug," and we will watch what the OS does with it, first the old way and then the new way. By the end I want the shift to feel inevitable instead of impressive.
Part 1: How terminal processes work
A process is a running program
When you run a program, the operating system creates a process, which is a live instance of that program with its own memory and an ID number called a PID. The program sitting on disk is inert. The process is that program while it is running, and when the process ends it is gone. The distinction is small, but I think it is the one everything else rests on.
The shell is a process whose job is to launch processes
The thing you type into, bash or zsh, is itself a process called a shell, and its entire job is to take what you type, find the matching program, and launch it. When you type claude and press Enter, the shell does two things in order.
First it clones itself. The Unix way to make a new process is to copy an existing one, so the shell makes a near-identical copy of itself with the same memory and the same open connections. The original is the parent and the copy is the child.
Then it replaces the clone's contents with your program. The child immediately overwrites itself with the claude program loaded from disk, so it is the same process with the same PID, but it is now running Claude Code instead of being a second shell.
In classic Unix these two steps are the fork() and exec() system calls. Modern applications usually call a higher-level helper that does both at once, but the underlying model is exactly this: copy, then replace. The consequence I care about is that your new process is a child of the shell, and that parent-child link is what everything below depends on.
The three wires: stdin, stdout, stderr
To the operating system almost everything is a file you read from or write to, including your keyboard and your screen. Every process is born with three of these connections already open, numbered 0, 1, and 2. Wire 0 is stdin, where the program reads input, pointed by default at your keyboard. Wire 1 is stdout, where it writes normal output, pointed by default at your screen. Wire 2 is stderr, where it writes errors, also pointed at your screen.
These are just pointers. When claude prints a line it is writing to wire 1, and wire 1 happens to point at your terminal, which is the only reason the text appears in front of you. And because the child inherits the parent's wires, the clone that becomes Claude Code gets the same three connections aimed at the same terminal. Claude reads your prompts off wire 0 and writes its responses to wire 1, straight to the terminal you are staring at. There is no magic here. It is wired in at birth.
Why closing the terminal kills the program
This is the part I think everyone feels and few can explain. Every terminal window has a controlling terminal, and the processes attached to it belong to a group led by your shell. When you close the window, the kernel notices the terminal is gone and sends a signal called SIGHUP, short for "hang up," a holdover from when terminals were physical phone lines. The default reaction to SIGHUP is to die immediately.
So the chain is short. Close the terminal, the kernel sends SIGHUP to the foreground group, and your program dies. This is not a limitation someone forgot to fix. It is the correct default, because a program reading from and writing to a terminal that no longer exists has nothing left to do. The problem only shows up when you want the work to outlive the window.
That is the whole foundation, and I would hold onto three facts from it: a process is a child of the shell, it is wired to the terminal through three connections, and it is tied to the terminal's life by a kill signal.
Part 2: How Claude Code originally ran
Originally claude was an ordinary foreground program, no different in shape from vim or node server.js. You ran claude, the shell cloned and replaced itself into Claude Code, and Claude's three wires pointed at your terminal. It read your prompts from wire 0 and streamed its reasoning, tool calls, and edits to wire 1, which was your screen. While it ran, your terminal was occupied, because that tab was Claude's tab and watching the text stream was the interface. One session lived in one terminal tab, and closing the tab sent SIGHUP and killed the session mid-thought.
For a single agent you are actively pairing with, I think this is a perfectly good design. It falls apart the moment you want several at once.
The tmux era, and why it was a tax
To run multiple agents, we reached for tmux, a terminal multiplexer, or simply opened many tabs. tmux solves exactly one problem: it keeps terminal sessions alive in memory even when you detach, so closing your window does not SIGHUP them. That is genuinely useful, but tmux is terminal-shaped and content-blind. It holds virtual terminals open and shuttles raw text in and out, and it has no idea whether the text inside is an AI agent, a database, or a game of snake.
That blindness is where the real day-to-day pain came from. You had to read text streams to know anything at all, because whether agent three was done, stuck, or waiting for permission could only be discovered by switching into its pane and reading it, and with ten agents the overhead of figuring out what was happening grew faster than the work itself. There was no file isolation either, so two agents editing the same repo in two panes would write over each other, and tmux offered zero protection because it is just terminals side by side. The whole arrangement was also fragile, since a misconfigured session, a dropped connection, or a sleeping laptop could make an agent vanish.
The deeper issue, as I see it, is a mismatch. An AI agent is not really a foreground program you watch, it is an asynchronous worker you dispatch and check on later. We were using a terminal-shaped tool to manage worker-shaped things and stapling custom scripts on to bridge the gap, and that mismatch was the friction.
Part 3: The architecture shift, the supervisor
The fix is not a better terminal. It is to stop tying the work to a terminal at all. Claude Code introduced a supervisor process, which is what Anthropic's own docs call it, and that single move resolves every pain point above. Here is what actually happens now when you background "fix the login bug."
The session becomes a child of the supervisor, not your terminal
The first time you background a task or open the dashboard, Claude Code starts one per-user supervisor, a single background process that owns all of your sessions. When you dispatch "fix the login bug," the session runs as its own Claude Code process, parented to the supervisor instead of to your terminal.
Recall the two reasons we found in Part 1 that a program dies on terminal close: it is a child of the shell, and its wires point at the terminal. Break both and the death chain breaks. The session's parent is now the supervisor and not your shell, so when closing your terminal sends SIGHUP to your shell's group, the session is not in that group and nothing tells it to die. And the session's three wires no longer point at your screen, because they are redirected to log files on disk, so it does not need your terminal to exist and does not care when the terminal goes away.
That is the entire trick behind closing your laptop lid and having the work survive. It is not new technology. It is the deliberate inverse of the setup that normally kills a process, and the work is simply decoupled from the window.
I should add one honest note for accuracy, since it is easy to overclaim here. The exact OS dance a program does to detach itself, the classic double-fork daemon recipe, is a C-program convention. Claude Code is a Node application and detaches through its own runtime's mechanism for spawning a detached child with redirected output. The principle is identical even though the literal syscall sequence is not, and I would not assert the syscalls unless I had read the source.
State lives on disk, and the dashboard just reads it
If the session's output no longer goes to your screen, how do you see what it is doing? The supervisor keeps the answer on disk, in your Claude config directory, which is ~/.claude/ by default. The supervisor's own log sits in daemon.log. The list of running sessions, which is how it reconnects to them after a restart, lives in daemon/roster.json. The live state of each session, meaning what it is doing, what it needs, and what it produced, lives in jobs/<id>/state.json.
When you run claude agents to open the dashboard, the dashboard is essentially a reader for these files, rendering each session as a row from that on-disk state. This is why I would call the dashboard disposable. Close it, crash it, or Ctrl+C out of it, and the sessions do not notice, because they were never talking to the dashboard. They are writing state that the dashboard happens to display.
One nice touch is worth knowing. The one-line summary of what each session is doing is not the raw log, it is generated by a small, fast Haiku-class model that turns the session's activity into a readable sentence, so you get "opened a PR fixing the auth redirect" instead of scrolling a transcript.
I should add one accuracy caveat too, because the clean version of this story tempts you to overstate it. It is wrong to say the system uses files for everything and keeps no live connections. The files are the durable, observable state, but when you actually attach to a running session and converse with it, you are reconnected to the live process and not editing a JSON file. I would treat the files as the dashboard's source of truth, not as the only channel that exists.
Git worktrees, where each agent gets its own copy of the code
This is the part that solves the collision problem tmux could not touch. By default, parallel sessions can read your working directory, but Claude Code blocks a backgrounded session from writing files until it moves itself into an isolated git worktree under .claude/worktrees/<id>/.
A worktree is a git feature, a second separate working directory attached to the same repository, sharing the same underlying object history. It is near-instant and cheap on disk because nothing is duplicated except the checked-out files. So "fix the login bug" gets its own copy of the code to edit, test, and break, a second agent refactoring something else gets its own copy, and neither can clobber the other or touch your main working directory until you decide to merge.
When the agent finishes you review its isolated diff, often surfaced as a pull request, and merge it if you like it. There is one gotcha I would remember: deleting the session deletes its worktree with it, so merge or push anything you want to keep before you delete, or it is gone.
The lifecycle that makes it feel like infrastructure
A few rules round it out. A session that is working, waiting on you, or attached stays alive, but once it has been idle and unattached for about an hour the supervisor stops the process to save resources while keeping its state on disk, and the next time you peek or reply it spins a fresh process back up from where it left off. When every session is done and no terminal is connected, the supervisor itself exits, and it restarts automatically the next time you background something. It even watches for Claude Code auto-updates and relaunches itself into the new version, with sessions surviving the restart.
There is a hard limit I would state plainly: this is local. Sleep or shut down your machine and the sessions stop, since they do not survive it, and claude respawn --all is how you bring them back. Ten parallel agents also burn your usage quota roughly ten times as fast as one.
The actual shift, in one line
The old model is that a session is a terminal tab you babysit. The new model is that a task is a worker you dispatch and check on. Everything technical above serves that one conceptual move. Reparenting to a supervisor is how the work outlives the window, on-disk state is how you observe it without babysitting a text stream, and git worktrees are how many workers run at once without fighting. None of the pieces are exotic, since daemons, file-backed state, and git worktrees are all decades old. What I keep coming back to is the recognition that an AI coding agent was never really a terminal program. It was an asynchronous worker wearing a terminal's clothes, and the supervisor just took the costume off.
Why "simple" is the load-bearing decision, not the aesthetic one
I want to be precise about where the simplicity lives, because it is easy to praise the wrong thing.
The parts are not impressive. A per-user daemon, three JSON files, and a few git worktrees are decades-old primitives any systems engineer could name, and if the achievement were "they used simple parts" it would not be an achievement. What I find impressive is the discipline of refusing to build anything above them.
Consider the obvious alternative. The serious, well-funded version of this feature is a cloud control plane, with hosted orchestration, a real database, a job queue, managed runtimes, and a web dashboard. Anthropic had every resource to build that, and instead shipped a background process that writes to ~/.claude/ and a terminal UI that reads those files back. To me, that is the tell. Simplicity chosen with the budget to do otherwise is a philosophy, while simplicity forced by constraint is just a small team, and this was the former.
The move is not "make everything simple" either. It is choosing which complexity to absorb internally so the user's mental model stays one sentence. There is genuine complexity inside the supervisor, including reattaching to a live process after the idle reaper killed it, the worktree creation and cleanup lifecycle, the Haiku summarization pass on every row, and restarting itself into a new binary mid-flight. None of it surfaces. What surfaces is "a task is a worker you dispatch." The hard part was deciding what the user never needs to see, and I think that maps directly onto the design stance Anthropic has argued publicly for agents, which is to start with the simplest thing that works and add machinery only when it earns its place. The supervisor is that argument applied to infrastructure instead of to prompts.
The part I would resist is reading this as pure elegance, or as uniquely Anthropic. It is also just good Unix-lineage systems design, composable and unopinionated and boring on purpose. And it bills you for the simplicity honestly, since it is local only, dies on sleep, and offers no cloud durability. They accepted a real limitation rather than build infrastructure to hide it, which I read as the philosophy showing its teeth and not only its taste, and it is the more interesting thing to write about, because a reader can feel the tradeoff being made instead of just admiring how clean it looks.
The economics are the same fact, viewed sideways
Here is why I think this connects to where value moves in agent tooling, and not just to good taste.
The primitives at the bottom are free because they are old and boring, and nobody can charge for a daemon or a git worktree. So the moment you build on commodity parts, all the defensible value gets pushed upward into the composition. The orchestration layer, the supervision model, and the judgment about what to hide and what to surface is the part that is hard to clone, and therefore the part worth gating.
Which means the simplicity at the base is not separate from the business model, it produces it. Boring primitives force the value up to the orchestration layer, and the orchestration layer is the product. Said the other way, the philosophy of keeping the parts simple and the economics of monetizing the composition are one decision seen from two angles.
That is the through-line I would pull into the broader story of coding agents. The same capability, dispatching and supervising parallel agents, started as something developers hand-rolled with tmux and shell scripts, got partially standardized in open tooling, and is now arriving as a gated, first-class feature inside the vendor's own client. The migration is not about the primitives changing, because they did not. It is about who owns the orchestration, and that ownership is exactly what simple, free primitives at the bottom make valuable at the top.