Claude Code transcripts are useful local evidence, but they are not a stream of identical chat messages. Each line is an independent JSON object, and the meaning of a line comes from both its top-level type and nested fields.
Start with the envelope
Read one line at a time. Blank, partial, or malformed lines should be ignored for the current pass rather than crashing the entire scan. A transcript may be growing while it is being read, so a partial final line can become valid on the next file change.
The fields Agent Island uses when classifying Claude activity include type, uuid, timestamp, message.stop_reason, isSidechain, isApiErrorMessage, and toolEndsTurn. Not every line contains every field, and a missing field is not permission to invent a state.
for each line:
if blank: continue
event = parse JSON
if parsing fails: continue
classify from the fields that are actually present
Separate user activity from assistant output
A user event is evidence that a later turn began. Assistant output is evidence that the agent produced work, but it is not automatically evidence that the whole session is finished. The parser must retain event order so later user or start activity can supersede an earlier completion marker.
The uuid and timestamp help preserve identity and ordering. They should not be replaced with file modification time: one file timestamp describes the container, while event timestamps describe individual records.
Treat sidechains as a different context
The isSidechain flag identifies activity that should not be treated as the primary user-facing handoff. A background subagent can finish while the parent session continues. Raising the same alarm for both would pull the user back before the main task actually needs them.
Filter sidechain events before producing a foreground needs-you state. They may still be useful for diagnostics, but they are not equivalent to a main-thread handoff.
Do not turn API errors into completion
An assistant-shaped envelope may carry an API or rate-limit error. isApiErrorMessage is therefore a guard, not decoration. Error output should enter the appropriate error state and must not be interpreted as a successful completed turn.
Likewise, message.stop_reason and toolEndsTurn need context. A stop marker can describe one model response; it does not prove that no later tool, user, or start event exists.
Reconstruct state, do not grep for a word
A robust reader reduces ordered events into a session state:
- parse valid records without failing the whole file;
- preserve event identity and semantic timestamps;
- exclude sidechain handoffs from foreground alerts;
- classify API errors separately;
- accept a completion candidate only when later activity has not superseded it.
This is why searching a transcript for stop_reason or completed is insufficient. A word match has no turn identity, no ordering policy, and no error guard.
Keep the privacy claim narrow
Agent Island reads these transcript records locally to reconstruct status. It does not upload session contents to an Agent Island service. The exact released behavior can be audited in the open-source v1.7.1 code; local parsing does not imply that every possible Claude Code transcript version has an identical schema.
