Adds `cmux tree` that prints the window > workspace > pane > surface
hierarchy with box-drawing characters. Includes server-side system.tree
RPC for single-round-trip performance.
Features:
- --all flag for all windows (default: current window only)
- --workspace flag to filter to a single workspace
- --json for structured JSON output
- Active path markers (◀ active) and caller identification (◀ here)
- Browser surfaces show their current URL
Closes https://github.com/manaflow-ai/cmux/issues/586
Add a cached lazy keychain fallback to SocketControlPasswordStore so
that authentication paths in TerminalController can transparently read
a legacy keychain password without blocking on every request. The
keychain is read at most once and the result is cached behind an
NSLock. File-based and environment passwords still take priority.
Closes https://github.com/manaflow-ai/cmux/issues/579
Moves socket control password from the macOS login keychain to a
plain file at ~/Library/Application Support/cmux/socket-control-password.
This eliminates the system keychain prompt that interrupts users on
first launch or after keychain changes.
- Directory created with 0700, file written with 0600 permissions
- One-time migration copies existing keychain password to the file,
deletes the keychain entry, and records a migration version in
UserDefaults so it runs only once
- CLI SocketPasswordResolver also reads from the file path
- Security framework import is now conditional (#if canImport)
- Adds SocketControlPasswordStoreTests covering round-trip, env
priority, path resolution, and migration behavior
Fixes https://github.com/manaflow-ai/cmux/issues/541
The equalize splits command was a no-op that always returned false.
Implement it by recursively walking the bonsplit tree and setting
every split divider position to 0.5. Also register the command in
the command palette with a "workspace has splits" precondition so
it only appears when there are multiple panes.
Adds a regression test that creates a nested split layout, skews
divider positions, equalizes, and verifies all dividers are at 0.5.
Fixes https://github.com/manaflow-ai/cmux/issues/571
Only enable .onHover tracking on TitlebarControlButton when the style
uses hoverBackground (e.g. pillGroup). Styles without a visible hover
background no longer install the tracking area, preventing the crash
on notification-bell hover.
Also switches the notifications anchor from .overlay to .background so
AppKit hit-testing no longer conflicts with the popover anchor view.
Includes regression test for the hover-tracking policy.
Fixes https://github.com/manaflow-ai/cmux/issues/537
During app launch, mouseMoved events can trigger hitTest on the drag
handle while SwiftUI is still modifying view state in a layout pass.
The previous blacklist approach (only deferring mouseMoved, cursorUpdate,
nil) let unexpected event types slip through — e.g. activation events
where NSApp.currentEvent is not the mouseMoved being routed — causing
contentView.hitTest() to re-enter SwiftUI views and trigger an exclusive
access violation.
Switch to a whitelist: only leftMouseDown (the sole event the drag
handle actually handles) proceeds with the full view-hierarchy walk.
All other event types bail out immediately. The deferred-event check
runs after suppression recovery (which uses only ObjC associated-object
calls, safe from Swift exclusivity) so stale suppression is still
cleared on passive events, but before the view-hierarchy walk that
triggered the crash.
Fixes#490
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevent crash (KERN_INVALID_ADDRESS at ghostty_surface_refresh) during
geometry reconcile after wake-from-sleep by adding proper lifetime
guards for freed surfaces:
- Re-read self.surface before each ghostty C call in forceRefresh()
instead of using a stale captured local that can outlive the surface
- Nil out self.surface in deinit before scheduling the async free Task,
so in-flight closures see nil and bail out
- Re-check surface validity in reconcileTerminalGeometryPass() after
reconcileGeometryNow() which can trigger AppKit layout that frees
surfaces
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cmux_daily_active deduplicates by UTC date, so PostHog hourly retention
cohorts show 0s. Add a companion cmux_hourly_active event that fires at
most once per UTC hour, deduped via UserDefaults. No flush() after
hourly events (let them batch). The existing 30-minute timer provides
adequate hour-boundary coverage without changes.
Cmd-based keyboard shortcuts (Cmd+T, Cmd+Shift+L, etc.) were blocked
while an IME had active composition (marked text), affecting Chinese
Pinyin, Japanese, Korean, and all other input methods. Since Cmd is a
system modifier never consumed by IME input sequences, exempt
Cmd-modified events from the three IME bypass points in the key event
chain.
Fixes#440
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add otherMouseDown/otherMouseUp handlers to GhosttyNSView that forward
middle-click (button 2) to Ghostty as GHOSTTY_MOUSE_MIDDLE. Ghostty
handles this as paste_from_selection, reading from the selection
clipboard. Non-middle buttons are passed to super for default handling.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>