Summary
When resuming a backgrounded Claude agent (a panel titled "resume-background-agent"), cmux launches:
claude --session-id <fresh-uuid> --settings {…cmux hooks…} --dangerously-skip-permissions
i.e. it mints a brand-new session id and starts an empty session, instead of attaching to / --resume-ing the agent's existing session. The user's real conversation is still alive as a different background-agent session in the Claude Code daemon. The freshly-minted id never receives a message, so Claude Code never writes a transcript for it — it becomes an unrecoverable "ghost" id.
Environment
- cmux: 0.64.16
- OS: macOS, Apple Silicon
- Claude Code: 2.1.177
Symptoms (user-visible)
- The panel shows an empty / very-early conversation ("most of my conversation is gone").
- Restarting cmux re-runs the same
--session-id <ghost> command → the empty session reappears every time, and the panel is eventually dropped from live state entirely.
claude --resume <ghost-id> in any terminal → No conversation found with session ID: <ghost-id> (correct — nothing was ever written there).
- The actual conversation is a separate live background agent under a different id; resuming that id gives
Session … is currently running as a background agent (bg).
Evidence — from cmux's own persisted state
~/Library/Application Support/cmux/session-com.cmuxterm.app-previous.json, the affected panel object:
{
"kind": "claude",
"sessionId": "<ghost-uuid>",
"workingDirectory": "~/Projects/<repo>",
"launchCommand": {
"arguments": ["…/claude", "--session-id", "<ghost-uuid>", "--settings", "…", "--dangerously-skip-permissions"]
}
}
Note the launch uses --session-id (create-new) with no --resume and no --fork-session. Other, working panels in the same window correctly used --resume <existing-id>.
The corresponding real agent, from claude agents --json:
{"id":"<real-id>","kind":"background","name":"resume-background-agent","status":"idle","state":"blocked"}
So the panel's tracked sessionId (<ghost-uuid>) does not match the live agent's real session id (<real-id>).
Expected
"Resume background agent" should attach to the existing background session, reusing the agent's real session id — e.g. the claude agents attach path, or claude --resume <existing-id> (optionally --fork-session if a divergent branch is intended). It should never mint a new empty --session-id. The panel's tracked sessionId should be the agent's actual session id, so that a later resume — in cmux or a plain terminal — lands on the real conversation.
Impact
The user is shown an empty session in place of their real conversation, and the mismatch persists across restarts, making it appear the conversation was permanently lost. (It wasn't — it was a live background agent under a different id — but cmux surfaced the wrong, empty id, with no way back to the right one from the UI.)
Summary
When resuming a backgrounded Claude agent (a panel titled "resume-background-agent"), cmux launches:
i.e. it mints a brand-new session id and starts an empty session, instead of attaching to /
--resume-ing the agent's existing session. The user's real conversation is still alive as a different background-agent session in the Claude Code daemon. The freshly-minted id never receives a message, so Claude Code never writes a transcript for it — it becomes an unrecoverable "ghost" id.Environment
Symptoms (user-visible)
--session-id <ghost>command → the empty session reappears every time, and the panel is eventually dropped from live state entirely.claude --resume <ghost-id>in any terminal →No conversation found with session ID: <ghost-id>(correct — nothing was ever written there).Session … is currently running as a background agent (bg).Evidence — from cmux's own persisted state
~/Library/Application Support/cmux/session-com.cmuxterm.app-previous.json, the affected panel object:{ "kind": "claude", "sessionId": "<ghost-uuid>", "workingDirectory": "~/Projects/<repo>", "launchCommand": { "arguments": ["…/claude", "--session-id", "<ghost-uuid>", "--settings", "…", "--dangerously-skip-permissions"] } }Note the launch uses
--session-id(create-new) with no--resumeand no--fork-session. Other, working panels in the same window correctly used--resume <existing-id>.The corresponding real agent, from
claude agents --json:{"id":"<real-id>","kind":"background","name":"resume-background-agent","status":"idle","state":"blocked"}So the panel's tracked
sessionId(<ghost-uuid>) does not match the live agent's real session id (<real-id>).Expected
"Resume background agent" should attach to the existing background session, reusing the agent's real session id — e.g. the
claude agentsattach path, orclaude --resume <existing-id>(optionally--fork-sessionif a divergent branch is intended). It should never mint a new empty--session-id. The panel's trackedsessionIdshould be the agent's actual session id, so that a later resume — in cmux or a plain terminal — lands on the real conversation.Impact
The user is shown an empty session in place of their real conversation, and the mismatch persists across restarts, making it appear the conversation was permanently lost. (It wasn't — it was a live background agent under a different id — but cmux surfaced the wrong, empty id, with no way back to the right one from the UI.)