Skip to content

fix(claude): honor CLAUDE_CONFIG_DIR when resolving the resume session id - #85

Merged
AThraen merged 1 commit into
mainfrom
fix/claude-config-dir
Aug 10, 2026
Merged

fix(claude): honor CLAUDE_CONFIG_DIR when resolving the resume session id#85
AThraen merged 1 commit into
mainfrom
fix/claude-config-dir

Conversation

@AThraen

@AThraen AThraen commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Fixes restored Claude sessions failing with No conversation found with session ID: <uuid>, leaving a bare shell prompt behind.

Root cause

ClaudeSessionService hardcoded ~/.claude as Claude's data directory:

Path.Combine(UserProfile, ".claude", "projects", projectDir)

Claude Code honors CLAUDE_CONFIG_DIR, and when it's set, conversations live under $CLAUDE_CONFIG_DIR/projects/ instead. A machine that has ever run without the env var keeps a stale ~/.claude/projects/ tree — so GetLastSessionId returned the newest id from the wrong store: a real, valid-looking UUID that current Claude has no record of.

This is why it looked like Claude had changed how --resume works. It hasn't; only where conversations are stored moved.

Evidence from the reporting machine

CLAUDE_CONFIG_DIR is set at User scope, so CodeShellManager.exe inherits it. For one project folder:

Store Newest .jsonl
~/.claude (stale, frozen ~2 months) 6270d0e9-971a-44ad-81b9-cf89434ab1cfexactly the id in the error
~/.claude-work (live) 8eaf0a22-4f5d-45a4-a579-0ccf20553e27, modified same day

Change

  • ResolveClaudeHome(configDir, userProfile)CLAUDE_CONFIG_DIR when set, else ~/.claude.
  • GetLastSessionId gains an internal overload taking the resolved home, so the lookup is testable without mutating process environment or depending on the real user profile. Public signature unchanged.

This deliberately does not fall back to the legacy directory when the resolved one has no session — returning null starts a fresh conversation, which is correct. Falling back would reintroduce the bogus-id failure.

Scope

Does not fix #75 (the same-folder resume race, where two sessions in one folder both resolve to the same id and the first session's own write poisons the lookup for the second). That's a separate root cause in the same code path; the durable fix there is persisting a ClaudeSessionId per session and launching with --session-id. This PR only ensures we read the right directory.

Verification

  • 9 new unit tests — env resolution (set / null / blank), stale-vs-live store selection, missing and empty project dirs, path→project-dir-name mapping, and the real on-disk layout where a <session-id>/ subdirectory and a memory/ dir sit next to <session-id>.jsonl
  • 215/215 tests pass; app builds clean
  • Written test-first; watched each fail

Manual check worth doing before merge: restart CodeShellManager and confirm sessions resume rather than erroring. I verified the id resolution against the real filesystem but did not perform a live --resume (that would have written into an in-use conversation).

🤖 Generated with Claude Code

…n id

Restored Claude sessions failed with "No conversation found with session ID:
<uuid>", leaving a bare shell prompt behind (the pwsh wrapper runs with -NoExit,
so claude's exit is visible rather than closing the pane).

ClaudeSessionService hardcoded ~/.claude as Claude's data directory. Claude Code
honors CLAUDE_CONFIG_DIR, and when that is set its conversations live under
$CLAUDE_CONFIG_DIR/projects/ instead. A machine that has ever run without the
env var keeps a stale ~/.claude/projects/ tree, so GetLastSessionId returned the
newest id from the *wrong* store - a real, valid-looking UUID that current Claude
has no record of.

Reproduced on the reporting machine: CLAUDE_CONFIG_DIR is set at User scope, so
CodeShellManager.exe inherits it. For one project folder the stale ~/.claude tree
resolved to 6270d0e9-... (last written two months earlier) - exactly the id in
the error - while the live store resolved to 8eaf0a22-..., modified that day.

ResolveClaudeHome(configDir, userProfile) now picks CLAUDE_CONFIG_DIR when set
and falls back to ~/.claude otherwise. GetLastSessionId gains an internal
overload taking the resolved home so the lookup is testable without touching
process environment or the real user profile; the public signature is unchanged.

Note this deliberately does NOT fall back to the legacy directory when the
resolved one has no session: returning null starts a fresh conversation, which
is correct, whereas falling back reintroduces the bogus-id failure.

Does not address issue #75 (the same-folder resume race) - that is a separate
root cause in the same code path.

Verified: 9 new unit tests (env resolution, stale-vs-live store selection, the
real on-disk layout where a <session-id>/ subdirectory sits next to
<session-id>.jsonl); 215/215 tests pass; app builds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@AThraen
AThraen merged commit b39e1d7 into main Aug 10, 2026
1 check passed
@AThraen
AThraen deleted the fix/claude-config-dir branch August 10, 2026 19:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Claude sessions don't always resume correctly on restore

1 participant