[BUG] Windows: Import silently skips every CLI transcript whose project path is stored with forward slashes in ~/.claude.json — whole directories never import, with no error surfaced

Status Fixed / completed
Reported on v2.1.278
Maintainer reply None cached
Activity 0 comments · opened Sep 21, 2026 · closed Sep 22, 2026

Summary

On Windows, Desktop's Import matches each transcript's cwd against the keys of projects in ~/.claude.json by exact string comparison. The CLI writes those keys with forward slashes (D:/16228/desktop/huawei_ascend_s9); Desktop writes them with backslashes (E:\Building). Transcripts always record cwd with backslashes.

The result: a project directory that has only ever been used from the CLI has no backslash key, so every transcript in it fails the trust lookup and is never even listed as an import candidate. The completion dialog reports success and does not mention them. The only trace is a counter in main.log.

I lost 7 sessions (~29 MB of work) this way and could not find them for two weeks.

Environment

  • Claude Code CLI 2.1.278 (native install, Windows 11 Pro for Workstations 26200)
  • Claude for Windows 2.2553.1 (c38127), Sep 17 2026
  • Auth: claude.ai subscription

What the log shows

%LOCALAPPDATA%\Claude\Logs\main.log:

[CCD-SessionRecovery] Scan complete: 4 recoverable, counts={"scannedTranscripts":640,"skippedUnparseable":0,"skippedFiltered":624,"skippedNotLost":0,"skippedUntrusted":12}
[CCD-SessionRecovery] Recovery complete: recovered=2, failed=2, skipped=0 of 4 candidates

skippedUntrusted is the bucket in question. Those transcripts get no per-session log line, and the dialog's "N sessions couldn't be imported" counts only the failed ones (sessions owned by a running process) — untrusted ones are invisible in both places.

Root cause

~/.claude.json on this machine, projects keys, grouped by separator style:

backslash  E:\caringSystem, E:\Building, C:\Users\16228, D:\16228\desktop\大二实训        -> imported fine
forward    D:/16228/desktop/huawei_ascend_s9, C:/WCH.CN, D:/16228/desktop/dzz, E:/Games  -> never imported

The backslash group is exactly the set of directories I had opened in Desktop at least once. The forward-slash-only group is exactly the set I had only ever used from the CLI. Several paths appear under both forms, which is how they got trusted at all.

Evidence

1. Controlled experiment. Four copies of one 18.4 MB transcript, each with a fresh sessionId, differing only in the stated variable:

| Variant | change | size | imported |
|---|---|---|---|
| control | none | 19.1 MB | no |
| slim | base64 image payloads emptied | 10.6 MB | no |
| cwd | all cwd normalized to the trusted project root | 19.1 MB | yes |
| both | both changes | 10.6 MB | yes |

Transcript size is irrelevant: the 19.1 MB variant with every screenshot intact imported; the 10.6 MB variant with a non-trusted cwd did not.

2. The counter tracks it exactly. skippedUntrusted moved in lockstep with how many non-trusted-cwd files were present: 11 (baseline) -> 12 (one such file added) -> 13 (two added).

3. Adding the missing key fixes it. I added a Desktop-shaped stub for the backslash form of a CLI-only directory:

"D:\\16228\\desktop\\huawei_ascend_s9": {
  "allowedTools": [],
  "mcpContextUris": [],
  "enabledMcpjsonServers": [],
  "disabledMcpjsonServers": [],
  "hasTrustDialogAccepted": true,
  "hasClaudeMdExternalIncludesApproved": false,
  "hasClaudeMdExternalIncludesWarningShown": false
}

The next Import recovered all 7 transcripts from that directory, which had never been importable before, and skippedUntrusted dropped from 13 to 2:

[CCD-SessionRecovery] Recovered CLI session 78f13ada-... (cwd=D:\16228\desktop\huawei_ascend_s9, ...)
[CCD-SessionRecovery] Recovered CLI session 67788bde-... (cwd=D:\16228\desktop\huawei_ascend_s9, ...)
... 7 total
[CCD-SessionRecovery] Recovery complete: recovered=7, failed=2, skipped=0 of 9 candidates

Adding backslash keys for the remaining forward-slash-only directories cleared skippedUntrusted to 0.

Second failure mode: /add-dir

A directory attached with /add-dir never gets a projects entry. Tool calls made while that directory is the working directory record its path as cwd. A single such record is enough to make the whole session untrusted — even though the session's own project root is trusted and the transcript lives in that project's directory.

Two of my sessions were lost this way: their project root E:\caringSystem is trusted, but they had /add-dir'd D:\16228\desktop\大赛资源, which has no entry at all. Rewriting every cwd in those transcripts to E:\caringSystem made both import immediately.

This makes /add-dir quietly destructive: using it costs you the ability to import that session, with no warning at the time and no error afterwards.

Impact

  • Whole project directories are missing from Desktop with no indication anything was skipped.
  • The affected sessions still show up in Desktop's sidebar under Other if they were ever bridged from another device (remote control), but only as the cloud mirror with a server-generated title — so the session looks present while the local transcript is not actually there.
  • Users have no way to discover the cause without reading main.log and diffing ~/.claude.json key formats.

Expected

  1. Compare paths, not strings: normalize separators and case on Windows before the trust lookup.
  2. Make the CLI and Desktop write projects keys in one canonical form, and migrate existing duplicates.
  3. Treat a transcript as trusted based on its session's project root, not on every cwd any tool call happened to record — or at minimum do not let an /add-dir path revoke trust for the whole session.
  4. Surface the skip. Imported N sessions. M sessions couldn't be imported. should include the untrusted ones and say why.

Workaround

Add a backslash-form stub key (shape above) to projects in ~/.claude.json for each CLI-only directory, then run Import again. For sessions broken by /add-dir, rewrite the cwd fields in the transcript to the project root, keeping sessionId unchanged.

Note that ~/.claude.json is written by running Claude Code processes; back it up first — a read-modify-write of my own clobbered four pluginUsage counters.

View original on GitHub ↗