Skip to content

Add configurable scrollback page shortcuts (fixes #4645) - #5590

Open
mrzv wants to merge 13 commits into
manaflow-ai:mainfrom
mrzv:scrollback-shortcuts
Open

mrzv wants to merge 13 commits into
manaflow-ai:mainfrom
mrzv:scrollback-shortcuts

Conversation

@mrzv

@mrzv mrzv commented Jun 8, 2026 •

Copy link
Copy Markdown

Summary

Add configurable shortcuts for scrolling.

The defaults are Shift+PgUp/PgDown.

In ~/.config/cmux/cmux.json:

{
  "shortcuts": {
    "bindings": {
      "scrollbackPageUp": "shift+pageup",
      "scrollbackPageDown": "shift+pagedown",
      "scrollbackLineUp": null,
      "scrollbackLineDown": null
    }
  }
}

scrollbackLineUp / scrollbackLineDown are intentionally unbound by default so shells and terminal apps can receive Shift+Up / Shift+Down. The user can bind them, for example:

{
  "shortcuts": {
    "bindings": {
      "scrollbackLineUp": "shift+up",
      "scrollbackLineDown": "shift+down"
    }
  }
}

Testing

Verified manually that the default shortcuts work.

Review Trigger (Copy/Paste as PR comment)

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

Checklist

  • I tested the change locally
  • I added or updated tests for behavior changes
  • I updated docs/changelog if needed
  • I requested bot reviews after my latest commit (copy/paste block above or equivalent)
  • All code review bot comments are resolved
  • All human review comments are resolved

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Adds configurable terminal scrollback shortcuts for page and line scrolling (fixes #4645). Defaults to Shift+Page Up/Down and also matches Fn+Up/Down; line scrolling is unbound by default so shells can receive Shift+Up/Down.

  • New Features

    • New actions: scrollbackPageUp, scrollbackPageDown, scrollbackLineUp, scrollbackLineDown; routed to the focused terminal and scoped outside browser panels.
    • Configurable via shortcuts.bindings in ~/.config/cmux/cmux.json; supports pageup/pagedown and aliases pgup/pgdn.
    • Shortcut recorder, matcher, and labels recognize Page Up/Down (including Fn+Up/Down) and arrow keys; labels localized in English and Japanese.
    • Docs, schema, and web help updated (includes line-scroll sign convention); changelog localization is resilient; tests added for defaults, alias parsing, keycode/Fn matching, routing, and sign convention.
  • Bug Fixes

    • Scrollback shortcuts don’t consume Shift+Up/Down when the TextBox input is focused; keystrokes pass through to the text view.

Written for commit 4009e61. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Configurable terminal scrollback shortcuts: Page Up, Page Down, Line Up, Line Down. Defaults: Shift+Page Up / Shift+Page Down; line-scroll shortcuts unbound by default.
  • UX

    • Shortcut lists now render Page Up / Page Down tokens with proper localized labels.
  • Localization

    • Added localized labels and changelog entries for the new shortcuts.
  • Documentation

    • Docs, examples, and schema updated for binding/unbinding these shortcuts.
  • Bug Fix

    • Shift+Arrow shortcuts no longer intercept text-input focus.
  • Tests

    • Added unit tests covering shortcut behavior, matching, and focus routing.

@vercel

vercel Bot commented Jun 8, 2026

Copy link
Copy Markdown

@mrzv is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds four configurable terminal scrollback actions (page/line up/down): key parsing/matching, UI display, runtime routing to TabManager, schema/web catalog updates, docs/localization, and tests.

Changes

Scrollback Navigation Shortcuts

Layer / File(s) Summary
Scrollback Action Definition
Packages/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction.swift, Packages/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction+Defaults.swift
Adds scrollbackPageUp, scrollbackPageDown, scrollbackLineUp, scrollbackLineDown; categorized under navigation with localized display names. Page shortcuts default to Shift+page keys; line shortcuts are unbound by default.
Keyboard Shortcut Configuration
Sources/KeyboardShortcutSettings.swift, Sources/KeyboardShortcutContext.swift
Adds KeyboardShortcutSettings.Action cases, localized labels, default shortcuts for page actions, and scopes these actions to .nonBrowserPanel.
ShortcutStroke Parsing & Matching
Sources/KeyboardShortcutSettings.swift
Parses multiple page-key aliases, records/stores page key codes, resolves page tokens to Carbon key codes, treats page keys as direct key-code matches, includes page codes in supported list, and special-cases arrow-key matching.
UI Key Display Rendering
Packages/CmuxSettingsUI/.../GlobalHotkeySection.swift, Packages/CmuxSettingsUI/.../KeyboardShortcutsSection.swift
Settings UI now renders pageUp/pageup and pageDown/pagedown as localized “Page Up” / “Page Down”.
Localization Strings & Web Messages
Resources/Localizable.xcstrings, web/messages/*
Adds localized key labels for page keys and display/label strings for the four scrollback actions; inserts a changelog translation key across many locales.
Execution Routing & TabManager APIs
Sources/AppDelegate.swift, Sources/TabManager.swift
AppDelegate routes new actions to the routed TabManager; TabManager adds scrollFocusedTerminalScrollbackPage(up:) and scrollFocusedTerminalScrollbackLine(up:) that delegate to performBindingAction when focus intent matches.
Schema & Web Shortcut Catalog
web/data/cmux.schema.json, web/data/cmux-shortcuts.ts
Schema allowlist and web shortcut catalog updated to include the four new action IDs and catalog metadata.
Docs, Examples & CHANGELOG
CHANGELOG.md, docs/configuration.md, skills/cmux-settings/references/shortcut-actions.md, web/app/.../docs/*
Documentation and examples updated to show the new scrollback bindings and config token mappings (Page Up/Page Down → pageup/pagedown).
Tests
cmuxTests/*
Adds unit/integration tests for default/unbound behavior, settings-file parsing canonicalization, stored-shortcut matching, context scoping, and a regression ensuring line shortcuts don’t steal Shift+Arrow when a TextBox is first responder.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • manaflow-ai/cmux#4436: Modifies shortcut matching in Sources/KeyboardShortcutSettings.swift and may overlap with the new page-key matching changes.
  • manaflow-ai/cmux#4445: Changes AppDelegate.handleCustomShortcut routing logic, intersecting with the routing additions here.
  • manaflow-ai/cmux#5178: Adds shortcut routing branches in AppDelegate, related to dispatch behavior introduced in this PR.

Suggested reviewers

  • Ari4ka

Poem

🐰 I hopped across the keymap neat,
Page keys, tokens, labels meet,
Scroll by page or line unbound,
Locales sang and tests were found,
A tiny rabbit's joyful beat.

🚥 Pre-merge checks | ✅ 18 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (18 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add configurable scrollback page shortcuts (fixes #4645)' clearly summarizes the main change—adding configurable shortcuts for scrollback navigation—and directly references the associated issue.
Linked Issues check ✅ Passed The PR implements all core requirements from issue #4645: bindable scroll shortcuts (scrollLineUp, scrollLineDown, and page variants), configurable via shortcuts.bindings in cmux.json, working without entering copy mode, with line shortcuts unbound by default to avoid shell conflicts.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the scrollback shortcuts feature: new enum cases, routing logic, UI support, localization, documentation, schema updates, and comprehensive tests. No unrelated modifications detected.
Cmux Swift Actor Isolation ✅ Passed All production Swift changes maintain proper actor isolation: new enum cases in Sendable types, new methods in @MainActor classes, no implicit MainActor leakage.
Cmux Swift Blocking Runtime ✅ Passed No blocking primitives introduced in production Swift code. New scrollback methods use guards and direct calls without synchronization.
Cmux No Hacky Sleeps ✅ Passed PR introduces no sleep/setTimeout/polling/timer code in TypeScript/JavaScript/shell production files. All changes are data structures, documentation, localization, or Swift code (out of scope).
Cmux Algorithmic Complexity ✅ Passed All new code paths execute in O(1) time with no collection scans or nested loops. Four enum cases added; existing loops not modified or moved to hotter paths.
Cmux Swift Concurrency ✅ Passed New scrollback code is synchronous with direct returns (no completion handlers, DispatchQueue background work, fire-and-forget Tasks, or new Combine patterns).
Cmux Swift @Concurrent ✅ Passed All new Swift functions are synchronous with no @concurrent or nonisolated async violations. New methods properly isolated on @MainActor with no async/actor isolation issues.
Cmux Swift File And Package Boundaries ✅ Passed All Swift additions respect file boundaries: oversized files receive <250 lines, responsibilities remain coherent, and feature logic is properly distributed across package/app targets.
Cmux Swift Logging ✅ Passed All production Swift code added complies with swift-logging.md: no print, debugPrint, dump, or NSLog in new app/runtime code; no ad hoc logging or MainActor Logger issues; no exposed secrets.
Cmux User-Facing Error Privacy ✅ Passed All user-facing strings in this PR comply with privacy rules: no vendor/provider names, credentials, or implementation details are exposed; generic product terminology is consistently used.
Cmux Full Internationalization ✅ Passed All Swift strings use String(localized:) with Localizable.xcstrings entries for en/ja; all 20 web locales have scrollbackShortcuts translations; code uses next-intl correctly.
Cmux Swiftui State Layout ✅ Passed SwiftUI changes add case statements in existing private static functions to handle pageUp/pageDown tokens. No new @Published, @StateObject, @EnvironmentObject, or layout-changing patterns introduced.
Cmux Architecture Rethink ✅ Passed Scrollback implementation shows clear single ownership path with no timing repairs, mutable caches, observers, or duplicate wiring.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR adds scrollback shortcuts via existing panes; no new NSWindow/NSPanel/NSWindowController/Window/WindowGroup created. Operates on terminal panes/views, within allowed scope.
Cmux Source Artifacts ✅ Passed All PR files are hand-written source, tests, docs, configs, and localizations—no artifacts, logs, caches, or scratch directories detected per source-control-artifacts rule.
Description check ✅ Passed The PR description covers all required sections: Summary (what changed and why), Testing (manual verification), Review Trigger, and completed Checklist with all items marked as done.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

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

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.

@greptile-apps

greptile-apps Bot commented Jun 8, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds four configurable terminal scrollback actions (scrollbackPageUp, scrollbackPageDown, scrollbackLineUp, scrollbackLineDown) with Shift+Page Up/Down defaults and line-scroll intentionally unbound so shells can receive Shift+Up/Down. The implementation adds a dual-path key matching strategy for Page keys (via NSEvent.SpecialKey and keycode) and an explicit arrow-key-by-keycode path, with thorough tests for alias parsing, keycode matching, routing, and the Ghostty sign convention.

  • Shortcut dispatch — four routing blocks in AppDelegate.swift delegate to new TabManager methods that guard on captureFocusIntent, ensuring Shift+Arrow keypresses pass through to TextBox and browser panels unchanged.
  • Key matching — KeyboardShortcutSettings.swift gains isPageShortcutKey and isArrowShortcutKey helpers, keyCodeToString entries for Page Up/Down, and a config-alias normalizer covering pgup/pgdn/page-up variants.
  • Localization — all new catalog keys carry both en and ja translations in Localizable.xcstrings, and all 20 web locale files receive the changelog entry; however, the changelog translation uses a fragile English-text prefix match (see comment on changelog/page.tsx).

Confidence Score: 5/5

Safe to merge; the feature is well-isolated, fully tested, and does not touch any shared state paths that could regress existing shortcuts.

The new shortcut actions are correctly guarded behind captureFocusIntent so they can't accidentally consume arrow keys when a TextBox or browser panel is active. The key-matching logic handles both real Page Up keys and Fn+Arrow laptop events through complementary code paths. Tests cover defaults, alias parsing, keycode matching, routing, and the Ghostty sign convention. The only open item is the fragile English-text prefix used to locate the changelog entry for translation, which is a maintainability concern rather than a runtime defect.

web/app/[locale]/docs/changelog/page.tsx — the changelog localization lookup is coupled to the English prose in CHANGELOG.md.

Important Files Changed

Filename Overview
Sources/KeyboardShortcutSettings.swift Adds pageup/pagedown key support via a dual-path matching strategy: early return in matches(event:) for Page keys recognized via NSEvent.SpecialKey, plus usesDirectKeyCodeMatching coverage for keyCode-based dispatch. Also adds isArrowShortcutKey path to ensure arrow key shortcuts always match by keyCode. Dead mixed-case branches in the key-display switch are unreachable (already noted in prior review thread).
Sources/AppDelegate.swift Adds four shortcut handler blocks for scrollback actions; routes each to tabManager.scrollFocusedTerminalScrollbackPage/Line. Pattern is consistent with surrounding shortcut routing code.
Sources/TabManager.swift Adds scrollFocusedTerminalScrollbackPage(up:) and scrollFocusedTerminalScrollbackLine(up:), both guarded by captureFocusIntent so they only fire when a terminal surface has focus. Static scrollbackLineBindingAction correctly encodes Ghostty's negative-for-up sign convention.
web/app/[locale]/docs/changelog/page.tsx Adds fuzzy prefix-match localization for one changelog entry. The match is anchored to the English text in CHANGELOG.md; any future edit to that text silently reverts non-English users to English copy.
Resources/Localizable.xcstrings Adds 8 new string keys (4 label + 4 displayName) with both en and ja translations — all new entries are fully translated, addressing the concern raised in the prior review thread.
cmuxTests/WorkspaceUnitTests.swift Adds unit tests for default shortcut values, alias canonicalization (pgup/pgdn etc.), and keyCode matching including Fn+Arrow laptop events. Comprehensive coverage.

Sequence Diagram

sequenceDiagram
    participant OS as macOS Event System
    participant AD as AppDelegate (shortcut monitor)
    participant SC as ShortcutStroke.matches(event:)
    participant TM as TabManager
    participant Term as Terminal Surface

    OS->>AD: NSEvent (e.g. Shift+PageUp)
    AD->>AD: matchConfiguredShortcut(event:, action: .scrollbackPageUp)
    AD->>SC: matches(event:)
    SC->>SC: recordableKey(from: event) → "pageup" via NSEvent.SpecialKey
    SC->>SC: isPageShortcutKey? → early-return true
    SC-->>AD: true
    AD->>AD: preferredMainWindowContextForShortcutRouting
    AD->>TM: scrollFocusedTerminalScrollbackPage(up: true)
    TM->>TM: "captureFocusIntent == .terminal(.surface)?"
    alt Terminal surface focused
        TM->>Term: performBindingAction("scroll_page_up")
        Term-->>TM: true
        TM-->>AD: true (event consumed)
    else TextBox or browser focused
        TM-->>AD: false (event passed through)
    end
Loading

Reviews (9): Last reviewed commit: "Match page shortcuts from Fn arrow keys" | Re-trigger Greptile

Comment thread Resources/Localizable.xcstrings
Comment thread Sources/KeyboardShortcutSettings.swift Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Packages/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction.swift`:
- Around line 213-216: The displayName for the new ShortcutAction cases
(.scrollbackPageUp, .scrollbackPageDown, .scrollbackLineUp, .scrollbackLineDown)
is currently hardcoded in ShortcutAction; replace those literal English strings
with localized lookups (e.g., NSLocalizedString or your project's string catalog
API) using unique keys (e.g., "shortcut.scrollbackPageUp.displayName", etc.) and
update the Localizable.strings (or catalog) with corresponding translations;
ensure the ShortcutAction.displayName computed property returns the localized
string for each of the four cases.

In `@Resources/Localizable.xcstrings`:
- Around line 128677-128693: Update the Japanese localizations for the
scrollback page labels so they are proper translations instead of copied
English: replace the "ja" value for the key shortcut.scrollbackPageDown.label
with "スクロールバックを1ページ下へ" and the "ja" value for shortcut.scrollbackPageUp.label
with "スクロールバックを1ページ上へ"; ensure the "stringUnit.state" remains "translated" for
both entries to match the pattern used by the line scrollback labels.
- Around line 125442-125475: Replace the English placeholders in the Japanese
localizations for the shortcut keys: update the "ja" stringUnit.value for
"shortcut.key.pageDown" and "shortcut.key.pageUp" to proper Japanese
translations (e.g., "ページダウン" and "ページアップ") so they are not identical to the
English values; modify the entries for the keys "shortcut.key.pageDown" and
"shortcut.key.pageUp" in Resources/Localizable.xcstrings to set the ja
localization to the suggested Japanese strings.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4419f4d7-2393-4cb4-ab9e-5fe2f09152a2

📥 Commits

Reviewing files that changed from the base of the PR and between 7135f32 and e82030e.

📒 Files selected for processing (11)
  • Packages/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction+Defaults.swift
  • Packages/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction.swift
  • Packages/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/GlobalHotkeySection.swift
  • Packages/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/KeyboardShortcutsSection.swift
  • Resources/Localizable.xcstrings
  • Sources/AppDelegate.swift
  • Sources/KeyboardShortcutContext.swift
  • Sources/KeyboardShortcutSettings.swift
  • Sources/TabManager.swift
  • web/data/cmux-shortcuts.ts
  • web/data/cmux.schema.json

Comment thread Packages/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction.swift Outdated
Comment thread Resources/Localizable.xcstrings
Comment thread Resources/Localizable.xcstrings Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Line 9: The new English-only changelog line in CHANGELOG.md must be localized
for all supported docs locales: update CHANGELOG.md (or move the entry into the
localized changelog files) so that the same changelog copy exists for every
locale listed in web/i18n/routing.ts; identify the locales from
web/i18n/routing.ts and add translated versions of the "Configurable terminal
scrollback shortcuts..." entry for each locale key, ensuring the localized copy
is used by the docs renderer (match filenames/locale suffixes used by existing
localized changelog entries and follow the existing localization pattern).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5766f29d-53f8-455a-8889-e10202d032df

📥 Commits

Reviewing files that changed from the base of the PR and between e82030e and a53f9c1.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • docs/configuration.md
  • skills/cmux-settings/references/shortcut-actions.md
  • web/app/[locale]/docs/configuration/page.tsx
  • web/app/[locale]/docs/keyboard-shortcuts/page.tsx
  • web/data/cmux-shortcuts.ts

Comment thread CHANGELOG.md Outdated
@mrzv

mrzv commented Jun 8, 2026

Copy link
Copy Markdown
Author

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 8, 2026

Copy link
Copy Markdown

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@mrzv I can't start this review because your workspace has reached its free monthly review limit. Reviews resume at the start of your next billing cycle. Paid plans include much higher monthly review limits. Upgrade now to resume reviews.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

1 similar comment
@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the TabManager scrollback methods
rg -n "scrollFocusedTerminal" Sources/TabManager.swift -A 5
echo "---"
# Check AppDelegate handling
rg -n "scrollbackPage\|scrollbackLine\|scrollback" Sources/AppDelegate.swift -C 3
echo "---"
# Check KeyboardShortcutSettings for the new actions and arrow key handling
rg -n "scrollback\|isArrowShortcut\|usesDirectKeyCode\|pageup\|pagedown" Sources/KeyboardShortcutSettings.swift -C 2
echo "---"
# Check KeyboardShortcutContext
rg -n "scrollback\|nonBrowserPanel" Sources/KeyboardShortcutContext.swift -C 3
echo "---"
# Check for existing Shift+Up / Shift+Down bindings that could conflict
rg -n "shift.*up\|shift.*down\|\.up\|\.down" Sources/KeyboardShortcutSettings.swift -i -C 2 | head -60
echo "---"
# Check the scroll_page_lines action format
rg -n "scroll_page_lines\|scroll_page_up\|scroll_page_down\|performBindingAction" Sources/TabManager.swift -C 3

Length of output: 1810


🏁 Script executed:

#!/bin/bash
# Check cmux-shortcuts.ts for the new entries
rg -n "scrollback" web/data/cmux-shortcuts.ts -C 3
echo "---"
# Check for existing shift+up/shift+down shortcuts to look for conflicts
rg -n "shift.*up\|shift.*down" web/data/cmux-shortcuts.ts -i -C 2
echo "---"
# Check docs/configuration.md new content
cat docs/configuration.md | tail -60
echo "---"
# Check schema updates
rg -n "scrollback" web/data/cmux.schema.json

Length of output: 4605


🏁 Script executed:

#!/bin/bash
# Get full KeyboardShortcutSettings scrollback section
rg -n "scrollback\|scrollBack\|isArrow\|usesDirectKey\|pageup\|pagedown\|pgup\|pg_up\|page.up" Sources/KeyboardShortcutSettings.swift -i -C 2
echo "==="
# Check performBindingAction signature/usage to understand the format
rg -n "performBindingAction" Sources/ -C 3 | head -60
echo "==="
# Check scroll_page_lines format — is it used elsewhere?
rg -rn "scroll_page_lines\|scroll_page_up\|scroll_page_down" Sources/ --type swift
echo "==="
# Check for existing shift+up / shift+down conflicts in defaults
rg -n "\.up\b\|\.down\b\|shiftUp\|shiftDown\|shift.*arrow\|arrowUp\|arrowDown" Sources/KeyboardShortcutSettings.swift -i -C 3 | head -80
echo "==="
# Inspect ShortcutAction+Defaults.swift for the new entries
fd "ShortcutAction+Defaults.swift" --exec cat {}

Length of output: 4466


🏁 Script executed:

#!/bin/bash
# Find ShortcutAction files
fd "ShortcutAction" --type f
echo "==="
# Get scrollback-related lines from KeyboardShortcutSettings
fd "KeyboardShortcutSettings.swift" --type f --exec rg -n "scrollback\|pageup\|pagedown\|isArrow\|usesDirectKey" {} -i -C 3
echo "==="
# Check if configValue is used for line shortcuts anywhere
rg -n "configValue\|scrollbackLine" web/data/cmux-shortcuts.ts -C 2
echo "==="
# Find the ShortcutAction+Defaults.swift
fd "ShortcutAction" --type f --exec cat {}

Length of output: 19586



@mrzv: I've reviewed PR #5590. The implementation is thorough — all the required locations are updated per project conventions (KeyboardShortcutSettings, Settings UI, schema, docs, localizations). Here are my findings:


Review of PR #5590 — Add configurable scrollback page shortcuts

🔴 Bug / Inconsistency

configValue missing for scrollbackLineUp / scrollbackLineDown in web/data/cmux-shortcuts.ts

Lines 136–139 of web/data/cmux-shortcuts.ts:

{ id: "scrollbackPageUp",   combos: [["⇧", "Page Up"]],   configValue: "shift+pageup",   description: { ... } },
{ id: "scrollbackPageDown",  combos: [["⇧", "Page Down"]],  configValue: "shift+pagedown",  description: { ... } },
{ id: "scrollbackLineUp",    combos: [["⇧", "↑"]],                                          description: { ... } },  // ← missing configValue
{ id: "scrollbackLineDown",  combos: [["⇧", "↓"]],                                          description: { ... } },  // ← missing configValue

The page variants correctly include configValue so the docs UI can generate copy-pasteable config snippets. The line variants are missing it. They should be:

{ id: "scrollbackLineUp",   combos: [["⇧", "↑"]], configValue: "shift+up",   description: { ... } },
{ id: "scrollbackLineDown", combos: [["⇧", "↓"]], configValue: "shift+down", description: { ... } },

🟡 Potential UX Issue — Default Shift+↑ / Shift+↓

These two keys are commonly intercepted by in-terminal applications:

  • readline / bash / zsh: Shift+Up / Shift+Down send \e[1;2A / \e[1;2B, used by fish's history-pager and other shells for interactive selection.
  • Vim visual mode: Shift+↑/↓ extend line selections.
  • tmux copy mode: similar arrow bindings.

Since cmux intercepts these at the macOS app level for terminal panels (.nonBrowserPanel context), they will be swallowed before the shell or running TUI sees them. Users running fish, interactive fzf sessions, or vim visual mode inside a cmux terminal will notice the keys stop working with the defaults in place.

Suggestion: Consider a less-conflicting default for the line variants, such as Cmd+Shift+Up / Cmd+Shift+Down, or document prominently that users should remap these if they use shell history-pager features. Alternatively, ship the line variants with nil defaults (unbound by default) and let users opt in.


🟡 Minor — scroll_page_lines sign convention

In Sources/TabManager.swift (line 2453):

return panel.performBindingAction(up ? "scroll_page_lines:-1" : "scroll_page_lines:1")

The -1 for "up" and +1 for "down" follows Ghostty's convention (negative = toward top of scrollback), but it's non-obvious to a reader. A short inline comment would help:

// Ghostty convention: negative = toward top of scrollback (up), positive = toward bottom
return panel.performBindingAction(up ? "scroll_page_lines:-1" : "scroll_page_lines:1")

✅ What looks good

  • All required locations are updated per the project's keyboard shortcut requirements: KeyboardShortcutSettings, Settings UI (new displayName cases with proper String(localized:defaultValue:)), ShortcutAction+Defaults.swift, cmux.schema.json, docs/configuration.md, skills/cmux-settings/references/shortcut-actions.md, and the web shortcuts docs page.
  • nonBrowserPanel context classification is correct — these are terminal-only actions.
  • Multiple pageup/pagedown aliases accepted in config parsing is a nice UX touch.
  • The isArrowShortcutKey special-case prevents Shift+↑/↓ from false-matching other shortcuts — good defensive coding.
  • Localization covers en + ja in both Localizable.xcstrings and web/data/cmux-shortcuts.ts, consistent with the project's established pattern.
  • Changelog and all locale JSON files updated.

🧠 Learnings used
Learnt from: atani
Repo: manaflow-ai/cmux PR: 819
File: Sources/AppDelegate.swift:3491-3493
Timestamp: 2026-03-04T14:06:16.241Z
Learning: For manaflow-ai/cmux PR `#819` (Japanese i18n), keep scope limited to localization changes; UX enhancements like preferring workspace.customTitle in workspaceDisplayName() or altering move-target labels should be handled in a separate follow-up issue.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3207
File: scripts/perf-activation-session.py:0-0
Timestamp: 2026-04-28T07:00:45.158Z
Learning: Repo: manaflow-ai/cmux — scripts/perf-activation-session.py (Python) — Synthetic scrollback fallback logic (as of commit 25004f18, PR `#3207`):
The harness first records `snapshot_with_real_scrollback` (benchmarked via RPC with the real shell-driven scrollback in place). It then compares the real captured scrollback character count against the configured budget threshold; the synthetic fallback RPC (`debug.session_snapshot_seed_scrollback`) is only invoked when the real scrollback chars fall below that budget. This replaces the earlier ca205f09 approach that gated solely on `scrollback_pending > 0`, because a runner can clear all pending terminals while still producing too few characters (e.g. slow CI, truncated output). Both the real and any synthetic measurement are recorded in the result artifact for auditability.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2528
File: Sources/cmuxApp.swift:6439-6444
Timestamp: 2026-04-03T03:35:58.703Z
Learning: Repo: manaflow-ai/cmux — KeyboardShortcutSettings.setShortcut(...) is a no-op when KeyboardShortcutSettings.isManagedBySettingsFile(action) returns true (i.e., the action is managed by settings.json). This prevents backfilling overrides into UserDefaults and preserves the settings file as the source of truth.

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-06-08T03:55:05.170Z
Learning: Every new cmux-owned keyboard shortcut must be added to `KeyboardShortcutSettings`, visible/editable in Settings, supported in `~/.config/cmux/cmux.json`, and documented in keyboard shortcut docs

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3784
File: README.md:161-161
Timestamp: 2026-05-09T04:48:39.144Z
Learning: In the cmux project (manaflow-ai/cmux), as of PR `#3784`, the shortcut assignments for the right-sidebar area were intentionally swapped:
- ⌘+⇧+E (Cmd+Shift+E) → `focusRightSidebar` action, user-facing label "Toggle right sidebar focus"
- ⌘+⌥+B (Cmd+Option+B) → `toggleFileExplorer` action, user-facing label "Open file explorer" (visibility toggle)
This change is reflected consistently across KeyboardShortcutSettings.swift, cmuxApp.swift, Localizable.xcstrings, web/data/cmux-shortcuts.ts, README.md, and the unit/routing tests. Do not flag the ⌘⇧E label as "Open file explorer" in any of these files — that label now belongs to ⌘⌥+B / toggleFileExplorer.

Learnt from: austinywang
Repo: manaflow-ai/cmux PR: 5178
File: web/data/cmux-shortcuts.ts:223-227
Timestamp: 2026-06-02T08:18:29.897Z
Learning: In the manaflow-ai/cmux project, `LocalizedText` in `web/data/cmux-shortcuts.ts` is intentionally typed as `{ en: string; ja: string }` — every shortcut entry in that file provides only English and Japanese descriptions. The keyboard-shortcuts docs renderer has an explicit English fallback for all other locales. This is the established design for the entire shortcuts data file. Reviewers should NOT flag individual shortcut entries for missing locale coverage beyond en/ja in this file; extending to additional locales would require a separate project-wide change to the shortcuts i18n system. The native macOS Settings UI label localization (via Localizable.xcstrings) is separate and does cover all supported catalog locales.

Learnt from: islee23520
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-29T04:20:21.124Z
Learning: Repo: manaflow-ai/cmux — In Sources/GhosttyTerminalView.swift (PR `#3275`), blocking Ctrl+B (the tmux prefix key) is an explicit product requirement for workspaces imported as real-tmux workspaces (i.e., where `realTmuxSessionId` is non-nil). The `shouldBlockRealTmuxShortcut` helper suppresses both keyDown and keyUp events for Ctrl+B when the surface's workspace is a real-tmux workspace, preventing the prefix from being sent to the underlying Ghostty terminal. This behavior must not be removed or gated further.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2528
File: Sources/cmuxApp.swift:6439-6444
Timestamp: 2026-04-03T03:37:25.743Z
Learning: Repo: manaflow-ai/cmux — In Sources/KeyboardShortcutSettings.swift, KeyboardShortcutSettings.setShortcut(_:, for:) is a no‑op when the action is managed by settings.json (isManagedBySettingsFile(action) == true), preventing UserDefaults backfill for file‑managed shortcuts.

Learnt from: alumican
Repo: manaflow-ai/cmux PR: 2051
File: Sources/AppDelegate.swift:9270-9276
Timestamp: 2026-03-24T13:50:07.535Z
Learning: Repo: manaflow-ai/cmux — KeyboardShortcutSettings.Action.toggleTextBoxInput defaults to Cmd+Option+B. Rationale: avoid conflict with the existing hard-coded Cmd+Option+T binding that triggers closeOtherTabsInFocusedPaneWithConfirmation() in AppDelegate.handleCustomShortcut(event:).

Learnt from: gaelic-ghost
Repo: manaflow-ai/cmux PR: 2262
File: web/messages/da.json:328-330
Timestamp: 2026-03-27T21:57:24.976Z
Learning: Repo: manaflow-ai/cmux — In web/messages/*.json i18n files, it is intentional for lower-confidence locales (e.g., da.json, ar.json, bs.json, th.json, km.json, etc.) to contain English-language fallback strings for newly added or updated keys. Only locales where the author is confident in the wording receive translated copy in the same PR. Do not flag untranslated/English strings in these locale files as a localization bug; they are a deliberate fallback strategy.

@mrzv

mrzv commented Jun 8, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f875855185

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/AppDelegate.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/app/`[locale]/docs/changelog/page.tsx:
- Line 42: The current strict full-string match for the changelog entry
(variable scrollbackShortcutsChangelogItem) is brittle and will miss small copy
edits; update the lookup/locale-matching logic to use a stable key or a tolerant
comparison instead — e.g., map the entry by a fixed identifier/slug (preferred)
or match using a normalized substring/startsWith/includes check against
scrollbackShortcutsChangelogItem so minor wording/punctuation changes in
CHANGELOG.md won't break the locale lookup; update all similar checks (including
the other changelog items referenced) to use the same stable-key or tolerant
comparison approach.

In `@web/data/cmux-shortcuts.ts`:
- Around line 138-155: The entries for the keyboard shortcuts with id
"scrollbackLineUp" and "scrollbackLineDown" are missing their configValue fields
so the docs UI cannot generate copy-ready snippets; add configValue: "shift+up"
to the scrollbackLineUp object and configValue: "shift+down" to the
scrollbackLineDown object in web/data/cmux-shortcuts.ts so those objects match
the page variants and provide the copy-ready configuration string for the UI.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 377c51c0-fd8b-45e7-b2c6-366460e56231

📥 Commits

Reviewing files that changed from the base of the PR and between f875855 and 5e53bdd.

📒 Files selected for processing (32)
  • CHANGELOG.md
  • Packages/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction+Defaults.swift
  • Sources/KeyboardShortcutSettings.swift
  • Sources/TabManager.swift
  • cmuxTests/AppDelegateShortcutRoutingTests.swift
  • cmuxTests/KeyboardShortcutContextTests.swift
  • cmuxTests/WorkspaceUnitTests.swift
  • docs/configuration.md
  • web/app/[locale]/docs/changelog/page.tsx
  • web/app/[locale]/docs/configuration/page.tsx
  • web/app/[locale]/docs/keyboard-shortcuts/page.tsx
  • web/data/cmux-shortcuts.ts
  • web/messages/ar.json
  • web/messages/bs.json
  • web/messages/da.json
  • web/messages/de.json
  • web/messages/en.json
  • web/messages/es.json
  • web/messages/fr.json
  • web/messages/it.json
  • web/messages/ja.json
  • web/messages/km.json
  • web/messages/ko.json
  • web/messages/no.json
  • web/messages/pl.json
  • web/messages/pt-BR.json
  • web/messages/ru.json
  • web/messages/th.json
  • web/messages/tr.json
  • web/messages/uk.json
  • web/messages/zh-CN.json
  • web/messages/zh-TW.json

Comment thread web/app/[locale]/docs/changelog/page.tsx Outdated
Comment thread web/data/cmux-shortcuts.ts
@mrzv

mrzv commented Jun 8, 2026

Copy link
Copy Markdown
Author

@codex review
@coderabbitai review
@greptile-apps review

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check current state of cmux-shortcuts.ts for scrollback entries
rg -n "scrollback" web/data/cmux-shortcuts.ts -C 4
echo "==="
# Check TabManager scrollback methods + comment on sign convention
rg -n "scrollFocusedTerminal\|scroll_page_lines\|scroll_page_up\|scroll_page_down" Sources/TabManager.swift -C 4
echo "==="
# Check ShortcutAction+Defaults for scrollback
fd "ShortcutAction+Defaults.swift" --exec rg -n "scrollback" {} -C 3
echo "==="
# Check the test coverage
rg -n "scrollback\|Scrollback" cmuxTests/ -l
echo "==="
# Verify nonBrowserPanel context
rg -n "scrollback\|nonBrowserPanel" Sources/KeyboardShortcutContext.swift -C 3

Length of output: 2292


🏁 Script executed:

#!/bin/bash
# Find TabManager and check scrollback methods
fd "TabManager.swift" --type f | head -5
echo "==="
fd "TabManager.swift" --type f --exec rg -n "scrollFocused\|scroll_page\|performBinding" {} -C 3
echo "==="
# Find KeyboardShortcutContext
fd "KeyboardShortcutContext.swift" --type f --exec cat {}
echo "==="
# Check test files
fd "WorkspaceUnitTests.swift" --type f --exec rg -n "scrollback" {} -C 2
fd "KeyboardShortcutContextTests.swift" --type f --exec rg -n "scrollback" {} -C 2

Length of output: 15063



@mrzv: The implementation looks solid. Here's a summary of the current state:

✅ All previous concerns addressed

  1. configValue for line shortcuts — Both scrollbackLineUp ("shift+up") and scrollbackLineDown ("shift+down") now have configValue fields. ✅

  2. UX default conflict (Shift+↑/↓) — Line shortcuts are shipped unbound by default (combos: []), confirmed by the unit tests:

    XCTAssertEqual(KeyboardShortcutSettings.Action.scrollbackLineUp.defaultShortcut, .unbound)
    XCTAssertEqual(KeyboardShortcutSettings.Action.scrollbackLineDown.defaultShortcut, .unbound)

    This preserves Shift+↑/↓ for shells/TUIs. ✅

  3. nonBrowserPanel context — All four actions are correctly classified. ✅

  4. Test coverage — testScrollbackShortcutDefaultsUsePageKeysAndLeaveLineScrollingUnbound, testScrollbackShortcutsAreScopedOutsideBrowserPanels, and the TextBox regression test are all present. ✅

🟡 One remaining minor nit

In Sources/TabManager.swift, the scrollFocusedTerminalScrollbackLine method uses "scroll_page_lines:-1" for up and "scroll_page_lines:1" for down. A short inline comment clarifying Ghostty's sign convention (negative = toward top/scrollback) would help future readers, but it's non-blocking.

Overall the PR is well-implemented and ready to merge.


🧠 Learnings used
Learnt from: austinywang
Repo: manaflow-ai/cmux PR: 5178
File: web/data/cmux-shortcuts.ts:223-227
Timestamp: 2026-06-02T08:18:29.897Z
Learning: In the manaflow-ai/cmux project, `LocalizedText` in `web/data/cmux-shortcuts.ts` is intentionally typed as `{ en: string; ja: string }` — every shortcut entry in that file provides only English and Japanese descriptions. The keyboard-shortcuts docs renderer has an explicit English fallback for all other locales. This is the established design for the entire shortcuts data file. Reviewers should NOT flag individual shortcut entries for missing locale coverage beyond en/ja in this file; extending to additional locales would require a separate project-wide change to the shortcuts i18n system. The native macOS Settings UI label localization (via Localizable.xcstrings) is separate and does cover all supported catalog locales.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3784
File: README.md:161-161
Timestamp: 2026-05-09T04:48:39.144Z
Learning: In the cmux project (manaflow-ai/cmux), as of PR `#3784`, the shortcut assignments for the right-sidebar area were intentionally swapped:
- ⌘+⇧+E (Cmd+Shift+E) → `focusRightSidebar` action, user-facing label "Toggle right sidebar focus"
- ⌘+⌥+B (Cmd+Option+B) → `toggleFileExplorer` action, user-facing label "Open file explorer" (visibility toggle)
This change is reflected consistently across KeyboardShortcutSettings.swift, cmuxApp.swift, Localizable.xcstrings, web/data/cmux-shortcuts.ts, README.md, and the unit/routing tests. Do not flag the ⌘⇧E label as "Open file explorer" in any of these files — that label now belongs to ⌘⌥+B / toggleFileExplorer.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2528
File: Sources/cmuxApp.swift:6439-6444
Timestamp: 2026-04-03T03:35:58.703Z
Learning: Repo: manaflow-ai/cmux — KeyboardShortcutSettings.setShortcut(...) is a no-op when KeyboardShortcutSettings.isManagedBySettingsFile(action) returns true (i.e., the action is managed by settings.json). This prevents backfilling overrides into UserDefaults and preserves the settings file as the source of truth.

Learnt from: islee23520
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-29T04:20:21.124Z
Learning: Repo: manaflow-ai/cmux — In Sources/GhosttyTerminalView.swift (PR `#3275`), blocking Ctrl+B (the tmux prefix key) is an explicit product requirement for workspaces imported as real-tmux workspaces (i.e., where `realTmuxSessionId` is non-nil). The `shouldBlockRealTmuxShortcut` helper suppresses both keyDown and keyUp events for Ctrl+B when the surface's workspace is a real-tmux workspace, preventing the prefix from being sent to the underlying Ghostty terminal. This behavior must not be removed or gated further.

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-05T06:21:41.663Z
Learning: Applies to **/*.swift : For Swift changes that add or materially change standalone cmux-owned windows, fail when diffs violate `.github/review-bot-rules/swift-auxiliary-window-close-shortcuts.md`: user-visible NSWindow, NSPanel, NSWindowController, SwiftUI Window, or WindowGroup code without stable cmux.* identifier and shared close-shortcut ownership through cmuxAuxiliaryWindowIdentifiers

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2528
File: Sources/cmuxApp.swift:6439-6444
Timestamp: 2026-04-03T03:37:25.743Z
Learning: Repo: manaflow-ai/cmux — In Sources/KeyboardShortcutSettings.swift, KeyboardShortcutSettings.setShortcut(_:, for:) is a no‑op when the action is managed by settings.json (isManagedBySettingsFile(action) == true), preventing UserDefaults backfill for file‑managed shortcuts.

Learnt from: alumican
Repo: manaflow-ai/cmux PR: 2051
File: Sources/AppDelegate.swift:9270-9276
Timestamp: 2026-03-24T13:50:07.535Z
Learning: Repo: manaflow-ai/cmux — KeyboardShortcutSettings.Action.toggleTextBoxInput defaults to Cmd+Option+B. Rationale: avoid conflict with the existing hard-coded Cmd+Option+T binding that triggers closeOtherTabsInFocusedPaneWithConfirmation() in AppDelegate.handleCustomShortcut(event:).

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-05T06:21:41.663Z
Learning: Applies to **/*.{swift,ts,tsx,js,jsx,plist} : For production changes, fail when diffs violate `.github/review-bot-rules/full-internationalization.md`: user-facing Swift text must use `String(localized:defaultValue:)` or equivalent localized API with matching translated string-catalog entry, app string catalog or Info.plist additions and edits must include translated entries for every locale already supported, and web UI, metadata, API response, rendered markdown, changelog, or user-facing data changes must read from `next-intl` or locale-specific source and update every locale listed in `web/i18n/routing.ts` with matching `web/messages/` entries

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-02T22:01:27.544Z
Learning: Applies to **/*.swift : Fail when diffs to Swift changes that add or materially change standalone cmux-owned windows violate `.github/review-bot-rules/swift-auxiliary-window-close-shortcuts.md`: user-visible NSWindow, NSPanel, NSWindowController, SwiftUI Window, or WindowGroup code without a stable cmux.* identifier and shared close-shortcut ownership through cmuxAuxiliaryWindowIdentifiers

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2528
File: Sources/KeyboardShortcutSettings.swift:509-528
Timestamp: 2026-04-03T03:35:27.463Z
Learning: Repo: manaflow-ai/cmux — In Sources/KeyboardShortcutSettings.swift, ShortcutStroke.isEscapeCancelEvent(_:) already gates the U+001B character-based escape checks behind a modifier guard: it computes `normalizedFlags` (stripping capsLock/function/numericPad) and only treats the escape character as cancel when `normalizedFlags.isEmpty` (or keyCode is 36/76). Modified bindings like Control+[ and Command+[ produce U+001B but have non-empty normalizedFlags, so they are NOT treated as cancel and can be recorded normally. Only the physical Escape key (keyCode 53) is unconditionally treated as cancel.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc16e15446

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/KeyboardShortcutSettings.swift
@mrzv

mrzv commented Jun 8, 2026

Copy link
Copy Markdown
Author

@codex review
@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 8, 2026 •

Copy link
Copy Markdown

@mrzv: Triggering a fresh review pass on PR #5590.

Based on the prior analysis, the implementation is in great shape — all previously flagged items have been resolved (missing configValue fields added, line shortcuts shipped unbound by default, correct nonBrowserPanel scoping, and test coverage added). The only outstanding minor note is the optional inline comment on the scroll_page_lines sign convention in Sources/TabManager.swift, which is non-blocking.


🧠 Learnings used
Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2528
File: Sources/KeyboardShortcutSettings.swift:509-528
Timestamp: 2026-04-03T03:35:27.463Z
Learning: Repo: manaflow-ai/cmux — In Sources/KeyboardShortcutSettings.swift, ShortcutStroke.isEscapeCancelEvent(_:) already gates the U+001B character-based escape checks behind a modifier guard: it computes `normalizedFlags` (stripping capsLock/function/numericPad) and only treats the escape character as cancel when `normalizedFlags.isEmpty` (or keyCode is 36/76). Modified bindings like Control+[ and Command+[ produce U+001B but have non-empty normalizedFlags, so they are NOT treated as cancel and can be recorded normally. Only the physical Escape key (keyCode 53) is unconditionally treated as cancel.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3784
File: README.md:161-161
Timestamp: 2026-05-09T04:48:39.144Z
Learning: In the cmux project (manaflow-ai/cmux), as of PR `#3784`, the shortcut assignments for the right-sidebar area were intentionally swapped:
- ⌘+⇧+E (Cmd+Shift+E) → `focusRightSidebar` action, user-facing label "Toggle right sidebar focus"
- ⌘+⌥+B (Cmd+Option+B) → `toggleFileExplorer` action, user-facing label "Open file explorer" (visibility toggle)
This change is reflected consistently across KeyboardShortcutSettings.swift, cmuxApp.swift, Localizable.xcstrings, web/data/cmux-shortcuts.ts, README.md, and the unit/routing tests. Do not flag the ⌘⇧E label as "Open file explorer" in any of these files — that label now belongs to ⌘⌥+B / toggleFileExplorer.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 4436
File: Sources/KeyboardShortcutSettings.swift:1546-1550
Timestamp: 2026-05-26T09:18:23.782Z
Learning: In `Sources/KeyboardShortcutSettings.swift` (`ShortcutStroke.matches`), `commandPrintableCharacterShouldBlockFallback` DOES include a `!flags.contains(.control)` guard (i.e., the full condition is: `flags.contains(.command) && !flags.contains(.control) && hasEventChars && eventCharsArePrintableASCII && (shortcutKeyIsLetter || eventCharacterIsLetterOrNumber)`). This allows Cmd+Ctrl shortcuts to still reach the ANSI/layout keyCode fallback path. The companion test `testCommandControlLetterWithPrintableEventCharacterDoesNotBlockFallback` (or similar) pins the regression that a printable event character for Cmd+Ctrl+U does NOT block fallback. Do NOT suggest removing the `!flags.contains(.control)` guard from this predicate.

Learnt from: islee23520
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-29T04:20:21.124Z
Learning: Repo: manaflow-ai/cmux — In Sources/GhosttyTerminalView.swift (PR `#3275`), blocking Ctrl+B (the tmux prefix key) is an explicit product requirement for workspaces imported as real-tmux workspaces (i.e., where `realTmuxSessionId` is non-nil). The `shouldBlockRealTmuxShortcut` helper suppresses both keyDown and keyUp events for Ctrl+B when the surface's workspace is a real-tmux workspace, preventing the prefix from being sent to the underlying Ghostty terminal. This behavior must not be removed or gated further.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 4436
File: Sources/KeyboardShortcutSettings.swift:1546-1549
Timestamp: 2026-05-26T08:01:05.889Z
Learning: In `Sources/KeyboardShortcutSettings.swift` (`ShortcutStroke.matches`), `commandPrintableCharacterShouldBlockFallback` intentionally does NOT include a `!flags.contains(.control)` guard. The rationale: when AppKit emits a printable character for a Command+Control combo (e.g., "u" for Cmd+Ctrl+U), a blanket control-key exemption would let the ANSI keyCode / physical punctuation fallback fire and allow an unrelated shortcut (e.g., Cmd+Ctrl+]) to steal the event. The existing logic already permits Command+Control layout fallback when AppKit instead emits a control character (tested by `testCommandControlLetterCanUseLayoutFallbackForControlCharacter`); the printable-character block path is tested by `testCommandControlPunctuationDoesNotStealPrintableLetterShortcut`. Do not suggest adding `!flags.contains(.control)` to this predicate.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2528
File: Sources/cmuxApp.swift:6439-6444
Timestamp: 2026-04-03T03:35:58.703Z
Learning: Repo: manaflow-ai/cmux — KeyboardShortcutSettings.setShortcut(...) is a no-op when KeyboardShortcutSettings.isManagedBySettingsFile(action) returns true (i.e., the action is managed by settings.json). This prevents backfilling overrides into UserDefaults and preserves the settings file as the source of truth.

Learnt from: austinywang
Repo: manaflow-ai/cmux PR: 5178
File: web/data/cmux-shortcuts.ts:223-227
Timestamp: 2026-06-02T08:18:29.897Z
Learning: In the manaflow-ai/cmux project, `LocalizedText` in `web/data/cmux-shortcuts.ts` is intentionally typed as `{ en: string; ja: string }` — every shortcut entry in that file provides only English and Japanese descriptions. The keyboard-shortcuts docs renderer has an explicit English fallback for all other locales. This is the established design for the entire shortcuts data file. Reviewers should NOT flag individual shortcut entries for missing locale coverage beyond en/ja in this file; extending to additional locales would require a separate project-wide change to the shortcuts i18n system. The native macOS Settings UI label localization (via Localizable.xcstrings) is separate and does cover all supported catalog locales.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2528
File: Sources/cmuxApp.swift:6439-6444
Timestamp: 2026-04-03T03:37:25.743Z
Learning: Repo: manaflow-ai/cmux — In Sources/KeyboardShortcutSettings.swift, KeyboardShortcutSettings.setShortcut(_:, for:) is a no‑op when the action is managed by settings.json (isManagedBySettingsFile(action) == true), preventing UserDefaults backfill for file‑managed shortcuts.

Learnt from: austinywang
Repo: manaflow-ai/cmux PR: 3968
File: Sources/Panels/BrowserPanelView.swift:4078-4091
Timestamp: 2026-05-19T02:56:37.768Z
Learning: In manaflow-ai/cmux (Swift), when handling omnibar selection navigation (N/P) in Sources/Panels/BrowserPanelView.swift and related key handling, only trigger repeats when the normalized modifier set is exactly [.command] or exactly [.control]. Do not treat chords with Shift or Option (e.g., ⌘⇧P, ⌘⌥N) as navigation; they must pass through to normal app shortcut routing. Use KeyboardLayout.normalizedCharacters(for:) to derive "n"/"p" across input sources before calling onMoveSelection.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3330
File: Sources/Panels/BrowserPanel.swift:2269-2270
Timestamp: 2026-04-30T10:45:30.357Z
Learning: Repo: manaflow-ai/cmux — Find UX contract (terminal + browser): Pressing Escape closes the visible find UI and clears the active search state, but the next Cmd+F should restore the previous query (selected for replacement). Implementation details: (1) BrowserPanel.swift — `searchState` didSet assigns `lastSearchNeedle = oldValue.needle` on teardown; `startFind()` initializes with `recoveredNeedle = lastSearchNeedle` and selects-all when non-empty; `hideFind()` sets `searchState = nil` and restores WebView focus if needed. (2) TabManager.swift — `startSearch()` passes `panel.surface.lastSearchNeedle` to `startOrFocusTerminalSearch(initialNeedle:)` to mirror browser behavior. (3) App/TerminalFindEscapeRouting.swift — Escape intercept closes terminal find (`searchState = nil`) and restores terminal focus. Do not flag persistence of `lastSearchNeedle` across Escape-close as a bug; it is by design and covered by UI tests.

Learnt from: alumican
Repo: manaflow-ai/cmux PR: 2051
File: Sources/AppDelegate.swift:9270-9276
Timestamp: 2026-03-24T13:50:07.535Z
Learning: Repo: manaflow-ai/cmux — KeyboardShortcutSettings.Action.toggleTextBoxInput defaults to Cmd+Option+B. Rationale: avoid conflict with the existing hard-coded Cmd+Option+T binding that triggers closeOtherTabsInFocusedPaneWithConfirmation() in AppDelegate.handleCustomShortcut(event:).

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3625
File: Sources/AppDelegate.swift:0-0
Timestamp: 2026-05-06T09:04:46.867Z
Learning: In manaflow-ai/cmux (Swift), when handling "consume after chord mismatch" in AppDelegate shortcut routing, also treat actions with usesNumberedDigitMatching as matches by using numberedShortcutDigit(event:shortcut) so Cmd+2…Cmd+9 are consumed correctly. Tests live in cmuxTests/AppDelegateShortcutRoutingTests.swift.

Learnt from: mrosnerr
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-28T22:24:18.018Z
Learning: Repo: manaflow-ai/cmux — In Sources/GhosttyTerminalView.swift (PR `#3237`, commit 9dcb9c2), the explicit-vs-baseConfig.initialInput resolution logic was extracted from `TerminalSurface.createSurface(for:)` into a standalone `TerminalSurface.resolveInitialInput(...)` static/instance method for unit-testability. Behavior is unchanged. A companion `TerminalSurfaceResolveInitialInputTests` suite asserts the contract, including byte-for-byte preservation of Ghostty raw-bytes startup-input via `baseConfig.initialInput`.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2528
File: Sources/AppDelegate.swift:2196-2200
Timestamp: 2026-04-03T03:36:45.112Z
Learning: Repo: manaflow-ai/cmux — In Sources/AppDelegate.swift, when KeyboardShortcutSettings.didChangeNotification fires, AppDelegate must clear configured-chord caches (pendingConfiguredShortcutChord and activeConfiguredShortcutChordPrefixForCurrentEvent) via clearConfiguredShortcutChordState() before refreshing tooltips/UI. Also clear chord state on applicationWillResignActive to avoid cross-activity leakage. Verified by cmuxTests/AppDelegateShortcutRoutingTests.swift::testShortcutChangeClearsPendingConfiguredChord.
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@teamleaderleo teamleaderleo added S3: minor Wrong behavior with a workaround area: terminal Ghostty surface, rendering, scrollback, escape sequences, fonts needs a call Finished and held for a team design or product decision (see #13742 and the gallery in #15427) labels Sep 30, 2026

This branch has not been deployed

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

Labels

area: terminal Ghostty surface, rendering, scrollback, escape sequences, fonts needs a call Finished and held for a team design or product decision (see #13742 and the gallery in #15427) S3: minor Wrong behavior with a workaround

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: bindable scroll shortcuts (scrollLineUp / scrollLineDown) without entering copy mode

2 participants