Skip to content

Add tab and workspace rename keyboard shortcuts (macOS)#3280

Merged
Jinwoo-H merged 5 commits into
stablyai:mainfrom
Fybex:feat/rename-shortcuts
Jun 3, 2026
Merged

Add tab and workspace rename keyboard shortcuts (macOS)#3280
Jinwoo-H merged 5 commits into
stablyai:mainfrom
Fybex:feat/rename-shortcuts

Conversation

@Fybex

@Fybex Fybex commented May 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #3193 (tab number-jump). Covers the rename portion of #3163 that was explicitly deferred there ("Rename shortcuts remain for a follow-up because Cmd+R / Cmd+Shift+R overlap with browser reload and force-reload behavior and need a keybinding/default decision").

This is meant as a base sketch — the defaults are the debatable part, so I've made the safe choices explicit below; feel free to take this branch and change the chords/scope however you prefer.

Two rebindable catalog actions:

  • tab.rename⌘R (macOS) — rename the active terminal tab
  • workspace.rename⌥⌘R (macOS) — rename the active worktree

The keybinding/default decision

  • ⌘R is free in the app/terminal focus zone. The browser pane owns its own ⌘R reload in its own focus zone, so the chord never reaches the app-level window handler when a terminal/app surface is focused — no guard needed, no collision with browser.reload.
  • Workspace rename uses ⌥⌘R, not ⌘⇧R, to leave app.forceReload (⌘⇧R) untouched. (⌘⇧R would have required remapping a built-in; avoided.)
  • Unbound on Windows/Linux. There Ctrl+R is the shell reverse-search and Ctrl+Shift+R is reload, and Ctrl+Alt+R has no safe/conventional default (often grabbed by the DE). Function keys aren't supported by the binding parser either. Mirrors the existing macOS-only sidebar.ports.toggle. Users bind them in Settings → Shortcuts.

How it works

Rename state lives locally in the inline editors (SortableTab, WorktreeTitleInlineRename). A global shortcut can't reach it directly, so it sets an id-based store flag the matching component consumes and clears once:

  • renamingTabId (tabs slice) — keyed by terminal-tab id (same id space as activeTabId)
  • renamingWorktreeId (worktree slice)
  • App.tsx dispatches: ⌘R → setRenamingTabId(activeTabId) when the active tab is a terminal; ⌥⌘R → reveal the active worktree (so its card is mounted even when filtered) then setRenamingWorktreeId.
  • WorktreeTitleInlineRename stays presentational — driven by a beginEditing prop + onBeginEditingConsumed callback that WorktreeCard derives from / clears the store flag (consume-always so it can't linger; skips opening while disabled).

Known limitations (open to direction)

  • Rename targets terminal tabs only — browser/editor tabs have no inline title editor, so ⌘R no-ops there.
  • Wired in the sidebar WorktreeCard but not WorkspaceKanbanCard — ⌥⌘R won't open rename in the kanban view yet (small follow-up if wanted).
  • macOS-only defaults by design.

Validation

  • pnpm typecheck
  • pnpm lint
  • pnpm test — added unit tests pass (catalog defaults + no-conflict via scope separation; both store flags set/clear). The only failing suite tests are unrelated live-network hosted-review integration tests.
  • Manually exercised ⌘R (terminal tab rename, incl. terminal-focused) and ⌥⌘R (worktree rename) in the dev app; confirmed ⌘R still reloads in a focused browser tab and ⌘⇧R still force-reloads.

🤖 Generated with Claude Code

Risk assessment

Risk: HIGH

Historic risk metadata backfill based on the existing risk:high label.

Risk: high

Historic risk metadata backfill based on the existing risk:high label.

Add two rebindable catalog actions:
- tab.rename (Cmd+R, macOS) — rename the active terminal tab
- workspace.rename (Cmd+Opt+R, macOS) — rename the active worktree

Both open the existing inline title editor via an id-based store flag
(renamingTabId / renamingWorktreeId) that the matching component consumes and
clears once. App-level Cmd+R stays clear of browser reload because the browser
pane owns its own focus zone, so the chord never reaches the app handler there;
Cmd+Opt+R is used for workspace rename to avoid the global Force Reload chord
(Cmd+Shift+R), which is left untouched. Both are unbound on Windows/Linux,
where Ctrl+R is the shell reverse-search and no safe default exists — users
bind them in Settings.

Follow-up to stablyai#3193 (tab number-jump); covers the rename portion of stablyai#3163.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Keep rename shortcuts scoped to the active workspace surface, make workspace rename visible from collapsed/compact sidebar states, and add component/keybinding seam coverage.
@nwparker

nwparker commented May 29, 2026

Copy link
Copy Markdown
Contributor

Review/fix pass on the rename shortcuts is pushed as cb2d264187.

What changed:

  • Scoped tab/workspace rename shortcuts to the active workspace surface so stale rename signals are not queued while another app view owns focus.
  • Made workspace rename visible when the sidebar is collapsed by opening/revealing the active workspace before setting the rename trigger.
  • Wired the compact workspace kanban card into the shared inline rename trigger.
  • Added focused keybinding/component seam coverage for macOS-only rename matching, tab rename trigger consumption, and worktree title begin-editing consumption.

CDP/manual evidence:

  • Terminal focus on the PR worktree + Cmd+R opened the tab inline rename input, focused it, and consumed renamingTabId; no workspace rename input opened.
  • App chrome focus on the PR worktree (Toggle sidebar button focused) + Cmd+R also opened the active terminal tab rename input.
  • Workspace rename with the sidebar collapsed + Cmd+Option+R reopened the sidebar, focused the "Rename workspace" input, and consumed renamingWorktreeId (sidebarOpen: true, focused worktree input, renamingWorktreeId: null).
  • Browser reload collision was kept bounded per follow-up: BrowserPane owns browser.reload/browser.hardReload for active browser panes via renderer chrome handling and the guest-focus IPC reload path, while App.tsx now only runs tab.rename for workspaceActive && activeTabType === 'terminal'; keybindings.test.ts keeps the intentional macOS tab.rename/browser.reload same-chord scope separation conflict-free.

Verification:

  • pnpm exec vitest run --config config/vitest.config.ts src/shared/keybindings.test.ts src/renderer/src/store/slices/tabs.test.ts src/renderer/src/store/slices/worktrees.test.ts src/renderer/src/components/tab-bar/SortableTab.rename-shortcut.test.tsx src/renderer/src/components/sidebar/WorktreeTitleInlineRename.begin-editing.test.tsx src/renderer/src/components/sidebar/WorktreeTitleInlineRename.test.tsx -> 6 files / 163 tests passed.
  • pnpm exec oxlint on touched files -> 0 warnings / 0 errors.
  • git diff --check -> passed.
  • pnpm run typecheck -> passed.
  • pnpm run lint -> passed.

Draft status preserved; not merged.

@nwparker

Copy link
Copy Markdown
Contributor

Revalidated this shortcut/default-decision branch and moved it out of draft.

Decision on the draft/default concern:

  • tab.rename remains macOS-only with Mod+R, and the tests keep the intentional scope separation from browser reload conflict-free.
  • workspace.rename remains macOS-only with Mod+Alt+R, leaving app force-reload and Windows/Linux shell/browser conventions untouched.
  • The reviewer commit keeps rename triggers scoped to the active workspace surface and makes collapsed-sidebar workspace rename visible before opening the editor.

Fresh validation on head cb2d2641877495298391e331b94eb7dfa5fd3640:

  • pnpm exec vitest run --config config/vitest.config.ts src/shared/keybindings.test.ts src/renderer/src/store/slices/tabs.test.ts src/renderer/src/store/slices/worktrees.test.ts src/renderer/src/components/tab-bar/SortableTab.rename-shortcut.test.tsx src/renderer/src/components/sidebar/WorktreeTitleInlineRename.begin-editing.test.tsx src/renderer/src/components/sidebar/WorktreeTitleInlineRename.test.tsx — 6 files / 163 tests passed.
  • pnpm run typecheck — node, CLI, and web typechecks passed.
  • pnpm exec oxlint on touched files — 0 warnings, 0 errors.
  • pnpm run lint — passed across 3051 files.
  • git diff --check origin/main...HEAD — passed.
  • git merge-tree --write-tree origin/main HEAD — clean, tree bfe13e6f8e679f44044663f8f4db7b6bb30ed160.

Manual/CDP evidence from the review pass remains applicable on this head:

  • Terminal focus + Cmd+R opened the terminal tab inline rename input and consumed renamingTabId without opening workspace rename.
  • App chrome focus + Cmd+R opened the active terminal tab rename input.
  • Collapsed sidebar + Cmd+Option+R reopened the sidebar, focused the workspace rename input, and consumed renamingWorktreeId.
  • Browser reload collision stays bounded by BrowserPane owning browser reload while App.tsx only runs tab.rename when the workspace surface is active and the active tab is terminal.

No merge performed.

@nwparker
nwparker marked this pull request as ready for review May 30, 2026 04:53
@nwparker nwparker added the risk:high High risk change label May 30, 2026
@AmethystLiang
AmethystLiang requested a review from Jinwoo-H June 3, 2026 16:50
@AmethystLiang AmethystLiang assigned Jinwoo-H and unassigned nwparker Jun 3, 2026
Jinwoo-H and others added 2 commits June 3, 2026 13:51
# Conflicts:
#	src/renderer/src/components/sidebar/WorkspaceKanbanCard.tsx
#	src/renderer/src/components/sidebar/WorktreeList.lineage-child-card.test.ts
#	src/renderer/src/components/sidebar/WorktreeList.tsx
#	src/renderer/src/store/slices/worktrees.test.ts
#	src/shared/keybindings.ts

@Jinwoo-H Jinwoo-H left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is a useful follow-up to the tab shortcut work.

I pushed a maintainer follow-up that:

  • keeps tab/workspace rename shortcuts in a shared conflict group so user overrides cannot bind both to the same active-workspace chord
  • reveals the active workspace before beginning workspace rename, so filtered/collapsed/offscreen sidebar rows still mount the editor
  • routes nested lineage child titles through the same inline rename surface
  • prevents rename shortcuts from targeting the background workspace while focus is in the floating workspace panel
  • preserves the current main-branch macOS Option punctuation fallback while merging latest main

Validation:

RUN v4.1.5 /Users/jinwoohong/orca/workspaces/orca/pr-review-3280

Test Files 6 passed (6)
Tests 233 passed (233)
Start at 16:18:27
Duration 957ms (transform 1.80s, setup 0ms, import 1.42s, tests 1.24s, environment 0ms)

  •  WARN  Unsupported engine: wanted: {"node":"24"} (current: {"node":"v26.0.0","pnpm":"10.24.0"})

[email protected] typecheck /Users/jinwoohong/orca/workspaces/orca/pr-review-3280
tsgo --noEmit -p config/tsconfig.node.json && tsgo --noEmit -p config/tsconfig.tc.cli.json && tsgo --noEmit -p config/tsconfig.tc.web.json

  •  WARN  Unsupported engine: wanted: {"node":"24"} (current: {"node":"v26.0.0","pnpm":"10.24.0"})

[email protected] lint /Users/jinwoohong/orca/workspaces/orca/pr-review-3280
oxlint && pnpm run lint:switch-exhaustiveness && node config/scripts/check-styled-scrollbars.mjs

src/renderer/src/components/right-sidebar/ChecksPanel.tsx:2083:5: warning react-hooks(exhaustive-deps): React Hook useCallback has unnecessary dependency: prNumber help: Either include it or remove the dependency array.
src/renderer/src/components/right-sidebar/ChecksPanel.tsx:2083:5: warning react-hooks(exhaustive-deps): React Hook useCallback has unnecessary dependency: pr.headSha help: Either include it or remove the dependency array.
src/renderer/src/components/right-sidebar/ChecksPanel.tsx:2083:5: warning react-hooks(exhaustive-deps): React Hook useCallback has unnecessary dependency: pr.prRepo help: Either include it or remove the dependency array.
src/renderer/src/components/right-sidebar/ChecksPanel.tsx:2248:5: warning react-hooks(exhaustive-deps): React Hook useCallback has unnecessary dependency: linkedGitLabMR help: Either include it or remove the dependency array.
 WARN  Unsupported engine: wanted: {"node":"24"} (current: {"node":"v26.0.0","pnpm":"10.24.0"})

[email protected] lint:switch-exhaustiveness /Users/jinwoohong/orca/workspaces/orca/pr-review-3280
oxlint --type-aware --config config/oxlint-switch-exhaustiveness.json src/main src/preload src/shared src/relay src/cli src/renderer/src config tests --quiet (existing ChecksPanel hook-dependency warnings only)

  • Electron dev app: verified ⌘R opens the terminal-tab rename input and ⌘⌥R opens the workspace rename input in the rendered UI.

# Conflicts:
#	src/main/git/status-upstream-probe-churn.test.ts
#	src/renderer/src/components/sidebar/WorktreeList.lineage-child-card.test.ts
@Jinwoo-H
Jinwoo-H merged commit 2ba6f00 into stablyai:main Jun 3, 2026
thomaszdxsn pushed a commit to thomaszdxsn/orca that referenced this pull request Jun 15, 2026
Adds configurable macOS shortcuts for renaming the active terminal tab and active workspace, with review follow-up fixes for conflict detection, sidebar reveal, lineage child rename surfaces, and floating workspace focus scoping.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:high High risk change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants