Multi-runtime
One team, three runtimes. Mix Claude Code, Codex, and Gemini per role.
# Today — works:cargo install teamctl --locked
# Or:curl -fsSL https://teamctl.run/install | shMost agent frameworks live inside one Python process. teamctl doesn’t. Each agent is its own real CLI — Claude Code, Codex CLI, or Gemini CLI — running in its own tmux pane on your machine. They survive reboots. They talk through a shared mailbox. They ask before they ship anything sensitive.
You declare the team once, in a YAML file. teamctl supervises them like services.
Multi-runtime
One team, three runtimes. Mix Claude Code, Codex, and Gemini per role.
Persistent
Agents survive reboots and crashes. tmux today; systemd / launchd planned.
Isolated by default
Each project is its own org chart. Cross-project bridges are opt-in and TTL’d.
Human-in-the-loop
Sensitive tool calls block on a Telegram approval before they run.
project: id: hello name: Hello Team cwd: .
channels: - name: all members: "*"
managers: manager: runtime: claude-code role_prompt: roles/manager.md can_dm: [dev] can_broadcast: [all]
workers: dev: runtime: claude-code reports_to: manager can_dm: [manager]That’s a real team. manager and dev are different processes — different tmux panes, different model contexts, different runtimes if you want. They DM each other and broadcast on a shared channel. reports_to is the org chart.
runtime — what kind of agent. Today: claude-code, codex, gemini.role_prompt — a Markdown file. The agent’s job description.can_dm / can_broadcast — who can talk to whom.reports_to — the team’s hierarchy.hitl.globally_sensitive_actions — which tool calls block on approval.teamctl init --template soloteamctl upThat’s the whole getting-started. tmux opens with panes for the manager and the dev. They start talking. Tap teamctl ps to see who’s alive. teamctl mail solo:manager reads the manager’s inbox. teamctl send solo:manager "research X and write a brief" kicks off a real task.
Want to see more team shapes? Browse examples/ in the repo:
hello-team — the 60-second first run.newsletter-office — a head-editor + reporters + blog repo. HITL on publish and merge_to_main.market-analysts — analyst-lead + 3 analysts.multi-runtime — same team, different runtimes per role.Plain comparison. No put-downs. We respect every tool here.
| teamctl | claude-squad | claude-flow | mcp_agent_mail | tmux + scripts | |
|---|---|---|---|---|---|
YAML-declared reports_to org chart | ✅ | ❌ | ❌ | n/a | ❌ |
| Multi-runtime (CC + Codex + Gemini) | ✅ | ✅ (also Aider) | partial (CC + Codex) | n/a | manual |
| Persistent across reboots | ✅ | ❌ | ❌ | n/a | manual |
| HITL approvals (Telegram) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Inter-agent mailbox bundled | ✅ | ❌ (shared workspaces) | partial (MCP tools, no mail layer) | ✅ (it is the mailbox) | ❌ |
| System-native supervision1 | planned | ❌ | ❌ | n/a | ❌ |
| Rust | ✅ | ❌ (Go) | ❌ (TS) | mixed | n/a |
How do I track cost per agent? Each agent is a real CLI session. Cost-per-agent is whatever your provider invoices for that session’s API key. teamctl detects rate-limit signals per runtime and respects them; per-agent token spend visibility is on the roadmap. See Cost & rate limits for the current story.
What stops the agents from spamming each other? Each project has one shared channel. Broadcast is allowlisted per agent (can_broadcast), not on by default for everyone. DMs are explicit — can_dm is a list. gc cleans the mailbox on a TTL. We chose to ship broadcast because real teams need it; the design intent is to keep it scoped, not to filter it out. See Coordination policy for the full reasoning.
GitHub · crates.io · MIT License · Rust · v0.2.9
teamctl’s persistent supervisor is tmux today; systemd and launchd back-ends are designed and on the roadmap. We mark this row “planned” rather than ✅ to keep the table honest. ↩