Grey the dot for a session nobody has prompted yet #26

Merged
pedromcaraujo merged 1 commit from status-dot-grey-fresh into main 2026-08-08 12:01:18 +01:00

Why

A brand-new session opened on red. The dot had no notion of "untouched": an empty session answers "idle", and the idle clock was seeded from the transcript's mtime — which is per-directory, so a fresh session in a repo you worked in yesterday was born two minutes stale.

What

Claude's terminal title already carries the answer. Its text is the conversation summary, and it stays the literal Claude Code until there is one — per-pane, nothing to install, same provenance as the busy/idle glyph. That gets its own fresh state and a grey dot.

The amber → red escalation goes with it, along with the whole clock behind it (_idle_since, the idle_for field, the transcript-age seeding). How long a channel has been sitting there says nothing about whether it wants you; all it reliably did was turn every dot red overnight.

dot meaning
hollow no session
grey session, nothing asked yet
green working
amber waiting on you

Also in here: the command palette left focus behind. closePalette focused the iframe window, which xterm doesn't read from — it listens on a hidden textarea, and a channel switch reloads the iframe, so at close time that textarea doesn't exist yet. focusTerm() targets the textarea and retries over the first half second, stopping once focus sticks; wired into palette close, iframe load and actions, so a lazygit popup gets the keyboard too. Skipped on touch, where focusing it is exactly what pops the Android keyboard.

Test plan

  • /status run against the live tmux server: an unprompted channel reports fresh, a summarised one idle, a spinning one busy
  • _classify over real titles — ✳ Claude Code → fresh, ⠂ Claude Code → busy (opening seconds of a first turn beat "untouched"), ✳ Bump forge git SHA → idle, non-claude pane → idle
  • After a SHA bump: palette → channel switch types straight into the terminal, no click; same for palette → lazygit
## Why A brand-new session opened on **red**. The dot had no notion of "untouched": an empty session answers "idle", and the idle clock was seeded from the transcript's mtime — which is per-*directory*, so a fresh session in a repo you worked in yesterday was born two minutes stale. ## What Claude's terminal title already carries the answer. Its *text* is the conversation summary, and it stays the literal `Claude Code` until there is one — per-pane, nothing to install, same provenance as the busy/idle glyph. That gets its own `fresh` state and a grey dot. The amber → red escalation goes with it, along with the whole clock behind it (`_idle_since`, the `idle_for` field, the transcript-age seeding). How long a channel has been sitting there says nothing about whether it wants you; all it reliably did was turn every dot red overnight. | dot | meaning | |---|---| | hollow | no session | | grey | session, nothing asked yet | | green | working | | amber | waiting on you | Also in here: the command palette left focus behind. `closePalette` focused the iframe *window*, which xterm doesn't read from — it listens on a hidden textarea, and a channel switch reloads the iframe, so at close time that textarea doesn't exist yet. `focusTerm()` targets the textarea and retries over the first half second, stopping once focus sticks; wired into palette close, iframe load and actions, so a lazygit popup gets the keyboard too. Skipped on touch, where focusing it is exactly what pops the Android keyboard. ## Test plan - [x] `/status` run against the live tmux server: an unprompted channel reports `fresh`, a summarised one `idle`, a spinning one `busy` - [x] `_classify` over real titles — `✳ Claude Code` → fresh, `⠂ Claude Code` → busy (opening seconds of a first turn beat "untouched"), `✳ Bump forge git SHA` → idle, non-claude pane → idle - [ ] After a SHA bump: palette → channel switch types straight into the terminal, no click; same for palette → lazygit
Grey the dot for a session nobody has prompted yet
All checks were successful
CI / check (pull_request) Successful in 7s
f47f85f2b9
A brand-new session opened on red. The dot had no notion of "untouched",
so an empty session answered "idle", and the idle clock was seeded from
the transcript's mtime — which is per-directory, so a fresh session in a
repo you worked in yesterday was born two minutes stale.

Claude's terminal title carries the answer: its text is the conversation
summary, and it stays the literal "Claude Code" until there is one. That
is per-pane and needs nothing installed, same as the busy/idle glyph.
A session in that state gets its own state and its own grey dot.

Drop the amber -> red escalation with it, and the whole clock behind it
(_idle_since, the idle_for field, the transcript-age seeding). How long
a channel has been sitting there says nothing about whether it wants
you; all it reliably did was turn every dot red overnight.

    hollow  no session
    grey    session, nothing asked yet
    green   working
    amber   waiting on you

Also fix the palette leaving focus behind. closePalette focused the
iframe window, which xterm doesn't read from — it listens on a hidden
textarea, and a channel switch reloads the iframe, so at close time that
textarea doesn't exist yet and the focus lands nowhere. focusTerm()
targets the textarea and retries over the first half second, stopping
once focus sticks. Wired into palette close, iframe load, and actions,
so a lazygit popup gets the keyboard too. Never on touch, where it is
exactly what pops the Android keyboard.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pedromcaraujo/forge!26
No description provided.