Agent view collapses same-named live sessions: a running bg fork is invisible in the picker that `--resume` points to

Resolved 💬 1 comment Opened Jul 2, 2026 by chriswithers-fuse Closed Jul 2, 2026

Summary

When a background fork of a session is running (--session-id <fork-id> --fork-session --resume <parent-transcript>), it inherits the parent session's custom title. If the parent is also alive as a named agent, claude agents --json correctly lists both sessions (same name, different sessionId), but the interactive claude agents view renders only one row for that name. Attaching via that row reaches the parent; the fork is unreachable from the picker.

Meanwhile, claude --resume <fork-id> refuses with:

Session <fork-id> is currently running as a background agent (bg). Use `claude agents` to find and attach to it, or add --fork-session to branch off a copy.

…which is circular: the command it points to cannot surface the session. The only options left are --fork-session (a divergent copy of a session that is itself still running, inviting three-way divergence) or waiting for the bg agent to finish. Related but distinct from #70170, which asks for a takeover path in --resume; this report is about the agent view making the recommended path a dead end.

Environment

  • Claude Code: 2.1.198
  • OS: macOS (Darwin 25.5.0), Apple Silicon

Reproduction

  1. Run an interactive named session in a project dir: claude --name myproject@mytask → session <parent-id>.
  2. A background fork of it is spawned via the daemon (observed process):

``
claude --session-id <fork-id> --fork-session --resume ~/.claude/projects/<project>/<parent-id>.jsonl --reply-on-resume ...
`
hosted under
claude --bg-pty-host /tmp/cc-daemon-<uid>/<hash>/pty/<fork-id-prefix>.sock ...`

  1. The fork's transcript begins with the inherited title, so both sessions share a display name:

``json
{"type":"custom-title","customTitle":"myproject@mytask","sessionId":"<fork-id>"}
``

  1. claude agents --json lists both (anonymized):

``json
{"sessionId":"<parent-id>","name":"myproject@mytask","status":"busy","state":null}
{"sessionId":"<fork-id>","name":"myproject@mytask","status":"busy","state":"working"}
``

  1. The claude agents TUI shows a single myproject@mytask row in Working. Selecting it attaches to the parent. There is no row for <fork-id>.
  2. claude --resume <fork-id> → the refusal quoted above, pointing back to the picker that can't show it.

The fork is healthy the whole time (its pty host and worker process are alive and mid-task); this is purely a discoverability/attach problem.

Expected

  1. One row per live session in the agent view, even when names collide — disambiguate with a session-id prefix, a (fork) marker, or the fork's own recent activity line.
  2. The --resume refusal should include enough identity to act on (name + how many sessions share it), and ideally an attach-by-id path (claude agents --select <session-id>, cf. #68064) so the message's advice is actionable from a script or when names collide.

Notes

  • title is null for every entry in claude agents --json even when a custom title exists in the transcript — same observation as #70170; populating it would make --json usable for disambiguation.

---

Correction / sharper diagnosis (after further investigation)

Step 5 above was wrong in one detail: the single TUI row attaches to the fork (the live session), not the parent. The full picture turned out to be:

  1. The daemon rotates a named agent's session ID: when a new prompt reached the named agent, the conversation continued as a brand-new session (--session-id <fork-id> --fork-session --resume <parent>.jsonl --reply-on-resume). The parent transcript froze at that moment, but claude agents --json still reports the parent as status: "busy" alongside the live fork — two same-named entries, one of them a stale claim.
  2. The user, holding a session ID copied from a path, ran claude --resume <fork-id> and got the bg-agent refusal — with no hint that this ID was the live continuation of the very chat already open in their terminal under the agent's name.
  3. Extra trap: paths like <session-dir>/tasks/<task-name>.output look session-addressable but are subagent outputs (symlinks to <session-dir>/subagents/agent-<task-name>.jsonl). Subagents have no top-level session ID, so no --resume incantation can ever reach them; nothing in the CLI says so.

So the actionable asks refine to:

  • Surface both same-named sessions distinctly in the TUI, and mark stale/frozen claims (parent hadn't written its transcript for 40+ minutes yet showed busy).
  • When --resume <id> hits a live bg session, say where it's attached (e.g. "currently attached in agent view as <name>") instead of only refusing.
  • When a user tries to resume something under a session's subagents//tasks/ dir, explain that subagents aren't resumable sessions and point at the parent session ID.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗