Skip to content

Add cmux Help menu resources - #3402

Merged
lawrencecchen merged 12 commits into
mainfrom
feat-codex-style-help-menu
May 1, 2026
Merged

lawrencecchen merged 12 commits into
mainfrom
feat-codex-style-help-menu

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented May 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Replace the old Codex-style Help menu with the cmux docs nav order, including Skills and an Agent Integrations submenu.
  • Add /docs/skills with the checked-in skills and skills.sh install flow.
  • Add skills.sh for local or GitHub-based skill installation.

Testing

@vercel

vercel Bot commented May 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 1, 2026 11:43pm
cmux-staging Building Building Preview, Comment May 1, 2026 11:43pm

@coderabbitai

coderabbitai Bot commented May 1, 2026 •

Copy link
Copy Markdown

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 a Help command group to the app with localized help/documentation links, feedback and update actions, and a Keyboard Shortcuts action; adds extensive English/Japanese localization entries; introduces a UI test for the Help menu; adjusts app activation policy when running under XCTest; adds skills installer script and web docs/pages for "Skills".

Changes

Cohort / File(s) Summary
Localization Strings
Resources/Localizable.xcstrings
Adds ~153 menu.help.* localization entries (English + Japanese) with extractionState set to manual.
macOS Help Menu & Routing
Sources/cmuxApp.swift, Sources/AppDelegate.swift
Implements a new .help CommandGroup, CmuxHelpResource enum, helpers to open URLs, route Feedback and Keyboard Shortcuts via AppDelegate, and skips syncActivationPolicy() under XCTest by setting .regular activation policy.
UI Tests / Test Helpers
cmuxUITests/SidebarHelpMenuUITests.swift
Adds testMainHelpMenuShowsCmuxResourcesAndOpensKeyboardShortcuts() and sidebarHelpResetMenuBarOnlyDefault(); updates launchAndActivate to tolerate CI/headless startup and wait for readiness/window presence.
Skills CLI installer script
skills.sh
New executable Bash installer for "cmux agent skills": option parsing, source-from-local-or-github-tarball, safe validation, copy/atomic install, --list and --dry-run modes.
Web Docs: Skills pages & nav
web/app/[locale]/components/docs-nav-items.ts, web/app/[locale]/docs/skills/page.tsx, web/messages/en.json, web/messages/ja.json
Adds Skills docs page, metadata, localized content (en/ja), and inserts docs.navItems.skills into nav; updates nav items and translations.
Sitemap
web/app/sitemap.ts
Adds /docs/dock, /docs/skills, and several /docs/agent-integrations/* entries; reorders/refreshes an existing browser-automation entry.
Tests & Misc
(various small edits)
UI test additions and test-launch robustness changes; no exported API changes.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant App as cmuxApp
    participant Delegate as AppDelegate
    participant System as System

    User->>App: Open Help menu
    App->>User: Display Help items (Docs, GitHub, Discord, Feedback, Updates, Shortcuts)

    alt Open external doc/link
        User->>App: Select doc/link
        App->>System: openURL(resource.url)
    else Send Feedback
        User->>App: Select "Send Feedback"
        App->>Delegate: routeToFeedbackComposer()
        Delegate->>System: present feedback composer (ensure window)
    else Keyboard Shortcuts
        User->>App: Select "Keyboard Shortcuts"
        App->>Delegate: openKeyboardShortcutsPrefs()
        Delegate->>System: open Shortcuts preferences pane
    else Check for Updates
        User->>App: Select "Check for Updates"
        App->>System: trigger update-check flow
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped into the Help menu bright,
With docs and feedback shining light,
Shortcuts, links, and updates in tow,
I nudged the prefs and watched them show,
A carrot-click for every byte! 🥕📚

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main changes: adding Help menu resources to the cmux app with localization, UI tests, and documentation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description includes all required template sections: Summary, Testing, Demo Video (Vercel preview link), Review Trigger instructions, and a Checklist, providing comprehensive documentation.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-codex-style-help-menu

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 May 1, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a macOS Help menu with cmux documentation links, reusing existing Send Feedback, Check for Updates, and Keyboard Shortcuts actions modeled after the Codex app, backed by a new CmuxHelpResource enum and localization entries.

  • presentFeedbackFromHelpMenu() silently drops the request when no window is active: Task { @MainActor in } fires before AppKit updates NSApp.keyWindow after showMainWindowFromMenuBar(), so openComposer(in: nil) is called and shouldHandleCommandPaletteRequest returns false for every observed window — no feedback composer opens.
  • Japanese translation "設定" for menu.help.configuration collides with the standard macOS word for "Settings", likely to confuse Japanese users.

Confidence Score: 3/5

Not safe to merge as-is — the Help menu Send Feedback action silently fails when no window is active.

One P1 logic bug (feedback silently dropped in the no-window edge case) pulls the score below the P1 ceiling of 4; combined with a P2 localization ambiguity the score lands at 3.

Sources/cmuxApp.swift — presentFeedbackFromHelpMenu race condition

Important Files Changed

Filename Overview
Sources/cmuxApp.swift Adds CmuxHelpResource enum, helpCommands CommandGroup, and two helper functions; presentFeedbackFromHelpMenu has a race condition where feedback is silently dropped when no window is active.
Resources/Localizable.xcstrings Adds nine new menu.help.* localization keys for EN and JA; the JA translation "設定" for menu.help.configuration collides with the standard word for "Settings".
cmuxUITests/SidebarHelpMenuUITests.swift Adds testMainHelpMenuShowsCmuxResourcesAndOpensKeyboardShortcuts; correctly pins locale to en_US to avoid localization-dependent assertions, and exercises the end-to-end menu click flow.

Sequence Diagram

sequenceDiagram
    participant User
    participant HelpMenu
    participant cmuxApp
    participant AppDelegate
    participant FeedbackBridge
    participant ContentView

    User->>HelpMenu: Click "Send Feedback"
    HelpMenu->>cmuxApp: presentFeedbackFromHelpMenu()
    alt keyWindow or mainWindow exists
        cmuxApp->>FeedbackBridge: openComposer(in: window)
        FeedbackBridge->>ContentView: post feedbackComposerRequested(object: window)
        ContentView->>ContentView: presentFeedbackComposer()
    else No active window (race condition path)
        cmuxApp->>AppDelegate: showMainWindowFromMenuBar()
        Note over AppDelegate: bringToFront(window) async AppKit
        cmuxApp->>cmuxApp: Task @MainActor fires before window is key
        cmuxApp->>FeedbackBridge: openComposer(in: nil)
        FeedbackBridge->>ContentView: post feedbackComposerRequested(object: nil)
        ContentView->>ContentView: shouldHandleCommandPaletteRequest returns false
        Note over ContentView: Silent failure — presentFeedbackComposer() never called
    end
Loading

Comments Outside Diff (1)

  1. Resources/Localizable.xcstrings, line 82-92 (link)

    P2 "設定" is the standard Japanese word for "Settings"

    The Japanese translation for menu.help.configuration ("Configuration" docs link) is "設定", which is identical to the word macOS uses for the system Settings app and the convention for app settings/preferences. A Japanese user scanning the Help menu will likely interpret "設定" as "open the app's Settings" rather than "open the Configuration docs page". Consider a more distinctive translation such as "設定ガイド" (Configuration Guide) or "設定ドキュメント" to match the other doc entries (e.g. "cmuxドキュメント") and disambiguate from the Settings panel.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (1): Last reviewed commit: "Add cmux Help menu resources" | Re-trigger Greptile

Comment thread Sources/cmuxApp.swift Outdated
Comment on lines +1216 to +1226
private func presentFeedbackFromHelpMenu() {
if let targetWindow = NSApp.keyWindow ?? NSApp.mainWindow {
FeedbackComposerBridge.openComposer(in: targetWindow)
return
}

AppDelegate.shared?.showMainWindowFromMenuBar()
Task { @MainActor in
FeedbackComposerBridge.openComposer(in: NSApp.keyWindow ?? NSApp.mainWindow)
}
}

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.

P1 Feedback silently dropped when no window is active

When NSApp.keyWindow ?? NSApp.mainWindow is nil, showMainWindowFromMenuBar() calls bringToFront(_:) synchronously, but AppKit window-key state isn't updated until the next run-loop cycle — after the Task { @MainActor in } has already fired. So NSApp.keyWindow ?? NSApp.mainWindow is still nil inside the task, openComposer(in: nil) posts the notification with object: nil, and shouldHandleCommandPaletteRequest(…requestedWindow: nil, keyWindow: nil, mainWindow: nil) returns false for every observed window — silently swallowing the request. The pattern used in TerminalController.swift (lines 7937–7944) calls makeKeyAndOrderFront + activate before openComposer, which avoids this race. At minimum, openComposer should be called without an explicit argument here so its default NSApp.keyWindow ?? NSApp.mainWindow evaluation happens lazily on notification receipt (after more run-loop cycles), or the call should be deferred until windowDidBecomeKey fires.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed by having showMainWindowFromMenuBar return the concrete main window and passing that window to FeedbackComposerBridge, so the feedback request is routed before key-window state matters.

— Claude Code

@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.

🧹 Nitpick comments (1)
cmuxUITests/SidebarHelpMenuUITests.swift (1)

68-73: ⚡ Quick win

Add an explicit assertion for “Check for Updates” in this new main Help menu test.

Since this PR also wires/reuses the Check for Updates action in the main Help menu, asserting its presence here would lock that contract down in the same test path.

✅ Suggested small test addition
         XCTAssertTrue(app.menuItems["cmux Documentation"].waitForExistence(timeout: 2.0))
         XCTAssertTrue(app.menuItems["What's New"].waitForExistence(timeout: 2.0))
         XCTAssertTrue(app.menuItems["Codex Integration"].waitForExistence(timeout: 2.0))
         XCTAssertTrue(app.menuItems["Automation & API"].waitForExistence(timeout: 2.0))
         XCTAssertTrue(app.menuItems["Send Feedback"].waitForExistence(timeout: 2.0))
+        XCTAssertTrue(app.menuItems["Check for Updates"].waitForExistence(timeout: 2.0))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmuxUITests/SidebarHelpMenuUITests.swift` around lines 68 - 73, The Help menu
UI test in SidebarHelpMenuUITests is missing an assertion for the "Check for
Updates" item; add a line mirroring the other checks that calls
XCTAssertTrue(app.menuItems["Check for Updates"].waitForExistence(timeout: 2.0))
inside the same test method so the main Help menu wiring for Check for Updates
is validated alongside "cmux Documentation", "What's New", "Codex Integration",
"Automation & API", and "Send Feedback".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@cmuxUITests/SidebarHelpMenuUITests.swift`:
- Around line 68-73: The Help menu UI test in SidebarHelpMenuUITests is missing
an assertion for the "Check for Updates" item; add a line mirroring the other
checks that calls XCTAssertTrue(app.menuItems["Check for
Updates"].waitForExistence(timeout: 2.0)) inside the same test method so the
main Help menu wiring for Check for Updates is validated alongside "cmux
Documentation", "What's New", "Codex Integration", "Automation & API", and "Send
Feedback".

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9d6b5d60-f487-496a-82b1-b4c32a2cd623

📥 Commits

Reviewing files that changed from the base of the PR and between b4d040d and f2febfc.

📒 Files selected for processing (3)
  • Resources/Localizable.xcstrings
  • Sources/cmuxApp.swift
  • cmuxUITests/SidebarHelpMenuUITests.swift

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@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: 1a4728ed8a

ℹ️ 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 on lines +85 to +89
XCTAssertTrue(app.menuItems["cmux Documentation"].waitForExistence(timeout: 2.0))
XCTAssertTrue(app.menuItems["What's New"].waitForExistence(timeout: 2.0))
XCTAssertTrue(app.menuItems["Codex Integration"].waitForExistence(timeout: 2.0))
XCTAssertTrue(app.menuItems["Automation & API"].waitForExistence(timeout: 2.0))
XCTAssertTrue(app.menuItems["Send Feedback"].waitForExistence(timeout: 2.0))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Set deterministic locale for Help menu assertions

The new UI test hard-codes English Help menu labels ("cmux Documentation", "What's New", etc.) but does not pin -AppleLanguages/-AppleLocale at launch, so it will fail on non-English runners even when the feature works. This file already uses locale pinning for other string-sensitive checks (for example in testCmdShiftPCheckQueryPrefersCheckForUpdatesBeforeAttemptUpdate), so this test should do the same or compare against localized expectations.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Pinned the Help menu UI test to en_US so English menu assertions are deterministic across localized runners.

— Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@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 the current code and only fix it if needed.

Inline comments:
In `@cmuxUITests/SidebarHelpMenuUITests.swift`:
- Around line 62-99: The test uses hard-coded English menu titles in
testMainHelpMenuShowsCmuxResourcesAndOpensKeyboardShortcuts which will fail on
localized runners; before launching the app (e.g., right after creating
XCUIApplication() and before launchAndActivate) set a stable locale by adding
app.launchArguments += ["-AppleLanguages", "(en)", "-AppleLocale", "en_US"] or
switch the menu lookups to use accessibility identifiers (set identifiers for
"Help", "cmux Documentation", "Keyboard Shortcuts", etc., in the app and replace
app.menuBars.menuBarItems[...] / app.menuItems[...] string lookups with those
identifiers) so the test is deterministic across locales; update requireElement
calls to use the chosen identifiers or keep the added AppleLanguages/AppleLocale
args if you prefer pinning to English.
- Around line 258-290: The final readiness check in launchAndActivate allows a
backgrounded app if any window exists, which can make menuBar access fail;
change the last sidebarHelpPollUntil predicate to require app.state ==
.runningForeground (remove the alternative app.windows.firstMatch.exists) so the
method only returns once the app is actually foreground-activated; update any
related timeout/assert message if needed to reflect that the app must be
runningForeground and keep using sidebarHelpPollUntil and app.activate() logic
as-is.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9eaac204-6673-4e18-8095-33bdc0eb40a9

📥 Commits

Reviewing files that changed from the base of the PR and between 1a4728e and 9bfec6d.

📒 Files selected for processing (1)
  • cmuxUITests/SidebarHelpMenuUITests.swift

Comment thread cmuxUITests/SidebarHelpMenuUITests.swift Outdated
Comment thread cmuxUITests/SidebarHelpMenuUITests.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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@skills.sh`:
- Around line 153-157: The code uses "$dest_dir/$skill_name" in rm and mv which
can act on "/" if dest_dir is empty; guard against an empty dest_dir by
enforcing a non-empty value before using it (e.g., use the parameter expansion
form to fail on empty) so tmp_target, dest_dir and skill_name operations cannot
target the root; add the check at the start of the block that creates tmp_target
(or immediately before rm -rf "$dest_dir/$skill_name" and mv "$tmp_target"
"$dest_dir/$skill_name") to validate dest_dir is non-empty and bail with a clear
error if it is.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: d2406229-f2fe-4a6b-bd0f-2e907df89a5f

📥 Commits

Reviewing files that changed from the base of the PR and between 9bfec6d and e49df5a.

📒 Files selected for processing (9)
  • Resources/Localizable.xcstrings
  • Sources/cmuxApp.swift
  • cmuxUITests/SidebarHelpMenuUITests.swift
  • skills.sh
  • web/app/[locale]/components/docs-nav-items.ts
  • web/app/[locale]/docs/skills/page.tsx
  • web/app/sitemap.ts
  • web/messages/en.json
  • web/messages/ja.json
✅ Files skipped from review due to trivial changes (4)
  • web/app/[locale]/components/docs-nav-items.ts
  • web/messages/ja.json
  • Resources/Localizable.xcstrings
  • web/app/sitemap.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • Sources/cmuxApp.swift

Comment thread skills.sh Outdated
@lawrencecchen
lawrencecchen force-pushed the feat-codex-style-help-menu branch from e49df5a to 4f7b584 Compare May 1, 2026 22:02
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@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: fdff976a0a

ℹ️ 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 skills.sh Outdated
Comment on lines +91 to +93
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd || true)"
if [[ -z "$source_dir" && -n "$script_dir" && -d "$script_dir/skills" ]]; then
source_dir="$script_dir/skills"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Ignore cwd skills when installer runs from stdin

When this script is executed via curl ... | bash, BASH_SOURCE[0] is empty, so dirname resolves to . and script_dir becomes the caller’s current directory. If that directory happens to contain a skills/ folder, the installer silently uses local files instead of downloading from GitHub, so --ref no longer controls what gets installed. This makes piped installs nondeterministic and can install stale or unrelated skills depending on where the command is run.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed by only using local source discovery when BASH_SOURCE[0] points to an actual script file. Piped installs now fall through to the GitHub archive unless --source is explicit.

— Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@lawrencecchen
lawrencecchen merged commit be541dc into main May 1, 2026
25 checks passed
@lawrencecchen
lawrencecchen deleted the feat-codex-style-help-menu branch May 1, 2026 23:54

This branch was successfully deployed

1 active deployment
Preview – cmux — 90e360d4 Deployed May 1, 2026 by vercel[bot]
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.

1 participant