tmux-multi-agent
Skill1 starsChanged 3 months agoMITView on GitHub
Drive and coordinate other interactive agent CLIs (Codex, Claude Code, aider, gemini, a plain shell, etc.) running in separate tmux panes — send them prompts/instructions, read their output, and hand work back and forth. Use this whenever you need to delegate to or talk with another agent or process living in a tmux pane, run a multi-agent workflow over tmux, "send this to the other agent / the codex pane / the right pane", relay a review or a handoff between agents, or whenever a message you sent with `tmux send-keys` to an agent CLI does not seem to have submitted. Covers pane discovery, robust message delivery (including the paste-detection double-Enter quirk), reading a pane's state, and bidirectional ping-back.
In this repositoryOne other file it gives its agents.
- humanize-writingSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 3 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 33
Never assume a send-keys worked.
- Distinctive: line 60
Look at the target before sending so you know what state it's in:
- Distinctive: line 98
If your message genuinely needs apostrophes, backticks, or is long/structured,
- Very specific: line 163
When you're handing off real work, prefer having the other agent record results in files/commits you can inspect directly (git show, Read) …
- Distinctive: line 179
When you delegate, tell the other agent your pane id and ask it to ping you when done — and remind it of the double-Enter, or its reply to …
- Very specific: line 187
If you're *expecting* a ping and it never comes, don't just wait — capture-pane your own pane and the other agent's pane: a common cause is …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Coordinating Multiple Agents over tmux
You are one agent in a tmux session; one or more other agents (or processes) run in sibling panes. This skill is how you talk to them reliably: find them, send them work, read what they did, and have them ping you back.
The whole thing is just tmux send-keys and tmux capture-pane — but a few
non-obvious failure modes will silently eat your messages if you don't account
for them. The rules below exist because each one burned a real handoff.
The loop
detect panes → inspect target state → send message → verify it submitted → read result
↑___________ (it didn't) _________|Never assume a send-keys worked. Always capture-pane afterward and confirm
the message actually left the input box. A swallowed message sits unsent and
invisible — you'll wait forever for a reply that was never triggered.
1. Detect panes — every session, never hardcode
Pane IDs (%0, %1, …) are stable within a session but change between
sessions. Re-discover them at the start of every coordination task; don't
trust an ID you remember from before.
tmux list-panes -a -F '#{pane_id} #{session_name}:#{window_index}.#{pane_index} #{pane_current_command} title=#{pane_title}'Identify the target by its pane_current_command (codex, claude, node,
python…) and/or pane_title, then refer to it by pane_id (e.g. %1) for
the rest of the task — pane_id is stable for the session and unambiguous,
whereas index-based targets (0.1) can shift if panes are added/closed.
Know your own pane id too (you'll hand it to the other agent so it can reply):
tmux display-message -p '#{pane_id}'2. Inspect before you send
Look at the target before sending so you know what state it's in:
tmux capture-pane -p -t %1 # full visible pane
tmux capture-pane -p -t %1 | grep -vE '^\s*$' | tail -12 # last non-blank lines- Idle (agent CLI showing an empty input box / prompt) → safe to send and submit; it will start working.
- Working (e.g. Codex shows
• Working (… esc to interrupt)) → you can still send; the message gets queued and picked up after the current turn. This is the normal way to "leave a note" for a busy agent.
3. Send a message — robustly
Lead every message with who you are. The receiving agent gets your text
dropped into the same input box a human types into — there is no built-in sender
header. Start each message with your identity and pane id, e.g.
[From Claude, pane %0] …. Without it the other agent can't tell your message
apart from its own user's, doesn't know who it's collaborating with, and can't
address its reply or know which pane to ping back. (When you ask it to ping you,
that "from + pane" line is also exactly what tells it where to send the reply.)
Beyond what you say, two delivery hazards: the shell mangling your text, and the agent CLI's input box swallowing your Enter.
3a. Don't let the shell rewrite your message
Build the message in a single-quoted variable so the shell doesn't expand $,
backticks, &&, etc. Keep single quotes and backticks out of the message
text itself (they break the quoting). Send it with -l (literal) so words
like Enter are sent as text, not interpreted as the Enter key:
MSG='Hello other agent — please run the test suite and report back.'
tmux send-keys -t %1 -l "$MSG"If your message genuinely needs apostrophes, backticks, or is long/structured, don't fight the quoting — put it in a file and send a short pointer instead (see §3c).
3b. Submit it — and expect to send Enter twice
Rich agent input boxes (Codex, Claude Code) run paste detection: a long or
pasted-in message gets collapsed into a [Pasted Content N chars] blob, and the
first Enter is consumed by that collapse instead of submitting. The fix is a
second Enter after a short beat:
tmux send-keys -t %1 Enter
sleep 1
tmux send-keys -t %1 EnterA plain shell pane (bash/zsh) submits on the first Enter — the double-Enter
is specifically for agent CLIs with a fancy input box. When in doubt, send the
second Enter; an extra Enter at an empty prompt is harmless.
3c. Long or structured briefs → send a file pointer
For anything beyond a couple of sentences, write the brief to a file (or, if it belongs in the project's durable record, a committed spec/doc) and tell the other agent to read and act on it. This sidesteps all quoting/paste issues and gives the brief a stable home:
cat > /tmp/handoff.md <<'EOF'
# Task for you
... full instructions, code blocks, anything ...
EOF
tmux send-keys -t %1 -l '[From Claude, pane %0] Read /tmp/handoff.md — it is your task brief. Execute it, then ping me in pane %0.'
tmux send-keys -t %1 Enter; sleep 1; tmux send-keys -t %1 Enter3d. Verify it submitted
sleep 2
tmux capture-pane -p -t %1 | grep -vE '^\s*$' | tail -8You're looking for the message to have left the input box — either the agent
is now Working, or (if it was busy) your text shows as a queued entry above
the working indicator while the input box returns to its empty placeholder. If
your full message is still sitting in the input box, the Enter didn't take —
send Enter again.
4. Read what the other agent did
capture-pane is your window into the other agent. Snapshot it to see progress,
results, or its "done" message:
tmux capture-pane -p -t %1 | grep -vE '^\s*$' | tail -25For long output, capture the scrollback with -S:
tmux capture-pane -p -t %1 -S -200 # last 200 lines of historyWhen you're handing off real work, prefer having the other agent record results
in files/commits you can inspect directly (git show, Read) over scraping its
pane — the pane is for state and short status, not the source of truth.
Notice quota/usage fields while you're reading the pane. Some agent CLIs surface account state in their pane or status line — e.g. a remaining-quota / weekly-limit percentage, a credits/balance figure, a rate-limit warning. If you spot one (especially trending low), don't act on it silently: surface it to the user at a natural moment ("the codex pane shows ~12% weekly quota left — want me to pace the handoffs?"). It's their account to manage, not yours; your job is to flag it so they can decide. Read such a figure as whatever it's labelled — "remaining/left/available" is a balance, not consumption — and quote the label rather than guessing.
5. Bidirectional ping-back
When you delegate, tell the other agent your pane id and ask it to ping you when done — and remind it of the double-Enter, or its reply to you will be swallowed exactly the way yours would be:
"When you're done, ping me in pane
%0. Note: my input box swallows the first Enter after a pasted message, so send your text, then Enter, wait ~1s, then Enter again, and capture-pane%0to confirm it submitted."
If you're expecting a ping and it never comes, don't just wait — capture-pane
your own pane and the other agent's pane: a common cause is the other agent's
ping sitting unsubmitted in your input box.
Gotchas — quick reference
| Symptom | Cause | Fix |
| Reply never arrives | First Enter swallowed by paste detection | Send Enter twice (text → Enter → sleep 1 → Enter) |
| Recipient treats your message as its human user's / replies to the wrong place | No sender attribution | Prefix every message with [From <you>, pane <id>] |
| Message text got corrupted/expanded | Shell interpreted $, backticks, && | Single-quote the var; keep ' and backticks out; or use a file |
send-keys "Enter" typed as the word Enter | Missing -l semantics / mixed args | Send text with -l, send Enter as its own send-keys call |
| Targeting the wrong pane | Hardcoded a stale %N from last session | Re-run list-panes each session; target by pane_id |
| Agent didn't react | It was working; message queued | Expected — it picks up queued input after its turn; verify via capture-pane |
| Can't tell if it submitted | Didn't verify | Always capture-pane after sending |
Worked example (full round-trip)
# 1. find the other agent and my own pane
tmux list-panes -a -F '#{pane_id} #{pane_current_command} #{pane_title}'
# %0 claude ... %1 codex ...
MINE=%0; THEM=%1
# 2. check it's ready
tmux capture-pane -p -t $THEM | tail -5
# 3. send a short instruction
MSG='[From Claude, pane %0] Run npm test and tell me pass/fail. Ping me in pane %0 when done (send Enter twice).'
tmux send-keys -t $THEM -l "$MSG"
tmux send-keys -t $THEM Enter; sleep 1; tmux send-keys -t $THEM Enter
# 4. confirm it took
sleep 2; tmux capture-pane -p -t $THEM | grep -vE '^\s*$' | tail -6 # expect "Working"
# 5. later: read the result
tmux capture-pane -p -t $THEM | grep -vE '^\s*$' | tail -25Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

