Quiet chip (the "16m" clock badge on a session row)
A small grey clock badge, reading 16m or 45m or 2h, at the right-hand end of a session row. It means exactly one thing: the session is running but has produced no output for that long. It is a silence timer, not an error and not a progress bar, and it clears the instant the session speaks again.
What it is
A small grey clock icon + duration — 16m, 45m, 2h — that appears on the right-hand end of a
session row in the left sidebar (and on the equivalent mobile row). It means exactly one thing:
This session is running, but it has produced no output for that long.
It is a silence timer, not an error and not a progress bar. A session that is genuinely working — thinking for a long time, waiting on a slow tool, running a big test suite — will wear the chip and be perfectly healthy. That is the point: the chip makes long silence visible so you can decide whether to look, without claiming anything is wrong.
Hovering the row shows "No output for a while" among the row's other indicator meanings; the chip's own label reads "Quiet for 16m — no output".
Where to find it
Look at the left sidebar: the chip sits at the right-hand end of a session row, and the same badge appears on the equivalent row on a phone. There is no menu or setting for it. It appears on its own after fifteen minutes of silence on a running session, and disappears the moment the session speaks again.
Hovering anywhere on the row explains it together with the row's other small badges; the chip's own label reads "Quiet for 16m — no output".
How it behaves
When it appears (and when it does not)
- Only on
runningorstartingsessions — the two statuses that can still emit output. A session that is paused, archived, errored, waiting on you, or finished never shows it, however old it is. (This deliberately mirrors the backend's own gate ingetSilentActiveSessionIds, and is deliberately narrower than the sharedLIVE_STATUSESset, which answers a different question — "does this session have a live process at all" — and would wrongly includeneeds_you/waiting/error.) - After 15 minutes of silence. Below the threshold the row shows nothing extra, so a healthy busy sidebar stays uncluttered.
- It updates itself on a 30-second tick. Nothing in the app ever announces "fifteen minutes of silence have now passed" — silence is the absence of events — so a timer is the only thing that can notice the crossing. The chip appears on its own while you are looking at the list, with no click, refresh, or new message needed.
- It disappears the moment the session speaks again, because the timer is measured from the
session's
lastActiveAt— and every output event refreshes that field live, without waiting for a refresh of the session list (see "Why the chip used to lie" below).
A future timestamp (from clock skew) or an unparseable one reads as not quiet — never as a negative
or NaN duration.
What it is NOT
- Not an alert. It is styled with muted
surfacetokens on purpose and is never given the amber "Needs You" or red error treatment. Nothing is asking for your attention. - Not the thing that rescues a stuck session. A separate main-process sweeper
(
session-silence-backstop-service.ts) is what actually acts on a genuinely stranded session. The chip is purely informational and takes no action. - Not "the session is broken." Long silence is normal for long tool calls and deep thinking.
Reading it next to the other row badges
A session row can carry several small indicators; the quiet chip renders immediately after the waiting badge. Common neighbours:
| Badge | Meaning |
|---|---|
Clock + 16m (grey) |
Quiet chip — running, but silent for 16 minutes |
>_ terminal glyph |
This session triggered N action(s) via the CLI |
| Hourglass / waiting badge | Parked waiting for a test slot |
| Coloured status dot | Running (green) · Needs You (amber) · Error (red) · Waiting (ember orange) |
Hovering the row explains all of them at once — that is the designed surface, rather than expecting you to hover each 12-px icon. (See the "known rough edge" below.)
Known rough edge — the ⋮ button overlaps the chip
The hover-revealed ⋮ "More actions" button is positioned over the row's right edge, which is exactly
where the quiet chip sits. On a row that renders a trailing chip the row now reserves clearance so the
chip stays hoverable; on rows without one the ⋮ still floats over the right edge, which is what keeps
session names from being truncated ~30 px early (see
session-sidebar-title-truncation-too-early-postmortem.md). Either way, hovering anywhere on the row
gives you the full explanation.
Why the chip used to lie (fixed 2026-09-03)
Between 2026-09-01 and 2026-09-03 the chip showed a number that was simply wrong: sessions that were
emitting output continuously wore 24m, 35m, 51m chips that only ever climbed. Opening one of those
sessions showed 6s since last response at the bottom of the conversation — the two readouts on screen
at the same time disagreed by 25 minutes.
The chip was measuring the right field; nothing was updating it. The renderer learned lastActiveAt
from exactly two places — a full session-list fetch, and a status-change push (which sets it to the
moment the status changed). Neither fires while a session simply keeps running. So a session that went
running and stayed running carried a lastActiveAt frozen at the start of its turn, and the chip
faithfully rendered how long the current turn had been going under the label "no output". The
detail-pane timer disagreed because it anchors on the conversation's own message rows instead, and the
database agreed with the detail pane — last_active_at for those same rows was under a minute old,
which is what proved the staleness was in the UI and not in the data.
The fix mirrors, in the renderer, the bump the database already does: every SESSION_OUTPUT event
advances the row's lastActiveAt. Two details make it honest and cheap:
- It anchors on arrival time, not the event's own timestamp. A streaming checkpoint deliberately reuses the turn's start time as its timestamp for the whole turn, so trusting that field would have bumped nothing. Receiving an event is the proof of activity.
- It rewrites the row at most once a minute. The chip ticks at 30 s against a 15-minute threshold, so the bump is throttled rather than fired on every token — otherwise a fast stream would rebuild the session list on every delta, which is the churn the streaming batch exists to prevent.
lastActiveAt is not a sidebar sort key (compareRegularSessions orders on status, the two message
timestamps, drag order, and start time), so keeping it fresh cannot reorder the list.
Why the timer lives on the row, not on the chip. The row is memoised, and a quiet session by
definition pushes no updates — so if only the chip watched the clock, only the chip would learn, and the
row's hover tooltip would sit frozen on "not quiet" for the whole quiet spell. That was a real bug: a row
grew a 16m chip whose meaning the tooltip never mentioned. useSessionQuiet now runs on the row and
stores a boolean, so React skips the re-render on every tick except the one that flips it — the row
re-renders once, when the chip appears, and a status that can never go quiet arms no timer at all.
(Fixed 2026-09-02 after a user asked what the "16m" meant and found the tooltip empty.)
Shipped 2026-09-01.
For agents
Where it lives in the code
- Component + hook: SessionQuietBadge.tsx
— exports
isSessionQuiet()(the pure 15-minute predicate),formatQuietDuration(), theuseSessionQuiet()hook that owns the tick, and theSessionQuietBadgechip that renders the number. - Mounted by SidebarSessionRow.tsx and MobileSessionRow.tsx.
- The row's hover text is assembled in session-indicator-tooltips.ts.
- Tests: session-quiet-badge.test.tsx and SidebarSessionRow.test.tsx.
Related
- Work through interrupted sessions — the guided pass over sessions that stopped abnormally.
- Working through paused sessions — the guided pass over paused sessions.
- Waiting detector — how Omniscio decides a session is waiting on you rather than busy.
Last verified 2026-10-05