A Claude Code transcript is not a clean chat export. It is a sequence of independent JSON objects written while the session is still alive. If you treat every assistant-shaped line as completion, you will eventually alert on an API error, a sidechain, or an old turn that has already been superseded.
This is the field-level reading model we use when reconstructing local session state.
Begin with the envelope
Read JSONL one line at a time. A blank line, malformed record, or partial final append should fail only that record for the current pass. The file may be changing while you read it, so the final line can become valid on the next filesystem event.
A useful projection includes fields such as:
typeuuidtimestampmessage.stop_reasonisSidechainisApiErrorMessagetoolEndsTurn
Not every event contains every field. Missing data is a reason to keep the state uncertain, not a reason to fill in a convenient default.
for each line:
if blank: continue
event = parse JSON
if parsing fails: continue
project only state-relevant fields
Keep user activity and assistant output separate
A user event means a later turn began. Assistant output means the model produced work, but it does not prove the session is over. Ordered event time matters because later user or start activity can invalidate an earlier completion candidate.
Use the event timestamp and stable identity. File modification time describes the container, not the individual turns inside it.
Sidechains are not main-thread handoffs
isSidechain changes the meaning of a finish event. A background subagent can complete while the parent session continues. If a desktop monitor pages the user for both events, it creates noise and can pull the user back before the main task needs input.
Sidechain records remain useful for diagnostics, but filter them before producing a foreground your-turn state.
API errors are not successful completion
An assistant-shaped event can contain a rate-limit or API failure. isApiErrorMessage therefore belongs in the state guard. Route that event into the appropriate error state instead of treating it as a finished turn.
The same caution applies to message.stop_reason and toolEndsTurn. A stop marker describes one model response. Later tool, user, or start activity can still exist.
Reduce ordered events into state
A reliable reader follows five steps:
- Parse valid records without aborting the file.
- Preserve event identity and semantic timestamps.
- Exclude sidechain finishes from foreground handoffs.
- Classify API and provider errors separately.
- Accept completion only when later activity has not superseded it.
Searching for the word completed cannot provide turn identity, ordering, or an error guard. Valid JSON is only the first gate.
Keep the privacy statement narrow
Agent Island performs this reconstruction from local session records and does not upload transcript content to an Agent Island service. That does not mean every Claude Code version will keep exactly the same event shape. Provider-aware parsing still needs tests, bounds, and conservative unknown states.
The longer field map, current limitations, and source links are in the canonical guide.
Top comments (0)