Skip to main content

Module turn

Module turn 

Source
Expand description

Turn detection for interactive TUIs piloted through the PTY.

“Has the program finished this turn and is it ready for the next input?” is the core question when driving a full-screen TUI (the claude CLI, codex, a REPL, …) like a human operator. We answer it with a hybrid signal:

Recognizers operate on already-rendered, ANSI-stripped screen lines, so they never deal with escape codes — only with the visible text a human sees.

Structs§

AntigravityRecognizer
Recognizer for the agy (Antigravity CLI, Gemini) TUI. Best-effort. Unlike claude/codex (Ink, alt-screen + in-place redraw), agy renders in append mode inside winx’s PTY: spent Generating… / esc to cancel frames ghost into later screens and are never cleared. We therefore lead with the idle hint ? for shortcuts, which only sits at the bottom of the screen when input is actually ready — a busy turn pushes it out of the tail — and only then fall back to the busy markers. Markers verified against a real agy 1.0.8 (Gemini 3.5 Flash) session captured through winx.
AutoRecognizer
Runs every app-specific recognizer and combines their verdicts by priority: Busy > AwaitingApproval > AwaitingInput > Unknown. A recognizer that sees the app working therefore always wins over one that only sees a (possibly stale) prompt glyph — so auto never reports a busy app as ready, while still falling back to Unknown (quiescence) for an unknown TUI.
ClaudeRecognizer
Recognizer for the claude CLI (Ink/React TUI). Markers verified against a real claude v2.1.x session captured through winx:
CodexRecognizer
Recognizer for the codex CLI (Ink TUI). Markers verified against a real codex-cli 0.139.0 (gpt-5.5) session captured through winx:
GenericConfigurable
A recognizer built from marker strings/regexes in config (crate::types::TurnRecognizerMarkers), so wait_for_turn can pilot an arbitrary TUI without bespoke code. Same scan discipline as the built-ins: busy across the whole screen (a long response can push its footer out of the tail), approval/input tail-scoped so a stale scrollback prompt can’t fire.
GenericRecognizer
No app knowledge: always TurnState::Unknown so the caller decides purely by quiescence. Correct (if conservative) for any TUI.

Enums§

TurnState
What an interactive program is doing right now, inferred from the screen.

Traits§

TurnRecognizer
Reads a rendered screen (ANSI already stripped, one String per line) and classifies the current turn state for a specific kind of TUI.

Functions§

recognizer_for
Build the recognizer for a hint string (auto | claude | codex | generic). Unknown hints fall back to auto.