Skip to content

feat(keybindings): add terminal cycling and split-focus shortcuts#2632

Open
janssonoskar wants to merge 7 commits intopingdotgg:mainfrom
janssonoskar:terminal-ctrl-tab-cycling
Open

feat(keybindings): add terminal cycling and split-focus shortcuts#2632
janssonoskar wants to merge 7 commits intopingdotgg:mainfrom
janssonoskar:terminal-ctrl-tab-cycling

Conversation

@janssonoskar
Copy link
Copy Markdown

@janssonoskar janssonoskar commented May 10, 2026

What Changed

Adds four keybinding commands for keyboard navigation in the terminal drawer:

  • terminal.next / terminal.previous: cycle terminals with wrap. Default ctrl+tab / ctrl+shift+tab.
  • terminal.focusLeft / terminal.focusRight: focus the terminal to the left/right within the current split, no wrap. Default mod+alt+arrowleft / mod+alt+arrowright (cmd+option+arrow on macOS, ctrl+alt+arrow elsewhere).

All four are gated on terminalFocus. Pure index helpers extracted to apps/web/src/terminalNavigation.ts with unit tests.

Closes #2630.

Why

The drawer already supports creating, splitting, and closing terminals from the keyboard. Moving between them requires the mouse. Defaults match Ghostty's platform defaults.

See #2630 for full context, including the cross-platform caveat (tested on macOS only) and the open question about how to handle the web variant where some of these keys are browser-reserved.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Adds new terminal navigation commands into ChatView’s global keydown handler, which could change keyboard behavior or conflict with browser/OS-reserved shortcuts (especially in web). Logic is straightforward and covered by unit tests, but impacts core interaction flow.

Overview
Adds four new terminal navigation commands—terminal.next, terminal.previous, terminal.focusLeft, and terminal.focusRight—with new default shortcuts and documentation updates (including a note about browser-reserved keys).

Wires these commands into ChatView so keyboard input can cycle between terminal groups (wraparound) and move focus left/right within a split (no wrap), using new shared helpers in terminalNavigation.ts with accompanying unit tests.

Extends the keybinding contract/schema and default keybindings list so these commands are recognized and test-covered in apps/web/src/keybindings.test.ts.

Reviewed by Cursor Bugbot for commit 4bc6864. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add terminal cycling and split-focus keybindings to ChatView

  • Adds four new commands: terminal.next, terminal.previous, terminal.focusLeft, and terminal.focusRight, registered in packages/contracts/src/keybindings.ts.
  • Default bindings (scoped to terminalFocus) map ctrl+tab/ctrl+shift+tab to cycle terminal groups with wrap-around, and mod+alt+arrow (macOS) / ctrl+alt+arrow (Linux/Windows) to move focus within the current split without wrap-around.
  • Introduces terminalNavigation.ts with two pure index helpers: nextCycleIndex (wrapping) and nextDirectionalIndex (bounded), used by the updated ChatView keydown handler.

Macroscope summarized 4bc6864.

janssonoskar and others added 3 commits May 10, 2026 14:19
Adds four new keybinding commands for keyboard-driven terminal navigation:

- terminal.next / terminal.previous — cycle terminals with wrap
  Default: ctrl+tab / ctrl+shift+tab (matches Ghostty, Windows Terminal)
  Alternate: alt+pagedown / alt+pageup (browser-safe; primary keys are
  reserved by Chromium/Firefox/Safari and cannot be intercepted in the
  web app)

- terminal.focusLeftPane / terminal.focusRightPane — directional pane
  focus within the current terminal, no wrap
  Default: mod+alt+arrowleft / mod+alt+arrowright (matches Ghostty,
  iTerm2: cmd+alt+arrow on macOS, ctrl+alt+arrow elsewhere)

All four are gated on `terminalFocus` so they only fire when focus is
inside a terminal and don't hijack ctrl+tab from the chat composer.

Pure index helpers (`nextCycleIndex`, `nextDirectionalIndex`) are
extracted to apps/web/src/terminalNavigation.ts with unit tests covering
wrap, edges, single-element, and out-of-range inputs.

Display labels for pageup/pagedown render as PgUp/PgDn.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
terminal.focusLeftPane  -> terminal.focusLeft
terminal.focusRightPane -> terminal.focusRight

The t3code codebase consistently uses "terminal" (the unit) and "split"
(the multi-terminal state); "pane" is not used anywhere else. Aligning
with native vocabulary keeps the command namespace consistent and
auto-generates cleaner labels in the keybindings settings UI:
"Terminal: Focus Left" / "Terminal: Focus Right".

Naming is still forward-compatible with vertical splits (pingdotgg#1049) — would
add terminal.focusUp / terminal.focusDown without renames.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
These were intended as browser-safe alternates to ctrl+tab, but on
macOS laptops without dedicated PageUp/PageDown keys, Fn+Option+Arrow
doesn't reliably synthesize Alt+PageUp/Down — the OS layer interferes.
Same problem VS Code has with its Ctrl+PageUp/Down terminal navigation.

Trying to bake browser support into defaults forces ergonomic
compromises. Keep the defaults targeted at the desktop app and direct
web-app users to customize via ~/.t3/keybindings.json. Docs updated to
reflect this.

The PgUp/PgDn display labels remain — users who add custom pageup/
pagedown bindings via the settings UI will still see clean labels.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 10006deb-ff8e-414a-b4ef-97c97a4272ef

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels May 10, 2026
Comment thread KEYBINDINGS.md
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented May 10, 2026

Approvability

Verdict: Needs human review

You can customize Macroscope's approvability policy. Learn more.

janssonoskar and others added 4 commits May 10, 2026 19:27
The user-facing commands are terminal.focusLeft / terminal.focusRight,
and the codebase uses "split" (not "pane") in UI-layer code. Rename
the internal callback to match.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Drops "pane" from describe/it labels to match the focusLeft/focusRight
command names. Each platform block now exercises both left and right
directions, and the terminalFocus guard test covers both. Added a
ctrl+shift+tab Linux/Windows assertion for terminal.previous symmetry.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Out of scope for the terminal navigation feature. No default binding
uses these keys after the alt+pageup/pagedown drop. Can be a separate
follow-up if needed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The note was inserted mid-list between terminal.focusRight and
commandPalette.toggle, breaking the bullet list in rendered Markdown.
Moved it after the list ends and dropped the em-dash for plain
punctuation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Keyboard shortcuts to navigate between terminals and splits

1 participant