cleanupPeriodDays: 0 silently disables all transcript persistence (docs say it disables cleanup)
Description
Setting cleanupPeriodDays: 0 in settings.json completely prevents session transcripts (.jsonl files) from being written to disk. The schema documentation says 0 means "disable cleanup" (i.e., retain transcripts forever), but the actual behavior is "disable all transcript persistence."
Expected Behavior
Per the settings schema:
"Number of days to retain chat transcripts (0 to disable cleanup)"
Setting cleanupPeriodDays: 0 should mean "never clean up old transcripts" — transcripts should still be written and retained indefinitely.
Actual Behavior
The appendEntry method in the session storage writer has a guard clause that checks cleanupPeriodDays:
async appendEntry(T, R = getSessionId()) {
let A = process.env.TEST_ENABLE_SESSION_PERSISTENCE === "true";
if (getEnv() === "test" && !A || getSettings()?.cleanupPeriodDays === 0 || isSessionPersistenceDisabled()) return;
// ... write logic never reached
}
When cleanupPeriodDays === 0, the function returns immediately without writing any transcript data. This means:
- No
.jsonltranscript files are created /resumereports "No conversations found"SessionEndhooks receive an emptytranscript_path(the file doesn't exist)- All session history is permanently lost
The cleanup function correctly treats 0 as "don't clean up":
function cleanup() {
let retentionMs = ((getSettings() || {}).cleanupPeriodDays ?? DEFAULT_DAYS) * 24 * 60 * 60 * 1000;
// When 0, retentionMs = 0, effectively meaning nothing is old enough to delete
}
But appendEntry incorrectly uses the same field as a persistence toggle.
Impact
- Users who set
cleanupPeriodDays: 0intending to keep transcripts forever actually lose all transcripts /resumebecomes completely non-functional- Session hooks that depend on
transcript_pathget empty/nonexistent paths (related: #13668) - The data loss is silent — no warning, no error, no log
Steps to Reproduce
- Add
"cleanupPeriodDays": 0to~/.claude/settings.json - Start a new Claude Code session
- Have a conversation
- Exit the session
- Check
~/.claude/projects/{project}/— no.jsonlfile exists - Run
/resume— "No conversations found"
Suggested Fix
Remove the cleanupPeriodDays === 0 check from appendEntry. The cleanup period should only affect the cleanup/retention logic, not the write path:
// Before (broken):
if (getEnv() === "test" && !A || getSettings()?.cleanupPeriodDays === 0 || isSessionPersistenceDisabled()) return;
// After (fixed):
if (getEnv() === "test" && !A || isSessionPersistenceDisabled()) return;
Environment
- Claude Code: v2.1.34
- OS: macOS 15 (arm64)
- Shell: zsh
Related Issues
- #13668 (PreCompact receives empty transcript_path — same root cause for users with this setting)
- #18311
- #13872
12 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Real-world data loss caused by this schema contradiction
Today I lost all my locally stored sessions across every project because of this exact bug.
What happened: I asked a Claude Code instance to update my
settings.jsonto never auto-delete sessions. It read the JSON schema description ("0 to disable cleanup") and told me to setcleanupPeriodDays: 0. I confirmed. On the next Claude Code startup, cleanup ran and wiped all existing session transcripts. Every session created after that was silently never persisted to disk (the write path skips transcript creation when the value is0).I didn't notice until hours later when I tried to
/resumea session and got "No conversations found." By then, everything was gone. Months of work context, debugging history, implementation decisions -- all of it destroyed silently. This is user data.The irony: I was explicitly trying to preserve my sessions. The schema told me (via Claude) to do the exact thing that destroys them.
Partial recovery: I'm on Arch Linux with btrfs and snapper configured on
/home. I had 5 snapshots spanning Jan 17 - Jan 28. Because the defaultcleanupPeriodDaysis 30 days, each older snapshot contained sessions that had already been cleaned up by the time the newer snapshots were taken. By merging all 5 snapshots from oldest to newest, I recovered the majority of my sessions -- but everything from Jan 29 - Feb 6 is permanently lost, no snapshot covered that window:Important: merge oldest-first because earlier snapshots may contain sessions that were already cleaned up by the default 30-day policy before later snapshots were taken.
The bigger picture: This isn't just about
cleanupPeriodDays: 0. Myhistory.jsonlshows I've been using Claude Code since September 2025, but my oldest recovered session transcript is from December 2025. Three months of sessions (September - December) were already silently destroyed by the default 30-day cleanup before today's incident even happened. The0value just made the destruction immediate and total rather than gradual and invisible. See also #22547 which covers the broader data loss issue with default cleanup behavior.For other affected users: recovery depends on your filesystem:
zfs list -t snapshotfor snapshots of your home dataset~/.claude/projects/in Time Machine backups -- check multiple dates for the same reason.jsonlfiles, but this is unlikely to succeed in practice.Fix applied: set
cleanupPeriodDays: 99999. The schema description needs to be corrected to match the actual behavior -- or better, the code should be fixed so that0actually means "disable cleanup" as the schema promises.Confirming @Mustafa-Esoofally's experience:
With
"cleanupPeriodDays": 0set, new transcripts / sessions are not being stored—new sessions are missing from resume, etc.—unexpected behavior.(However, in my brief experience, it seems Claude Code did not delete pre-existing sessions [aged <30 days] at the time.)
[CC 2.1.56 | macOS 26.3]
Also repeating and confirming, as elsewhere, Claudes and users alike are being confused by the explicit contradiction between the official JSON schema for Claude Code settings:
and the Claude Code Docs > Configuration > Claude Code settings page:
Just lost months of convos with the value set to 10000, not sure its only a 0 issue.
What?? I saw the docs page first so I knew 0 was not going to be good, so I was going to go for 1000 or something. This is a terrible oversight. It kind of makes sense/explainable (not excusable) that they didn't plan for 10_000 (well, the company has not existed for that long) but if there is a bug that causes that to break things that's terrible.
Hit this on Claude Code 2.1.74, macOS Darwin 24.6.0 (Apple Silicon).
I had
cleanupPeriodDays: 0set to keep transcripts forever. I noticed nothing wrong until today, when--resumeand/resumeboth reported "No conversations found" after a full day of use.What I found:
~/.claude/projects/<project>/.jsonltranscript — onlysubagents/andtool-results/subdirssessions-index.jsonlast updated Feb 3, over a month staleThe schema says
"0 to disable cleanup". The docs say"Setting to 0 immediately deletes all sessions."The code does a third thing: skips writes entirely. Three sources, three different behaviors — all of them lose your data.At bare minimum, this should log a warning rather than silently discard transcripts. And
0should do what the schema says: keep everything.Repeating what I posted here: https://github.com/anthropics/claude-code/issues/22547#issuecomment-4058057305, this is seriously dangerous issue, user sessions should never be deleted without confirmation anyway.
@bcherny Can we at least fix the json schema docs before it destroys more users data ??
Same here. A Claude Code instance set
cleanupPeriodDays: 0trying to disable cleanup. lost all session transcripts across every project. Months of history gone. No way to recover.Same thing happened to me and I lost all my history. Why is this bug still not fixed?
I can't believe they're just leaving such a critical bug unfixed. At the very least, they could've added some kind of guard against the fatal state or put out an announcement when it was first reported. They could've avoided the whole issue just by fixing the documentation.
This was fixed in v2.1.89 —
cleanupPeriodDays: 0is now rejected as invalid (with an error shown in /status) instead of silently disabling all transcript persistence. If you're still seeing this in the latest version, please comment with your version and repro and we'll reopen.This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.