一键导入
tmux-usage
How to use tmux effectively when working with Claude Code agent teams — session hierarchy, attach/detach, scripting teammate panes, common pitfalls.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
How to use tmux effectively when working with Claude Code agent teams — session hierarchy, attach/detach, scripting teammate panes, common pitfalls.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
This skill should be used when the user asks about "how to store data in a plugin", "what file format to use for plugin storage", "YAML vs JSON in a plugin", "how to keep task files in sync", "streaming storage", "frontmatter metadata", "data storage for hooks", "writing files in MCP servers", "concurrent writes in plugin storage", "file format selection", "storing plugin state", or "persistent data in Claude Code plugins".
Review a GitHub pull request and post inline feedback via the GitHub review system. Used by the run-agent composite action; the body below is the prompt that drives claude-code-action.
How to author agent files (frontmatter + system prompt body) for the agent-teams project — file structure, naming, frontmatter fields, prompt conventions.
Use this skill when you need to fetch public Reddit content (posts, comments, subreddits, user activity) without authentication. Trigger when: - User asks about Reddit posts, comments, or subreddit content - Research requires public Reddit data - Fetching specific Reddit posts by URL
Use at every task-lifecycle decision point (before TaskCreate, before TaskUpdate→in_progress, after TaskUpdate→completed) when you need help applying the task-management doctrine — atomicity check, breakdown planning, status-transition validity, or follow-up capture. Forks into an isolated context so the parent's window stays lean. Returns a ≤5-sentence imperative instruction the parent should execute. Trigger phrases — "is this task atomic?", "should I break this down?", "what task should I start next?", "I just completed a task, what now?", "plan my next move on the task list", "audit my task list discipline".
Use when the handler asks to fold user-scope settings into the canonical repo-scope file, when an agent restart wiped out plugin enablement / marketplace registrations that need to be recovered, or when audit shows drift between `$CLAUDE_CONFIG_DIR/settings*.json` and `$AGENT_REPO/.claude/settings.json`. Trigger phrases — "merge my settings", "fold user-scope into repo-scope", "settings-merge", "recover the settings drift", "what plugins are enabled in my user-scope but not committed?". Requires `$AGENT_REPO/.claude/settings.json` to already exist as the target.
| name | tmux-usage |
| description | How to use tmux effectively when working with Claude Code agent teams — session hierarchy, attach/detach, scripting teammate panes, common pitfalls. |
How to use tmux effectively when working with Claude Code agent teams.
tmux is a terminal multiplexer — it lets you run multiple terminal sessions inside a single window, detach from them, and reattach later. Agent teams use tmux as the backend for visible teammate panes.
Server (one per user, runs in background)
└── Session (named group of windows)
└── Window (like a tab)
└── Pane (split within a window)
| Command | What It Does |
|---|---|
tmux new-session -s name | Create a named session |
tmux attach -t name | Attach to an existing session |
tmux detach (or Ctrl+B d) | Detach from current session |
tmux list-sessions | List all sessions |
tmux list-panes -t session | List panes in a session |
tmux kill-session -t name | Kill a session |
tmux kill-server | Kill all sessions |
tmux commands inside an attached session start with a prefix key (default: Ctrl+B). After pressing the prefix:
| Key | Action |
|---|---|
d | Detach |
% | Split pane vertically |
" | Split pane horizontally |
| Arrow keys | Move between panes |
[ | Enter copy/scroll mode (exit with q) |
z | Toggle pane zoom (fullscreen) |
Source: tmux Getting Started
When teammateMode is set to tmux, Claude Code uses tmux to create visible panes for each teammate. The lead session manages the tmux layout automatically.
tmux -CC for iTerm2)Task tool, Claude Code creates new tmux panesThese work within the Claude Code UI, not at the tmux level:
| Control | Function |
|---|---|
| Shift+Up/Down | Cycle through teammates (in-process mode) |
| Ctrl+T | Toggle task list |
| Ctrl+O | Toggle verbose transcript (shows tool usage and execution details) |
| Shift+Tab | Toggle permission mode (lead coordination only) |
| Escape | Interrupt teammate's turn |
When running in iTerm2 outside a tmux session, Claude Code uses tmux -CC (control mode). Instead of rendering the green tmux status bar and using prefix keys, tmux sends structured text commands to iTerm2, which renders them as native macOS windows and tabs.
What changes in control mode:
tmux -CC attach)How claude-team handles this:
# If not already in a tmux session and tmux mode is selected:
exec tmux -CC new-session -- claude --dangerously-skip-permissions "${TEAM_FLAGS[@]}"
The claude-team helper auto-launches tmux -CC when needed, so users don't have to start tmux manually.
Sources: tmux Control Mode Wiki, iTerm2 tmux Integration
tmux send-keysSends key presses to a target pane as if you typed them.
Basic syntax:
tmux send-keys -t <target-pane> "text to type" Enter
How it works: tmux checks each argument against a list of key names (like Enter, Escape, Tab, C-c, C-m). If the argument matches a key name, the corresponding key press is sent. Otherwise, the literal characters are sent.
Key arguments (case-sensitive):
| Argument | Key Sent |
|---|---|
Enter | Return/Enter key |
C-m | Carriage return (same as Enter) |
Escape | Escape key |
C-c | Ctrl+C (interrupt) |
Tab | Tab key |
Space | Space character |
BSpace | Backspace |
Enter Must Be a Separate ArgumentThis is the most common send-keys mistake:
# CORRECT — Enter is a separate argument, recognized as a key name
tmux send-keys -t %3 "hello world" Enter
# WRONG — Enter is inside the quotes, sent as literal characters "E-n-t-e-r"
tmux send-keys -t %3 "hello world Enter"
# WRONG — \n is not interpreted by tmux as a key press
tmux send-keys -t %3 "hello world\n"
The -l flag disables key name lookup entirely — with -l, Enter is sent as five literal characters. Don't use -l if you need Enter to work.
Source: tmux send-keys reference, tmux(1) man page
send-keys May Not Actually SubmitSending keys to a pane does NOT guarantee the application receives or processes them. The keys are injected into the pane's terminal input buffer, but the running application may not be in a state to accept them.
Situations where send-keys appears to work but nothing happens:
Application is processing / busy — The target application (e.g., Claude Code) is mid-execution and not reading from stdin. The keys sit in the buffer until the application next reads input, which may be never (if the application exits first) or much later.
Pane is in copy mode — If someone pressed Ctrl+B [ to enter scroll/copy mode, the pane is no longer forwarding keys to the application. Keys are interpreted as copy-mode commands instead.
Application has its own input model — Interactive applications like Claude Code don't use simple line-based stdin. They may use raw terminal mode where Enter doesn't mean "submit" — the application controls when and how input is processed.
Race conditions — If you send keys immediately after spawning a process, the process may not have started reading input yet. There's no built-in mechanism to wait for "ready."
Enter included in the quoted string — Per the gotcha above, "text Enter" sends literal characters, not a key press.
Claude Code requires a second Enter — Even when send-keys correctly types text and sends Enter, Claude Code may display the text at the prompt but not process it until a second Enter is sent. This is a timing/buffering issue — Claude Code's input handler may not have been ready when the first Enter arrived, so it queued the text but didn't submit it.
Observed in this session (two incidents):
tmux send-keys to a Claude Code teammate pane (QA agent) did not result in the command being submitted. The pane showed the text was typed but it was never processed.Mitigation strategies:
Enter after a short delay: tmux send-keys -t %3 "text" Enter && sleep 1 && tmux send-keys -t %3 Entersleep delay before send-keys to let the process initializetmux capture-pane to check if the application is ready before sendingSendMessage tool over send-keys for inter-agent communicationPanes are identified by session, window, and pane index:
# By pane ID (most reliable — unique across sessions)
tmux send-keys -t %3 "command" Enter
# By session:window.pane
tmux send-keys -t mysession:0.1 "command" Enter
# By session name (targets the active pane)
tmux send-keys -t mysession "command" Enter
Pane IDs (like %3) are assigned by tmux and visible in the team config's tmuxPaneId field.
capture-panetmux capture-paneCaptures the visible contents of a pane — useful for monitoring teammate activity without attaching.
Basic syntax:
# Print pane contents to stdout
tmux capture-pane -t <target-pane> -p
# Capture full scrollback history
tmux capture-pane -t %3 -p -S -
# Save to a file
tmux capture-pane -t %3 -p -S - > /tmp/pane-output.txt
Useful flags:
| Flag | Purpose |
|---|---|
-p | Print to stdout (instead of paste buffer) |
-t target | Target pane |
-S start | Start line (- = beginning of history, 0 = first visible line) |
-E end | End line (- = end of visible content) |
-e | Include escape sequences (preserves colors) |
-J | Join wrapped lines (useful for parsing) |
Use case for agent teams: Check what a teammate is doing without switching focus:
# What's on the screen of pane %3 right now?
tmux capture-pane -t %3 -p
# Get the full scrollback
tmux capture-pane -t %3 -p -S - > /tmp/teammate-output.txt
Source: tmux capture-pane guide, Baeldung: tmux logging
tmux new-session -dCreates a new session without attaching to it — the session runs in the background.
Syntax:
tmux new-session -d -s <session-name> -c <working-directory> [-- command args...]
| Flag | Purpose |
|---|---|
-d | Don't attach (detached/background) |
-s name | Session name |
-c path | Working directory for the session |
-- cmd | Command to run in the session |
Example — launching Claude Code in background:
# Start a Claude Code session in the background
tmux new-session -d -s agent-team -c ~/src/nsheaps/agent-team -- \
claude --dangerously-skip-permissions --teammate-mode tmux
# Later, attach to it
tmux attach -t agent-team
# Or for iTerm2 control mode:
tmux -CC attach -t agent-team
Example — launching ct (claude-team) in a detached session:
tmux new-session -d -s ct-session -c ~/src/nsheaps/claude-utils -- ct --mode tmux
Source: tmux Getting Started, tmux(1) man page
Some tools require a real interactive terminal with a human at the keyboard. They cannot be driven by tmux send-keys or launched in detached sessions without additional work.
gum (interactive TUI):
The claude-team helper uses gum choose for the mode picker. This requires:
If you launch ct in a detached session (tmux new-session -d), the gum picker will fail or hang because there's no attached terminal. You must either:
tmux attach -t name), then interact with gum--mode tmux (bypasses gum entirely)Observed in this session: ct was launched in a detached tmux session. The gum interactive picker required the user to attach to the session and make a selection before Claude Code would start.
Claude Code session input:
Claude Code uses a custom terminal input model (not simple line-based stdin). Sending text via tmux send-keys may type the text visually but the Claude Code session may not process it as a user message. This was observed when trying to use send-keys to make the QA agent report its name — the text appeared but was not submitted.
For inter-agent communication, always use SendMessage instead of send-keys. The SendMessage tool is designed for this purpose and bypasses the terminal input layer entirely.
| Scenario | Works with send-keys? | Better Alternative |
|---|---|---|
| Simple shell commands | Yes | — |
| Answering yes/no prompts | Usually | echo "y" | command |
| Interactive TUI (gum, fzf) | No | Skip with CLI flags |
| Claude Code user input | Unreliable | SendMessage tool |
| Starting a background process | Yes (via detached session) | — |
When a teammate agent is unresponsive (stuck mid-turn and not processing messages), send the ESC key via tmux to interrupt its current turn and allow pending messages to propagate:
tmux send-keys -t <pane-id> Escape
The pane ID can be found in the team config's tmuxPaneId field, or by listing panes:
tmux list-panes -a -F '#{pane_id} #{pane_title}'
This sends the Escape key to the target pane, which interrupts Claude Code's current turn. After the interruption, the agent will process any queued inbox messages on its next turn.
If you try to create a tmux session while already inside one, you get this warning. Set TMUX='' to override, or use tmux new-session -d to create it detached.
Pane IDs (%N) are ephemeral — they're assigned when the pane is created and don't persist across tmux server restarts. If a pane ID from the team config doesn't work, list current panes:
tmux list-panes -a -F "#{pane_id} #{session_name} #{pane_current_command}"
After a team session ends, tmux sessions may linger. Clean up with:
# List all sessions
tmux list-sessions
# Kill a specific session
tmux kill-session -t agent-team
# Kill everything
tmux kill-server
Issues documented in the Claude Code GitHub repository that affect agent teams using tmux. These were discovered through research and direct experience.
| Issue | Description | Impact |
|---|---|---|
| #25375 | Pane index mismatch — Claude Code hardcodes 0-based indexing, conflicts with user's pane-base-index setting | Messages target wrong teammate pane |
| #23415, #24108 | Teammate inbox never polled — spawned teammates never read inbox files on macOS tmux backend | Teammates stuck idle, never receive instructions |
| #24771 | Messaging disconnection with iTerm2 -CC — lead's messaging system disconnects from teammate sessions in control mode | Teammates launch but don't communicate |
| #23615 | Send-keys corruption at scale — splitting current pane for many teammates garbles output | Garbled pane content |
Workaround for pane index: Query pane-base-index at runtime rather than assuming 0-based indexing. Any orchestration script should use tmux show-options -g pane-base-index to get the actual value.
Workaround for inbox polling: If teammates aren't receiving messages, check that the inbox JSON files are being written to ~/.claude/teams/{team-name}/inboxes/. The issue may be specific to certain tmux + macOS configurations.
Source: Claude Code Agent Teams Issues