You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Claude Code session JSONLs form fork chains. New session files are minted in two scenarios (verified empirically and by source reading):
/branch slash command -- mints forkSessionId = randomUUID(), copies source messages with forkedFrom: { sessionId, messageUuid } into a new file (commands/branch/branch.ts:61-160 in claude-code source).
--fork-session CLI flag on resume -- writes source messages into a new file using the startup-minted ID, with the same forkedFrom pointer on line 1 (utils/sessionRestore.ts:436-463).
Each fork's first line is a compact_boundary row carrying forkedFrom: { sessionId, messageUuid }. csb currently treats every UUID as an independent session. The chain relationships are invisible in csb list, csb show, and the SQLite index.
For long-running thread of work that has been forked multiple times, this means:
csb show <uuid> says nothing about what session this was forked from.
csb show <uuid> says nothing about whether any forks-of-this-session exist.
csb rebuild-index correctly populates the columns for existing sessions.
csb show <uuid> displays parent and forks when present.
csb chain <uuid> walks ancestry + descendants.
Test fixtures: a 3-deep chain (parent + child + grandchild); independent sessions; fork with multiple children.
CHANGELOG entry under ### Added.
README docs for new schema + commands.
Design considerations
Microcompact never forks.services/compact/microCompact.ts and services/compact/apiMicrocompact.ts contain no randomUUID or switchSession calls. Chain detection can ignore microcompact rows.
/clear produces a new sessionId but no forkedFrom./clear is logically a fresh-start, not a fork. The line-1-forkedFrom discriminator handles this correctly: a /clear-cleared session's line 1 won't have forkedFrom, so is_fork=false.
Compaction in-place (the common case) writes a compact_boundary row at row N>1 without forkedFrom. No fork detection triggered. Correct.
Fork-of-rehomed-session (interaction with dz claude-rehome): if a session has been rehomed via hardlink to a different project-dir slug, its forks (created via /branch afterwards) will land in getProjectDir(getOriginalCwd()) -- the cwd-derived dir, not the rehomed dir. csb's chain walker should follow parent_session_id regardless of which project-dir slug the parent or child lives in. The walk is by UUID, not by location.
Refs djdarcy/dazzle-claude-code-history-viewer#? (chain-aware timeline view) -- CCHV-side complement; depends on csb chain-awareness for the data model.
Analysis
Detailed empirical baseline + source citations:
notes/architecture/2026-05-04__14-47-31__both_claude-code-session-fork-chain-and-compaction-model.md -- the data model, the 4-deep AMD_INTIGRITI chain, claude-code source citations
notes/architecture/2026-05-04__18-37-44__senior_q2-q3-q4-claude-code-session-internals.md -- session-ID minting inventory (only bootstrap/state.ts:331 and commands/branch/branch.ts:68 mint sessionIds in normal use), switchSession semantics, microcompact non-fork confirmation
notes/cli/2026-05-03__15-43-24__both_csb-start-at-semantics-and-folder-listing-config.md -- the originating UX investigation
Originating session reference: DAZZLECMD__fix-broken-claude-code-session (2026-05-03/04). The chain phenomenon was discovered while diagnosing why the AMD_INTIGRITI session was unresumable; the chain itself is what made the slug-vs-cwd divergence visible.
Problem
Claude Code session JSONLs form fork chains. New session files are minted in two scenarios (verified empirically and by source reading):
/branchslash command -- mintsforkSessionId = randomUUID(), copies source messages withforkedFrom: { sessionId, messageUuid }into a new file (commands/branch/branch.ts:61-160in claude-code source).--fork-sessionCLI flag on resume -- writes source messages into a new file using the startup-minted ID, with the sameforkedFrompointer on line 1 (utils/sessionRestore.ts:436-463).Each fork's first line is a
compact_boundaryrow carryingforkedFrom: { sessionId, messageUuid }. csb currently treats every UUID as an independent session. The chain relationships are invisible incsb list,csb show, and the SQLite index.For long-running thread of work that has been forked multiple times, this means:
csb show <uuid>says nothing about what session this was forked from.csb show <uuid>says nothing about whether any forks-of-this-session exist.csb resume <uuid>(when it exists, per Alpha CLI launcher for claude-code-history-viewer -- csb view (Alpha #3) #14) cannot warn the user that they are resuming a session with active forks (which would duplicate post-fork content if compaction lands).Real-world example
The AMD_INTIGRITI session investigation found a 4-deep chain in
~/.claude/projects/C--/:csb listshows these as four independent rows. The fork relationships are invisible.Proposed solution
Add chain-awareness to csb's index and display:
Schema additions
Add columns to the sessions table:
parent_session_idforkedFrom.sessionIdif presentparent_message_uuidforkedFrom.messageUuidif presentis_forksubtype === 'compact_boundary' && forkedFromon line 1Indexer changes
In
metadata.py, when reading line 1, also extractforkedFromif present and persist to the new columns. No new file reads -- already touching line 1.Display changes
csb show <uuid>:csb list:--show-chainflag that adds parent/forks lines to each entry.[fork:23f58cd1]) next to forked sessions in the header.csb chain <uuid>(new subcommand):(parent_session_id == <uuid>)to find descendants.Implementation approach
Phase 1 -- index + minimal display
forkedFromfrom line 1 during normal indexing.csb show <uuid>includesparent:andforks:lines when applicable.Phase 2 -- chain command
csb chain <uuid>subcommand.--depth Nto limit traversal.Phase 3 -- chain-aware
csb resume(depends on Alpha #14)Acceptance criteria
parent_session_id,parent_message_uuid,is_forkcolumns.forkedFrom.csb rebuild-indexcorrectly populates the columns for existing sessions.csb show <uuid>displays parent and forks when present.csb chain <uuid>walks ancestry + descendants.### Added.Design considerations
services/compact/microCompact.tsandservices/compact/apiMicrocompact.tscontain norandomUUIDorswitchSessioncalls. Chain detection can ignore microcompact rows./clearproduces a new sessionId but noforkedFrom./clearis logically a fresh-start, not a fork. The line-1-forkedFromdiscriminator handles this correctly: a/clear-cleared session's line 1 won't haveforkedFrom, sois_fork=false.compact_boundaryrow at row N>1 withoutforkedFrom. No fork detection triggered. Correct.dz claude-rehome): if a session has been rehomed via hardlink to a different project-dir slug, its forks (created via/branchafterwards) will land ingetProjectDir(getOriginalCwd())-- the cwd-derived dir, not the rehomed dir. csb's chain walker should followparent_session_idregardless of which project-dir slug the parent or child lives in. The walk is by UUID, not by location.Related issues
csb list shows stale data. Chain-awareness will require rebuild after schema migration.csb viewAlpha gate. Chain-awareness pairs naturally with the viewer launcher.start atsemantics fix. Both fixes derive truth from the on-disk file (slug or line 1), not from JSONL content aggregates.djdarcy/dazzle-claude-code-history-viewer#?(chain-aware timeline view) -- CCHV-side complement; depends on csb chain-awareness for the data model.Analysis
Detailed empirical baseline + source citations:
notes/architecture/2026-05-04__14-47-31__both_claude-code-session-fork-chain-and-compaction-model.md-- the data model, the 4-deep AMD_INTIGRITI chain, claude-code source citationsnotes/architecture/2026-05-04__18-37-44__senior_q2-q3-q4-claude-code-session-internals.md-- session-ID minting inventory (onlybootstrap/state.ts:331andcommands/branch/branch.ts:68mint sessionIds in normal use),switchSessionsemantics, microcompact non-fork confirmationnotes/cli/2026-05-03__15-43-24__both_csb-start-at-semantics-and-folder-listing-config.md-- the originating UX investigationOriginating session reference:
DAZZLECMD__fix-broken-claude-code-session(2026-05-03/04). The chain phenomenon was discovered while diagnosing why the AMD_INTIGRITI session was unresumable; the chain itself is what made the slug-vs-cwd divergence visible.