cleanupPeriodDays: 0 silently disables all transcript persistence (docs say it disables cleanup)

Status Fixed / completed
Maintainer reply ✓ Yes — ashwin-ant
Activity 12 comments · opened Feb 6, 2026 · closed Apr 18, 2026
💡 Likely answer: A maintainer (ashwin-ant, collaborator) responded on this thread — see the highlighted reply below.

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 .jsonl transcript files are created
  • /resume reports "No conversations found"
  • SessionEnd hooks receive an empty transcript_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: 0 intending to keep transcripts forever actually lose all transcripts
  • /resume becomes completely non-functional
  • Session hooks that depend on transcript_path get empty/nonexistent paths (related: #13668)
  • The data loss is silent — no warning, no error, no log

Steps to Reproduce

  1. Add "cleanupPeriodDays": 0 to ~/.claude/settings.json
  2. Start a new Claude Code session
  3. Have a conversation
  4. Exit the session
  5. Check ~/.claude/projects/{project}/ — no .jsonl file exists
  6. 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

View original on GitHub ↗

12 Comments

github-actions[bot] · 6 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/20612
  2. https://github.com/anthropics/claude-code/issues/13668
  3. https://github.com/anthropics/claude-code/issues/2543

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

bengous · 6 months ago

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.json to never auto-delete sessions. It read the JSON schema description ("0 to disable cleanup") and told me to set cleanupPeriodDays: 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 is 0).

I didn't notice until hours later when I tried to /resume a 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 default cleanupPeriodDays is 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:

# 1. List available snapshots
sudo snapper -c home list

# 2. Merge from oldest to newest (--ignore-existing means later data wins)
sudo rsync -a --ignore-existing /home/.snapshots/<OLDEST>/snapshot/<user>/.claude/projects/ ~/.claude/projects/
sudo rsync -a --ignore-existing /home/.snapshots/<NEXT>/snapshot/<user>/.claude/projects/ ~/.claude/projects/
# ... repeat for each snapshot, oldest to newest

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. My history.jsonl shows 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. The 0 value 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:

  • btrfs with snapper/timeshift/btrbk: check for snapshots as shown above -- merge ALL available snapshots from oldest to newest to maximize recovery
  • ZFS: check zfs list -t snapshot for snapshots of your home dataset
  • macOS Time Machine: look for ~/.claude/projects/ in Time Machine backups -- check multiple dates for the same reason
  • ext4/xfs/no snapshots: the data is gone unless you have a separate backup system. Do not write to the disk unnecessarily -- a forensic recovery tool might recover recently deleted .jsonl files, 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 that 0 actually means "disable cleanup" as the schema promises.

tnnrnet · 6 months ago

Confirming @Mustafa-Esoofally's experience:
With "cleanupPeriodDays": 0 set, 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]

tnnrnet · 6 months ago

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:

"cleanupPeriodDays": {
"type": "integer",
"minimum": 0,
"description":
"Number of days to retain chat transcripts (0 to disable cleanup)",
"examples": [
20,
30,
60
],
"default": 30
},

and the Claude Code Docs > Configuration > Claude Code settings page:

cleanupPeriodDays |
Sessions inactive for longer than this period are deleted at startup.
Setting to 0 immediately deletes all sessions.
(default: 30 days)
danieliser · 6 months ago

Just lost months of convos with the value set to 10000, not sure its only a 0 issue.

hesreallyhim · 5 months ago
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.

chrisvaillancourt · 5 months ago

Hit this on Claude Code 2.1.74, macOS Darwin 24.6.0 (Apple Silicon).

I had cleanupPeriodDays: 0 set to keep transcripts forever. I noticed nothing wrong until today, when --resume and /resume both reported "No conversations found" after a full day of use.

What I found:

  • 184 session directories under ~/.claude/projects/<project>/
  • None contain a .jsonl transcript — only subagents/ and tool-results/ subdirs
  • sessions-index.json last updated Feb 3, over a month stale
  • All conversation history gone, with zero warning

The 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 0 should do what the schema says: keep everything.

aszenz · 5 months ago

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 ??

seonglae · 5 months ago

Same here. A Claude Code instance set cleanupPeriodDays: 0 trying to disable cleanup. lost all session transcripts across every project. Months of history gone. No way to recover.

Ajido · 4 months ago

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.

ashwin-ant collaborator · 4 months ago

This was fixed in v2.1.89cleanupPeriodDays: 0 is 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.

github-actions[bot] · 4 months ago

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.