Repository navigation
fix(agent-status): keep a lead waiting on you while its tmux teammate runs tools - #32009
AmoabaKelvin wants to merge 3 commits into
Conversation
A tmux teammate is a separate claude process that inherits the lead pane's ORCA_PANE_KEY, so its tool hooks replaced the lead's waiting state. Fixes #30833
A teammate hook after the lead died forgot the exit before anything took the pane.
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 22 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Superseded by #31780, which landed the same fix on main: a hook from a different process of the pane owner's own provider no longer takes over the owner's row. It also covers the SSH/WSL relay and the server's status update. This branch's tmux-teammate replay test (lead waiting on AskUserQuestion, then the teammate's SessionStart, Bash calls, Stop and TeammateIdle, plus the dead-lead exit case) passes on main unchanged, so nothing is left to merge. |
ELI5
A Claude Agent Teams "tmux" teammate is a second Claude process. It inherits the lead's Orca pane id, so Orca treated every teammate tool call as the lead's own. When the lead asked you a question, the teammate's next Bash call flipped the lead back to Working, and the operator never saw Needs You.
What Changed
AskUserQuestionwith a tmux teammate running tools showed "Needs permission" for a moment, then Done (teammate's SessionStart), then Working for the rest of the question. The row label also changed to the teammate's<teammate-message ...>prompt.Root cause: Claude runs tmux teammates in its own private tmux server (
claude-swarm-<pid>), started from the lead pane, so each teammate process inheritsORCA_PANE_KEY. Their hooks arrive on the lead's pane with noagent_idand a differentsession_id, which the Claude fold reads as the lead's own events. The pane-ownership rule already said a nested CLI that inherits the pane key owns neither its turn nor its children (shouldSuppressInheritedTerminalStatus), buthasOtherAgentProcessOwneronly compared provider kinds, so a nested Claude inside a Claude pane slipped through.The fix extends that rule: a same-provider hook from a different proven process (the hook already reports its sender's pid and start time) is an inherited nested CLI while the owner lives. The existing probe that runs before normalization now covers it too, so a Claude relaunched after the old one crashed still takes the pane on its first hook, and the old owner's exit stays recorded until a successor is admitted.
Also affected: a
claude -pstarted from the lead's Bash tool no longer rewrites the lead's row. Subagents and in-process teammates are unchanged (same process). Windows hooks don't capture a process yet, so Windows is unchanged.Why
Attributing teammate activity to its own child row isn't possible from these hooks: tmux teammates never send
SubagentStart, carry noagent_id, and the lead'sbackground_taskslists them asteammatetasks the roster deliberately skips. The pane owner is the one fact the hooks prove, and the ownership code already owns that decision for other providers. "Waiting always wins" alone wouldn't help either, since the teammate's SessionStart and Stop also reset the lead to Done.Mixed versions: no wire change. An older SSH/WSL relay keeps forwarding teammate hooks (old behaviour) until it updates; the rule runs on the host that can probe the processes.
Linked Issue
Fixes #30833
Linear: STA-11256
Visual Proof
Real Claude Code 2.1.308 lead in an Orca terminal,
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 claude --teammate-mode tmux, teammate running 12 sequentialsleep 5 && dateBash calls while the lead'sAskUserQuestionis open.Before (base
ad0bf9a3932): spinner and the teammate's prompt on the lead row while the question is open.After (this branch): attention icon on the workspace, tab and lead row, lead prompt kept, for the full 90s the teammate ran tools.
Testing
I manually tested these changes locally
Automated tests added/updated, or explained why not below
Captured the real hook stream from Claude Code 2.1.307 with a logging hook: the teammate process posts SessionStart, PreToolUse/PostToolUse, Stop, TeammateIdle and SessionEnd with the lead's
ORCA_PANE_KEY, its ownsession_id, and noagent_id.Hidden dev builds of base and branch (macOS), same repro over CDP: base showed Needs permission → Done → Working; branch held Needs permission for 90s of teammate tool calls and settled to Done after answering.
server-claude-tmux-teammate.test.tsreplays that order through the HTTP hook server (lead waits, teammate tools/Stop/TeammateIdle, lead answers) and checks the dead-lead exit is kept when only the teammate reports afterwards. Both fail on the pre-fix code.Focused suites: agent presence, idle process owner, owed notifications, nested roster, Claude subagents, relay presence.