Commit graph

30 commits

Author SHA1 Message Date
Austin Wang
c4bc18d906
Fix ARC workspace inheritance crash and native Zig helper builds (#2283)
* Fix ARC workspace inheritance crash and native Zig helper builds

* Fix Nightly Cmd+N workspace creation crash

* Restore safe terminal config snapshots for Intel Nightly
2026-03-28 03:05:00 -07:00
Austin Wang
63904811f9
Revert "Fix Intel second-surface config inheritance crash (#2179)" (#2267)
This reverts commit 1f4fc476ab.
2026-03-27 20:07:12 -07:00
Austin Wang
1f4fc476ab
Fix Intel second-surface config inheritance crash (#2179) 2026-03-26 23:41:21 -07:00
Pratik Pakhale
b9c656b90c
feat: cmux.json for custom commands (#2011)
* Pre-launch app for browser UI test on headless CI runners

XCUIApplication.launch() blocks ~60s then fails on headless WarpBuild
runners because foreground activation requires a GUI login session.

Apply the same pre-launch strategy used for the display resolution test:
- CI shell launches the app with env vars before running xcodebuild
- Test detects pre-launched app via manifest, uses activate() instead of
  launch() to avoid killing and relaunching the app
- Falls back to clicking the window for focus via accessibility framework

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

* Revert "Pre-launch app for browser UI test on headless CI runners"

This reverts commit a540e2fd99aaa1395b91a8d50caa797cdd7551b8.

* feat: cmux.json for custom commands

* tests: add cmux  json tests

* fix: pr review feedback: validation, translations, input handling, and palette improvements

  - Fix Danish ("Overfladedef inition") and Norwegian ("rotmapp") translation typos
  - Add empty-string check for baseCwd fallback in command palette handlers
  - Coalesce \r\n into single Return keypress in sendInput
  - Redact command text from timeout log to prevent secret leakage
  - Add decode-time validation: reject hybrid/empty commands, ambiguous layout
    nodes, wrong split children count, and empty pane surfaces
  - Namespace custom command IDs with "cmux.config.command." prefix
  - Forward command description to palette subtitle when available
  - Update tests for new validation rules and ID prefix

* fix: address PR review feedback — per-window config isolation, blank validation, ancestor walk,
  palette sanitization

* fix: fallback to current dir cmux.json watching if no any cmux.json found in full acesor walk

* ci: trigger CI for fork PR

* Add directory trust for cmux.json command confirmation

The confirm dialog now shows the actual command text and has an "Always
trust commands from this folder" checkbox. When checked, future confirm
commands from that directory skip the dialog.

Trust is scoped to the git repo root if the cmux.json is inside a repo,
so trusting once covers all subdirectories. Non-git directories are
trusted by exact path. Global config is always trusted.

Trusted directories are persisted in ~/Library/Application Support/cmux/
trusted-directories.json.

* Add trusted directories section to Settings

Shows all trusted directories with per-directory revoke buttons and a
Clear All option. Placed in a "Custom Commands" section between
Automation and Browser in Settings.

* Replace trusted directories list with editable textarea

One path per line, with a Save button that activates on changes.
Users can add, remove, or edit paths directly.

* Auto-save trusted directories on edit, remove Save button

Matches the behavior of other textarea settings (browser host
whitelist, external URL patterns) which auto-save via @AppStorage.

* Sanitize command text in confirm dialog against BiDi attacks

Strip zero-width and BiDi override characters from the command preview
so the dialog shows exactly what will be executed.

---------

Co-authored-by: austinpower1258 <austinwang115@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
2026-03-24 22:28:46 -07:00
Lawrence Chen
656786fb71
Fix tmux notification attention routing 2026-03-20 20:20:54 -07:00
Lawrence Chen
2eae782739 Merge remote-tracking branch 'origin/main' into pr-ssh-stack-main
# Conflicts:
#	.github/workflows/ci.yml
#	CLI/cmux.swift
#	Sources/GhosttyTerminalView.swift
#	Sources/SocketControlSettings.swift
#	Sources/TabManager.swift
#	Sources/TerminalController.swift
#	Sources/Workspace.swift
#	ghostty
#	scripts/reload.sh
2026-03-13 17:56:38 -07:00
Lawrence Chen
cd04bb8932
Merge origin/main into feat-cmux-themes-command 2026-03-13 17:22:12 -07:00
austinpower1258
4bb212510e fix(cmux): preserve split cwd while shell cwd is stale 2026-03-13 17:02:48 -07:00
Lawrence Chen
5f074f810e
Fix session restore replay for transient terminal states 2026-03-13 07:20:18 -07:00
Lawrence Chen
601e5a92e4 Merge origin/main into pr-ssh-stack-main 2026-03-13 04:18:07 -07:00
Lawrence Chen
2596f78380
Add settings to disable pane ring and flash (#1217)
* Add setting to disable unread pane ring

* Add setting to disable pane flash

* Label notification toggles for accessibility

* Clean up notification settings review follow-ups
2026-03-13 03:52:56 -07:00
Lawrence Chen
19b59cae37 Reapply "Merge pull request #239 from manaflow-ai/issue-151-ssh-remote-port-proxying"
This reverts commit f7cbbad434.
2026-03-12 15:54:26 -07:00
Lawrence Chen
f7cbbad434 Revert "Merge pull request #239 from manaflow-ai/issue-151-ssh-remote-port-proxying"
This reverts commit 78e4bd32ba, reversing
changes made to cf75da8f8a.
2026-03-12 14:45:58 -07:00
Lawrence Chen
d67090994e Merge branch 'main' into issue-151-ssh-remote-port-proxying 2026-03-11 15:56:47 -07:00
Lawrence Chen
ec10dfdaec
Add browser find focus debug logs (#1162)
* Add browser find focus debug logs

* Allow browser find bar focus in portal host

* Add split and terminal find debug logs

* Avoid stealing search focus across splits

* Generalize panel focus restore intent

* Unify split focus intent activation

* Address focus restore review feedback

* Yield inactive panel focus before restore

* Gate browser find focus retries by generation

* Avoid repeated browser focus invalidation

* Keep browser find ownership while find bar is open
2026-03-10 19:31:52 -07:00
Lawrence Chen
bdebc8ecc9 Merge branch 'main' into issue-151-ssh-remote-port-proxying
# Conflicts:
#	CLI/cmux.swift
#	Sources/ContentView.swift
#	Sources/GhosttyTerminalView.swift
#	Sources/Panels/BrowserPanel.swift
#	Sources/Panels/BrowserPanelView.swift
#	Sources/TabManager.swift
#	Sources/TerminalController.swift
#	Sources/Workspace.swift
#	Sources/WorkspaceContentView.swift
#	ghostty
2026-03-09 18:36:59 -07:00
Austin Wang
b824147dcb
Fix notification ring dismissal on direct terminal clicks (#1126)
* Add regression test for terminal notification click dismissal

* Dismiss terminal notifications on direct clicks

* Add regression for focused terminal notification ring

* Keep focused terminal notifications unread until click

* Verify direct notification dismiss triggers flash

* Use focus-flash path for direct notification dismiss

* Align notification dismiss flash with ring geometry
2026-03-09 17:55:07 -07: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
5d463af122
Fix ghost terminal surface rebind after close (#808)
* Fix ghost terminal lifecycle rebind race

* Address review feedback on portal regression checks

* Address follow-up review feedback
2026-03-03 15:20:42 -08:00
Lawrence Chen
bfe36f817d Address remaining PR #239 review findings 2026-02-28 19:14:46 -08:00
Lawrence Chen
47f4b5e55a Address PR review feedback for SSH remote workspace flow 2026-02-28 17:36:07 -08:00
Lawrence Chen
c179ee74ea Merge origin/main into issue-151-ssh-remote-port-proxying 2026-02-28 17:17:30 -08:00
Lawrence Chen
1392bd16d7 Revert "Use workspace color for notification ring and selection bar (#664)"
This reverts commit 4bfe95d125.
2026-02-27 18:24:51 -08:00
Lawrence Chen
4bfe95d125
Use workspace color for notification ring and selection bar (#664)
- Notification/focus flash uses workspace customColor (fallback: accent)
- Selection bar/indicator uses workspace customColor when set
- Flash color propagated through Panel.triggerFlash(color:) API
- Browser panel flash overlay uses workspace color
- Regression tests for flash color resolution

Fixes https://github.com/manaflow-ai/cmux/issues/557
2026-02-27 18:14:19 -08:00
austinpower1258
17d8956789 Fix Cmd+W terminal close in terminal+browser split 2026-02-24 21:54:25 -08:00
Lawrence Chen
927b0eb2d1 Implement session persistence pass 1 with multi-window restore 2026-02-22 15:39:59 -08:00
Lawrence Chen
3295c45199 fix: launch cmux ssh via startup command instead of typed input 2026-02-21 01:06:10 -08:00
Lawrence Chen
cae40d1a4c
Sidebar ports on own line, wider sidebar, CMUX_PORT env vars (#160)
* Sidebar ports on own line, wider sidebar, CMUX_PORT env vars

- Move listening ports to dedicated sidebar row (removed from branch/directory line)
- Allow sidebar to resize up to 2/3 of screen width (was capped at 360px)
- Add CMUX_PORT, CMUX_PORT_END, CMUX_PORT_RANGE env vars per workspace
- Each workspace gets a dedicated port range (default: base 9100, range 10)
- Add settings UI for port base and range size
- Add portOrdinal to Workspace, monotonic counter in TabManager

Closes #129

* Make port ordinal counter static to avoid overlap across windows

Each window creates its own TabManager, so a per-instance counter
would reset and reuse port ranges. Making it static ensures unique
ranges across all windows.

* Fix portOrdinal race: pass through Workspace init instead of setting after

The first TerminalPanel is created inside Workspace.init, so setting
portOrdinal after init returns meant the initial terminal always got
ordinal 0. Pass portOrdinal as an init parameter and set it before
the TerminalPanel is created.

* Fix P2/P3: snapshot port settings at surface creation, use window screen for sidebar cap

P2: Port base/range are now snapshotted on TerminalSurface when the
panel is created, so changing settings mid-session won't cause
inconsistent CMUX_PORT values across terminals in the same workspace.

P3: Sidebar max width now uses NSApp.keyWindow?.screen instead of
NSScreen.main, so multi-monitor setups get the correct 2/3 cap for
the display the window is actually on.

* Fix P1: snapshot port base/range once per app session, not per panel

Port base and range size are now static properties on TerminalSurface,
initialized once from UserDefaults at first access. This prevents
overlapping port ranges across workspaces when settings are changed
mid-session (e.g., workspace 1 with range=10 at 9110-9119, then
range changed to 5, workspace 2 would overlap at 9110).
2026-02-20 14:12:14 -08:00
Lawrence Chen
de666ff05b Fix split blackout race and stabilize focus handoff 2026-02-19 17:10:27 -08:00
Lawrence Chen
50f0dd334d
Fix frozen terminals after split churn (#12)
* Fix blank terminal after split operations and add visual tests

## Blank Terminal Fix
- Add `needsRefreshAfterWindowChange` flag in GhosttyTerminalView
- Force terminal refresh when view is added to window, even if size unchanged
- Add `ghostty_surface_refresh()` call in attachToView for same-view reattachment
- Add debug logging for surface attachment lifecycle (DEBUG builds only)

## Bonsplit Migration
- Add bonsplit as local Swift package (vendor/bonsplit submodule)
- Replace custom SplitTree with BonsplitController
- Add Panel protocol with TerminalPanel and BrowserPanel implementations
- Add SidebarTab as main tab container with BonsplitController
- Remove old Splits/ directory (SplitTree, SplitView, TerminalSplitTreeView)

## Visual Screenshot Tests
- Add test_visual_screenshots.py for automated visual regression testing
- Uses in-app screenshot API (CGWindowListCreateImage) - no screen recording needed
- Generates HTML report with before/after comparisons
- Tests: splits, browser panels, focus switching, close operations, rapid cycles
- Includes annotation fields for easy feedback

## Browser Shortcut (⌘⇧B)
- Add keyboard shortcut to open browser panel in current pane
- Add openBrowser() method to TabManager
- Add shortcut configuration in KeyboardShortcutSettings

## Screenshot Command
- Add 'screenshot' command to TerminalController for in-app window capture
- Returns OK with screenshot ID and path

## Other
- Add tests/visual_output/ and tests/visual_report.html to .gitignore

* Add browser title subscription and set tab height to 30px

- Subscribe to BrowserPanel.$pageTitle changes to update bonsplit tabs
- Update tab titles in real-time as page navigation occurs
- Clean up subscriptions when panels are removed
- Set bonsplit tab bar and tab height to 30px (in submodule)

* Fix socket API regressions in list_surfaces, list_bonsplit_tabs, focus_pane

- list_surfaces: Remove [terminal]/[browser] suffix to keep UUID-only format
  that clients and tests expect for parsing
- list_bonsplit_tabs --pane: Properly look up pane by UUID instead of
  creating a new PaneID (requires bonsplit PaneID.id to be public)
- focus_pane: Accept both UUID strings and integer indices as documented

* Fix browser panel stability and keyboard shortcuts

- Prevent WKWebView focus lifecycle crashes during split/view reshuffles
- Match bracket shortcuts via keyCode (Cmd+Shift+[ / ], Cmd+Ctrl+[ / ])
- Support Ghostty config goto_split:* keybinds when WebView is focused
- Add focus_webview/is_webview_focused socket commands and regression tests
- Rename SidebarTab to Workspace and update docs

* Make ctrl+enter keybind test skippable

Skip when the Ghostty keybind isn't configured or when osascript can't send keystrokes (no Accessibility permission), so VM runs stay green.

* Auto-focus browser omnibar when blank

When a browser surface is focused but no URL is loaded yet, focus the address bar instead of the WKWebView.

* Stabilize socket surface indexing

* Focus browser omnibar escape; add webview keybind UI tests

- Escape in omnibar now returns focus to WKWebView\n- Add UI tests for Cmd+Ctrl+H pane navigation with WebKit focused (including Ghostty config)\n- Avoid flaky element screenshots in UpdatePillUITests on the UTM VM

* Fix browser drag-to-split blanks and socket parsing

* Fix webview-focused shortcuts and stabilize browser splits

- Match ctrl/shift shortcuts by keyCode where needed (Ctrl+H, bracket keys)
- Load Ghostty goto_split triggers reliably and refresh on config load
- Add debug socket helpers: set_shortcut + simulate_shortcut for tests
- Convert browser goto_split/keybind tests to socket-based injection (no osascript)
- Bump bonsplit for drag-to-split fixes

* Fix split layout collapse and harden socket pane APIs

* Stabilize OSC 99 notification test timing

* Fix terminal focus routing after split reparent

* Support simulate_shortcut enter for focus routing test

* Stabilize terminal focus routing test

* Fix frozen new terminal tabs after many splits

* Fix frozen new terminal tabs after splits

* Fix terminal freeze on launch/new tabs

* Update ghostty submodule

* Fix terminal focus/render stalls after split churn

* Fix nested split collapsing existing pane

* Fix nested split collapse + stabilize new-surface focus

* Update bonsplit submodule

* Fix SIGINT test flake

* Remove bonsplit tab-switch crossfade

* Remove PROJECTS.md

* Remove bonsplit tab selection animation

* Ignore generated test reports

* Middle click closes tab

* Revert unintended .gitignore change

* Fix build after main merge

* Revert "Fix build after main merge"

This reverts commit 16bf9816d0856b5385d52f886aa5eb50f3c9d9a4.

* Revert "Merge remote-tracking branch 'origin/main' into fix/blank-terminal-and-visual-tests"

This reverts commit 7c20fb53fd71fea7a19a3673f2dd73e5f0c783c4, reversing
changes made to 0aff107d787bc9d8bbc28220090b4ca7af72e040.

* Remove tab close fade animation

* Use terminal.fill icon

* Make terminal tab icon smaller

* Match browser globe tab icon size

* Bonsplit: tab min width 48 and tighter close button

* Bonsplit: smaller tab title font

* Show unread notification badge in bonsplit tabs and improve UI polish

Sync unread notification state to bonsplit tab badges (blue dot).
Improve EmptyPanelView with Terminal/Browser buttons and shortcut hints.
Add tooltips to close tab button and search overlay buttons.

* Fix reload.sh single-instance safety check on macOS

Replace GNU-only `ps -o etimes=` with portable `ps -o etime=` and
parse the dd-hh:mm:ss format manually for macOS compatibility.

* Centralize keyboard shortcut definitions into Action enum

Replace per-shortcut boilerplate with a single Action enum that holds
the label, defaults key, and default binding for each shortcut. All
call sites now use shortcut(for:). Settings UI is data-driven via
ForEach(Action.allCases). Titlebar tooltips update dynamically when
shortcuts are changed. Remove duplicate .keyboardShortcut() modifiers
from menu items that are already handled by the event monitor.

* Fix WKWebView consuming app menu shortcuts and close panel confirmation

Add CmuxWebView subclass that routes key equivalents through the main
menu before WebKit, so Cmd+N/Cmd+W/tab switching work when a browser
pane is focused. Fix Cmd+W close-panel path: bypass Bonsplit delegate
gating after the user confirms the running-process dialog by tracking
forceCloseTabIds. Add unit tests (CmuxWebViewKeyEquivalentTests) and
UI test scaffolding (MenuKeyEquivalentRoutingUITests) with a new
cmux-unit Xcode scheme.

* Update CLAUDE.md and PROJECTS.md with recent changes

CLAUDE.md: enforce --tag for reload commands, add cleanup safety rules.
PROJECTS.md: log notification badge, reload.sh fix, Cmd+W fix, WebView
key equiv fix, and centralized shortcuts work.

* Keep selection index stable on close

* Add concepts page documenting terminology hierarchy

New docs page explaining Window > Workspace > Pane > Surface > Panel
hierarchy with aligned ASCII diagram. Updated tabs.mdx and splits.mdx
to use consistent terminology (workspace instead of tab, surface
instead of panel) and corrected outdated CLI command references.

* Update bonsplit submodule

* WIP: improve split close stability and UI regressions

* Close terminal panel on child exit; hide terminal dirty dot

* Fix split close/focus regressions and stabilize UI tests

* Add unread Dock/Cmd+Tab badge with settings toggle

* Fix browser-surface shortcuts and Cmd+L browser opening

* Snapshot current workspace state before regression fixes

* Update bonsplit submodule snapshot

* Stabilize split-close regression capture and sidebar resize assertions

* Change default Show Notifications shortcut from Cmd+Shift+I to Cmd+I

* Fix update check readiness race, enable release update logging, and improve checking spinner

* Restore terminal file drop, fix browser omnibar click focus, and add panel workspace ID mutation for surface moves

* Add Cmd+digit workspace hints, titlebar shortcut pills, sidebar drag-reorder, and workspace placement settings

* Add v2 browser automation API, surface move/reorder commands, and short-handle ref system to TerminalController

* Add CLI browser command surface, --id-format flag, and move/reorder commands

* Extend test clients with move/reorder APIs, ref-handle support, and increased timeouts

* Harden test runner scripts with deterministic builds, retry logic, and robust socket readiness

* Stabilize existing test suites with focus-wait helpers, increased timeouts, and API shape updates

* Add terminal file drop e2e regression test

* Add v2 browser API, CLI ref resolution, and surface move/reorder test suites

* Add unit tests for shortcut hints, workspace reorder, drop planner, and update UI test stabilization

* Add cmux-debug-windows skill with snapshot script and agent config

* Update project docs: mark browser parity and move/reorder phases complete, add parallel agent workflow guidelines

* Update bonsplit submodule: re-entrant setPosition guard, tab shortcut hints, and moveTab/reorderTab API

* Add browser agent UX improvements: snapshot refs, placement reuse, diagnostics, and skill docs

- Upgrade browser.snapshot to emit accessibility tree text with element refs (eN)
- Add right-sibling pane reuse policy for browser.open_split placement
- Add rich not_found diagnostics with retry logic for selector actions
- Support --snapshot-after for post-action verification on mutating commands
- Allow browser fill with empty text for clearing inputs
- Default CLI --id-format to refs-first (UUIDs opt-in via --id-format uuids|both)
- Format legacy new-pane/new-surface output with short surface refs
- Add skills/cmuxterm-browser/ and skills/cmuxterm/ end-user skill docs
- Add regression tests for placement policy, snapshot refs, diagnostics, and ID defaults

* Update bonsplit submodule: keep raster favicons in color when inactive
2026-02-13 16:45:31 -08:00