Relocating a project dir (symlink / new mount) orphans all session history, memory & context — project keyed by raw cwd path

Status Open
Maintainer reply None cached
Activity 4 comments · opened Jun 26, 2026

Summary

Claude Code stores per-project state (session transcripts, MEMORY.md, todos, scratchpad) under ~/.claude/projects/<slug>, where <slug> is derived from the literal absolute working-directory path. When a project's directory is relocated — e.g. ~/dev becomes a symlink to an external drive /Volumes/SanDisk2/dev, or the tree is moved to a new mount — Claude Code treats it as a brand-new project. The entire prior session history, memory, and context are orphaned under the old path slug, and storage fragments across multiple slugs (-Users-<user>-dev-... vs -Volumes-SanDisk2-dev-...) for what is the same repo.

Repro

  1. Have a project at ~/dev/foo with accumulated session history + MEMORY.md.
  2. Move ~/dev to an external drive and symlink it back (~/dev -> /Volumes/SanDisk2/dev), or otherwise reach the same project via a different absolute path.
  3. Start Claude Code in the project.
  4. A new ~/.claude/projects/<new-slug> is created; prior sessions / memory / todos under the old slug are not carried over; the same conversation can even appear under two different slugs.

Impact

  • Continuity loss across all projects after a directory move.
  • MEMORY.md and recalled context silently not applied (they live under the old slug).
  • Duplicated/fragmented project dirs; very confusing.
  • Compounds with git: stale remote-tracking refs after the move fake "N commits ahead / diverged" until git fetch, and fatal: not a git repository ... GIT_DISCOVERY_ACROSS_FILESYSTEM not set errors appear for repos under the /Volumes mount.

Suggested fix

Key project identity by something stable instead of the raw cwd path:

  • resolve symlinks / realpath consistently when computing the project slug, and/or
  • derive identity from the git remote URL or a persisted .claude/project-id, and/or
  • detect when the same repo appears under a new path and offer to migrate/merge the existing project storage.

Environment

  • macOS (darwin), Claude Code CLI.
  • ~/dev symlinked to an external volume /Volumes/SanDisk2/dev.

View original on GitHub ↗

3 Comments

github-actions[bot] · 2 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/70470
  2. https://github.com/anthropics/claude-code/issues/41630
  3. https://github.com/anthropics/claude-code/issues/34437

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

BasedGPT · 2 months ago

Your sessions are all there — just split across two directory slugs because the path changed. When ~/dev started resolving through /Volumes/SanDisk2/dev, Claude Code hashed a different ~/.claude/projects/ slug for the same repo, so old sessions stranded under the original key while new ones accumulated under the new one.

I built a toolkit that consolidates them: diagnose.py in BasedGPT/claude-code-session-recovery maps both slug directories against your Desktop metadata and shows the exact session count under each key. Once you have that picture, rewrite_metadata_cwd.py updates the cwd field in each affected metadata file so Desktop pulls everything under a single slug going forward.

One thing before the rewrite: the memory directory (~/.claude/projects/<old-slug>/memory/) splits on the same key. Copy it from the old slug into the new one manually before running rewrite_metadata_cwd.py.

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

josefgosch · 17 days ago

Still reproducible on 2.1.229 (Linux), and worth noting it also hits a case with no symlinks or mounts involved: plain directory reorganisation.

I moved a plugin repo one level deeper to group it with two upcoming sibling projects:

~/Work/wordpress/myplugin  →  ~/Work/wordpress/suite/myplugin

Nothing about the project changed — same repo, same disk, same machine. But the state directory is keyed by the literal path, so 9 sessions (~30 MB of transcripts) plus the project's MEMORY.md entries were orphaned under the old slug.

The manual fix works and is a one-liner:

mv ~/.claude/projects/-home-user-Work-wordpress-myplugin \
   ~/.claude/projects/-home-user-Work-wordpress-suite-myplugin

The problem is that it requires knowing the state directory exists, knowing the path-to-slug encoding, and doing it before the next session starts in the new location. Most people will only find out afterwards, when the history is already gone.

One concrete gap that would be cheap to close, separate from the larger identity question: claude project currently exposes only purge. There is a supported way to delete project state but none to relocate it. A sibling command would cover the deliberate case without needing to solve stable project identity first:

claude project move <old-path> <new-path> [--dry-run]

That leaves the automatic detection in the original report (realpath resolution, git-remote matching) as the fix for the cases users don't see coming — but at least gives those of us who do know about the move a documented way to keep our history.

Showing cached comments. Read the full discussion on GitHub ↗