Closed as not planned
Closed as not planned
Copy link
Description
What happened
- Open a terminal pane in Ovis (or drop into the terminal lens from an agent session).
- Launch any interactive terminal application or TUI (e.g.,
vim,nano,htop,fzf,less, or an interactive agent prompt). - Press Escape (for instance, to exit insert mode in Vim, cancel search in
fzforless, or navigate TUI menus). - Actual behavior: The Escape key gets captured / swallowed by Ovis or the browser environment and does not reach the running TUI program (
\x1bis not delivered). This makes it impossible to exit modes or cancel operations via keyboard in TUIs. - Expected behavior: In the terminal lens with terminal focus, pressing Escape should immediately send
\x1b(ESC) through the active pty/WebSocket connection to the running program, without being intercepted or swallowed.
How often
Every time
Ovis version
0.4.21 (latest main)
How it runs
herdr plugin / bun run start / web client
Server PC
Linux x64, herdr 0.9.3
Device and browser
Desktop browser (Chrome / Firefox / Edge / Safari) and installed PWA
How the device reaches the server
This PC (localhost) / LAN address
How it signs in
Nothing (this PC) / Token
Agent and PC
Any terminal / shell pane or CLI agent (e.g. bash/zsh, Claude Code, Codex), local PC
Technical Context & Suspected Areas
Note: The following technical analysis was generated via automated codebase inspection and has not been human-verified:
- xterm custom key handler: In
src/lib/useTerminalMount.ts,term.attachCustomKeyEventHandlerinspects key events. WhenEscapeis pressed without modifiers, it returnstruewithout callingpreventDefault(), which may allow window/browser capture handlers to intercept or cancel the key. - Window capture handlers: Several components attach capture-phase listeners on
windowforEscape(e.g.,src/lib/useSidebarLayout.ts,src/components/CommandPalette.tsx,src/lib/useFocusTrap.ts). If focus state or modal detection has any discrepancy,event.stopPropagation()in capture listeners may swallowEscapebefore it reaches xterm's hidden textarea. - Browser Fullscreen / Keyboard Lock: In Chromium-based browsers, full-screen and web apps require
navigator.keyboard.lock(["Escape"])to prevent the browser from consumingEscapefor browser-level navigation/exit actions. - herdr ESC delay & PTY serialization: In
server/core/input.ts, herdr buffers/holds loneESC(~150ms) to disambiguateAlt+keycombinations, which could also contribute to dropped or stalled escape sequences in fast interactive TUIs.
Steps to Reproduce
# In an Ovis terminal pane:
vim
# Press 'i' to enter insert mode
# Type some text
# Press 'Escape' to return to normal mode
# Note: Remains in insert mode; Escape is not registered by VimMetadata
Metadata
Assignees
Labels
No labels
Activity
devswha commentedon Oct 31, 2026
I tried to reproduce this on the latest
main(38686a2, 0.4.21) and could not: a lone Escape reached the program in the pane every time.Setup. An isolated herdr 0.9.5 test session (no real workspace) and a fresh Ovis server on loopback, built from that commit. The pane ran a small raw-mode recorder (
process.stdin.setRawMode(true)) that writes down every byte it reads. Each check counts as passed only if\x1bshows up in both places: the browser's WebSocketinputframe and the bytes the program read from its pty.What passed (30 checks, 0 failed):
navigator.platformset to Linux and again set to macOS:iabcthen Escape (the vim insert-mode case); the program read69 61 62 63 1bworkingandidle, in the terminal lens: a single Escape and a double Escape both arrived.\x1band the program reads it.Not covered: real Safari, and an installed PWA window. WebKit could not run on this test machine.
About the suspected areas in the report: xterm's key handler returning
truefor Escape is how xterm sends the key itself (it callspreventDefaulton its own). The window-level Escape listeners act only while their dialog, menu or drawer is open. Neither one dropped the key in any of the cases above.To track this down, could you share:
bun run start, or another way.od -c, press Escape and then Enter, and paste what it prints. If033shows up, the key reached the pane and the program is the next suspect.Update: WebKit and the Mac app (macOS 27.0.1 test Mac, served by the same isolated test server, all on the same
mainbuild)safaridriverwith real key events. A single Escape,iabcthen Escape, two Escapes in a row, and Escape after opening the palette (Cmd+Shift+K) and closing it with Escape: every check passed. The pty read1beach time, and the Escape that closed the palette did not also reach the pane.Ovis.dmg, a WKWebView window), with OS-level key presses (System Eventskey code 53). A single Escape,iabcthen Escape, two Escapes, Escape after the palette, and Escape with the window in native full screen all reached the pane. In full screen, Escape went to the terminal and did not leave full screen.Desktop WebKit and the Mac app deliver Escape the same way Chrome and Firefox do. The questions above still apply.
devswha commentedon Nov 3, 2026
I tested this again on the current
main(4bc043d, 0.4.22). I still could not reproduce it.Setup. I used an isolated herdr 0.9.5 test session and a fresh Ovis server on loopback with an empty state directory. The browser was headless Chrome, driven by Playwright. The pane ran a raw-mode recorder that writes down every byte the program reads. A check passed only if the browser sent an
inputframe containing\x1band the program read1b.What passed (15 checks):
navigator.platformset first to Linux and then to macOS:iabcthen Escape (the program read69 61 62 63 1b)workingandidle: a single Escape and a double Escape.vi -u NONE):i, some text, Escape, then:wq. The file was written, so Escape left insert mode.One thing I did see: a key pressed right after the terminal opens, before its connection is ready (well under a second here), is not sent. This happens to a letter as well as to Escape. After that, every Escape arrived. If your Escape fails only right after you open or switch to a pane, please tell us. That would be a different and narrower bug.
The questions in my earlier comment still apply: the version and how Ovis is installed, the browser, anything open when Escape fails, any IME, keyboard layout or key remapper, and the output of
od -cin the failing pane. Without one of these, we have no case where Escape is dropped that we can track down.fix(terminal): never lose keys typed before the terminal takes input (#…
devswha commentedon Nov 5, 2026
Closing this, since it does not reproduce on main. Thanks again for the report, @kjohnsen.
iabc+ Escape (69 61 62 63 1b), Escape after the command palette, Claude panes working and idle, realvileaving insert mode, and the phone key bar's Esc.If Escape still fails for you on a current version, please reopen with the version, browser, what is open when it fails (IME, keyboard layout or remapper), and the output of
od -cin the failing pane after pressing Escape, and we will look again.kjohnsen commentedon Nov 5, 2026
Sorry for the delay. Ok, it looks like this is a result of something in my browser extensions (actually, narrowed it down to Vimium). It doesn't reproduce when I open in an incognito window. Thanks!