[BUG] Inherited CLAUDE_CODE_CHILD_SESSION silently disables all transcript persistence - total conversation loss on process exit

Resolved 💬 4 comments Opened Jul 3, 2026 by JackPayne123 Closed Jul 4, 2026

Summary

If claude starts with CLAUDE_CODE_CHILD_SESSION present in its environment (inherited, not set by the harness itself), it treats itself as a child session and silently never writes its transcript to ~/.claude/projects/<slug>/<session-id>.jsonl. The session looks completely normal - turns complete, hooks fire, sidecar dirs (<session-id>/tool-results/, ~/.claude/session-env/<session-id>/) are created - but the conversation exists only in process memory. When the process exits (or is killed), the entire conversation is unrecoverable, and claude --resume <session-id> reports:

No conversation found with session ID: <session-id>

There is no warning, error, or any on-disk artifact indicating persistence was disabled.

Environment

  • Claude Code 2.1.200 (macOS, Darwin 25.5.0, zsh)
  • cleanupPeriodDays: 99999 (retention cleanup ruled out)

Reproduction

cd ~/some-trusted-project

# A) control - clean env: transcript appears within seconds of the first turn
claude   # chat one turn -> ~/.claude/projects/<slug>/<id>.jsonl exists

# B) with the inherited var: transcript NEVER appears
CLAUDE_CODE_CHILD_SESSION=1 claude   # chat, complete multiple turns
# -> no <id>.jsonl after minutes of completed turns; only sidecar dirs exist
# kill the process -> conversation gone; --resume says "No conversation found"

A/B/C isolation (same directory, same command, interactive session on a PTY, one completed turn each):

| env | transcript written? |
|---|---|
| full env inherited from a Claude Code Bash tool | no (never) |
| same, minus all CLAUDE* vars | yes (~27 KB within seconds) |
| same, minus only CLAUDE_CODE_CHILD_SESSION | yes (~30 KB within seconds) |

How the var leaks in practice (why this is a real data-loss trap)

Claude Code exports CLAUDE_CODE_CHILD_SESSION (alongside CLAUDECODE, CLAUDE_CODE_SESSION_ID, ...) into the environment of Bash tool processes. Anything a session launches from there inherits it - including GUI apps: on macOS, open -a propagates the caller's environment to the launched app.

In our case, a Claude session rebuilt and relaunched a terminal-multiplexer app (an "agent board" that spawns claude in embedded panes). The app inherited the var and passed it to every pane. Every agent spawned in those panes ran for hours with zero persistence; an app restart then destroyed several conversations at once, hours of work each. Nothing in the UI or on disk distinguished these sessions from healthy ones until the moment they were gone.

The same trap applies to any wrapper, daemon, tmux server, or dev app that a Claude session (re)starts and that later launches claude.

Expected behavior

Some combination of:

  1. An inherited CLAUDE_CODE_CHILD_SESSION (i.e. the process is not actually a spawned child of the harness) should not disable transcript persistence for a top-level interactive session - or the marker should be something a plain env inheritance cannot forge, and cleared for user-facing interactive sessions.
  2. If persistence is intentionally disabled, say so loudly: a visible banner in the TUI and/or a refusal to start interactively, not a silent no-write.
  3. Sidecar artifacts are written to the real project dir either way, which makes the missing transcript look like deletion rather than never-written - consistent behavior would help diagnosis.

Actual behavior

Silent, total conversation loss on process exit, discovered only when resume fails.

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗