Skip to content

feat: support user keybindings TOML#1802

Closed
Whamp wants to merge 3 commits into
stablyai:mainfrom
Whamp:codex/keybindings-toml
Closed

feat: support user keybindings TOML#1802
Whamp wants to merge 3 commits into
stablyai:mainfrom
Whamp:codex/keybindings-toml

Conversation

@Whamp

@Whamp Whamp commented May 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds user-configurable keybindings backed by a hand-edited TOML file. Yes it's kind of a massive PR . . .

  • Introduces a shared keybinding catalog with action IDs, platform defaults, shortcut surfaces, commands, chord parsing, matching, display labels, and conflict diagnostics.
  • Loads overrides from ~/.orca/keybindings.toml on macOS/Linux and %USERPROFILE%\.orca\keybindings.toml on Windows.
  • Wires the effective keymap through main-process IPC/preload and the window, browser, menu, terminal, paste, xterm bypass, and Settings surfaces.
  • Updates Settings > Shortcuts to show effective bindings, source, diagnostics, and Open/Reveal/Reload actions.
  • Creates a complete commented starter TOML from the catalog, so users can see every supported action without freezing current defaults as overrides.

Background and scope

This PR was not requested. Don't feel obligated to merge it if keyboard rebinding is out of scope for Orca right now, or if you would rather continue through another branch. I opened it as my best attempt to match the scope discussed in prior work and so that i could make orca functional on my linux system since the hardcoded keybindings were causing havoc.

Behavior notes

  • Override values can be a single chord string, an array of chord strings, or "none".
[keybindings.linux]
# Single chord string
"terminal.clear" = "ctrl+k"

# Array of chord strings
"terminal.paste" = ["ctrl+v", "ctrl+shift+v", "shift+insert"]

# Unbind an action
"sidebar.left.toggle" = "none"
  • A user override replaces the full chord set for that action on the active platform.
  • Invalid TOML, unknown actions, invalid chords, and conflicts produce diagnostics while Orca keeps running with defaults.
  • does not allow arbitrary PTY byte sequences; terminal input is configurable only through named catalog actions.

Visual change

Settings > Shortcuts now includes the config path, Open/Reveal/Reload actions, diagnostics, source labels, and the effective keybinding list.

orca-keybindings-settings

AI code review summary

Cross-platform compatibility: checked shortcut platform handling, labels, and paths. The implementation maps Node platforms to macos, linux, and windows, uses path.join for the user config path, keeps Windows display paths explicit, preserves platform-specific defaults in the catalog, and keeps Electron menu accelerators on platform-aware paths.

Security: checked local file parsing and IPC exposure. The TOML file is read from the user's home directory only, parsed with smol-toml, never evaluated, and invalid entries are ignored with diagnostics. The new IPC surface returns keybinding snapshots, reloads the local config, and opens/reveals the local config file; it does not expose secrets or run user-supplied commands.

Testing

  • pnpm lint (passes with existing warnings in unrelated GitHub project components)
  • pnpm run typecheck:node
  • pnpm run typecheck:web
  • pnpm run build (build passed; local dev CLI symlink creation under /usr/local/bin reported permission denied but exited successfully)
  • pnpm vitest run --config config/vitest.config.ts src/shared/keybindings/*.test.ts src/shared/window-shortcut-policy.test.ts src/main/keybindings/*.test.ts src/main/ipc/keybindings.test.ts src/main/menu/register-app-menu.test.ts src/main/browser/browser-guest-ui.test.ts src/renderer/src/components/terminal/app-shell-shortcut-policy.test.ts src/renderer/src/components/terminal-pane/terminal-shortcut-policy.test.ts src/renderer/src/components/terminal-pane/terminal-paste-keybinding.test.ts src/renderer/src/components/terminal-pane/xterm-bypass-policy.test.ts src/renderer/src/store/slices/keybindings.test.ts
  • pnpm run test:e2e -- tests/e2e/keybindings-config.spec.ts
  • pnpm test was attempted locally, but unrelated orchestration/runtime tests failed because the checked-out better-sqlite3 native module was built for a different Node ABI (NODE_MODULE_VERSION 145 vs local Node's 137). The keybinding-specific suite above passed.

X handle: @hampsonw

@nwparker
nwparker self-requested a review May 14, 2026 08:35
@nwparker

Copy link
Copy Markdown
Contributor

Will try to take a look in the next 1-2 days

This has def gotten brought up a few times and I think it makes sense and I'd love to solve it soon. Thanks for the PR 🫡

@nwparker nwparker self-assigned this May 15, 2026
# Conflicts:
#	src/main/browser/browser-guest-ui.ts
#	src/main/browser/browser-manager.ts
#	src/main/index.ts
#	src/main/ipc/register-core-handlers.test.ts
#	src/main/ipc/register-core-handlers.ts
#	src/main/window/createMainWindow.ts
#	src/preload/api-types.ts
#	src/preload/index.ts
#	src/renderer/src/App.tsx
#	src/renderer/src/components/Terminal.tsx
#	src/renderer/src/components/settings/ShortcutsPane.tsx
#	src/renderer/src/components/terminal-pane/TerminalPane.tsx
#	src/renderer/src/components/terminal-pane/keyboard-handlers.ts
#	src/renderer/src/components/terminal-pane/xterm-bypass-policy.test.ts
#	src/renderer/src/components/terminal-pane/xterm-bypass-policy.ts
#	src/renderer/src/store/index.ts
#	src/renderer/src/store/slices/diffComments.test.ts
#	src/renderer/src/store/slices/store-session-cascades.test.ts
#	src/renderer/src/store/slices/store-test-helpers.ts
#	src/renderer/src/store/slices/tabs.test.ts
#	src/renderer/src/store/types.ts
@nwparker

Copy link
Copy Markdown
Contributor

Hey @Whamp I took at look at this, thanks alot for it! I did a bigger pass and also did the UX editor as well as JSON support
It's in the latest release.

Let me know if that resolves things! I hope so!
If not let me know

@nwparker nwparker closed this May 22, 2026
@Whamp

Whamp commented May 22, 2026

Copy link
Copy Markdown
Contributor Author

Fantastic thanks for the review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants