[BUG] SSH Remote: `projects` field in remote ~/.claude.json becomes null after desktop restart — jsonl files intact, UI shows 'No messages yet' for every session
Summary
After restarting the Claude Code desktop client while connected to a remote host via SSH Remote, the sidebar shows "No messages yet" for every conversation. Investigation on the remote shows the top-level projects field of ~/.claude.json has been nulled out, while the .jsonl transcript files in ~/.claude/projects/<project>/ are intact and continue to be appended to in real time.
This appears related to #54187, #53717, and #34324 but with a stricter form of the corruption — the projects map is entirely missing instead of just having empty sessions[] arrays per project.
Environment
- Client: Claude Code Desktop on Windows 10/11
- Connection: SSH Remote via OpenSSH 9.6 (Windows native OpenSSH)
- Server: Ubuntu 24.04.4 LTS (Noble Numbat), claude-code installed under
/root - Working dir on remote:
/root
State of remote ~/.claude.json after bug triggers
>>> import json
>>> d = json.load(open('/root/.claude.json'))
>>> list(d.keys())
['cachedGrowthBookFeatures', 'unpinOpus47LaunchEffort', 'firstStartTime',
'opusProMigrationComplete', 'sonnet1m45MigrationComplete', 'seenNotifications',
'migrationVersion', 'userID', 'cachedExperimentFeatures',
'cachedExtraUsageDisabledReason', 'skillUsage']
>>> d.get('projects')
None
>>> type(d.get('projects'))
<class 'NoneType'>
No projects map at all — not {}, not per-project entries with empty sessions[].
Data side is intact
$ ls ~/.claude/projects/-root/*.jsonl | wc -l
14
$ du -sh ~/.claude/projects/-root/
17M
$ for f in ~/.claude/projects/-root/*.jsonl; do
python3 -c "import json
bad = 0
for l in open('$f'):
try: json.loads(l)
except: bad += 1
print('$f', bad)"
done
# every file: 0 malformed
The currently-active session's .jsonl continues being appended to within seconds of sending a message from the (broken) UI, so the CLI/backend write path is fine. Only the index is broken.
UI symptom
- Sidebar lists conversations as normal.
- Clicking any conversation shows "No messages yet" — including the one I am actively sending messages to.
- After restarting Claude Code on the desktop, no messages render at all.
Repro context
- Long-running conversation (~1000 lines, ~2 MB in the .jsonl).
- Closed the desktop window while SSH session was active.
- Reopened — broken state since.
Difference from #54187
#54187 (macOS local) reports sessions[] arrays per project go empty. In this SSH-remote case, the projects map is entirely missing (null). Possibly the same root cause hitting a different code path that writes through ~/.claude.json, or a separate bug masked as the same UI symptom.
What would help
Happy to share:
- Sanitized
~/.claude.json(after strippinguserIDand tokens). - Diagnostics on the active jsonl that keeps being appended to despite the broken index.
- Try a specific repro on request.
Workaround attempted
Reconstructing the projects map manually from filesystem scan was attempted but I want maintainer guidance on the exact expected schema (sessions array of {id, ...}? other required keys per project?) before writing to my own ~/.claude.json. Will report back if I find a safe regeneration script.
Showing cached comments. Read the full discussion on GitHub ↗
6 Comments
Same UI symptom (Linux remote, Windows client, v2.1.149) — but
projectsfield is intact here. Suggests rehydration bug is independent of the index corruption.Hit the same UI symptom in a different environment, but the root-cause hypothesis from the OP (nulled
projectsin remote~/.claude.json) does not apply in my case — the field is a healthy dict on both ends. So either there are two bugs producing the same UI symptom, or the null-projectscorruption is downstream of a more general rehydration failure in the SSH Remote code path.Environment
| Side | Detail |
|---|---|
| Local app | Claude Code Desktop 1.9255.2 (MSIX,
WindowsApps\Claude_1.9255.2.0_x64) || Local CLI sidecar |
claude.exe2.1.149.0 under%APPDATA%\Claude\claude-code\2.1.149\|| OS local | Windows 11 Home 10.0.26200 |
| SSH client | OpenSSH_for_Windows_9.5p2, LibreSSL 3.8.2 |
| Remote OS | Ubuntu 24.04.4 LTS (Noble), Linux 6.8.0-90 x86_64 |
| Remote CLI |
/root/.claude/remote/ccd-cli/2.1.149|| Remote cwd |
/root|UI symptom (same as OP)
After restarting Claude Code Desktop while connected to the remote project via SSH Remote, every conversation in the sidebar shows "No messages yet". Clicking any session yields the empty state. However: sending a new message does preserve context — Claude responds as if it had read the full prior transcript, even though the UI didn't render any of it. So the CLI side rehydrates fine, the UI side does not.
~/.claude.jsonis intact on both ends (key difference from OP)Remote (
/root/.claude.json):\
\\`python['cachedGrowthBookFeatures', 'unpinOpus47LaunchEffort', 'firstStartTime',
'opusProMigrationComplete', 'sonnet1m45MigrationComplete', 'seenNotifications',
'migrationVersion', 'userID', 'cachedExperimentFeatures',
'cachedExtraUsageDisabledReason', 'skillUsage', 'projects']
<class 'dict'>
['/root']
['allowedTools', 'mcpContextUris', 'mcpServers', 'enabledMcpjsonServers',
'disabledMcpjsonServers', 'hasTrustDialogAccepted',
'projectOnboardingSeenCount', ...]
\
\\`Local (
C:\Users\<user>\.claude.json):projectspresent, 402 entries, including the remote SSH project keyssh:root@<vps-ip>:~.So in my case the index in both files is valid — yet the UI still fails to render.
Server-side data is healthy
\
\\\$ ls ~/.claude/projects/-root/*.jsonl | wc -l
12
$ du -sh ~/.claude/projects/-root/
18M
\
\The active session's
.jsonlgrew from ~115 KB to ~474 KB during the diagnostic session in real time, confirming the CLI write path is fine. No malformed lines.Remote-server log on each Desktop restart shows a clean reconnect cycle
/root/.claude/remote/run/<id>/remote-server.log:\
\\\[Server] Connection closed: @
[Server] New connection from: @
[shellenv] Extracted shell PATH (117 chars)
[process.Manager] Process <uuid> started, PID=<pid>, command=/root/.claude/remote/ccd-cli/2.1.149
[process.Manager] Starting stdout streaming for process <uuid>
[process.Manager] Starting stderr streaming for process <uuid>
\
\A fresh CLI process is spawned per reconnect, but there is no event indicating the server replays the historical
.jsonlto the desktop client — only stdout/stderr streaming of the newly-spawned process. Matches the observed UI behavior.Local
main.log: app starts but no SSH-rehydrate eventTail of
%APPDATA%\Claude\logs\main.logimmediately after restart:\
\\\2026-05-28 09:25:19 [info] Starting app { appVersion: '1.9255.2', isPackaged: true, platform: 'win32', arch: 'x64', nodeVersion: '24.15.0' }
2026-05-28 09:25:19 [info] [CCD] Initialized with version 2.1.149
2026-05-28 09:25:19 [info] [growthbook] next refresh in 60 min
2026-05-28 09:25:19 [info] [IdleManager:session] Initialized with 900s timeout
2026-05-28 09:25:19 [info] [IdleManager:preview] Initialized with 1800s timeout
2026-05-28 09:25:19 [info] Not main instance, returning early from app ready
\
\No
SSH Remote-specific rehydrate log line is visible at info level around the restart. Happy to capture at debug level if there's an env var to enable it.Suggested narrowing
projectsmap valid on both ends — so the fix can't be only "defend against nullprojects"..jsonlvia RPC and silently drops the response, vs. relying onprojects[].sessions(which #54187 reports also goes empty).Can attach full
remote-server.log, sanitized~/.claude.jsonfrom both ends, and per-file jsonl line counts on request.Pinned the regression to a specific desktop version, plus a verified workaround. Environment: Claude Desktop for Windows (Microsoft Store/MSIX) + WSL2 remote, reproduced through current desktop 1.11847.5 / CLI 2.1.170. Same UI symptom as the OP, but like @Fasted93 my remote
~/.claude.jsonprojectsmap is intact — supporting the theory that the rehydration failure is independent of that index corruption.What's actually broken
The desktop UI renders chat history exclusively from local per-session mirror files on the Windows side:
These are byte-identical (prefix) copies of the real transcripts on the remote/WSL side. The app never falls back to reading the remote transcript: no mirror → "No messages yet", no matter how healthy the remote files are (
claude --resumeon the remote works fine throughout).On my machine a mirror directory was created for every new session up to Jun 3 04:53, then never again. The updater log (
%APPDATA%\Claude\logs\main.log) shows exactly one relevant event in that gap:Every session created before that update has a mirror and renders fine; every session created after has none and shows "No messages yet". Still broken in 1.10628.2, 1.11187.1, 1.11187.4, 1.11847.5.
Notably, mirror syncing still works — the app keeps appending to mirrors that already exist. Only mirror creation for new sessions stopped, and it fails silently (no errors in
ssh.log/main.log; the code path just never runs).⇒ Regression introduced in desktop 1.10628.0 (~Jun 3): per-session transcript-mirror creation no longer happens for remote (WSL/SSH) sessions.
Workaround (verified)
Since the app adopts mirrors that exist, seed them yourself. For one session, from WSL:
Fully restart the desktop app (quit from the tray too). History renders again, and the app resumes syncing that mirror on its own.
Script that seeds all sessions at once (idempotent; never modifies the remote-side transcripts — re-run it whenever a new session goes "No messages yet"): seed-claude-mirrors.sh
For SSH remote setups the mechanism is the same, only the copy crosses machines: pull each
<session-id>.jsonlfrom the remote~/.claude/projects/<project-dir>/into local%USERPROFILE%\.claude\projects\ssh-<session-id>\(scp/sftp), then restart the app.⚠️ Don't "fix" this by wiping the desktop app's data
%USERPROFILE%\.claude\projectsholds the only history the UI can render. Deleting it blanks your still-working sessions too — and reinstalling doesn't help, every build since 1.10628.0 has the regression.I can confirm this bug. Exact same issue and context (issue on claude desktop only, windows machine -- ssh --> wsl2)
Experiencing same bug.
Seems to happen to all remote (ssh) sessions after closing Claude Code.
[Windows (without WSL) -> Linux]
I found the cause (sort of) of this bug.
This bug does NOT happen when you use an ssh private key file.
It ONLY happens when you manually enter a password when prompted.
In fact, I had a connection I hadn't bothered to set up a private key for, upon restarting claude code, all history was lost.
But upon moving that connection to properly use an ssh keyfile, all the history reappeared!
I can confirm @1n5aN1aC solution works.