Silent retention cleanup deletes session transcripts with no warning, opt-in, or recovery
Summary
A user actively working in Claude Code (Cursor extension, anthropic.claude-code-2.1.141-darwin-arm64) lost the ability to resume, view, or recover all Claude Code conversation transcripts in a given workspace older than the current session, including a session from the previous day, because a built-in cleanup process silently deleted those transcripts from disk. The user received no prompt, no warning, and no Trash-style soft-delete. The retention setting (cleanupPeriodDays) was never surfaced, never set explicitly, and the observed retention behavior is inconsistent with the documented 30-day default — sessions newer than 30 days are still missing. When the user discovered the loss, the Cursor resume picker presented an empty workspace history, leaving the user with no in-product hint that data had ever existed there.
Specific concerns
- No consent prompt. Cleanup runs out of the box with no install-time disclosure or first-run dialog. Users who treat their conversation history as durable working knowledge are silently mistaken about the persistence model.
- No UI surface for retention.
cleanupPeriodDaysis documentation-only. There is no UI in Cursor's Claude Code extension or the CLI to view current retention, see when next cleanup will run, see what will be deleted, or cancel a pending cleanup.
- Hard delete, no Trash. Deleted transcripts go straight to
unlink(). No soft-delete folder, no grace period, no--restorecommand, noclaude restoresubcommand. macOS Trash is bypassed.
- Observed behavior diverges from documented retention. With a documented 30-day default and today's date 2026-05-14, sessions from 2026-04-14 onward should survive. In this workspace, the most recent surviving transcript material is 2026-03-04 — 71 days ago. Either the documented default is wrong, the cleanup uses a different rule (delete-on-extension-update, delete-on-session-end, delete-on-
/clear, delete-on-cursor-restart), or there's a separate deletion path triggered by something other than the 30-day timer.
- Subagent orphan pattern is a smoking gun. When the parent
<sessionId>.jsonlis deleted but the<sessionId>/subagents/subdirectory is left behind, the result is dead weight: tens of MB of subagent transcripts that reference a parent session that no longer exists, cannot be resumed, and are not surfaced in any UI. Either the cleanup should be transactional (delete the dir AND the subagents together, OR delete neither), or both should be retained.
- Cleanup is timed to session start — the worst possible moment. Running cleanup ~12 minutes after a Claude Code session starts means a user who opens Claude Code today to look up what they discussed yesterday triggers the very cleanup that deletes yesterday's transcript. The interaction is destructive at the exact moment the user most needs the data.
- Cross-version risk. The Cursor Claude Code extension updated on 2026-05-13 (the day of the lost session). The user attempted version rollback to recover — which had no effect, because the data lives in
~/.claude/and is not version-coupled. Anthropic should clarify whether extension upgrades trigger their own cleanup, and whether transcripts written by an older extension version are at risk on first run of a newer version.
- No telemetry or audit trail. No log of what was deleted, when, or why. A user has no way to confirm what they lost or build a case for restoration.
Suggested fixes
- Surface a retention disclosure on first run; default to longer or infinite retention until the user opts in.
- Add a soft-delete tier: move deleted transcripts to
~/.claude/projects/<workspace>/.trash/for N days before unlink, withclaude restoreto recover. - Make cleanup transactional: never delete a parent
.jsonlwhile itssubagents/directory still has content. - Don't run cleanup at session-start; run it on session-end, or on an idle timer that respects the "user just opened Claude Code" signal.
- Add an explicit log of cleanup actions to
~/.claude/cleanup.logwith timestamps and deleted file list. - Expose
cleanupPeriodDays(and acleanupEnabledboolean) in a settings UI, not just via JSON. - Reconcile documented vs. actual retention behavior; if reproducible, treat it as a bug.
Reproduction conditions
- macOS 25.5.0 (Darwin)
- Cursor IDE with Claude Code extension
anthropic.claude-code-2.1.141-darwin-arm64 - A
cwdcontaining a literal space (e.g.Chrome Extentions/proj-universal-capture-cursor) — produces dual slug variants under~/.claude/projects/. - No
cleanupPeriodDaysoverride in~/.claude/settings.json. - File of interest:
~/.claude/.last-cleanup(rewritten each cleanup pass; contains a single ISO timestamp).
On-disk evidence
~/.claude/.last-cleanupupdated 2026-05-14 13:13:20 PT (today). File born 2026-05-07.- 8 orphan
<sessionId>/subagents/directories survive in the affected workspace (Feb 12 – Mar 4 content, ~15 MB, 72 files), with no parent.jsonlfor any of them. ~/.claude/file-history/confirms 6 session UUIDs were active on 2026-05-13 — none of those UUIDs have any surviving session directory or transcript anywhere in~/.claude/projects/.- User's
~/.claude/settings.jsoncontains nocleanupPeriodDayskey — running on whatever the binary default is.
Timeline (2026-05-14 PT)
| Time | Event |
|---|---|
| 12:59:22 | First Claude Code session of the day starts (a different Cursor workspace) |
| 13:01:02 | Second Claude Code session starts in the affected workspace |
| 13:13:20 | Cleanup pass runs and updates .last-cleanup |
The cleanup runs ~12 minutes after session start. The deletion of yesterday's transcripts is most plausibly attributed to this pass.
37 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Thanks for the duplicate suggestions. I've reviewed the three referenced issues and want to flag this report as same bug family but with materially new evidence — please keep it open rather than auto-closing.
Cross-reference
cleanupPeriodDays: 99999was set and ignored. Lists "version upgrade reset" as suspected root cause.What this report adds that the three above do not
anthropic.claude-code-2.1.141-darwin-arm64). The three predecessors are all CLI. This widens the scope..last-cleanupmtime: the cleanup pass runs ~12 minutes after a Claude Code session starts. This is the worst possible moment — a user opening Claude Code to recall yesterday's session triggers the cleanup that deletes yesterday's session. Suggests the fix in #41458 root-cause analysis is on the right track (cleanup running before settings fully resolve, or in the wrong subprocess context).Ask
Please retain this issue and consolidate with #46621 / #41458 as part of an active investigation rather than closing as a duplicate. The new platform (Cursor extension), version (2.1.141), and timing evidence (cleanup-at-session-start, same-day-upgrade-correlation) materially advance the diagnosis. Happy to provide the full local forensic report on request.
Local forensic file path on the affected machine for cross-reference:
docs/transcripts/claude-code/2026-05-14_session-recovery-forensics.md+1, 1800+ husks on macOS, v2.1.150, default settings, May 24 cleanup wiped years of work. Have now spent 9+ hours debugging with no way to get them back. Claude code silently deleted all of my /project session jsonl files with no warning, no asking for permission. Then when claude code suggested filing a bug report here, it immediately got flagged by the bot saying it was a duplicate. So how many more people are living through this who are not being allowed to echo the issue here? This is more than an "oops". This is catastrohpic for long term development work if you aren't backing up your local files. I generally have no reason to - claude project files would have been the only reason. Who knew that anthropic would decide all of my chats with all of the logic, reasoning, decisions and why should just be deleted with no warning. I echo the user who said "whose files did they think those were anyway"?
It's wiping out MY DATA and hard work.
I hit this issue and built a recovery tool for the macOS + Time Machine case: https://github.com/garrettmoss/restore-claude-history
Some caveats re scope:
~/.claude/projects/. Doesn't touch Claude Desktop session storage (YET. Working on it.)The README also has the one-line
~/.claude/settings.jsonchange ("cleanupPeriodDays": 36500) that's supposed to defang the documented cleanup going forward. Worth setting even if you don't need recovery — (though per #41458 the setting isn't always honored, which is partly why a recovery path matters).Open to suggestions/fixes if needed.
Lost months of chat history on a personal project, and much else, on many different Claude "updates".
Filed #62250 with the same loss; folding it here as a duplicate. Adding the mechanism and a stopgap that complement this thread.
Deletion is keyed on file mtime, not the transcript's own last-activity timestamp.
cleanupOldSessionFilesinsrc/utils/cleanup.tswalks~/.claude/projects/<slug>/and callsunlinkIfOld, which deletes any*.jsonl/*.castwithstat.mtime < now - cleanupPeriodDays. Because mtime is externally mutable, anything that touches it flips the outcome: a restore (cp,tar -x,rsyncwithout-a), a sync client, or a script that sets mtimes to a session's true (old) last-activity date makes a present session look old, and it is silently deleted on the next sweep. (I hit exactly this: normalizing session mtimes for picker chronology made ~30-day-old sessions eligible and deleted 11.) Keying retention on the last in-file messagetimestampinstead of mtime would close this whole class of accidental loss.cleanupPeriodDays: 0is an overloaded footgun.getCutoffDate()with0returns now (deletes everything), andshouldSkipPersistence()treats=== 0as "don't persist". So the value that intuitively reads as "off" instead wipes all transcripts and stops writing new ones.The large-value workaround is not reliable (see #41458 / #45735): processes started with
--setting-sources local, or the SDK'ssettingSources: [](including autonomously spawned subagents), run cleanup that ignorescleanupPeriodDaysfrom~/.claude/settings.jsonand fall back to the default 30. SocleanupPeriodDays: 999999does not protect anyone who runs subagents or SDK sessions.A
SessionStartbackup hook is a nice stopgap until this is fixed: it copies transcripts out of the deletion path, independent of the buggy setting. The on-disk JSONL is append-only (/rewindorphans a dead branch and keeps appending; it does not shrink the file), so one high-water-mark backup per file is lossless: copy only when the backup is missing or the live file has grown. Keying on grew-only (not mtime, not size-differs) makes it both mtime-immune and shrink-safe.~/.claude/hooks/backup-sessions.sh:~/.claude/settings.json:Even if cleanup deletes a transcript, the latest state survives outside
~/.claude/projects/.Fix directions echoing this thread: retain by the in-file last-activity timestamp (not mtime); archive or trash instead of
unlink; make it opt-in or use a much longer default; and make the restricted-setting-source paths honorcleanupPeriodDays.---
Already lost sessions to this (on ext4)? An after-the-fact recovery toolkit - volatility-ordered: stop writes, dump live
claude --resumeprocess memory + webview state, take backup/ext4-journal wins, then raw-disk carve + journal-extent recovery - is at ojura/claude-skills (recover-deleted-sessions-ext4). It's triage, not a fix; theSessionStartbackup hook above is what keeps you from needing it.@ojura — thanks for the mtime/cleanup analysis above, it's the most informative comment I've seen so far. I've updated my repo's notes to credit it (and walked back some over-confident framing as a result): https://github.com/garrettmoss/restore-claude-history/blob/master/NOTES.md#why-updates-seem-to-trigger-this
Your
SessionStarthook is the right shape for forward-looking backup, which is the gap my Time Machine recovery tool doesn't fill (yet). I'd like to use it as the reference implementation for abackup_claude_history.pyalongside the restore script — credit you, link this comment, then extend with a CLI, restore-from-backup verb, retention policy, etc. Want to be involved (co-author, reviewer, anything), or happy for me to just run with it and credit?Also noticed your repo
claude-patches— that's a separate impressive rabbit hole. Likely not too much overlap with what I'm doing but good to know it exists.@garrettmoss sure, I will have my Claude talk to your Claude 😁
Adding a data point on scope, because this one hurt.
On macOS,
cleanupPeriodDayswas never surfaced to me — I found out only when/resumecame up nearly empty. On disk: 773 session folders, but only 132 surviving.jsonltranscripts. Roughly 640 conversations spanning January through mid-May were silently deleted, each leaving an orphanedsubagents//tool-results/folder behind. Like the OP, my observed retention was far shorter than the documented 30 days — survivors only go back about a week.No warning, no soft-delete, no recovery path: no Trash, and any backup or snapshot I had postdated the deletion. The only thing I could partially salvage was the prompts I'd typed (from
history.jsonl) — none of Claude's actual work.Months of context, gone with zero notice. Please make this opt-in, or at minimum warn before deleting and soft-delete to Trash rather than unlinking. Thanks for tracking this.
@KirkPX have a look at the .jsonl carving skill in ojura/claude-skills, it might save some chats.
Adding a Windows Desktop data point.
Lost two sessions in the same project (
Billy AI FishandBilly AI Fish 2, 44 and 52 days old) to today's startup cleanup on Claude Code Desktop 2.1.156 / Windows 11. Both were explicitly maintained as long-running reference threads — the verbatim chat was active continuation context for ongoing hardware/software work on a Raspberry Pi side-project, not idle scratch.After the cleanup, the sidebar shows "Sitzung nicht auf dem Datenträger gefunden" ghost entries (same symptom as #62959). The
.jsonlfiles in~/.claude/projects/<project>/and the corresponding%APPDATA%\Claude\local-agent-mode-sessions\<workspace>\<project>\local_<sid>\.claude\projects\…paths were already unlinked, with no Recycle Bin entry (cleanup usesfs.unlink).Two concrete points for the fix discussion:
cleanupPeriodDays: 0is rejected by schema validation with a message recommending a large number instead (workaround:36500). That validation error is currently the only place the workaround is documented — discoverable only after data loss. Accepting0as the intuitive "never clean up" value would close a real UX gap at effectively zero cost.MEMORY.md/project_*.mdfiles under~/.claude/projects/<project>/memory/survived and made partial reconstruction possible — genuinely good design. But a curated summary isn't a substitute for the verbatim flow that captures why particular decisions were made; you can rebuild the what from memory files, not the reasoning behind tried-and-rejected approaches.Strong +1 to soft-delete to the OS Recycle Bin, UI exposure of
cleanupPeriodDays, and a pre-cleanup warning with per-session pin.I need this fixed. Claude is literally destroying work information I have generated with my tokens. This is an unacceptable state.
Thanks @ojura — your
unlinkIfOld/ mtime analysis (and the--setting-sources local/settingSources: []override that defeats a highcleanupPeriodDays) is the clearest root-cause account on this bug — and @garrettmoss for the open-source recovery script.A couple of data points and one ask, observed on
claude-opus-4-8/ Claude Code, 2026-05-30 (default config, nocleanupPeriodDaysset):~/.claude/projects/so cleanup can't reach it. (Without a prior backup it's filesystem carving, per @ojura / @garrettmoss — far harder.)For breadth, the documentation gaps are tracked separately from this bug: #51779, #38576, #63777 (cleanup-scope omissions) and #63842 (session pinning).
One ask of Anthropic: before any delete, prompt for consent or move files to the OS trash/Recycle Bin (or a
~/.claude/trash/grace area) — and makecleanupPeriodDayshonoured by all setting sources, including SDK-spawned subagents (the gap @ojura identified). An optional export-on-cleanup (a compact JSONL/MD snapshot at deletion time) would make even an expired session recoverable.I was surprised by this today - I've only been using Claude Code for a bit over a month, luckily I made backups (for the purposes of using cross coding agent search) but this should definitely be surfaced without having to do a Q&A with Claude.
and when I pressed further...
For users wanting an independent recovery layer before this is fixed: Clean My Agent (I'm the author) backs up and exports session JSONLs before any cleanup pass runs.
Corroborating with an independent case, plus a primary-source timeline of how this behavior and its disclosure evolved (claude-code
CHANGELOG.md, npm publish timestamps, and Wayback Machine snapshots of the docs).Another independent data-loss case
cleanupPeriodDayskey in any settings file — binary default in effect.~/.claude/.last-cleanupconfirms the sweep runs at session start, consistent with this issue's observation (it even ran mid-investigation when a stray CLI invocation spawned a session).~/.claude/plans/that a surviving 2026-06-09 transcript references as existing was gone by 2026-06-12, while a newer plan file (mtime 2026-05-30) survives — consistent with an age-based sweep of~/.claude/plans/that I cannot find in any changelog entry or documentation. Maintainers: please enumerate the complete set of paths the retention sweep touches.Transcripts are load-bearing data — by the product's own design
The strongest argument that silent deletion is wrong here isn't any individual workflow; it's that Claude Code itself treats transcripts as durable data and builds features on top of them:
--resume,--continue, and/forkare transcript-backed — the resume picker is an implicit promise that history persists.A system that encourages building a knowledge substrate on these files, then deletes that substrate on a rolling 30-day fuse without telling anyone, is internally contradictory. Transcripts are not cache; the artifact records what was decided, the transcript is frequently the only record of why.
Verified timeline (CHANGELOG.md + npm publish dates + Wayback)
| Date | Version | Event |
|---|---|---|
| 2025-05-17 | v0.2.117 | Changelog: "Introduced settings.cleanupPeriodDays" — the deletion behavior ships |
| 2025-06-15 | — | Wayback,
docs.anthropic.com/en/docs/claude-code/data-usage: sole disclosure is "Users' local Claude Code clients may store sessions locally for up to 30 days so that users can resume them. This behavior is configurable." — framed as a privacy reassurance ("up to 30 days"), not a data-loss warning; setting not named || 2025-09-03 | — | Wayback: "Local caching" bullet appears on the same page; still "(configurable)" with no setting name |
| 2026-03-24 | v2.1.83 | "Fixed tool result files never being cleaned up, ignoring the
cleanupPeriodDayssetting" — sweep scope grows || 2026-03-31 | v2.1.89 | "
cleanupPeriodDays: 0… rejected with a validation error — it previously silently disabled transcript persistence" — the only "keep forever"-adjacent value removed; minimum is now 1, retention-forever requires an arbitrarily large number || 2026-04-10 | v2.1.101 | "Fixed
--setting-sourceswithoutusercausing background cleanup to ignorecleanupPeriodDaysand delete conversation history older than 30 days" — a confirmed fail-destructive path: when settings resolution fails, cleanup falls back to the 30-day default and deletes. This corroborates #41458 (explicit99999setting, 490 sessions deleted anyway) || 2026-04-15 | v2.1.110 | "Fixed session cleanup not removing the full session directory including subagent transcripts" — confirms the orphaned
subagents/dirs documented in this issue were the sweep's doing, and the fix was to delete more, not to warn || 2026-04-21 | v2.1.117 | "The
cleanupPeriodDaysretention sweep now also covers~/.claude/tasks/,~/.claude/shell-snapshots/, and~/.claude/backups/" — a directory named backups is now age-swept || 2026-04-30 | v2.1.126 |
claude project purgeadded with--dry-run,-i,-y— the manual deletion path gains exactly the safety affordances the automatic path still lacks || Apr 1 – May 6, 2026 | — | Wayback bisection of
code.claude.com/docs/en/data-usage: the namecleanupPeriodDaysfirst appears on the user-facing data page in this window — ~11 months after the behavior shipped, and only after #41458/#46621 were filed |Two structural points fall out of this timeline:
/en/data-usageis about Anthropic's server-side data handling; client-side destruction of local files is buried inside it, originally phrased as a privacy guarantee ("up to 30 days"). A user asking "will Claude Code delete my files?" would never look there — and for the first year, the page didn't name the setting that controls it.On the suggested fixes
Everything in this issue's list, with two points sharpened:
--setting-sourcesconfigurations, subprocess environment), cleanup must be skipped, not defaulted to 30 days. A?? 30fallback in a deletion path converts every settings-resolution bug into permanent data loss.unlink; a cleanup log of what was deleted when.Workaround status (for others landing here)
is schema-valid and is honored on 2.1.175 — verified empirically: a transcript aged exactly 30 days survived a cleanup pass that ran after the setting was added. But per #41458 and the v2.1.101 changelog entry, a large value is not a guarantee — any settings-resolution failure reverts to fail-destructive defaults. The only real protection today is external backups of
~/.claude/projects/.---
Transparency note: this comment was researched and drafted by Claude Code itself (Claude Fable 5), at my direction and with my review — the changelog mining, npm timestamp mapping, and Wayback bisection above were agent-performed. The loss was discovered the same way: the agent went looking for artifacts from its own past sessions and found the transcripts already deleted.
This bug is non-sense. Please either (1) make auto deletion opt-in with "keep forever" as the default, (2) prompt the user before deleting anything, or (3) show a clear warning in settings. Real failure case: take parental or medical leave for more than 30 days, come back, everything is gone.
+1, and I want to underline the "no warning" part. I lost 201 sessions to cleanupPeriodDays with zero indication that a deletion was pending or had already happened. I only found out when I went looking for an old session and it was just gone.
A couple of concrete follow-ups from my own run-in with this:
1. A minimal warning would have prevented my entire loss. It does not need to be fancy. Even a startup line like:
with a daily reminder until deletion would be enough. The issue is not that cleanup exists, it is that it is silent and irreversible. A 7-day heads-up with a one-key escape hatch turns a data-loss event into a non-event. Alternatively, users could "pin" certain sessions to mark them safe from deletion.
2. The mtime keying punishes your most valuable sessions. Cleanup keys on file mtime, so the sessions most likely to get deleted are the long-lived, high-context ones that have been sitting on the back burner. Not touched recently, but definitely not meant to disappear. "Dormant" is being treated as "disposable," and those are often opposites (research threads, long-lived reference and analysis work, architecture discussions you come back to once a month).
3. Partial-recovery workaround if you already got hit: your typed prompts survive even after the transcript is gone, because
~/.claude/history.jsonlis not part of the cleanup sweep. Group its entries bysessionIdand you can rebuild your half of every deleted conversation. The assistant replies are gone, but the prompts bring back a surprising amount of context. I used this to salvage 201 deleted sessions. It is a workaround, not a fix, and it should not be necessary.Agree with @ProIcons on the core point:
These are the user's files on the user's machine. Whether and when they get deleted should be the user's call, not a silent default. Automatic tidying is fine as a feature. It is not fine as a default, and it really should not be the fallback when settings fail to resolve (the fail-destructive path in the v2.1.101 changelog shows that is a real code path, not a hypothetical).
Getting consent is cheap. Prompt once on first startup after the feature lands (which also covers upgrades of existing installs), or at the very least right before the first pass that would delete anything. Give two clear choices ("keep everything" or "clean up after N days") and delete nothing until the user picks one. Warnings, previews, and soft-delete all help, but they are patches on a default that should not exist. Ask first and this whole category of "my sessions just vanished" reports goes away.
Just got hit by this in #62476 . I'm flabbergasted this is still unfixed after 2 months.
How is deleting the user's conversation history without their consent okay??
Another data point: lost a 239-prompt session spanning 3+ weeks of work (May 11–Jun 5) on macOS — returned to resume it on day 34 and the transcript had been silently purged. Nothing in Trash, no archive, no recovery; only my prompts survived via history.jsonl. Also filed #76173 with concrete proposals (soft-delete to archive > startup warning + confirm > minimum: deletion log + a hint in the resume-failure message pointing at cleanupPeriodDays).
Session transcripts never written to disk (not deleted) — 4 long sessions lost in one day, Windows 11
I lost 4 session transcripts on the same day. The signature overlaps with this issue (orphaned
subagents/directories,cleanupPeriodDaysnot protecting), but I have one piece of evidence thatpoints to a different mechanism than deletion, so I'm posting it here in case it helps narrow this down.
Environment
cleanupPeriodDays: 365What was lost
A census of ~90 projects / 2323 transcripts found exactly 4 orphaned session directories
(directory present,
<sessionId>.jsonlabsent) — all from the same day, across the 2 projects workedthat day:
| sessionId | duration |
|---|---|
|
b21d6a4d-…| 13:35 → 18:38 (~5h) ||
004077ca-…| 14:15 → 19:16 (~5h) ||
8555a0a7-…| 18:38 → 20:32 (~2h, process alive until 21:33) ||
21ae8066-…| 19:54 → 20:37 |All four are the long sessions of that day. In one of the two projects, 13 short sessions
interleaved in the same hours survived intact. No other transcript is missing anywhere on the system.
The key evidence: the file was never on disk
A VSS shadow copy taken at 16:43 that day — i.e. 3 hours into session
b21d6a4d, while it wasactively running and still had 2 hours to go — contains the project's other 22
.jsonlfiles butnot
b21d6a4d….jsonl.So this is not an
unlink()that happens late in the session, and not a cleanup pass that ranafterwards. The transcript was already absent from disk while the session was healthy and running,
and it never reappeared. Backups running at 13:46, 14:00, 18:52, 19:42 and 19:48 never captured it
either (the mirror is append-only and never purges, and it did capture other live sessions'
.jsonlfiles while they were being written — so "file was locked, robocopy skipped it" is ruled out).
Correlated:
history.jsonlstopped persisting at the same time~/.claude/history.jsonlhas zero entries for all 4 sessionIds. Its last record that day is at13:44:46, and nothing more until the following day — despite continuous work across three
projects until at least 21:33. The shadow copy confirms this: the 16:43 snapshot of
history.jsonlhas mtime 13:44 and is byte-identical to what survives today.
The discriminating pattern
What was lost is exactly the set of files Claude Code keeps open in append mode for the lifetime
of the session: the 4 transcripts + the corresponding window of
history.jsonl.100% of what is written open→write→close survived, including writes at 20:38 in the very same
session directories:
subagents/*.meta.json,tool-results/(PDFs, images, txt),file-history/,security/,tasks/.This is why I think it's worth distinguishing from a delete-based explanation: nothing was deleted,
the long-lived append writes simply stopped landing on disk.
Ruled out with direct evidence
<uuid>.jsonlwhile leaving the sibling<uuid>/directory untouched.robocopy SRC DEST /MIR /XX;/MIRand/XXact on the destination only, robocopy never writes to the source. No/MOV,/MOVE,unlink,rmanywhere in hooks/scripts.cleanupPeriodDays— set to 365. Also, per the docs the age-based cleanup removes the.jsonltogether with itssubagents/; the subdirectories surviving indicates that path did not run.Not available
The NTFS USN journal had already rotated (32 MB circular) by the time I investigated, ~1 day later,
so I could not confirm or rule out a
FILE_DELETErecord. Worth noting for anyone else debugging this:pull the USN journal immediately — it's the one source that would settle delete-vs-never-written.
Impact / mitigation
No work was actually lost, because conclusions were written to files during the session rather than at
the end. But the session's reasoning is gone, and a SessionEnd backup hook cannot protect against
this — the file never reaches disk, and in an abnormal termination the hook doesn't even fire (the
8555a0a7process was alive at 21:33 and its SessionEnd never ran).Detection that would have caught it same-day: check for session directories that have no sibling
<sessionId>.jsonl. Happy to share the script.This needs to be an opt-in feature rather than opt-out, both in the setting itself, and even if I want to use a 30-day "cleanup" (I don't), it should ask me anytime it wishes to delete this important information.
and NEVER delete log files that are outside the scope of a project. If I'm working in Project A with Claude Code, then the only log files (if any) that are removed should be from Project A, not from other projects.
It should also be possible to use
/configor some mechanism to see the setting that Claude is using. Deleting files is a "dangerous" operation and if we have the wrong spelling ofcleanupPeriodDayswe need a way to make sure that the setting is being read as expected.Was hit by this today too... Pretty bummed about it to say the least...
Just devastated by the loss of certain conversation transcripts that I had planned to share with people. How could a company make a decision to delete all of their customers data, irreversibly, without notice? That's wild. They must not have any lawyers.
Hey ojura, I have seen the same failure after a restore: the transcript is present, then the next cleanup pass treats its old mtime as the retention signal. A copy keyed on file growth avoids making the backup decision from that timestamp.
I built
BasedGPT/claude-code-session-recoverywithbackup_claude_state.pyfor keeping the Desktop metadata and~/.claude/projects/transcript layers together, andsession_watch.pyto flag a transcript that disappears or shrinks between starts. For an existing machine, runpython tools/diagnose.pyfirst and follow the exact command it prints. Before restoring an archive, setcleanupPeriodDaysto36500, then restore the files and complete the printed metadata step. That is a safeguard for the ordinary cleanup path, not a fix for the restricted setting-source cases you listed.The grew-only hook you sketched is a useful stopgap because it keeps the latest transcript copy outside the cleanup path without relying on mtime.
Hope this helps, if my tools are able to help you, would appreciate a ⭐ :)
Reproducing this today (2026-08-05, Claude Code CLI). No
cleanupPeriodDaysoverride was set — default 30 applied. The oldest surviving transcript across every project in~/.claude/projects/was dated exactly 30 days prior to the check, boundary-precise, matching the pattern others have reported here.The actual issue for me isn't a UI quirk, it's that my own work is just gone. Design discussions, debugging context, the reasoning behind decisions — deleted by a background sweep on startup that I never opted into and was never told about. I only found out because I went looking for a conversation from a couple of months back and it wasn't there. Given how many people in this thread only discovered the cutoff after already losing work, I'd add my voice to the ask: disclose this on first run, and don't destroy data silently with no confirmation.
These session rollup jsonl's have cost BILLIONS USD to produce; Paid with clients money either via subsidized subscriptions, or at actual API pricing - potentially costing tens of thousands of USD in API costs per user. These transcripts contain a treasure trove of mineable knowledge and insights. They also serve as a proof of work, justifying the spend. Someone else who ultimately footed the bill may at some point want to audit the user to confirm how the tokens were spent.
Plus this: https://github.com/anthropics/claude-code/issues/62272
Claude Code has no right to default auto-delete valuable data belonging to the user, produced through an expensive service paid by the user.
The only correct solution is to archive (move and zip by month) not discard old JSONLs, unless configured otherwise.
It is possible that Anthropics is intentionally defaulting to a short cleanup to limit outstanding traninign data available in the wild that can later be harvested and used for training by their competitors, while they retain their own copy at their end. This is disgusting.
Pretty much everyone has voiced my thoughts here... this is a massive violation of trust, a huge violation of what should be allowed on a personal computer, and hundreds of hours of lost discussions, work, and context that I will never be able to recover. To find this out, as others have said with ZERO prompt, warning, or even knowing that this was a thing before I went back to work on a project from last month and finding out everything was gone just astounds me.... This never even crossed my mind as a possibility it is so absurdly a violation of anything that is even remotely appropriate for a software product to do. At a minimum, this should be a prompt, an alert, a "delay for 1 week" , being able to turn it off, being able to change the schedule, flat out part of the setup process and for gods-sake the default should have been OFF to begin with. I have months of work now that is gone, with no way to recover those transcripts or details (surprise, I use Claude Code for a lot more than just Coding!) and.... I'm this sets me on serious levels of anger, hate, and depression. ...And, yes I have backups with Time Machine, no I dont keep months worth because my backup is for me to restore if it's stolen, busted, dropped, or damaged beyond repair... NOT because I assume that a software product is going to delete my work history whenever it wants. This is just absolutely insane... You could almost expect this from the web chat version of Claude where they have to store your data, but NEVER expect this to happen on your own computer.
Keep an outside copy of
~/.claude/projects/before the next cleanup pass. I have seen this class of loss happen when cleanup treats a transcript's filesystem mtime as its age: a restored.jsonlcan look old even when it was just copied back, so the next pass removes it again.I built
BasedGPT/claude-code-session-recoverywithbackup_claude_state.pyto snapshot both the Desktop metadata directory and~/.claude/projects/, andsession_watch.pyto flag a transcript that disappears or shrinks between starts. Runpython tools/diagnose.pyfirst on the current machine and follow the exact command it prints. If you restore from Time Machine or another archive, setcleanupPeriodDaysto36500before extraction, run the printed metadata step, then restore your normal value. That protects the ordinary cleanup path; it does not address the restricted setting-source cases described here.For ongoing protection, schedule the backup outside
~/.claude/projects/and keep the copy keyed on file growth, not mtime. That gives you a recoverable copy if cleanup runs again while the upstream retention bug is still present.Hope this helps, if my tools are able to help you, would appreciate a ⭐ :)
A data point and a reframing, from someone who hit this yesterday.
The data point. While auditing my own
~/.claude/projects/I indexed the directory, workedfor about 90 minutes, and re-indexed. Two transcripts had been deleted in between — 14 and
15 July, while I was actively working on that directory. No prompt, no warning, nothing in
the log. I only noticed because I happened to be comparing two counts taken either side of it.
So "silent" is stronger than it sounds: the deletion can happen mid-session, to files you are
in the middle of using, and the only way to know is to have measured before and after.
The reframing. Most of the discussion here is "how long should transcripts be kept", and
the counter-argument to a long default is always exposure — the files are plaintext and they
contain whatever was on screen. In my case that was real: an audit recovered live Azure storage
keys, a SQL admin password and a Twilio token from mine, none of which I had ever typed. They
arrived as tool output.
But that trade only exists because the archived copy has to hold the raw text. It doesn't.
I built a redacting archiver over my own transcripts: patterns plus hash-matching of
known-revoked values, writing gzipped copies to a separate host. 113.8 MB → 48.1 MB, one
afternoon. Verification: a rotated password appears in 18 live files and 0 archived ones,
while control phrases survive 38/38 and 27/27 — secrets gone, content intact. That copy can be
kept indefinitely without the exposure objection applying to it, which turns "30 days or
forever" into a much less interesting question.
Two things I'd have wanted to know before building it, in case anyone else tries:
files, because every pattern assumed
key=valueshape and it also appeared in prose("the plaintext password
<value>for SQL login"), which matches nothing. Secrets getdiscussed, not just configured.
keys; it had matched
dust-ma|sk-filtersandri|sk-and-environment.pdf.I've filed the redaction side separately as #86707 rather than pile it onto this thread, since
this one is about the deletion behaviour. Not asking for anything here — just adding the
mid-session-deletion observation, and the note that redaction changes the shape of the
retention argument rather than picking a side in it.
TL;DR - this "purge" feature is rude... You should always let devs know when you're about to destroy their work, and ask for permission/confirmation. I've lots months of important work.
---
I just came back from a month's leave and got hit by this twice! Once at home, and then again at work!
At home, I didn't realise what had happened... I opened
claude agentsand heaps of my convos were missing.I didn't really think anything of it at the time... just thought "gee it's going to be really annoying finding the convos to reopen". I was still on holiday mode... so didn't do any investigation into the matter...
Then the same thing happened at work!
Luckily, I created a Claude crash recovery script/prompt, which keeps track of conversations that I don't explicitly close myself so I can easily find and reopen them after a computer restart or crash! Except when I ran it, Claude told me there were no transcripts matching the conversation ids being tracked! "Wtf!" I thought... and began to Google. This is when I learned about the retention/purge policy. 30 days! FFS!
I'm freaking devastated!
I've had convos going for months working on architectures and ideating and brainstorming... and now it's all lost!
Not just the brainstorming.... but also all the decisions made while implementing features, and all the techniques learned along the way now lost!
It's all just gone! I'm back at square one, besides the things I remember or had materialised into code or issues.
It's very rude behaviour/functionality! Not in the least helpful.
At the very least, ask!
"Hey, you have some very long and old convos that haven't been touched in 30 days. Here's the list... if you want me to delete any, just click the checkbox next to the convo, to confirm the delete"
A possible glimmer of hope...
The convos that I enabled remote access are still on my phone app!
I can't interact with them because the convos no longer exist on my computer, but at least I have them for the time being....
I just hope they don't get wiped too before I have a chance to copy and save them.
for those still being impacted by this issue, I have written a comprehensive cli tool (complete with an easy to use tui) which can recover/restore lost sessions (best effort reconstruction from jsonl), transplant sessions from one local dir to another (rehome a project and its sessions resume cleanly from the new location), and sync everything to a safe local destination, as well as periodic backup via git (optional git-crypt) with support for remote backends (github or any other git remote server)
even outside recovery it's extremely useful as a general session explorer (as the tui is called).. see where every session on your machine lives, project by project, which are backed up, stale, or lost, and jump back into any of them with one key
also has ai powered session search and reconstruction with your choice of model (claude, codex, or fully local via ollama)
this is a proper maintained project, not a quick script.. tested, versioned releases, self-updating, works for both claude code and codex
https://github.com/rexovas/session-protect
brew install rexovas/tap/session-protectorcurl -fsSL https://get.rexov.as/session-protect | shon the redaction concern raised above.. personally, I feel that's not the domain of a backup/explorer tool, it's the domain of claude code itself (hooks are the right layer, scrub secrets at write time before they ever hit disk, rather than after the fact).. a backup tool that rewrites your transcripts is a backup tool you can't fully trust, so this tool deliberately backs up exactly what the agent wrote, byte for byte (git-crypt encryption covers the case where backups leave your machine)
@br3nt give it a try to reconstruct your lost sessions.. the tool surfaces all lost sessions on your machine and can rebuild them into resumable ones
@codebytere-ant @bcherny can you please look into this? This seems like really bad defaults, also quite some duplicates, and user trust is lost by setting those silent defaults.