[BUG] Named Agent-tool teammates overwrite their lead's background job resumeSessionId; a respawn of the lead after a teammate's turn resumes the teammate's transcript
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (closest: #79757, #82489, #89624 — all about a resumed or backgrounded session minting a new id; none covers a teammate rewriting its lead's job pointer)
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code (observed on 2.1.283; the code path is unchanged in the 2.1.284 changelog)
What's Wrong?
A named Agent-tool subagent (Agent tool with name, which runs as a separate process with --agent-name <n> --team-name session-<job id> under the tmux swarm backend) inherits the lead's CLAUDE_JOB_DIR and CLAUDE_CODE_SESSION_KIND=bg. On every turn, a process with those two variables writes its own session id into ~/.claude/jobs/<job>/state.json → resumeSessionId. So each teammate turn repoints the lead's job record at the teammate's transcript. A live lead writes its own id back on its next turn (measured: 7 s later), so nothing is visible while the lead keeps taking turns.
If the lead's process is gone while the pointer names a teammate, the next respawn of the job resumes the teammate's conversation under the lead's name and job. The lead's own transcript is intact on disk but unreachable from the agents view: the row shows the lead's name, and opening it shows the teammate's conversation. Sending it a prompt continues the teammate's transcript.
Respawn paths that follow the pointer:
claude --bg --resume <lead-session-id>— measured: the prompt lands in the teammate's transcript, the lead's is untouched.- The agents-view attach-stall restart ("Session not responding — restarting it…", event
tengu_bg_attach_stall_respawn) — observed on five real sessions over six days. In every case the lead'sbg-pty-hosthad been SIGSTOPped by a local disk-pressure watchdog, so it could not redraw on attach, the daemon killed it and resumedresumeSessionId, which a teammate had written. claude stop <job>then a wake, and the daemon's idle retire then a wake, use the same field. Not separately measured (see below).
Side effects seen on the way:
- A lead respawn rebuilds
~/.claude/teams/session-<job>/config.jsonand deletes itsinboxes/folder, so teammates that outlive the lead's respawn can no longer be messaged. claude stop <job>prints "stopped" for a SIGSTOPped session but leaves its process alive; a--bg --resumeissued then starts a copy under a new session id.
What Should Happen?
resumeSessionId should be written only by the job's own lead process — for example by not inheriting CLAUDE_JOB_DIR (or by clearing CLAUDE_CODE_SESSION_KIND) in teammate processes. claude --bg --resume <session-id> should resume that session id, not whatever the job pointer currently says. Teammates should not become the job's resume target under any path.
Error Messages/Logs
# ~/.claude/jobs/<job>/state.json, polled every 2 s while a lead with one named teammate ran
# (job e0368c13, lead e0368c13-7a64-4234-a98e-585caf374e79, teammate b005fd4e-82ba-49f2-8897-a49b3bfdfc22)
resumeSessionId = e0368c13-... # lead idle
resumeSessionId = b005fd4e-... # teammate takes a turn
resumeSessionId = e0368c13-... # 7 s later: lead's next turn writes it back
resumeSessionId = b005fd4e-... # lead process stopped, teammate poked: stays here
# then: claude --bg --resume e0368c13-7a64-4234-a98e-585caf374e79 "append X to a file"
# → "append X" appears in b005fd4e-....jsonl; e0368c13-....jsonl unchanged
Agents view on the real incidents: Session not responding — restarting it… followed by the row (lead's name) showing the teammate's conversation.
Steps to Reproduce
claude --bg --name exp-lead "spawn one teammate named exp-mate via the Agent tool (pass name: exp-mate), then end your turn".- Poll
~/.claude/jobs/<job>/state.json: when exp-mate starts,resumeSessionIdbecomes exp-mate's session id; it flips back on the lead's next turn. - Stop the lead's process (kill its worker, or SIGSTOP it), then send exp-mate a message (write to its inbox).
resumeSessionIdbecomes exp-mate's id and stays. claude --bg --resume <lead-session-id> "append X to a file"— the prompt runs in exp-mate's transcript; the lead's transcript is unchanged.- Set
resumeSessionIdback to the lead's id by hand and repeat step 4 — the prompt now runs in the lead's transcript. (This edit is the workaround.)
Claude Model
Not model dependent (daemon/job bookkeeping).
Is this a regression?
Unknown — first noticed with named Agent-tool subagents on 2.1.28x; the same --team-name process model is used by TeamCreate teammates.
Claude Code Version
2.1.283 (also present in the job/daemon files on 2.1.284)
Platform
Not platform dependent (daemon/job bookkeeping).
Operating System
macOS (darwin arm64), native install
Terminal/Shell
iTerm2 / zsh; the takeover surfaces in the agents view (claude agents)
Additional Information
Related: #79757 (job record names a transcript other than the real conversation), #82489 (backgrounding mints a new id without the transcript), #89624 (resumeSessionId points to itself on --bg -r). #89624's observation that resumeSessionId is always the session's own id is the same write path: every bg-kind process writes its own id there on every turn; the bug here is that a teammate process shares the lead's job dir and so writes into the lead's record.
Workaround used: stop the lead's process if it is still alive, set resumeSessionId back to the lead's session id in state.json, back up ~/.claude/teams/session-<job>/ (the respawn deletes its inboxes), then claude --bg --resume <lead-session-id>.