[Other]: `Cmd + [` / `Cmd + ]` cycles panes in creation order, not visual order — and there's no directional pane navigation
- Dominant language
- TypeScript
- Stars
- 71.3k
- Forks
- 4.7k
- Avg merge
- 14h 54m
- Merged PRs (30d)
- 520
Description
### Details
## Summary
`Cmd+]` / `Cmd+[` (`terminal.focusNextPane` / `focusPreviousPane`) cycle through panes in **the order the panes were created**, not the order they appear on screen. After a few splits — or after dragging panes to reorder them — the cycle order no longer matches anything you can see on screen.
Separately, I'd love to have **directional pane navigation** (modifier + arrow keys), but the natural chords are already taken by existing default bindings. I'd like to hear how people think this should be approached.
## What's actually happening
The cycle is an index step over the pane manager's pane list, and that list is the insertion order of a `Map` keyed by a monotonically increasing pane id. So it is, literally, creation order.
Visual layout lives somewhere else entirely — in the DOM split tree. Splitting inserts the new pane next to its source, and drag-to-reorder detaches the pane and re-inserts it elsewhere in the tree. Neither operation touches the `Map` ordering.
Because the two orders are maintained independently, they drift apart. There's also no focus-history / MRU tracking anywhere in the codebase, so the current behavior isn't "most recently used" either — it really is just creation order.
## Reproduction
**By splitting a pane that isn't the most recently created one:**
1. Start with pane A. Split right → pane B. Visual order `[A B]`, cycle order `[A B]`. ✅
2. Focus A. Split right → pane C. C is inserted next to A, so the visual order becomes `[A C B]` — but the cycle order is `[A B C]`.
3. From A, press `Cmd+]`. Focus skips C, the pane visually adjacent to A, and jumps to **B**, the far-right pane.
**By dragging panes:**
Drag a pane to a different position. The DOM tree updates; the pane `Map` does not. The cycle order stays locked to the original creation order, permanently out of sync with what's on screen.
## Prior art: other terminals
Orca's `Cmd+[` / `Cmd+]` match Ghostty's macOS defaults. Ghostty documents its `goto_split` action as:
> Focus on a split either in the specified direction (`right`, `down`, `left` and `up`), or in the adjacent split in the order of creation (`previous` and `next`).
So Ghostty's `Cmd+[` / `Cmd+]` are creation-order too. But Ghostty pairs them with a **directional** set that Orca never picked up:
| Ghostty (macOS) | Action |
|---|---|
| `Cmd+Opt+←/→/↑/↓` | `goto_split: left / right / up / down` |
| `Cmd+[` / `Cmd+]` | `goto_split: previous / next` (creation order) |
iTerm2 uses the same `Cmd+Opt+Arrow` chord for directional split navigation. tmux binds `prefix + Arrow` to `select-pane -L/-R/-U/-D`, and Vim binds `Ctrl-w h/j/k/l`. Directional navigation is essentially universal — Orca is the outlier in having only the cycle.
## What I'd like to discuss
**I'd like to see modifier + arrow key navigation between panes.** I'm not confident about the right way to get there, though, so I'd rather ask than propose.
The natural chord is taken, and so is its obvious alternative. Each is exactly half-occupied:
| | `←` | `→` | `↑` | `↓` |
|---|---|---|---|---|
| `Cmd+Opt` | `worktree.history.back` | `worktree.history.forward` | *free* | *free* |
| `Cmd+Shift` | *free* | *free* | `worktree.navigateUp` | `worktree.navigateDown` |
Claiming only the free halves would be the worst outcome — under the same modifier, two arrows would navigate panes and two would navigate worktrees. To free up a whole four-arrow family, one of the existing pairs has to move.
Two directions came to mind.
**1. Change what `Cmd+[` / `Cmd+]` cycle through: top-left to bottom-right order instead of creation order.**
No new shortcuts; it just makes the existing ones predictable, and drag-reorders would be picked up automatically. But you still can't move in a specific direction.
**2. Leave `Cmd+[` / `Cmd+]` alone, consolidate the worktree shortcuts under `Cmd+Shift`, and use `Cmd+Opt+Arrow` for pane navigation.**
This matches Ghostty and iTerm2. The catch is that `worktree.history.back/forward` is intercepted in the main process with no editable-target guard, so it fires even while you're typing in a text input. That looks deliberate — `Cmd+Opt+Arrow` isn't a text-editing chord on macOS, so it's safe to grab globally. Moving it onto `Cmd+Shift+Arrow` would break "select to start/end of line" app-wide, so an editable-focus carve-out would be needed first.
Before anything else, I'm curious whether people think this feature is worth having at all. If it is, I'd like to hear which of the two directions seems better — or whether there's an approach I haven't considered.
Contributor guide
Assessment
This issue has not been assessed yet.