feat(tui): add configurable keymap support#18593
Merged
fcoury-oai merged 13 commits intomainfrom Apr 28, 2026
Merged
Conversation
e9358e0 to
057921d
Compare
18c791a to
03229de
Compare
Contributor
|
Smoke tested the new |
canvrno-oai
approved these changes
Apr 27, 2026
Add typed `tui.keymap` config, schema coverage, default keymap docs, and runtime keymap resolution for existing TUI shortcuts. Wire the resolved bindings through app, composer, list, pager, approval, and onboarding input handlers so users can reassign built-in keys.
Add argument comments to keymap-related TUI callsites that pass opaque literal values, keeping them compliant with the anonymous argument lint.
Remove the legacy Enter/Tab submission fallback so composer submit and queue actions are dispatched only through the resolved keymap bindings. Add regression coverage for remapped submit and queue keys to ensure unconfigured Enter/Tab presses no longer bypass `tui.keymap`.
Document keymap preset stability, single-key binding semantics, explicit unbind behavior, and the runtime snapshot contract used by TUI handlers. Clarify how resolved keymaps propagate into active bottom-pane surfaces so future remap changes keep cached bindings synchronized.
Remove the keymap preset config surface from PR1 so runtime resolution falls back directly to built-in defaults after user overrides. This keeps the initial keymap capability focused on action remapping and leaves versioned default migrations out of the first PR.
Remove onboarding from the configurable keymap surface and keep its startup shortcuts hard-coded. Users cannot remap keys before onboarding, so exposing those actions in `[tui.keymap]` adds config surface without a practical customization path.
bf42bc5 to
285a24b
Compare
80e5dfe to
bf1fc4b
Compare
etraut-openai
approved these changes
Apr 28, 2026
## Why PR1 (#18593) makes keymaps configurable, but manually editing `[tui.keymap]` still requires users to know context names, action names, supported key syntax, and which bindings are currently coming from defaults versus custom config. The goal of this PR is to turn that model into a guided TUI workflow: users can open `/keymap`, browse supported actions, see current/default/custom state, capture a replacement key, and let Codex validate and persist the edit safely. This is PR2 in the keymap stack: - PR1: #18593: configurable keymap foundation - PR2: #18594: `/keymap` picker and guided remapping UI - PR3: #18595: Vim composer mode and the remap option ## How It Works https://github.com/user-attachments/assets/d40feb02-7f9e-4478-811a-d00f7f955133 The `/keymap` command opens a tabbed shortcut picker backed by the runtime keymap introduced in #18593. The picker organizes actions by common shortcuts, custom overrides, unbound actions, and context-specific tabs such as app, composer, editor, navigation, and approval. Selecting an action opens an action menu that explains the current binding, its config path, whether it comes from a root-level override or the default keymap, and the available operations. Depending on the current state, users can set a key, replace one binding, replace all bindings, add an alternate binding, or clear the custom override. Captured keys are serialized back to canonical `tui.keymap.<context>.<action>` config entries. Before writing, the edited config is re-resolved through `RuntimeKeymap`, so the same parser and conflict validation used at startup also protect interactive edits. If the new binding conflicts with another active action, Codex shows the conflict instead of persisting an invalid config. ## Reviewer Entry Points - [`codex-rs/tui/src/keymap_setup.rs`](https://github.com/openai/codex/blob/fcoury/keymap-command/codex-rs/tui/src/keymap_setup.rs): guided remapping flow, capture view, edit outcomes, and conflict handling. - [`codex-rs/tui/src/keymap_setup/actions.rs`](https://github.com/openai/codex/blob/fcoury/keymap-command/codex-rs/tui/src/keymap_setup/actions.rs): action catalog and config/runtime accessors for editable actions. - [`codex-rs/tui/src/keymap_setup/picker.rs`](https://github.com/openai/codex/blob/fcoury/keymap-command/codex-rs/tui/src/keymap_setup/picker.rs): tabbed picker construction and row rendering. - [`codex-rs/core/src/config/edit.rs`](https://github.com/openai/codex/blob/fcoury/keymap-command/codex-rs/core/src/config/edit.rs): config edit helpers used to write keymap overrides atomically. - [`codex-rs/tui/src/chatwidget/slash_dispatch.rs`](https://github.com/openai/codex/blob/fcoury/keymap-command/codex-rs/tui/src/chatwidget/slash_dispatch.rs): `/keymap` dispatch and queue-drain behavior. ## What Changed - Added the `/keymap` slash command. - Added a reusable keymap setup module with action picker, action menu, replace-one menu, capture view, and conflict surface. - Added keymap edit events so app-level code can apply, validate, persist, and refresh runtime bindings after a user remaps an action. - Added config edit helpers and tests for setting, replacing, and clearing `tui.keymap` entries. - Added snapshot coverage for the picker, action menu, capture view, and keymap search/index behavior. This PR intentionally does not add Vim mode or the remap option; those are isolated in #18595. ## Validation - `cargo check -p codex-tui` on this branch after rebasing onto #18593 ## Documentation Follow-Up When the stack ships, the Codex CLI documentation on `developers.openai.com/codex` should mention `/keymap` as the guided way to inspect and edit shortcuts, alongside the lower-level `[tui.keymap]` config documentation added in #18593.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The TUI currently handles keyboard shortcuts as hard-coded event matches spread across app, composer, pager, list, approval, and navigation code. That makes shortcuts hard to customize, makes displayed hints easy to drift from actual behavior, and makes future keymap work riskier because there is no central action inventory.
This PR adds the foundation for configurable, action-based keymaps without adding the interactive remapping UI yet. Onboarding intentionally stays on fixed startup shortcuts because users cannot reasonably configure keymaps before completing onboarding.
This is PR1 in the keymap stack:
/keymappicker and guided remapping UIDesign Notes
The new model resolves named actions into concrete runtime bindings once from config, then passes those bindings to the UI surfaces that handle input or render shortcut hints.
The main concepts are:
global,chat,composer,editor,pager,list, orapproval.global.open_transcript,composer.submit, orpager.close.ctrl-t,alt-backspace, orpage-down. Multi-step sequences such asctrl-x ctrl-s,g g, or leader-key flows are not part of this PR.What Changed
TuiKeymapconfig support under[tui.keymap], including typed contexts/actions, key alias normalization, generated schema coverage, and user-facing config errors.RuntimeKeymapresolution incodex-rs/tui/src/keymap.rs, including fallback precedence, built-in defaults, explicit unbinding, and per-context conflict validation.codex-rs/tui/src/onboarding/keys.rsinstead of exposing them through[tui.keymap].Validation
The branch includes focused coverage for config parsing, key normalization, runtime fallback resolution, explicit unbinding, duplicate-key conflict validation, default keymap consistency, onboarding startup key behavior, and UI hint snapshots affected by resolved key bindings.