anomalyco / anomalyco/opencode

fix(tui): generalize contextual keybind precedence

Open
#42,377 0 comments 0 reactions 0 assignees View on GitHub

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+d but no DELETE /api/shell/:id reached 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.interrupt with default Ctrl+D passes 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.