The Terminal Built for Claude Code Agent Teams
How teru handles multi-agent workflows natively — CustomPaneBackend, OSC 9999, MCP server, and process graph. No tmux, no cloud, no config.
The Terminal Built for Claude Code Agent Teams
I want to tell you about the moment I realized every terminal emulator was built for a world that no longer exists.
I was running a Claude Code agent team — a team-temporal job with a backend developer agent, a frontend developer agent, and an orchestrator coordinating them. Five processes, two workspaces, one goal. The agents were doing exactly what they were supposed to do. My terminal was a disaster. Panes were fragmenting across tmux, the tiling manager had no idea which window belonged to which team, and I was manually reorganizing layouts while the agents were trying to work.
That’s when I started building teru, an AI-first terminal emulator written in Zig. This post is about the specific problem it solves: being the right environment for a Claude Code terminal with native agent team support.
The Problem: Three Config Layers, Zero Coordination
If you run Claude Code with agent teams today, you’re managing three separate systems that don’t know about each other:
- The multiplexer (tmux) — handles panes and sessions, knows nothing about processes
- The tiling manager — handles windows, knows nothing about what’s inside them
- Shell scripts — glue that tries to bridge the two, breaks when anything changes
Claude Code’s agent team feature spawns multiple Claude instances in parallel, each in its own pane. tmux creates those panes just fine. What it can’t do is tell you which pane is running which agent, automatically assign agents to workspaces by team, color-code pane borders when an agent succeeds or fails, or let one agent query another’s output.
The terminal emulator sees bytes. tmux sees panes. Your tiling manager sees windows. None of them see agents.
Ghostty explicitly does not support Claude Code’s split-pane mode. It’s a deliberate choice — they’re building a fast, focused emulator, not an agent runtime. That’s fair, but it means Ghostty users are back to tmux scripts when running agent teams.
What teru Does Differently: CustomPaneBackend
teru implements the CustomPaneBackend protocol from Claude Code issue #26572. When Claude Code detects teru via the CLAUDE_PANE_BACKEND_SOCKET environment variable (which teru sets automatically), it sends JSON-RPC directly to the terminal instead of shelling out to tmux.
The protocol has 7 operations. The one that matters most is spawn:
{
"method": "spawn",
"params": {
"argv": ["claude", "--agent", "backend-dev"],
"metadata": {
"group": "team-temporal",
"role": "backend-dev"
}
}
}
When teru receives this, it creates a new pane, registers it in the ProcessGraph with the agent’s metadata, and auto-assigns it to the correct workspace based on the group field. No tmux. No shell scripts. No manual layout management.
The full operation set (spawn, write, capture, kill, list, get_self_id, and the push notification context_exited) gives Claude Code complete programmatic control over pane lifecycle.
Auto-Workspace Assignment
The group field in the spawn metadata is how teru organizes agent teams. Agents with "group": "team-temporal" all land in the same workspace. Agents with "group": "team-svelte" land in a different one. You switch workspaces with Ctrl+Space, 1–9 — the same keybindings you’d use for any other workspace.
When a team finishes, its workspace clears. You never touch a layout file.
OSC 9999: Any Process Can Be an Agent
The CustomPaneBackend protocol handles Claude Code specifically, but teru’s agent protocol goes further. Any process — a shell script, a Rust binary, a Python worker — can self-declare as an AI agent using OSC 9999 escape sequences:
# Declare yourself as an agent, join a group
printf '\e]9999;agent:start;name=backend-dev;group=team-temporal\a'
# Update progress mid-run
printf '\e]9999;agent:status;progress=0.6;task=Building API\a'
# Signal completion
printf '\e]9999;agent:stop;exit=success\a'
teru parses these sequences and immediately updates the ProcessGraph and the visual display. Pane borders color-code by status: cyan for running, green for done, red for failed. The status bar shows agent counts. You can see at a glance that three agents are running and one finished successfully — without reading any output.
MCP Server: Cross-Agent Communication
This is the part that makes teru genuinely different as a terminal for AI agents. teru runs an MCP server over a Unix socket at /run/user/$UID/teru-$PID.sock. Any Claude Code instance can connect to it and query the terminal’s state.
Add this to your Claude config:
{
"mcpServers": {
"teru": {
"command": "socat",
"args": ["UNIX-CONNECT:/run/user/1000/teru-PID.sock", "STDIO"]
}
}
}
That unlocks 6 tools for cross-agent communication:
| Tool | What it does |
|---|---|
teru_list_panes |
List all panes with id, workspace, and status |
teru_read_output |
Get recent N lines from any pane |
teru_get_graph |
Full process graph as JSON |
teru_send_input |
Type into any pane’s PTY |
teru_create_pane |
Spawn a new pane |
teru_broadcast |
Send text to all panes in a workspace |
The orchestrator agent in a team-temporal workflow can call teru_read_output to check what the backend-dev agent just output, then use teru_send_input to unblock it if it’s waiting on a prompt. Agents coordinating with agents, through the terminal, without any shared filesystem state or custom IPC.
Process Graph: DAG Tracking for Every Process
Every process teru spawns — agent or not — gets a node in the ProcessGraph, a directed acyclic graph that tracks parent-child relationships and agent metadata. You can query it in milliseconds via teru_get_graph. The result is JSON: every node’s ID, PID, name, group, status, and edges to its children.
This is what makes the pane border color-coding work. It’s not a heuristic based on exit codes — it’s a live DAG update from the OSC 9999 protocol, propagated to every visual element that cares about agent status.
Hook Listener: 16 Claude Code Lifecycle Events
teru’s hook system (configured via hook_on_agent_start and similar keys in ~/.config/teru/teru.conf) can execute external commands on any of 16 Claude Code lifecycle events — PreToolUse, PostToolUse, SessionStart, SessionStop, and more. A team finishing can trigger a notification. An agent error can trigger a custom sound. A PostToolUse event can update a dashboard. The terminal is a participant in the workflow, not just a display surface.
No Cloud, No Account
Cloud-dependent AI terminals require an account, send data to external servers, and add a round-trip to every terminal interaction. teru is a 1.3MB binary. It runs entirely on your machine. No telemetry. No account. No network calls from the terminal itself — only from the Claude Code processes running inside it.
The MCP server listens on a Unix domain socket. Cross-agent communication stays local. Process graph queries return in milliseconds because they’re in-memory. Everything that needs to be fast is fast because nothing leaves the machine.
Getting Started
On Arch Linux:
paru -S teru
This requires Zig 0.16 (paru -S zig-master-bin). For other distros, build from source:
git clone https://github.com/nicholasglazer/teru.git
cd teru
make release
sudo make install
The AI integration docs walk through the full Claude Code setup. The multiplexer docs cover workspace management and layout options.
If you run Claude Code with agent teams and the current terminal situation is frustrating you, teru was built for exactly this. The terminal for AI agents should understand agents — not just pass their bytes through.