Repository navigation
fix(terminal): recognize Claude drafts with labelled input boxes and the default hidden cursor - #37171
Conversation
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 2 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
…poser Claude Code's default caret hides the native cursor and parks it at a painted caret cell, so its composer (labelled or bare) was never detected: the draft leaked into screen reads and automatic mail was not held. Accept a hidden cursor on the Claude prompt only inside a complete composer frame with the cursor right of the glyph. On the normal buffer the parked cursor suffices (Claude drops the inverse caret paint on focus-out); on an alternate or unknown buffer the cursor cell must also be inverse. Both facts are read per call from xterm, only while the cursor is hidden. The closing rule now comes from the row where the continuation walk stopped, removing the extra rows-below scan. Codex and boxed composers keep rejecting hidden cursors.
Review loop statusThe problem. Orca reads Claude Code's input box off the terminal screen so it can keep an unsent draft separate from the agent's output and hold automatic messages (mail from other agents) until the draft is sent or cleared. Two current Claude Code shapes broke that. A label in the box's top border (for example a custom agent name) made Orca reject the box. And Claude Code 2.1.316 hides the real terminal cursor by default and paints its own caret, which Orca read as "no input box", so on default settings no Claude draft was recognized at all. Users saw drafts mixed into The change for users. On default Claude Code settings, labelled or not, an unsent draft is now recognized: screen reads return it separately, automatic messages wait for it and deliver once it is sent or cleared, including after the user switches to another pane. Bare-border Claude, Codex and boxed-composer detection are unchanged. What the review found and fixed.
Deferred (no failing input found).
Verified. Unedited Claude Code 2.1.316 recordings on default settings (labelled and unlabelled, mid-draft caret, empty box, draft after focus loss) and native-cursor recordings at 100 and 40 columns, run through the real terminal emulator: the For Brennan's review.
Intended differences from the common pattern are listed in the PR description. Main was synced once before the final CI run (merge |
Problem. When Claude Code is waiting for input, Orca reads its input box off the terminal screen so it can keep the user's unsent draft apart from the agent's output and hold back automatic messages (mail from other agents) until the draft is sent or cleared. Two current Claude Code shapes defeated that. A mode label in the box's top border (for example a custom agent name such as
──── ultracode ──) made Orca reject the box. And Claude Code 2.1.316 hides the terminal's real cursor by default and draws its own caret; Orca took any hidden cursor to mean "no input box", so on default settings no Claude draft was recognized at all, labelled or not. The result:orca terminal read --screenand screen/tail reads mixed the draft into output, and automatic messages could be typed into the middle of the user's unsent text.What changes for users. On default Claude Code settings, with or without a top-border label, a typed but unsent draft is now recognized: screen reads return it separately from output, automatic messages wait for it, and they deliver once it is sent or cleared. This also holds after the user switches to another pane (the agent stops drawing its caret when its pane loses focus, but the draft is still recognized). Existing bare-border Claude, Codex and boxed-composer detection are unchanged. Tracked in #36478 and STA-13041.
How it works. The box is still recognized from its shape: the
❯prompt with a top border above it (plain, or a rule of at least 8 characters followed by a label) and a plain closing border right where the draft ends. Bottom-border matching stays strict, so a draft line such as-------- coverage --------stays part of the draft. When the real cursor is hidden, Orca accepts it as the caret only if it is parked inside that complete box, and only if the terminal is on its normal screen or the cell under the cursor is drawn in reverse video (the agent's own caret). Full-screen apps that draw a similar box therefore stay unrecognized. Both facts are read fresh from the terminal on every read; nothing is saved or sent anywhere, and a missing fact counts as unknown. The closing-border check reuses the existing row scan, so a read does no extra row work.Plan: full review path because this detector feeds a hold on automatic messages. Screen-only box recognition is needed because Orca reads arbitrary terminals, user-started and SSH agents, provider snapshots and IME composition, where no agent identity is available. A design panel chose accepting a parked hidden cursor on the normal screen, plus reverse-video evidence elsewhere, after a recording showed the agent's caret disappears when its pane loses focus. No saved state or wire change.
Intended differences from the common pattern: the closest terminal classifier first verifies the agent was launched by the tool and then requires a visible cursor on the prompt row. Orca keeps structural box evidence because it must work for SSH panes (whose foreground process is
ssh), identity-free snapshot replays and renderer-only IME handling, and accepts a hidden parked cursor because current Claude Code hides the real cursor by default. It also reconstructs drafts whose caret sits below the prompt row (wrapped or multi-line input), which a prompt-on-cursor-row rule misses.Validation: unedited Claude Code 2.1.316 terminal recordings on default settings, labelled and unlabelled, at 100 columns, including a mid-draft caret, an empty box, and the same draft after the pane loses focus; plus native-cursor recordings at 100 and 40 columns (a wrapped draft). Reviewers also replayed the default 40-column recordings and 135 other recorded agent and TUI screens without a false match. Tests run them through the real terminal emulator and cover the
terminal read --screencommand, screen/tail projection, holding and then delivering an automatic message, provider snapshot round trips (a normal-screen draft is detected, a full-screen lookalike is not), placeholder masking during IME composition, shell❯prompts and rule-prefixed draft text. QA is the CLI/orchestration tests row; no layout or app lifecycle changed.Known limits: the empty Claude Code 2.1.316 custom-agent box draws no placeholder, so placeholder masking is covered by a synthetic case. A snapshot replayed without its screen-mode sequences would be read as the normal screen; Orca's snapshot producers always include them.