loading…
Search for a command to run...
loading…
Enables Claude Code and OpenAI Codex to ask each other questions through iTerm panes, with no daemon or per-project configuration.
Enables Claude Code and OpenAI Codex to ask each other questions through iTerm panes, with no daemon or per-project configuration.
Let Claude Code and OpenAI Codex panes talk to each other — by label, by iTerm session name, or by session id. N agents, M agents, mix-and-match. No daemon. No
.configper project.
┌──────────── iTerm window ─────────────┐
│ claude (left) codex (right) │
│ ─────────────────── ─────────────── │
│ > implement quoter > [teammate-mcp │
│ I'll ask Codex... ASK ... what │
│ ⏺ Codex answered: is 2+2?] │
│ 4 • 4 │
└───────────────────────────────────────┘
teammate-mcp is a tiny MCP server that gives every loaded CLI a
small toolbox:
ask(target, question, timeout) — primary. target is a label, an
iTerm session name, or a session-id prefix.list_panes() — every live pane + its label/name/id/job/cwd.register_self(label) — attach a label to the calling pane at runtime.broadcast(message, targets=[...]) — push to multiple panes at once.ask_codex / ask_claude — legacy 1:1 shortcuts; still work when
exactly one of each CLI is running.The server uses the iTerm2 Python API
to push the prompt into the target pane and read the reply back via a
unique marker (<<DONE_…>>).
Existing multi-agent harnesses fall into two camps:
teammate-mcp aims for a third option: the two agents are visibly
running in your terminal next to each other, you can read both
transcripts in real time, and the only "infrastructure" is a few
hundred lines of Python that pushes text and reads screens.
Captured live during development on macOS 14, iTerm 3.6.8, Claude Code 2.1.119 + Opus 4.7, Codex 0.125.0:
{"event":"ask.enqueue","id":"…c5d085","from_":"claude","to":"codex","len":49}
{"event":"ask.send", "id":"…c5d085","to":"codex","session_id":"7E39032F-…"}
{"event":"ask.complete","id":"…c5d085","answer_len":3}
The ask.send → ask.complete interval was 3.0 seconds for a
prompt of "What is two plus two? Answer with the digit only" — the bulk
of which is Codex thinking time, not the bridge. Five consecutive runs
all closed the loop in 1.5 – 4.5 seconds.
Six independent timing reports captured in tests/results/ are
included in the repo so you can audit the numbers yourself.
git clone https://github.com/jonghklee/teammate-mcp.git
cd teammate-mcp
uv venv
uv pip install -e .
# Claude Code
claude mcp add teammate -s user -- $PWD/.venv/bin/teammate-mcp serve
# Codex
codex mcp add teammate -- $PWD/.venv/bin/teammate-mcp serve
You have two options:
Option A — let bin/team open a fresh iTerm window for you:
./bin/team
Option B — use any iTerm window you already have open. Just run
claude in one pane and codex in another. teammate-mcp finds them
by process name; no labels needed.
Drop templates/AGENTS.md into your project root. Both Claude Code
and Codex will pick it up automatically (it's the convention they
both follow). The file tells them how and when to call each other.
For more than one agent of either type, label each pane before launching its CLI:
# pane 1
export TEAMMATE_LABEL=plan
claude
# pane 2
export TEAMMATE_LABEL=worker
codex
# pane 3
export TEAMMATE_LABEL=tester
codex --yolo
The MCP server auto-registers each pane to its label on startup. Then from any pane:
ask("worker", "implement foo()")
ask("tester", "write tests for foo()")
ask("plan", "review this design") # from worker, asking back
You can also address a pane by the iTerm session name (cmd+I) or by
any prefix of its UUID — ask("Worker A", …) or ask("7B5B0D11", …).
./bin/install-statusline
Adds a statusLine block to ~/.claude/settings.json and a precmd
hook to ~/.zshrc that updates the iTerm tab title from
$TEAMMATE_LABEL. Both Claude (native statusLine) and Codex (tab
title) show the label visibly. Idempotent; backs up your existing
settings.
In the Claude pane:
Ask the worker pane what timezone library it prefers in Python.
You'll see Claude call ask, the question appear in the worker
pane, Codex respond there, and Claude relay the answer.
┌──────────────────────────────────────────────────────┐
│ Claude pane Codex pane │
│ ───────────── ───────────── │
│ user prompt [teammate-mcp ASK …] │
│ │ tool call ▲ │
│ ▼ │ async_send_text │
│ ┌──────────────┐ │ │
│ │ teammate-mcp │ ─────────────┘ │
│ │ (FastMCP) │ ◄────── async_get_screen_contents │
│ └──────────────┘ │
│ │ │
│ └─► returns extracted answer to Claude │
└──────────────────────────────────────────────────────┘
For each ask_codex (or ask_claude) call:
pending/ → inflight/ atomic rename).TEAMMATE_<UPPER>_SESSION_ID env overrideps-style), find any
claude or codex process, read its TERM_SESSION_ID env var,
and match that against iTerm's session list. This works through
tmux, login shells, and pyenv wrappers — anywhere the
environment variable is inherited.jobName / commandLine matching with cwd
preference.async_send_text the prompt + a request to terminate the reply
with the marker.async_get_screen_contents for the marker. Because the prompt
we typed contains the marker text (it gets echoed in the pane), the
server requires the marker to appear twice before treating the
reply as complete.ask.complete, return the answer to the caller.There is exactly one thing to configure (once): the MCP registration in step 2 above. After that, any iTerm window with claude+codex panes just works — including windows that were already open before you installed teammate-mcp.
You never write a .teammate.toml, you never teammate start, you
never have to remember which session id is which.
uv pip install -e ".[dev]"
pytest # 18 unit + integration tests
python scripts/auto_demo.py # full end-to-end demo (spawns iTerm)
The unit tests cover the queue, ANSI/marker handling, server module import, and the iTerm session-discovery logic with mocks. The end-to-end demo opens a real iTerm window and exercises a Claude → Codex → Claude round trip; it requires both CLIs to be logged in and will incur their normal API charges.
Per-run timing reports are written to tests/results/*.jsonl. The
ones already committed to the repo are real, not synthetic.
"iTerm Python API is not enabled" — Settings → General → Magic →
"Enable Python API" ✓. The first time teammate-mcp connects, iTerm
also prompts for permission; click Allow.
"asyncio.run() cannot be called from a running event loop" — you're
on a teammate-mcp older than 0.1.0. Pull main; the tools are now
declared async.
"Tool returned an answer that's just my own prompt echo" — the prompt-target pane is running the wrong CLI (e.g., the lookup picked a sibling pane that had the same process running). Pin the pane explicitly:
export TEAMMATE_CLAUDE_SESSION_ID=<unique id from iTerm>
export TEAMMATE_CODEX_SESSION_ID=<unique id from iTerm>
(You can read each pane's unique id from
Window menu → Window Settings → Identifier, or via AppleScript.)
"Marker not detected within timeout" — the agent on the other end
forgot to emit <<DONE_…>>. Add an explicit reminder in your
AGENTS.md. The bundled template already includes this.
MIT — see LICENSE.
This project crystallised from conversations on top of public research into how Claude Code and Codex are being run in 2026:
The implementation owes its iTerm Python API patterns to the iTerm2 docs at https://iterm2.com/python-api/.
CCB 같은 사전 설정 없이 claude / codex가 서로에게 질문할 수 있게 해주는 작은 MCP 서버입니다.
claude와 codex를 띄우기만 하면 됩니다.
라벨도, config도, daemon도 없습니다.TERM_SESSION_ID 매칭)합니다 — tmux 안에서 띄워도 작동합니다.~/.teammate-mcp/logs/<날짜>.jsonl에 기록됩니다.설치는 위 영문 Quick start 1~3단계, 사용법은 그냥 평소처럼 Claude에게 "Codex에게 물어봐"라고 시키면 됩니다.
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"teammate-mcp": {
"command": "npx",
"args": []
}
}
}