Commit graph

1049 commits

Author SHA1 Message Date
Lawrence Chen
bb052198e5
Document browser navigation verification loop (#974)
* Document browser navigation verification loop

* Add docs regression test for browser navigation guidance

* Remove invalid docs text inspection test
2026-03-05 20:57:18 -08:00
Lawrence Chen
d4e16ae8c8
Add browser js_error recovery guidance (#975)
* Add browser js_error recovery guidance

* Add docs regression test for browser js_error guidance
2026-03-05 20:51:47 -08:00
Lawrence Chen
f3f17cfc38
Fix browser get selector examples (#976)
* Fix browser get selector examples

* Add docs regression test for browser get selector examples
2026-03-05 20:51:30 -08:00
Austin Wang
b848d60b0d
Merge pull request #925 from jleechanorg/fix-split-cwd-inheritance
Fix split CWD inheritance and bash job notification spam
2026-03-05 20:34:25 -08:00
Lawrence Chen
d2ba5eefde
Add regression test commit policy to CLAUDE.md (#982)
Two-commit structure for bug fix PRs: first commit adds the failing
test (CI red), second commit adds the fix (CI green). Proves in the
GitHub PR UI that the test genuinely catches the bug.
2026-03-05 20:09:57 -08:00
Lawrence Chen
085e192bca
Add diagnostics for empty browser snapshots (#977) 2026-03-05 20:01:05 -08:00
jleechan
24a8056b49 tests: fix split CWD e2e assertion signal and early aborts 2026-03-05 19:54:30 -08:00
Austin Wang
c5577dd495
Fix flaky CLI socket listener recovery (#952) (#954)
* Harden socket listener health checks and path handling

* Make socket health probe non-blocking

* Address PR feedback for issue 952 recovery guard

* Run issue 952 regression guard without pytest dependency

* Harden socket probe timing and health telemetry

* Handle missing git in issue 952 regression guard

* Address remaining PR 954 review fixes
2026-03-05 19:52:59 -08:00
Lawrence Chen
d99fa96c09
Fix browser screenshot to return image URL (#936)
* Return browser screenshot image URL

* Make screenshot path/url best effort

* cli: omit screenshot png_base64 from json output

* browser wait: fail fast on js errors and include screenshot in help

* browser wait: avoid main-actor default world warning

* tests: scope contentWorld regression check to function signature

* browser screenshot: clean up output handling and tests

* browser wait: resolve snapshot refs in selector waits
2026-03-05 19:09:29 -08:00
Austin Wang
5f43a3fc32
Fix notification unread persistence when workspaces regain focus (#971)
* Fix notification unread persistence on focus

* Address review feedback on notification unread fix
2026-03-05 18:56:03 -08:00
Lawrence Chen
a08ad56244
Prevent agents from building/launching untagged cmux DEV (#979)
Agents were following CLAUDE.md instructions to run bare xcodebuild
without -derivedDataPath, producing untagged cmux DEV.app that shares
the default debug socket and steals window focus.

Replace bare xcodebuild instruction with reload.sh --tag. Replace
E2E/Basic tests sections with a unified testing policy that forbids
local test runs and requires tagged builds.
2026-03-05 18:41:22 -08:00
Lawrence Chen
6347571b7c
Fix Dvorak Cmd+C colliding with notifications shortcut (#762)
* Fix layout-safe command shortcut matching

* Fix unshifted symbol shortcut coercion

* Fix layout handling for hardcoded Cmd shortcuts

* Support Cmd/Ctrl modifier hold shortcut hints

* Address PR shortcut review feedback

* Handle Caps Lock in command shortcut matching

* Address remaining PR shortcut review comments

* Handle Cmd+Ctrl+F control-character fallback

* Tighten shortcut hint hold-delay test

* Expose shortcut hint visibility in settings

* Restore Cmd+digit fallback on symbol-first layouts

* Stabilize shortcut regression coverage

* Align shortcut hint toggle with Cmd/Ctrl behavior

* Restore Claude workflow file

* Match Claude workflow file to main

* Keep shortcut hint hold behavior command-only

* Restore command shortcut fallback when layout data is unavailable

* Preserve command-aware shortcut translation
2026-03-05 18:32:42 -08:00
Lawrence Chen
0fb2b414b0
"Claude PR Assistant workflow" (#965) 2026-03-05 17:19:02 -08:00
Lawrence Chen
e49e572505
Fix browser Cmd+F overlay clipping in portal mode (#916)
* Fix browser Cmd+F overlay clipping in portal mode

* Fix browser Cmd+F panel update regression

* Fix browser find overlay lifecycle and focus

* Extract regression test helpers for browser find guards

* Restore new-tab Cmd+F overlay and harden test helper

* Fix browser Cmd+F focus handoff race

* Fix browser Cmd+F focus loss across page load

* Address review feedback on browser find focus guards

* Add Cmd+F pane-switch regression UI tests

* Run Cmd+F pane-switch regressions from existing UI suite

* Restore browser find focus on pane refocus

* Stabilize Cmd+F pane-switch regressions with focus-state recorder

* Make autofocus race UI test wait on deterministic page signal

* Fix cmuxTests WebViewRepresentable init after browser search state param
2026-03-05 15:36:47 -08:00
Austin Wang
9b215eddab
Fix browser portal pane drag routing and uploads (#961) 2026-03-05 15:27:17 -08:00
Austin Wang
6d0c90c8c8
Fix sidebar branch refresh after checkout (issue #666) (#905)
* Fix sidebar branch refresh after checkout

* Fix bash PR probe not refreshing on checkout (PR review feedback)

When HEAD changes (e.g. git checkout), the bash integration now resets
_CMUX_PR_LAST_RUN=0 so the PR probe is forced to re-run immediately.
This matches the zsh integration which already sets _CMUX_PR_FORCE=1
on HEAD change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 12:45:04 -08:00
Lawrence Chen
1408cbb68c
Flush PostHog hourly active events immediately (#934)
* PostHog: flush hourly active captures immediately

* PostHog: move focus-triggered active tracking off main queue

* Lighten PostHog app focus hot path

* Address review: dedupe PostHog event names
2026-03-05 04:00:04 -08:00
Lawrence Chen
3d6645cb18
Add PR template section for demo videos (#933)
* Add PR template section for demo videos

* Remove PR template author exemption note

* Refine PR template with review trigger checklist
2026-03-05 03:05:35 -08:00
Yuki Yamashina
11197a49c4
Fix startup SIGSEGV: pre-warm locale before SentrySDK.start (#927)
Locale initialization on the main thread (os.locale.ensureLocale /
NSLocale._preferredLanguages) can race with Sentry's background
init thread calling posix.getenv, causing a SIGSEGV and leaving
the SDK disabled.

Related to #836
2026-03-05 03:03:32 -08:00
atani
3a5bd8494c
fix: avoid NSTextView tracking loop in omnibar mouseDown (#928)
* fix: avoid NSTextView tracking loop in omnibar mouseDown (#917)

Replace the synthetic mouseUp timeout workaround with direct cursor
positioning via NSTextView.characterIndexForInsertion(at:). The previous
approach posted a fake mouseUp event via NSApp.postEvent after 3 seconds,
but the NSTextView tracking loop does not always dequeue events from the
application event queue when stuck in an infinite
NSTextLayoutManager.enumerateTextLayoutFragments cycle, so the hang
persisted.

The new approach bypasses super.mouseDown entirely when the field editor
is already active, positioning the cursor (or extending the selection
with Shift+click) without entering the tracking loop. Drag-to-select is
not supported in this code path, but for a single-line omnibar this is
an acceptable trade-off.

* fix: handle double-click, UTF-16 length, and shift-click anchor

Address review feedback:

- Forward double/triple-click events to editor.mouseDown(with:) to
  preserve word and line selection without entering NSTextField's
  tracking loop
- Use (editor.string as NSString).length instead of String.count for
  NSRange clamping (NSRange uses UTF-16 indices)
- Track shift-click anchor independently via shiftClickAnchor property
  to correctly handle bidirectional selection extension

* fix: reset shiftClickAnchor on keyDown to prevent stale anchor

Clear the shift-click selection anchor whenever a key is pressed, so
that keyboard navigation (arrow keys, Shift+arrow, Home/End, etc.)
properly invalidates the mouse-originated anchor. A subsequent
Shift+click will then use the current selection position as anchor
instead of a stale value from a prior mouse interaction.

* fix: reset shiftClickAnchor in performKeyEquivalent and on re-focus

Key equivalents (Cmd+A, Cmd+V, etc.) bypass keyDown and go through
performKeyEquivalent, so the anchor must also be cleared there.
Similarly, re-focusing the field (currentEditor() == nil path) should
reset the anchor since selectAll changes the selection state.
2026-03-05 02:31:23 -08:00
Lawrence Chen
017f4416d0
Prompt bug reporters to test NIGHTLY (#930) 2026-03-05 01:48:09 -08:00
sminamot
bf28f5df4b
Skip Ctrl fast path during IME composition (#790)
During IME composition (e.g. Japanese input), Ctrl+H should delete
composing characters via the IME, not bypass it and send a backspace
directly to the terminal. Add a hasMarkedText() check so the fast path
is only taken when no IME composition is active, letting
interpretKeyEvents() handle the key instead.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 00:24:40 -08:00
jleechan
00b7357fdc Add split CWD inheritance demo GIF
Visual proof of fix: split panes inherit CWD from the source panel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 22:33:55 -08:00
jleechan
00451417c2 Fix test false positives: verify new pane/tab identity before checking CWD
Address PR review comments:
- Test1: record original panel ID, wait for a *different* panel to report
  the expected CWD — prevents false pass when focus stays on source pane
- Test2: record original tab ID, wait for a *different* tab with the
  expected CWD — prevents false pass when checking the old workspace
- Remove unused `as e` exception bindings (Ruff F841)
- Shell race (set -m) was already fixed in 4402a5b0 via disown

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 22:09:11 -08:00
jleechan
4402a5b0ed Fix bash job spam: use disown instead of set +m
set +m only suppresses notifications for jobs started after it runs.
Jobs that complete between prompts still trigger Done output.
Using disown removes jobs from bash job table entirely so bash
never prints completion notifications for them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 22:03:05 -08:00
jleechan
648f4c00db WORKING: Fix split CWD inheritance and bash job notification spam
- Pass inherited working directory when creating split panes (panelDirectories
  fallback to currentDirectory)
- Suppress bash job-done "[N] Done ..." notifications in shell integration
  by toggling job control (set +m / set -m) around background probes
- Add integration test for split/tab CWD inheritance

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 21:57:01 -08:00
Eray Bozoglu
2712cabac9
Fix orphaned child processes when closing workspace tabs (#889)
* Fix orphaned child processes when closing workspace tabs

When closing a workspace tab via the sidebar X button, child processes
(login → zsh → claude) survived as orphans because TabManager.closeWorkspace()
only removed the workspace from the tabs array without explicitly freeing
Ghostty surfaces. It relied on ARC to cascade deallocation, but SwiftUI views
and Combine publishers held references, delaying or preventing
ghostty_surface_free() (which sends SIGHUP) from ever running.

This adds explicit teardown on the workspace close path:
- TerminalSurface.teardownSurface(): idempotent method to free the Ghostty
  runtime surface eagerly, matching the existing deinit logic
- TerminalPanel.close() now calls teardownSurface() to ensure SIGHUP is sent
- Workspace.teardownAllPanels() iterates all panels and closes them
- TabManager.closeWorkspace() calls teardownAllPanels() before removing
  the workspace from the tabs array

* Harden workspace teardown and ownership checks

* Address follow-up teardown review feedback

---------

Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com>
2026-03-04 20:00:35 -08:00
Lawrence Chen
604ba6fcab
Fix Cmd+F Escape passthrough into terminal (#918)
* Fix find-bar Escape passthrough to terminal

* Keep find Escape suppression armed until key-up
2026-03-04 19:26:05 -08:00
Austin Wang
6fe1410918
Fix terminal link opens to stay in source workspace (#912) 2026-03-04 19:21:45 -08:00
Austin Wang
8193e55dae
Fix background terminal startup for unfocused workspaces (#920) 2026-03-04 19:21:32 -08:00
Lawrence Chen
26bef7316e
Fix custom notification sound staging reliability (#919) 2026-03-04 19:19:07 -08:00
Austin Wang
39a0da2b7e
Fix sidebar branch refresh during agent-driven git checkout (#671) 2026-03-04 19:13:19 -08:00
Austin Wang
80baae355a
Add browser camera permission support and metadata (#760) (#913) 2026-03-04 18:56:22 -08:00
Lawrence Chen
0a490b0e03
Fix Claude wrapper hook errors when cmux socket is stale (#868)
* Fix Claude wrapper hook injection when cmux socket is stale

* Harden socket listener lifecycle and rearm policy

* Unset CLAUDECODE in stale-socket passthrough

* Harden listener cleanup and bound claude ping probe

* Guard socket unlink during listener startup window
2026-03-04 18:52:57 -08:00
Austin Wang
34989e8ad0
Fix portal browser click focus after workspace switch (#908) 2026-03-04 18:36:26 -08:00
Lawrence Chen
895fb802c8
Add 16 new languages to localization (#895)
* Add localization for 16 new languages

Add translations for all 637 UI string keys and 3 InfoPlist keys in:
ar, bs, da, de, es, fr, it, ko, nb, pl, pt-BR, ru, th, tr, zh-Hans, zh-Hant

Update AppLanguage enum and knownRegions to include all 18 languages.
Total supported languages: en, ja + 16 new = 18.

* Reorder languages: English first, rest alphabetical, explicit display names

Use "Chinese Simplified" / "Chinese Traditional" naming. Show native script
with English name in parentheses for non-Latin languages.

* Add Chinese native characters to language display names

* Delay language restart dialog until picker dropdown closes

* Fix Arabic bidi rendering in language picker with LTR mark

* Defer AppleLanguages write to app launch, fix picker animation lag

Writing AppleLanguages to UserDefaults triggers synchronous locale
recalculation on the main thread, causing the picker dropdown dismiss
animation to stutter. Since a restart is already required, move the
AppleLanguages write to init() on next launch instead of onChange.

* Fix reset path and add apply() back to delayed onChange

- resetAllSettings() now calls LanguageSettings.apply(.system) and
  shows restart alert if language was changed from launch value
- onChange also calls apply() inside the 0.3s delay block, so
  AppleLanguages is set before restart (avoids two-restart issue)
- init() still calls apply() as belt-and-suspenders for launch

* Fix deferred alert race: re-check current language in closure

If user changes language then changes back within 0.3s, the stale
closure would fire with the old value. Now reads current appLanguage
inside the closure instead of capturing newValue.

* Fix Spanish and Danish translations: restore missing diacritics

Spanish was missing all áéíóúñ characters (now 315 diacritics).
Danish was missing all æøå characters (now 401 diacritics).
Both languages fully retranslated with correct orthography.

* Fix reset restart alert: compare new value against launch language

Was comparing previousLanguage against languageAtLaunch, which would
miss the case where user launched in Spanish and reset to System
(Spanish != Spanish = false, so no alert). Now compares the new
appLanguage (system) against languageAtLaunch.
2026-03-04 18:04:33 -08:00
Austin Wang
76835662f5
Fix CLI socket autodiscovery for tagged cmux sockets (#832) 2026-03-04 18:03:25 -08:00
Ismail Pelaseyed
d72b014d6d
feat: add markdown viewer panel with live file watching (#883)
* Add markdown viewer panel with live file watching

Introduce a new PanelType.markdown that renders .md files in a dedicated
panel using MarkdownUI (SwiftUI), with live file watching via DispatchSource
so content auto-updates when the file changes on disk.

- New MarkdownPanel class with file system watcher (write/delete/rename/extend)
- New MarkdownPanelView with custom cmux theme (headings, code blocks, tables,
  blockquotes, inline code, lists, horizontal rules, light/dark mode)
- Full workspace integration: SurfaceKind, creation methods, tab subscription
- Session persistence: snapshot/restore across app restarts
- V2 socket command: markdown.open (validates path, resolves workspace, splits)
- CLI command: cmux markdown open <path> with routing flags and help text
- Agent skill: skills/cmux-markdown/ with SKILL.md, openai.yaml, and references
- Cross-link from skills/cmux/SKILL.md to the new markdown skill
- SPM dependency: gonzalezreal/swift-markdown-ui 2.4.1

* Fix unreachable guard in markdown subcommand dispatch

Use looksLikePath() to distinguish subcommands from path arguments
so the guard can catch unknown subcommands and future subcommands
are parsed correctly.

* Use .isoLatin1 fallback instead of .ascii for encoding recovery

ASCII is a strict subset of UTF-8, so falling back to .ascii after
UTF-8 fails is dead code. Use .isoLatin1 which accepts all 256 byte
values and covers legacy encodings like Windows-1252.

* Mark fileWatchSource as nonisolated(unsafe) for deinit safety

deinit is not guaranteed to run on the main actor, so accessing
@MainActor-isolated storage is a data race under strict concurrency.
DispatchSource.cancel() is thread-safe, so nonisolated(unsafe) is
sufficient with a documented invariant that writes only occur on main.

* Fix file watcher reattach: retry loop with cancellation guard

- Replace one-shot 500ms retry with up to 6 attempts (3s total window)
  so files that reappear after a slow atomic replace are picked up
- Add isClosed flag checked before each retry to prevent restarting
  the watcher after close()/deinit

* Harden path validation in markdown.open command

Reject directories and non-absolute paths before panel creation
to prevent ambiguous behavior and generic downstream failures.

* Always reattach file watcher on delete/rename events

After an atomic save (delete old + create new), the DispatchSource still
points to the old inode. Previously we only reattached when the file was
unreadable, so successful atomic saves left the watcher on a stale inode
and live updates silently stopped. Now we always stop and reattach:
immediately if the new file is readable, via retry loop if not.

* Restore markdown panels even when file is missing at launch

MarkdownPanel already handles unavailable files gracefully (shows
'file unavailable' UI and retries via the reattach loop). Dropping
the panel on restore lost the user's layout for files that may
reappear shortly after (network drives, build artifacts, etc.).

* Harden markdown CLI parsing and startup reconnect behavior

---------

Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com>
2026-03-04 17:48:28 -08:00
Qian Wan
6f210dd2c7
Fix voice dictation text insertion path in GhosttyNSView. (#857)
* Fix voice dictation text insertion path in GhosttyNSView.

* Fix AX selected text decoding to use explicit length
2026-03-04 17:25:39 -08:00
Lawrence Chen
80bbfdf206
Add custom file support for notification sounds (#869)
* Add custom-file notification sound option

* Add notification permission controls and test action

* Allow notification enable retries from settings

* Add notification permission flow debug logging
2026-03-04 17:18:07 -08:00
Lawrence Chen
28977c8e3b
Fix browser panel lifecycle after WebContent process termination (#892)
* Fix browser panel webview lifecycle after web content crashes

* Fix BrowserPanel observer lifecycle during webview replacement

* Fix WebKit termination delegate and harden lifecycle regression check
2026-03-04 16:23:22 -08:00
Yoshiki Agatsuma
76bdf7631a
Add find-in-page (Cmd+F) for browser panels (#837) (#875)
JavaScript-based find using TreeWalker + <mark> highlights with
match counter, next/previous navigation, and drag-to-corner overlay
matching the existing terminal find bar.

- BrowserFindJavaScript: JS generation for search/next/prev/clear
- BrowserSearchOverlay: SwiftUI overlay with IME-safe onSubmit
- BrowserSearchState: Observable state (needle/selected/total)
- TabManager routing: Cmd+F/G dispatches to browser when focused
- Visibility filter: skips script/style/hidden/aria-hidden elements
- Stale DOM guard: isConnected check in next/previous scripts
- Navigation cleanup: clears find on didFinish and didFailNavigation

Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com>
2026-03-04 16:15:15 -08:00
Orkhan Rzazade
5baf0d1a3b
fix: prevent crash in parseNotificationPayload when fields are empty (#881)
Swift's split(separator:) omits empty subsequences by default, so a
payload like "||" or "||body" produces an empty or misaligned array.
Accessing parts[0] unconditionally then triggers an out-of-bounds trap
(EXC_BREAKPOINT / SIGTRAP).

Two changes:
1. Pass omittingEmptySubsequences: false to preserve field positions
   across the pipe delimiters, so "title||body" correctly yields
   ["title", "", "body"] instead of ["title", "body"].
2. Guard parts[0] with a bounds check, consistent with how parts[1]
   and parts[2] are already accessed.

Reproduces when cmux notify is called with empty --title or via
Claude Code's Notification hook where env vars may be empty.
2026-03-04 16:05:43 -08:00
Lawrence Chen
b07532c522
Add Language setting for per-app locale override (#886)
* Add Language setting to Settings for per-app locale override

Uses UserDefaults AppleLanguages to override locale without changing
macOS system language. Picker shows System/English/Japanese with a
restart prompt when the selection changes.

* Address review feedback: guard relaunch and reset behavior

- Guard relaunchApp() against Process launch failure (don't terminate
  if the new instance didn't start)
- Prevent restart dialog from firing during Reset All Settings

* Add localization requirement to CLAUDE.md

All user-facing strings must use String(localized:) with keys in
Localizable.xcstrings and translations for all supported languages.

* Fix relaunch: use detached shell so open survives app exit

The previous approach spawned open as a child process that could get
killed when the parent terminated. Now spawns a shell with sleep+open
that outlives the current process.

* Fix shell injection risk and SwiftUI state batching in language setting

- Pass bundle path via environment variable instead of interpolating
  into shell command string
- Defer isResettingSettings=false to next run loop tick so onChange
  handler reliably sees the guard during Reset All Settings
2026-03-04 16:03:33 -08:00
Connor Callison
80eca0de48
Handle TLS authentication challenges to fix Microsoft device compliance (#806)
WKWebView rejects all authentication challenges by default when
webView(_:didReceive:completionHandler:) is not implemented, using
.rejectProtectionSpace. This silently breaks TLS client-certificate
flows like Microsoft Entra ID Conditional Access, which verifies
device compliance via a certificate stored in the system keychain
by MDM enrollment.

By implementing the delegate method and returning
.performDefaultHandling, the system's standard URL-loading behaviour
takes over: the keychain is searched for matching client identities,
MDM-installed root CAs are trusted, and any configured SSO extensions
(e.g. Microsoft Enterprise SSO) can intercept the challenge.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-04 15:48:18 -08:00
Lawrence Chen
102931d975
Reduce typing lag by hiding invisible views from accessibility tree (#862)
Profiling shows the main thread spends ~24% of time in
AccessibilityViewGraph.needsUpdate walking invisible SwiftUI views
during every layout pass, blocking key event dequeue.

- Add .accessibilityHidden on inactive workspaces in the ZStack
  (opacity-0 but still walked by the accessibility subsystem)
- Add .accessibilityHidden on NotificationsPage and the tabs
  container when their respective selection is not active
- Mark GhosttyTerminalView's HostContainerView (empty portal
  placeholder) as non-accessible since the terminal surface
  lives in the AppKit portal layer above SwiftUI
2026-03-04 15:40:57 -08:00
Lawrence Chen
bd6fa9e8bc
Extract SettingsPickerRow to enforce correct picker style (#887)
Every settings picker needs .pickerStyle(.menu), controlWidth, and
.labelsHidden(). Missing any of these causes layout bugs (like the
notification sound picker rendering as an expanded control). This
new SettingsPickerRow component bakes in the correct modifiers so
future pickers get them by construction. Migrates all 8 existing
settings pickers.
2026-03-04 15:04:59 -08:00
atani
2c330efb8a
feat: add Japanese localization with String Catalog (#819)
* Add i18n infrastructure with String Catalog and Japanese translations

Introduce String Catalog (.xcstrings) for localization support:
- Localizable.xcstrings: 195 UI string entries with en and ja translations
- InfoPlist.xcstrings: Info.plist strings (microphone usage, Finder menu items)
- project.pbxproj: add xcstrings to build phase and ja to knownRegions

* Replace hardcoded UI strings with String(localized:defaultValue:)

Migrate all user-facing strings across 11 source files to use
String(localized:defaultValue:) API (macOS 13+). Each string references
a key in Localizable.xcstrings, with the English text preserved as
defaultValue for fallback.

Files modified:
- KeyboardShortcutSettings: 28 shortcut labels
- SocketControlSettings: mode names and descriptions
- TabManager: placement labels, color names, close dialogs
- BrowserPanel/BrowserPanelView: error pages, context menus, tooltips
- UpdateViewModel/UpdatePopoverView/UpdatePill: update UI states
- NotificationsPage: notification panel labels
- SurfaceSearchOverlay: search bar placeholder and tooltips
- AppDelegate: menus, dialogs, command palette items

* Fix localization gaps from review feedback

Address review comments from CodeRabbit, Greptile, and Cubic Dev AI:
- Use interpolated String(localized:) instead of concatenation for
  version/progress strings in UpdateViewModel
- Localize remaining hardcoded strings in AppDelegate: window labels,
  rename dialog, status menu items, unread notification count
- Localize insecure HTTP alert body in BrowserPanel
- Add 12 new entries to Localizable.xcstrings with Japanese translations

* Fix String(localized:defaultValue:) keys to use StaticString

The localized: parameter requires StaticString when defaultValue: is
used. Move string interpolation from the key to defaultValue only,
and revert maxWidthText to plain strings since they are only used for
layout width calculation.

* Localize remaining UI strings across all source files

Add String(localized:defaultValue:) to all user-facing strings in:
- cmuxApp.swift: settings screen, menus, about panel, dialogs (~180 strings)
- ContentView.swift: command palette, sidebar context menu, dialogs (~200 strings)
- Workspace.swift: rename/move/close tab dialogs, tooltips (~20 strings)
- UpdateTitlebarAccessory.swift: titlebar tooltips, notifications popover (~10 strings)
- TerminalNotificationStore.swift: notification permission dialog (4 strings)
- CmuxWebView.swift: browser context menu items (2 strings)
- AppDelegate.swift: CLI install/uninstall alerts (6 strings)

Add 418 new entries to Localizable.xcstrings with Japanese translations.
Extract sidebar context menu into separate @ViewBuilder to fix Swift
type-checker timeout in large body.
Fix xcstrings format specifiers for interpolated strings (%lld, %@).

Total: 624 localization entries covering the full UI.

* Address review feedback: fix missing localizations and terminology

- Localize javaScriptDialogTitle URL branch in BrowserPanel
- Localize cantReach error message in BrowserPanel
- Localize close other tabs dialog message in TabManager
- Localize workspace accessibility label in ContentView
- Fix unread notification singular/plural (split into two keys)
- Fix insecure connection apostrophe inconsistency (unify to U+2019)
- Rename socketControl.fullOpen.description to socketControl.allowAll.description
- Remove dead code: renameTargetNoun function
- Fix terminology inconsistencies in xcstrings:
  - Unify "Developer Tools" to デベロッパツール
  - Unify "Jump to Latest Unread" phrasing
  - Unify "Flash Focused Panel" terminology
  - Fix dialog.enableNotifications.notNow translation

* fix: address remaining PR 819 review feedback

* fix: use a single localized key for close-other-tabs

* fix: avoid inflection markup in close-other-tabs message

* Address review feedback: localize tooltip, fix subtitle concat, unify keys

- Localize menubar tooltip unread count (hardcoded English -> localized)
- Replace subtitle string concatenation anti-pattern with single localized
  keys containing interpolation placeholders
- Unify workspace fallback key to workspace.displayName.fallback
- Remove unused workspace.defaultName key from xcstrings
- Add Japanese translations for new tooltip and subtitle keys
2026-03-04 14:58:28 -08:00
Lawrence Chen
422c86e822
Fix notification sound picker using wrong style in Settings (#885)
The notification sound picker was missing .pickerStyle(.menu) and
controlWidth, causing it to render as an expanded picker with a large
empty area instead of a compact dropdown menu. Apply the same pattern
used by all other settings pickers.
2026-03-04 14:41:04 -08:00
Yoshiki Agatsuma
a4bf2214fe
Fix browser address bar Japanese IME input (#789) (#867)
* Fix browser address bar Japanese IME input (#789)

* Remove redundant comments
2026-03-04 14:32:52 -08:00