Renamed project root: session registry never revalidates stored cwd — new sessions inherit the dead path, project-scoped settings/hooks/memory all silently fail to load, and the harness recreates the deleted directory

Status Open
Reported on v2.1.219
Maintainer reply None cached
Activity 3 comments · opened Aug 1, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

After renaming a project's root directory on disk (mv /Users/me/old-name /Users/me/new-name), several related behaviors combine into a real footgun:

(1) The per-session shell snaps back to the dead path after every Bash call ("Shell cwd was reset to /Users/me/old-name"). Expected for sessions that were already running — but:

(2) Sessions launched after the rename inherit the dead path too, because the stored project entry/session record (~/.claude/sessions/<pid>.json, cwd field) is set from the old registry value at launch and is never revalidated against the filesystem. Verified: a session launched 75 minutes after the rename was born with the dead cwd.

(3) Project-scoped .claude/settings.json (hooks and permissions) silently fails to load entirely for a session rooted at the dead path — confirmed live: a session whose registered root was the dead pre-rename path had no .claude/settings.json there at all, while the correctly-configured file (including a PreToolUse hook) lived only at the real, renamed root. Two real gated tool calls (a git push, an Agent call) both went through with zero interception — not a hook-dispatch bug, the hook was simply never registered. Re-tested from a session genuinely rooted at the correct path: both calls were correctly intercepted. This is a silent, total loss of project-scoped hooks/permissions enforcement, with no error or warning.

(4) Project-scoped persistent memory is orphaned too. Claude Code keys project memory by project root (~/.claude/projects/<munged-project-root>/memory/). After the rename, sessions rooted at the new path get a fresh, empty memory directory — the entire accumulated memory store stays keyed to the old path's entry and is silently invisible to correctly-rooted sessions. Verified: a post-rename session rooted at the new path started with zero recalled memories while ~85 memory files sat under the old entry.

(5) The harness silently recreates the deleted directory tree at the old path (observed: <old-path>/.claude/scheduled_tasks.lock and a duplicate of a repo file written there by a background mechanism), so the dead path resurrects itself with no warning. Deleting the stub is futile while any old-path session lives — the lock file is actively held.

No data loss — live processes' OS-level cwd resolves correctly through the rename (verified via lsof), and the real repo is untouched. But the combination cost real debugging time across multiple sessions, and nothing ever surfaces "your project path no longer exists / was recreated" or "project-scoped config/memory for this session did not load."

What Should Happen?

Any one of: the project registry revalidates its stored path at session launch (or follows the inode/offers to update when the directory is gone); a visible warning that the configured project directory no longer exists, or that project-scoped settings/hooks/memory could not be found at the registered root and the session is running without them; or at minimum, no silent recreation of the deleted path. Renaming/moving a project should migrate (or at least surface) all state keyed to the old root — settings, hooks, and memory alike — rather than silently falling back to an unconfigured/memoryless state with no indication anything is missing.

Error Messages/Logs

Steps to Reproduce

(1) Open a Claude Code session in project /tmp/demo-a; leave it running.

(2) mv /tmp/demo-a /tmp/demo-b

(3) In the running session, run any Bash command → observe "Shell cwd was reset to /tmp/demo-a".

(4) Open a new session from the same project entry in the app → its Bash cwd is also /tmp/demo-a (dead), and ~/.claude/sessions/<pid>.json records "cwd": "/tmp/demo-a".

(5) That new session has no project-scoped .claude/settings.json in effect (any hooks/permissions configured at the real, renamed root are silently not loaded) and no access to project memory accumulated at the real root.

(6) Observe /tmp/demo-a reappear on disk containing .claude/scheduled_tasks.lock.

Claude Model

None

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.219 (desktop app)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Related issues: #54175 (docs: moved launch-directory behavior undocumented), #55587 (preview_start after project rename, closed as duplicate), #18236 (Bash after deleted working directory). This report is specifically about the persistent registry + silent recreation + silent project-scoped settings/hooks/memory loss for post-rename new sessions, which none of those cover.

View original on GitHub ↗

3 Comments

josealf · 3 days ago

Same root cause, with a minimal reproduction procedure that does not require reinstall or any special setup:

mkdir proj-a && cd proj-a
claude -p "Remember this codeword: ABRAKADABRA. Reply with just: stored"
claude -p --continue "What codeword did I give you? Reply with just the codeword."
# -> ABRAKADABRA

cd .. && mv proj-a proj-b && cd proj-b
claude -p --continue "What codeword did I give you? Reply with just the codeword."
# -> "I don't have any codeword from you in this conversation."

A new project folder is created for the new path; the original transcript stays in ~/.claude/projects/<old-encoded-path>/, intact but unreferenced. Nothing reports that anything is missing.

Verified on CLI 2.1.243, Windows. The folder-naming scheme is not platform-specific, so I would expect the same issue unix like OSes (not tested there).

Worth noting this is just one case among several for the same design — the folder name below ~/.claude/projects/ is derived from the full project/working pathname and is the sole lookup key, so any variation in that string detaches history:

  • This issue — a renamed or moved directory changes the string, so lookup targets a folder that does not exist and the original is left orphaned.
  • #48394 (closed) — the same rename trigger, reported in April. Closed not_planned by automation, not sure if it was triaged.
  • #89283 (open) — the same UNC directory gets written two different ways (\\host\share vs //host/share), so one directory ends up with two project folders. The stale one takes precedence on restart, history appears to disappear, and the reporter says one transcript was lost for good.
  • #87552 (closed) — a path containing non-ASCII characters is encoded two different ways (Unicode NFC vs NFD), so the same directory ends up with two project folders and the history is split between them.

Addressing these one trigger at a time leaves the next one open. A stable per-project identity would cover all of them; failing that, detecting that transcripts exist under a name that no longer resolves — and reporting it — would turn a silent failure into an easily solvable one.

BasedGPT · 2 days ago

The transcript is likely still present under the old project slug. Renaming the folder changes the path key used for project-scoped sessions, so new sessions resolve the renamed folder while earlier records remain attached to the old cwd. That also explains why the old hooks, permissions, and project memory stop appearing without implying that the conversation data was deleted.

I built BasedGPT/claude-code-session-recovery for this file-layer split. From that checkout, run python tools/diagnose.py first and follow the exact command it prints. It compares the stored cwd and project slug with the transcript locations, distinguishing one project split across two session sets from a genuinely missing JSONL file before any metadata rewrite.

Before starting another --continue in the renamed folder, compare the old and new ~/.claude/projects/<slug>/ directories and inspect the cwd record in one affected transcript. Keep a byte-for-byte copy of the old directory. If the diagnosis identifies a supported path repair, apply it only after checking that the transcript count and hashes are unchanged; otherwise leave the files in place rather than guessing at a new project key.

Hope this helps, if my tools are able to help you, would appreciate a ⭐ :)

josealf · 2 days ago

Thanks for your feedback. Actually, I already solved my problem. In my case, my main computer died and I took the drive from it to another, mounting it with a different drive letter. I wanted to restore my profile exactly as it was on the old computer and I hit the documented issue. With Claude's help, I succeeded and along the way, like you, I ended up developing a tool to automate the recovery process. The result is at https://github.com/josealf/claude-profile-migrate. After that, I wanted to report the problem upstream, but I found this and the other related threads.