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
This issue has 12 comments on GitHub. Read the full discussion on GitHub ↗