Session history lost/hidden after renaming project folder (session discovery keyed only to old path)

Status Open
Maintainer reply None cached
Activity 3 comments · opened Aug 14, 2026

Summary

Renaming a project folder makes Claude Code's existing session history for that project invisible in the session picker (observed in the VSCode extension), even though the transcript data is fully intact on disk.

Root cause

  • Session transcripts live under ~/.claude/projects/<sanitized-abs-path>/<session-id>.jsonl, where the directory name encodes the workspace's absolute path (/ and _ both become -).
  • Each JSONL line also embeds the workspace path in a cwd field (and absolute paths appear throughout tool-call args/results).
  • After a folder rename, the session directory keyed to the old path is never associated with the new path, so the picker shows no history for the renamed workspace — despite the .jsonl transcript being present and uncorrupted under the old path's directory.

Repro steps

  1. Open a project folder in VSCode with the Claude Code extension, start a session, do some work.
  2. Rename the project folder on disk (Finder/Explorer or mv).
  3. Reopen the renamed folder in VSCode.
  4. Session history for that workspace is empty in the sidebar — the prior session appears lost.

Workaround (manually verified)

  1. Find the old session dir: ~/.claude/projects/<old-sanitized-path>/.
  2. Copy <session-id>.jsonl (+ its sidecar dir) into ~/.claude/projects/<new-sanitized-path>/.
  3. Find/replace the old absolute path with the new one throughout the .jsonl (appears in cwd fields and in tool-call paths).
  4. Fully restart VSCode (a reload wasn't enough in testing) — the session then appears in the picker for the renamed workspace.

Suggested fix

  • Fall back to matching sessions by the cwd field(s) recorded inside the transcript, not solely by directory-name-encoded path, and/or
  • Add a "relink session to this workspace" command so users aren't hand-editing JSONL, and/or
  • On opening a workspace with no matching session dir, detect orphaned session dirs (e.g. by git remote/dir-contents heuristics) and offer to migrate them.

Environment

  • Claude Code VSCode extension
  • macOS (Darwin 25.3.0)

View original on GitHub ↗

3 Comments

Strongich · 1 month ago

Reproduced on Linux + the bare terminal CLI (no VS Code), so this isn't macOS/VSCode-specific. This is also the case with --continue, which silently starts a new session instead of erroring.

Environment

  • Claude Code 2.1.245 (native install)
  • Ubuntu 24.04.4 LTS, kernel 7.0.0-30-generic, zsh, xterm-256color
  • No IDE extension involved

Repro

mkdir /tmp/repro-old && cd /tmp/repro-old
claude -p "reply with the single word OK and nothing else"     # -> OK

ls ~/.claude/projects/ | grep repro
# -tmp-repro-old                          <- one session dir

mv /tmp/repro-old /tmp/repro-new && cd /tmp/repro-new
claude -p --continue "reply with the single word OK"           # -> OK  (no error!)

ls ~/.claude/projects/ | grep repro
# -tmp-repro-new                          <- NEW dir, NEW session id
# -tmp-repro-old                          <- original transcript, orphaned

--continue silently starts a new session

--continue after the rename does not fail and does not warn -- it just begins a fresh conversation:

old/ee5e45ef-….jsonl   13 lines   grep "and nothing else" -> 4 hits   cwd=/tmp/repro-old
new/920f0312-….jsonl   13 lines   grep "and nothing else" -> 0 hits   cwd=/tmp/repro-new

Workaround confirmed on Linux — and no restart needed

The manual relink works, and unlike the VS Code case (which needed a full restart) the very next CLI invocation picks it up immediately:

P=~/.claude/projects
rm -f "$P/-tmp-repro-new"/*.jsonl        # discard the accidental empty session
sed 's#/tmp/repro-old#/tmp/repro-new#g' \
    "$P/-tmp-repro-old/ee5e45ef-….jsonl" > "$P/-tmp-repro-new/ee5e45ef-….jsonl"

cd /tmp/repro-new
claude -p --continue "what was my first message to you? quote it exactly"
# -> "reply with the single word OK and nothing else"

Same session ID resumed, full history intact, no restart. That suggests the lookup is a plain startup-time path-slug match rather than anything cached, so a fallback that scans orphaned dirs' cwd fields should be enough to fix it.

Suggested minimum

Even before full "sessions follow the folder" support (#79215, #69752): make --continue/--resume fail loudly when the project dir for the current cwd doesn't exist but no session is found, instead of silently opening a new one. Silent context loss is the damaging half of this bug.

BasedGPT · 1 month ago

The transcript files are still there, but they are under the old project slug. Renaming the folder changes the path used to derive ~/.claude/projects/<slug>/, so the renamed workspace looks empty even though the session data is intact.

I built BasedGPT/claude-code-session-recovery for this file-layer split. Run python tools/diagnose.py from the toolkit first and follow the exact command it prints. That distinguishes a project-slug mismatch from a missing transcript file before you copy or rewrite anything.

For the check in your report, compare the old and new project directories and inspect the cwd records inside one transcript. Keep a byte-for-byte backup of the old directory before applying any path repair; a fresh --continue that starts a new session is a sign the old transcript was not relinked.

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

likemusic · 22 days ago

Confirming on Linux/WSL2 CLI 2.1.278 (so it isn't VSCode-specific), and adding two details to the workaround in the issue body, both found the hard way while migrating a 92 MB / 42-session project today.

  1. The find-and-replace has to be boundary-aware. My project was ~/Projects/belfermer and a different project ~/Projects/belfermer-docker sits next to it; a plain replace of the old path also rewrites every mention of the sibling. s{<old-path>(?![-\w])}{<new-path>}g is the minimum. The same non-injectivity bites the slug encoding itself, where both / and _ map to - (cf. #21085, #80264).
  1. The transcripts are not the whole story. Relinking only *.jsonl leaves the project half-migrated. Also keyed to the old absolute path: the sidecar <session-id>/tool-results/*.txt files, ~/.claude/projects/<slug>/memory/ (project memory — silently lost, no warning), ~/.claude/history.jsonl (up-arrow prompt history), ~/.claude.json → projects["<path>"] (trust + allowedTools + MCP servers), ~/.claude/sessions/<pid>.json, ~/.claude/jobs/<id>/state.json, and every one of those again under ~/.claude/profiles/<name>/. Also worth knowing: ~/.claude.json is rewritten in full from an in-memory copy when any other live session exits, so edit it with no other sessions running.

Filed #96018 for a built-in claude project mv covering all of it, plus a startup hint when a populated slug directory exists for a path that no longer resolves — the two prior requests for such a command (#70470, #24789) were auto-closed as duplicates and locked.