/rename renames other concurrent sessions (cross-session title contamination, no resume involved)

Status Open
Reported on v2.1.231
Maintainer reply ✓ Yes — bcherny
Activity 4 comments · opened Aug 13, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Environment

  • Claude Code version: 2.1.231 (latest at time of filing)
  • Platform: Linux (Ubuntu, kernel 6.8.0-1051-aws)
  • Launch mode: fresh claude --dangerously-skip-permissions sessions, several in parallel (tmux panes), all in the same project directory. No --resume, --continue, or forking involved.

Summary

Renaming one session with /rename renames other concurrently running sessions too. This looks related to #81899 and #80906, but with an important extra data point: it reproduces with fresh parallel sessions only - no resume or fork is required.

Evidence from local state

  1. Live-session registry (~/.claude/sessions/*.json): after renaming one session to new-3, five distinct live sessions (different PIDs, different sessionIds, different tmux panes, including background sessions) all had "name": "new-3". Other names were also duplicated across pairs of unrelated sessions.
  1. Transcript cross-stamping: the rename is not just a display issue. Each affected session's transcript (~/.claude/projects/<proj>/<sessionId>.jsonl) received a custom-title event stamped with that session's own sessionId, e.g. in a session that was never manually renamed to this value:

``json
{"type":"custom-title","customTitle":"new-3","sessionId":"fc442b96-..."}
``

So each session genuinely believes it was renamed. The affected sessions also emit "The user named this session X" system reminders into the model context, misleading the model about user intent.

  1. Massive re-stamping: title events accumulate hundreds of times per transcript. One session has the same title written 501 times, another 226 times. One transcript contains the titles of four different sessions interleaved (165 + 22 + 4 + 3 events), with the effective (last) title belonging to a different session than the one the user actually named it.

Impact

  • Sessions become indistinguishable in the resume picker (five sessions all named the same).
  • The injected system reminders tell the model the user renamed the session when they did not.
  • Title history in transcripts is polluted with hundreds of duplicate events.

Repro (as observed)

  1. Start several claude sessions in parallel in the same project directory (fresh sessions, no resume).
  2. /rename one of them.
  3. Observe ~/.claude/sessions/*.json: other sessions' name fields take the new value; other sessions' transcripts gain custom-title events stamped with their own sessionIds.

Happy to provide sanitized registry/transcript excerpts on request.

View original on GitHub ↗

4 Comments

bcherny collaborator · 15 days ago

Reproduced on v2.1.233 (macOS) — but only when the parallel sessions share one background-job identity, which is very likely what is happening in your setup.

With plain fresh sessions started from a normal shell, /rename only touched the renamed session. The cross-rename appears as soon as the sessions inherit the same CLAUDE_JOB_DIR environment variable, which happens when a claude session (or the tmux server whose panes later run claude) is launched from inside a background Claude Code session's shell — e.g. a background session running tmux new-session/tmux split-window or claude via its Bash tool. Steps:

  1. Start two interactive claude sessions in the same directory, both with the same CLAUDE_JOB_DIR pointing at an existing background job's directory (this is what a shell spawned from a background session gives you).
  2. In session A run /rename new-3.

Observed: session B's name banner switches to new-3 immediately, ~/.claude/sessions/*.json shows both live sessions named new-3, and each session records the title (and the "user named this session" reminder) as its own.
Expected: only session A is renamed.

Assessment: this looks like a genuine bug. Every session in that situation watches the same job state file to pick up renames made from the fleet view, so a rename in one is replayed into all of them. The interactive session inherits the background job's identity even though it is not that job; the check should be tighter (or the variable should not leak into nested launches). The hundreds of duplicate title records are a side effect: once a session has a title, it periodically re-writes it to the end of its transcript so it stays discoverable, which multiplies the wrong title.

A quick way to confirm on your side: in an affected pane run echo $CLAUDE_JOB_DIR — if it is set (and identical across the panes), that is the trigger; starting the panes from a shell where it is unset avoids it. Not a recent regression: this sync path has been present since roughly v2.1.113.

🤖 Generated with Claude Code

dreaming-k2 · 13 days ago

Confirmed on our side (original reporter's machine, v2.1.231, Linux) - your diagnosis matches exactly.

We checked CLAUDE_JOB_DIR in /proc/<pid>/environ for all 20 live sessions in the registry:

  • Every session that ever got cross-renamed (including all 6 tmux panes where the contamination was originally observed) carries the IDENTICAL CLAUDE_JOB_DIR=~/.claude/jobs/5d9c422e.
  • Every session that never got renamed by another session's /rename has the variable unset.

Perfect correlation, zero exceptions. The inheritance path is also exactly what you hypothesized: the tmux server hosting those panes was started from inside a background Claude session's shell, so every interactive claude launched in any pane inherited that one background job's identity.

Workaround that works for us: tmux set-environment -gu CLAUDE_JOB_DIR on the affected server plus unset CLAUDE_JOB_DIR in existing shells before starting new sessions; already-running sessions keep the shared identity until restarted.

Happy to provide sanitized environ/registry dumps if useful.

bernardocabral04 · 6 days ago

Additional controlled evidence, isolating the propagation to the receive side of the messaging socket — no /rename, no TUI, no resume/fork involved.

Environment

  • Claude Code 2.1.241, Linux (CachyOS, kernel 7.1.6-1)
  • A profile (CLAUDE_CONFIG_DIR) with ~20 concurrent sessions: a mix of claude --bg background agents and interactive sessions, several sharing a project directory
  • All third-party tooling stopped for the measurement (we run an external fleet daemon that reads session metadata; it was shut down to exclude it)

Reproduction (1 message → 14 sessions renamed)

  1. Pick one idle session; read messagingSocketPath from its sessions/<pid>.json (peerProtocol: 1).
  2. Send exactly one line to that one socket:

``json
{"type":"control","action":"rename","name":"fanout probe"}
``

  1. Within ~4 seconds, 14 sessions/<pid>.json files in the profile carried "name": "fanout probe" — each keeping its own correct sessionId/socket. Verified 0 files carried the name before the send.

So the contamination does not require the /rename command at all: whatever the receiving session (or the shared background supervisor) does with an incoming control rename fans it out to every peer in the profile. This is presumably the same internal path /rename lands on, which would explain the original report.

Two extra data points

  • Propagation is nondeterministic. Sending a second rename (the original name, to the same single socket) updated only the targeted session; the other 13 kept the probe name until their metadata files were edited directly. So the fan-out is not a reliable "broadcast" either — it looks like a race in whatever sync loop picks the rename up.
  • formerNames shows one propagator pass per rename event. Untouched sessions accumulate the full sequence of other sessions' renames, with nameSince timestamps ~15 ms apart per event across all files — consistent with a single writer sweeping the profile on each rename, and matching the mtime evidence in the issue body (every sessions/<pid>.json rewritten in the same second).

Impact beyond cosmetics

With ~15 background agents in one profile, any rename (including agents naming themselves programmatically via the socket) renames the whole fleet, and name-based cross-session messaging becomes unusable — every name collides, so messages misroute. We have had to route around it by addressing sockets only, and to stop sending control renames entirely.

Happy to provide the raw formerNames chains or run variations of the probe if useful.

bernardocabral04 · 6 days ago

Follow-up: the fan-out is scoped to interactive sessions only.

Profiling the same profile after the probe above: all 14 contaminated sessions/<pid>.json were "kind": "interactive"; every "kind": "bg" session (claude --bg) was untouched — including bg sessions running in the same working directories as the victims. So the propagation is keyed on session kind, not on a shared project directory: whatever gossips the rename lives in the interactive/tty session path, and background agents never participate.

Practical implication for anyone hitting this with agent fleets: spawning workers with claude --bg sidesteps the contamination entirely.