anomalyco / anomalyco/opencode
fix(tui): generalize contextual keybind precedence
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Problem
Context-specific TUI actions can share a physical key with global or managed-textarea bindings. PR #42366 fixes the observed Shell-tab failure by giving the default Ctrl+D binding first refusal, but the mechanism is deliberately literal and local:
if (event.name !== "d" || !event.ctrl) return
if (!shortcuts.list("composer.shell.kill").includes("ctrl+d")) return
A user rebinding composer.shell.kill to another editor-owned key can recreate the same precedence bug. Other textarea-backed contextual surfaces may have the same class of issue but do not yet have collision tests.
Investigation
Confirmed during #42366:
- The Shell tab displayed
kill ctrl+dbut noDELETE /api/shell/:idreached the server. - The existing server removal path correctly terminated the process group once invoked.
- A raw key interceptor in the active Shell tab restored the live TUI behavior.
Checked adjacent surfaces:
composer.subagent.interruptwith defaultCtrl+Dpasses the current focused-textarea/global-exit harness, so it is not a confirmed sibling bug.- DialogSelect-based delete actions are modal and use
InputRenderable, which the managed textarea layer excludes. - Mini-TUI queued-prompt and subagent actions already use elevated priority.
Still needing focused interaction coverage:
- Permission rejection textarea: Return /
Ctrl+D - Textual FormPrompt controls: Return / Tab / Escape
- Autocomplete destructive action:
Ctrl+D - Composer navigation and configured non-default bindings while an editor remains focused
Desired direction
Provide a reusable, configuration-aware way for an active contextual layer to take precedence over global/editor bindings. Avoid per-component raw-event checks for one literal default shortcut.
Acceptance criteria
- Contextual commands can claim their configured bindings without hard-coding physical keys.
- Disabled (
none) bindings remain disabled. - Multi-binding and rebinding behavior is preserved.
- Focused textarea editing still wins when no active contextual command claims the key.
- Add collision tests for the affected composer and textarea-backed surfaces above.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue does not name files or test paths; start by tracing the active contextual layer, managed textarea bindings, and the Shell-tab raw key interceptor described here. Exercise the listed collision cases, including configured and disabled bindings, then add focused interaction coverage for the affected composer and textarea-backed surfaces. Done means contextual commands claim their configured keys while textarea editing still wins when no command claims them.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100