Inspiration
I kept running into the same problem when coding agents worked through terminals: every tool call behaved like a disposable shell. The working directory reset, environment variables disappeared, SSH sessions had to reconnect, and long-running or interactive processes were awkward to recover. In one real workflow, repeated SSH connections even triggered fail2ban on my own machine.
A terminal is naturally stateful. I wanted agents to have that same continuity without inventing a separate tool for every environment.
What it does
Aiterm is a local stdio MCP server that gives Codex and other MCP clients a real, persistent terminal backed by tmux.
An agent can open one PTY, change directories, export variables, authenticate to SSH once, enter a container or REPL, start a long-running process, and continue using the same session across later tool calls. SSH, Docker, WSL, REPLs, and coding-agent TUIs are not separate protocols; they are simply interactive programs running inside the same terminal.
Aiterm also provides:
- Token-reduced reads that preserve useful evidence while folding noisy output
- Five-layer completion detection using process exit, explicit marks, expected output, quiescence, and timeout
- Interactive launchers for Codex and other coding-agent TUIs
- Structured launch and close receipts for reliable orchestration and retry
- A destructive-command tripwire with an explicit override
- Human co-driving through the same tmux session
How I built it
The server is written in TypeScript on Node.js using the Model Context Protocol SDK. The core talks to tmux through send-keys, buffers, and capture-pane, while keeping stdout reserved for MCP JSON-RPC.
The design intentionally keeps the primitive small: open, send, read, key, list, and close. State lives in the PTY rather than in a growing collection of SSH-, Docker-, or REPL-specific tools.
Codex and GPT-5.6 were used as engineering collaborators to inspect the implementation, challenge API and recovery contracts, generate focused regression cases, and verify failure paths. I kept final product and architecture decisions explicit rather than accepting generated changes blindly.
Build Week extension
Aiterm existed before Build Week, so I kept the new work visible in dated commits. During the submission window I meaningfully extended it with:
- Safe serialized delivery for long PTY input
- A managed interactive agent launcher with bounded result recovery
- Correlated operation IDs that prevent duplicate or misattributed results after timeouts
- Machine-readable launch and idempotent close receipts
- A hardened readiness gate that prevents prompts from disappearing during TUI startup redraws
The current source has a 262-test regression suite covering normal operation, races, malformed events, security boundaries, recovery, and tmux integration.
Challenges
The hardest problem was deciding when an interactive command is actually complete. Process exit is insufficient for shells and TUIs, prompt matching breaks with customized or nested prompts, and output silence alone can be ambiguous. Aiterm therefore reports how completion was determined and returns an explicit incomplete result on timeout instead of silently pretending success.
Another difficult boundary was recovery. If a caller times out after sending work to an agent, retrying the prompt can duplicate the action. Correlated operations and structured receipts let the caller recover the original result without resending the work.
What I learned
Agent tools need more than execution. They need continuity, bounded observation, explicit failure, and recoverable side effects. A thin terminal primitive can support local shells, remote machines, containers, REPLs, and other agents while remaining understandable enough to audit.
Aiterm is MIT licensed and installs with npx -y aiterm-mcp on Node.js 18+ with tmux.
Built With
- codex
- developer-tools
- gpt-5.6
- model-context-protocol
- node.js
- tmux
- typescript
Log in or sign up for Devpost to join the conversation.