$ inspect session --freshness

Is Your AI Coding Session Stalled, Working, or Finished?

A quiet transcript is ambiguous. The last meaningful turn event and its age provide a safer answer than a file timestamp or process check alone.

A Claude Code or Codex session is finished when its latest meaningful event closes the current turn and no newer user activity has started another one. It is stalled only when it was recently observed working, then stopped producing fresh session activity without a completion marker. Silence by itself proves neither state.

This distinction matters for alerts. Mark a quiet tool call as finished and the user gets interrupted too early. Treat an old completion as fresh and the same alarm returns after every app launch.

Read the last meaningful event

Transcript files contain more than conversation turns. They may include titles, mode changes, bookkeeping, tool results, and child-agent traffic. The newest JSON line is therefore not necessarily the newest state change.

For Claude Code, a main-chain assistant event with end_turn, stop_sequence, or stop can close the turn. A later user event starts another turn and cancels that completed state. For Codex, task_complete or turn/completed closes a turn, while task_started, turn/started, or a later user message makes the session active again.

The parser walks backward until it finds one of those events. Metadata after a completion does not change the turn identity or its semantic timestamp.

latest meaningful event          classification
assistant output, no stop       working
task started or user message    working
main turn completed             your turn
metadata or title change        keep prior state
no recent meaningful activity   idle or stalled

Exclude false completion markers

Two records can look like a finished turn without handing control back to the user.

Older Claude Code transcripts can mix subagent events into the main JSONL and mark them with isSidechain. A child agent may finish while the main turn keeps running, so sidechain completion events are ignored when classifying the main session.

Claude Code can also write a rate-limit or API-error message in an assistant envelope with stop_sequence. The isApiErrorMessage flag distinguishes it from a normal completion. The session needs an error or quota treatment, not a "your turn" alarm.

These exceptions are covered by release tests. The fixtures include a sidechain completion during a main turn, a main completion followed by sidechain traffic, and an API-error line that resembles a terminal assistant event.

Use semantic time before file time

A file's modification time answers when bytes changed. It does not answer when the conversation changed state.

Claude Desktop writes lastActivityAt after some turn completions as bookkeeping. In observed sessions, that write followed the assistant event by a few seconds. If any newer desktop timestamp suppressed completion immediately, the alarm would disappear depending on which scan happened first.

Agent Island keeps a 25-second bookkeeping grace after a finished Claude turn. Desktop activity inside that interval does not erase the completion. Activity well after it indicates that the user returned or another turn began, so the old alarm is suppressed.

The same rule fixes another stale-state problem. Touching an old transcript to update a title cannot resurrect a week-old completion. The timestamp attached to the user or assistant event remains the source of truth.

Freshness turns events into states

A completion marker cannot stay actionable forever. Neither can a stalled label.

In the released 1.7.1 state model, activity inside 18 seconds is immediately active. A session without a completion remains working through the first five minutes. If the monitor previously saw it working and the activity then goes quiet, it can show stalled for up to 15 minutes. A completed turn stays in needsYou for 20 minutes. All session attention expires after 30 minutes.

fresh output or start event      working
completion under 20 minutes     your turn
recently working, now quiet     stalled (bounded to 15 minutes)
semantic activity over 30 min   idle

These are conservative UI windows, not claims about the agent's internals. The five-minute boundary does not prove a crash. It marks a change from observed activity to an interval that deserves a glance.

Retract the alert when the evidence changes

Session state is revised every time a meaningful event arrives. The reminder layer should follow the same rule.

Agent Island waits one second before delivering a new your-turn alert. A fast reply or follow-up write can cancel the pending delivery. If the user replies after the panel appears, the next transcript scan removes that turn from the active needs-you set and closes the panel.

The first scan after app launch is treated as history rather than news. A finished turn that predates the monitor's current run is recorded without firing a fresh alarm. A twelve-hour remembered-key window also prevents the same acknowledged turn from returning after a restart.

What the status does not claim

A local status companion classifies observable session events. It cannot know whether a long-running command is healthy, whether an agent's reasoning is useful, or how long a task has left. It also should not infer completion from a still process icon or a quiet terminal.

The practical decision tree stays narrow: find the latest meaningful main-turn event, compare it with newer activity, apply a bounded freshness window, and retract the result when the evidence changes.

Agent Island 1.7.1 uses this local model for Claude Code and Codex. The project is free and MIT licensed. See how those per-thread states are combined across multiple sessions, or read the focused Claude Code status monitor guide.