Skip to content

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

@Mustafa-Esoofally

Description

@Mustafa-Esoofally

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: PreCompact hook receives empty transcript_path #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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:corebugSomething isn't workingdocumentationImprovements or additions to documentationhas reproHas detailed reproduction stepsplatform:macosIssue specifically occurs on macOS

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions