Skip to content

physwkim/caucus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

124 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

caucus

A terminal multiplexer for teams of AI coding agents.

Status: v1 feature-complete, pre-1.0. The pivot from an async file-based meeting protocol to a live multiplexer is done: the live multiplexer, the MCP control plane, layout control, the transcript overlay, and session persistence/resume have all landed. docs/design.md now matches the shipped code. The CLI and MCP surfaces are not yet stable — expect changes before 1.0.

What it is

caucus is a full-screen terminal multiplexer — think tmux or zellij — purpose-built for running a team of Claude Code / Codex agents on one problem. Each agent gets its own panel. You watch every agent's session live, side by side.

One panel is the main worker: a Claude Code (or, with --agent-cli codex, a Codex) agent you talk to directly. It is not a passive boss — it does the work. You give it a task; it does the small, sequential parts itself, and for work that parallelizes it spawns sub-agent panels and hands each a focused piece. The main worker is the intelligence; caucus is the frame that lets it reach into the sub-agents' terminals.

        you
         │  keystrokes
         ▼
 ┌───────────────────────────────────────────────┐
 │  caucus  (full-screen multiplexer process)      │
 │  ┌──────────┬──────────┬──────────┬──────────┐  │
 │  │ main     │ worker   │ worker   │ worker   │  │  ← panel = agent, one PTY each
 │  │ (claude) │ (claude) │ (codex)  │ (claude) │  │
 │  └──────────┴──────────┴──────────┴──────────┘  │
 │   pty (portable-pty) · term (vte grid) ·         │
 │   render (ratatui)   · input routing             │
 │   MCP server ◄──────── main worker drives subs   │
 └───────────────────────────────────────────────┘

What it is not

  • Not a general-purpose multiplexer. caucus knows about agent roles, turn boundaries, and a main worker orchestrating sub-agents. For plain human terminal multiplexing, use tmux or zellij.
  • Not a replacement for claude-code. That drives a single agent. caucus arranges many of them into a team.
  • Not a "swarm intelligence platform." No learning loop, no auto-tuning, no proprietary memory. caucus is one thing: a live frame for a main worker that fans work out to parallel sub-agents.

How it works

caucus owns the terminal. It manages a PTY per panel (portable-pty), parses each agent's output into a screen grid (vte + a hand-written grid), and renders the panels (ratatui). tmux and zellij are not dependencies — they are studied as references for the grid and layout design.

The main worker drives sub-agents over MCP. caucus runs an MCP server. The main worker gets ten caucus tools (see MCP tools below) so a single instruction from you turns into the main worker decomposing the task, spawning sub-agent panels, and feeding each one its sub-task as real keystrokes.

Sub-agents are dynamic parallel workers. The team is not a fixed roster of specialists — not even a fixed set of roles. The main worker splits a task into sub-tasks and spawns as many sub-agents as the work needs, and it is not limited to a preset role list: spawn_role takes a free-form role label plus an optional inline prompt, so the main worker invents a role on the fly — naming it, writing its instructions, and choosing its model and backend CLI (claude / codex) entirely by its own judgment. The named presets (worker, architect, backend, reviewer, …) are convenient starting points; any other label is an ad-hoc role built on the generic worker defaults. Each code-writing sub-agent gets its own git worktree, so parallel work stays isolated and the main worker merges the results. It spawns and kills panels as the work demands — caucus reflows the layout — and watches per-panel token usage to send /compact or /clear when a context grows inefficient. caucus provides the mechanism; the main worker owns the policy.

Panels are fully interactive. A caucus panel is a real bidirectional terminal, not a read-only view. You — or the main worker — can type into any panel, including driving interactive flows such as a claude login or an OAuth device-code prompt.

Turn completion is live. Each agent's Claude Stop hook posts to a caucus socket the moment a turn ends — no polling, no sentinel files. The main worker sees "that sub-agent finished its turn" immediately and reacts.

Keymap

caucus reserves a single prefix key, Ctrl-A by default, for its own commands. Every other keystroke — including Ctrl-C — is encoded to terminal bytes and forwarded verbatim to the focused panel's PTY, so an agent CLI sees a real terminal.

The prefix is configurable, so it can dodge a collision with an outer multiplexer — for example a tmux remapped to Ctrl-A. Pass --prefix b or set CAUCUS_PREFIX=b to use Ctrl-B instead (any letter; a bare b or a ctrl-b / ^b form both work). The table below shows the default; substitute your prefix for Ctrl-A.

Key Action
Ctrl-A then n / focus the next panel
Ctrl-A then p / focus the previous panel
Ctrl-A then q quit caucus
Ctrl-A then z toggle zoom on the focused panel
Ctrl-A then < move the focused panel one step earlier
Ctrl-A then > move the focused panel one step later
Ctrl-A then Space cycle the layout arrangement mode
Ctrl-A then t toggle the transcript overlay
Esc (overlay open) hide the transcript overlay
Ctrl-A then [ open the scrollback pager (focused panel)
Ctrl-A then Ctrl-A send a literal Ctrl-A to the panel

The layout modes cycled by Ctrl-A Space are Tiled, EvenHorizontal, EvenVertical, and MainVertical — caucus reflows the panels into the chosen arrangement.

The transcript overlay (Ctrl-A t) is a read-only team observation view: one row per panel showing role, derived state, completed-turn count, worktree branch, and the first line of the agent's last message. Esc hides it; it does not capture input, so every other key still reaches the focused panel while it is open.

The scrollback pager (Ctrl-A [) is a tmux copy-mode-style view of the focused panel's terminal scrollback (the grid ring, up to 10,000 rows). It opens at the newest line; ↑/↓ k/j scroll a line, PgUp/PgDn a page, g/Home jumps to the oldest line, G/End to the newest, and Esc/q exits. Unlike the transcript overlay, the pager captures input — keys drive scrolling and none reach the panel's PTY — and shows a frozen snapshot (the panel keeps running; new output appears after you exit).

MCP tools

caucus exposes ten tools to the main worker over MCP. The main worker calls them to spawn, drive, observe, and reap sub-agent panels:

Tool What it does
send_keys Type text into a panel's terminal; enter=true appends a newline.
broadcast Send the same text to several panels at once — a round's fan-out.
ctrl_c Send Ctrl-C (interrupt) to a panel.
read_panel Read a panel's captured output (modes below).
spawn_role Spawn a sub-agent panel. role is a free-form label; an inline prompt becomes the role's instructions; worktree / model / agent_cli overrides.
kill_panel Kill a panel; its worktree (if any) is enqueued for cleanup.
list_panels List every live panel with its role and derived state.
register_round Register a round; caucus pushes the panels' results back when they settle (or fallback_secs). A per-panel backlog queue keeps early finishers working until their tasks drain.
read_menu Read a panel's interactive selection menu (question + numbered options).
select_option Answer a panel's selection menu by picking an option number.

read_panel takes a mode: screen (the visible grid), scrollback (the full scrollback buffer), since_last_turn (everything since the last prompt — the whole turn, no racing the screen), or last_message (the agent's final message from its turn signal).

When a sub-agent stops mid-turn on an interactive chooser (an AskUserQuestion-style menu), no turn signal fires, so the panel reads awaiting_selection and its round cannot settle on its own. caucus detects the menu and pushes the main worker a notice; the main worker answers it with read_menu + select_option (or, for a free-text reply, picks the menu's "type something" option, then send_keys), unblocking the round.

CLI

caucus with no subcommand launches the multiplexer TUI. The subcommands are for bootstrap, inspection, and resume — live control is exposed to the main worker over MCP, not the CLI.

caucus                              # launch the multiplexer TUI in the current git repo
caucus --roles architect,backend,reviewer
                                    # launch with an initial panel roster
caucus --agent-cli codex            # run the main worker on codex instead of
                                    # claude (default); sub-agent backends are
                                    # still chosen per spawn_role
caucus init [--install-hook]        # create .caucus/ + bin/turn-signal;
                                    # --install-hook merges the Claude Stop hook
caucus doctor                       # check git / agent CLIs / hook / role allowlists
caucus role list                    # list known roles
caucus role show <name>             # show one role's full spec
caucus sessions [--format json]     # list resumable sessions, newest first
caucus resume <session_id>          # relaunch the TUI restoring a persisted session

(caucus signal post and caucus mcp-serve also exist but are internal — the Stop hook and the main worker's Claude Code instance invoke them, not a human.)

Sessions

A caucus session is otherwise ephemeral — when caucus exits, the agent processes die. To make a session resumable, caucus writes a session record to .caucus/sessions/<session_id>/session.json whenever the panel roster changes: the roles, their order, each panel's CLI/model, any worktree branch, and the Claude conversation id.

caucus sessions lists those records (id, age, panel count, topic). caucus resume <session_id> relaunches the TUI and recreates the panels from the record — re-attaching worktrees on their branches and continuing each Claude conversation via claude --resume.

Install

git clone https://github.com/physwkim/caucus.git
cd caucus
cargo install --path .       # places `caucus` on $PATH

Requirements:

  • git 2.20+
  • Claude Code CLI (claude 2.x) on PATH
  • Codex CLI (codex) on PATH — optional, for Codex-backed roles
  • Rust 1.85+ (edition 2024)

No tmux dependency — caucus is its own multiplexer.

Roles

Roles are presets, not a closed set. The main worker is free to spawn an ad-hoc role — spawn_role(role="<any label>", prompt="<its instructions>", …) — and caucus builds it on the generic worker defaults (tool allowlist, permission mode) under that label, with the inline prompt as its system prompt. The presets below are the named starting points; reach for one when a sub-task clearly calls for it, and invent a role when none fits.

The embedded presets are read-only defaults; override per-project in <repo>/.caucus/roles.toml or globally in ~/.caucus/roles.toml:

Role Agent CLI Default model Tools Permission mode
main claude opus Read, Glob, Grep, Edit, Write, Bash, TodoWrite, Web* default
worker claude sonnet Read, Glob, Grep, Edit, Write, Bash, TodoWrite acceptEdits
architect claude opus Read, Glob, Grep, WebFetch, WebSearch, TodoWrite plan
backend claude sonnet + Edit, Write, Bash acceptEdits
reviewer claude opus Read, Glob, Grep, Bash default
qa claude haiku Read, Glob, Grep, Bash default
scribe claude haiku Read, Glob, Grep, Edit, Write acceptEdits
serious-reviewer codex (codex picks) Read, Glob, Grep, Bash default

main is the orchestrator panel you talk to; worker is the default sub-agent the main worker spawns for parallel work. The remaining presets are optional specialist hints — use them when a sub-task clearly calls for one, or go off-list with a free-form role as above.

For a worked orchestration pattern — a continuous review → fix → regression loop driven by main over a durable review doc — see docs/review-loop.md.

Cost tiers reflect each role's cognitive load: Opus where shaping decisions and finding subtle issues matters, Sonnet where executing a defined plan suffices, Haiku where the work is mechanical. The default-model column uses claude CLI tier aliases (opus / sonnet / haiku) so caucus follows the latest generation automatically; pin a version in roles.toml for reproducibility.

System-prompt templates live under roles/. Each preset role inherits the claw-code "4-constraint scaffolding" (delegated task / only tools / no questions / concise result); a free-form role's inline prompt is its system prompt verbatim, so write that scaffolding into it when you want it.

The system prompt reaches each backend differently: claude gets it via --append-system-prompt, and codex via its -c instructions=… base- instructions override — so a Codex-backed role (preset or free-form) also runs with its instructions.

Every role's allowed_tools includes mcp__kodex: a sub-agent queries the kodex knowledge graph (recall_for_task) to self-serve codebase context — so the main worker hands each one a lean brief and lets it fetch the depth, and records discoveries with learn. kodex is the user's global MCP server; swap or drop it per-project in roles.toml.

Related projects

  • tmux — reference for the session / pane / keystroke-routing model.
  • zellij — Rust multiplexer; reference for the vte-based grid and layout engine. caucus reuses the same published crates (vte, portable-pty) zellij stands on rather than vendoring zellij itself.
  • dmux — TUI for humans running many agents in parallel.
  • claw-code — Rust port of claude-code; source of the role scaffolding and lane-event model.

License

MIT.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages