/add-dir writes a persistent, bidirectional project→project link (.session-aliases) that merges an entire other project's sessions into /resume
Environment
- Claude Code v2.1.205 (native installer build)
- macOS, Darwin 23.6.0
- Reproduces in a plain terminal and in the VS Code integrated terminal
Summary
The docs state the picker shows, by default, "sessions from the current worktree, plus sessions started elsewhere that added the current directory with /add-dir."
In practice, once you /add-dir B while working in project A — even as a session-only add (not "remember", it doesn't touch settings.local.json) — Claude Code writes a persistent link into a hidden file, and the picker then merges all of B's sessions into A's picker (and, bidirectionally, all of A's into B's). It is per-project, not per-session; persistent, not session-scoped; and bidirectional.
Mechanism / root cause
~/.claude/projects/<sanitized-A>/.session-aliases is a newline-delimited list of other project folders whose sessions get merged into A's resume picker. /add-dir (and resuming a session from another directory) appends the other project's folder path to it. The picker (loadSameRepoMessageLogs → getStatOnlyLogsForWorktrees) then reads those folders wholesale.
Empirical proof via --debug-file, run from project A:
/resume: loading sessions for cwd=/…/project-a, worktrees=[/…/project-a]
/resume: found 600 session files on disk
Project A has 18 own sessions on disk. The other 582 are project B's entire history. Emptying A/.session-aliases and re-running → found 18. So a single shared /add-dir pulled in 582 unrelated sessions, of which exactly one had ever added the current directory.
Steps to reproduce
cd project-a && claude→/add-dir /abs/path/to/project-b→ exit.cd project-a && claude --resume→ the default view (not Ctrl+A) now lists all of project-b's sessions.cd project-b && claude --resume→ lists project-a's sessions too (bidirectional).- Survives restarts.
cat ~/.claude/projects/<sanitized-a>/.session-aliasesshows project-b's folder path.
(Sanitized folder = the project's absolute path with non-alphanumeric chars replaced by -.)
Expected
Per the docs, only the specific session(s) that actually added the current directory via /add-dir should surface — not the entire other project.
Problems this causes
- Granularity: docs promise "sessions … that added the current directory" (per-session); the code merges the whole project folder (per-project).
- Scope: a session-only
/add-dirproduces a permanent link. - Direction: adding B while in A also makes A appear in B's picker — never requested.
- Visibility: stored in a hidden, misleadingly named file (
.session-aliasesreads like Ctrl+R rename aliases, but it holds folder paths); not surfaced by/add-dir,/permissions,/config, or~/.claude.json; no UI to inspect or remove it. Effectively undebuggable. - No pruning: links never expire; stale
.session-aliases.bakfiles can even resurrect old links.
Suggested fix (take with a grain of salt, fix it however you want)
- Key the association by session, not by project folder. Transcripts already record every
cwd/added directory per line, so the picker can surface exactly the sessions that touched the current dir — self-cleaning, no side file needed. If a persisted index is wanted for performance, store foreign session references, not foreign project folders. - Don't persist a link for a session-only
/add-dir. - Make it one-directional (or make the reverse an explicit opt-in).
- Give it a management surface (related: #27935 requests
/remove-dir) and an honest filename.
Workaround
rm ~/.claude/projects/<sanitized-project>/.session-aliases
Not a duplicate
Distinct from the "shows ALL projects by default" regression (#46887, #46445, #46688, #46784). This is the specific /add-dir link that merges one other project's sessions wholesale, persistently, and bidirectionally, via .session-aliases.