Technical writing from the initech project.
March 28, 2026
Why We Built a Terminal Multiplexer for AI Agents
We spent the last month building a Go TUI that manages multiple Claude Code agents running in parallel. It replaced tmux as our session runtime. Here's why we built it, what it does differently, and what we learned.
The multi-agent coding pattern is simple: give each role a terminal running Claude Code with role-specific instructions. A supervisor coordinates. Engineers implement. QA validates. A shipper releases. Each agent gets a CLAUDE.md that encodes its identity, constraints, workflow, and communication protocol.
We ran this pattern across four projects before building initech. It shipped real software: parallel engineering, independent QA validation, release gating, institutional memory that persists across sessions. The pattern works.
But running it on tmux breaks in three ways that get worse as you add agents.
tmux send-keys has no delivery guarantee. You send a message to an agent's pane and hope it arrives. When it doesn't (the pane was busy, the process had exited, the window name was wrong), there's no error. A completion report from eng to super drops, super doesn't know eng finished, QA never gets dispatched, and the bead stalls for an hour until someone manually checks.
In tmux, a hung agent and a productive one look identical. A stalled agent and an idle one look identical. An agent that finished its bead and an agent that's mid-implementation look identical. The only way to know is to peek each pane manually. With 9 agents, that's 9 manual checks every 10-15 minutes.
tmux doesn't know what work exists, who's assigned to what, or that an agent just marked a task as ready for QA. All orchestration lives in the supervisor's context window. Context compacts. Messages get lost. The supervisor forgets eng finished. The dispatch chain stalls.
The through-line: tmux is a general-purpose terminal multiplexer being asked to do a job that requires application-level intelligence.
Each session runs a Unix domain socket. initech send writes text to an agent's PTY through the emulator (same path as real keyboard input), then polls for confirmation: did the message get submitted, or is it stuck at a paste dialog? The sender gets an explicit OK or error within seconds.
$ initech send eng1 "fix the auth bug in middleware.go" $ initech peek eng1 -n 20
We tried JSONL session log tailing first. It was unreliable: Claude writes to JSONL at conversation boundaries, not at a predictable cadence. During a 45-second thinking pause, zero entries. Any timeout heuristic is wrong for some value of the timeout.
The fix: track when the PTY last produced output. Claude Code's spinner animates at 10-30 fps during thinking, tool execution, and response generation. The only state with zero output is idle-at-prompt. A 2-second byte recency threshold gives reliable binary activity detection with no false positives.
Green dot means working. Gray means idle. Yellow means idle with tasks waiting. The overlay shows every agent's state without opening any pane.
While JSONL failed for activity detection, it's perfect for semantic events. The session logs contain tool use results (bd commands with their output), assistant messages (DONE/FAIL patterns), and error sequences. The event system parses these for:
* Bead completion: agent ran bd update --status ready_for_qa
* Stalling: no output for 10+ minutes with a bead assigned
* Error loops: 3+ consecutive tool failures
* Bead claims: auto-detected from bd commands, no extra CLI call needed
Events surface as toast notifications. The operator sees "eng1 completed ini-bhk.3" in green before super even reports it.
Each agent's ribbon badge shows its current bead assignment. The overlay shows every agent's state and bead at a glance. When an agent goes idle after holding a bead, the TUI injects a notification directly into the supervisor's pane: "[from initech] eng1 is now idle (bead: ini-bhk.3). Check if work is complete." The supervisor doesn't have to poll. The runtime tells it.
Every number above was produced by the tool itself. initech managed the agents that built initech. The beads that tracked the work were created, groomed, dispatched, QA'd, and closed through the same TUI that was being built.
The TUI is the runtime. The templates are the intelligence. An engineer agent with a bad CLAUDE.md produces bad code regardless of how well the TUI manages its pane. We rewrote all 11 role templates three times during the project, each time codifying lessons from actual agent failures: when engineers skip PLAN comments, when QA rubber-stamps, when super does work instead of dispatching.
We tried three approaches before landing on PTY byte recency. JSONL tailing (too slow, unpredictable write cadence), terminal output rate (SIGWINCH causes false positives), and prompt detection (fragile to UI changes). The spinner byte flow approach only works because Claude Code's TUI always produces output when it's working. If Claude Code ever changes to a static "thinking..." display, we're back to square one.
The supervisor agent's number one failure: doing implementation work instead of dispatching to an engineer. It happens because dispatching feels slow (write a message, wait for the agent to claim, wait for the result). But the whole point of multi-agent is specialization. We added "Not using agents" as the first critical failure mode in the supervisor template.
Every agent eventually forgets to comment PLAN before coding, or forgets to push before marking ready_for_qa, or forgets to clear its bead display. The auto-notify feature (TUI tells super when an agent goes idle) exists because agents forget to report completion. Guardrails in the templates help but don't eliminate this. Process compliance is a gradient, not a binary.
Session portability is unstarted. Moving a session between machines (MacBook to workbench) requires manual rsync. The PRD describes an initech migrate command that doesn't exist yet.
Resource management is behind a flag. Auto-suspend/resume under memory pressure (the feature that would double effective agent capacity on a 36GB laptop) is implemented but gated behind --auto-suspend because the policy hasn't been tested enough in real sessions.
Onboarding is rough. A new user who runs initech for the first time sees 7 panes with no guidance. Status bar tips cycle at the bottom, but there's no operator guide documenting the full workflow. The tool was built by its own user, and it shows.
Sample size is one. initech has built one project: itself. Every claim about effectiveness is based on dogfooding. The next proof point is building something else with it.
brew tap nmelo/tap && brew install initech mkdir myproject && cd myproject initech init initech
Source: github.com/nmelo/initech