Commit graph

48 commits

Author SHA1 Message Date
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
e6a293bd78 Merge remote-tracking branch 'origin/main' into issue-151-ssh-remote-port-proxying 2026-03-11 18:21:39 -07:00
Lawrence Chen
6849b83f8d
Reduce typing lag from sidebar re-evaluation and hitTest overhead (#1204)
* Add typing hot path timing diagnostics

* Add stress workspace debug menu item

* Restore stress workspace preload debug path

* Reduce typing lag from sidebar re-evaluation and hitTest overhead

hitTest: gate divider/sidebar/drag routing to pointer events only,
avoiding two full view-tree walks per non-pointer event.

forceRefresh: replace per-keystroke ISO8601DateFormatter + FileHandle
I/O with dlog() in DEBUG builds.

TabItemView: replace @EnvironmentObject subscriptions with plain refs
and precomputed parameters, add Equatable conformance to skip body
re-evaluation when parent rebuilds with unchanged values. @self changed
re-evaluations dropped from 668 to 1 during rapid typing.

* Add typing-latency guardrail comments and CLAUDE.md pitfalls

Strategic comments on hitTest, TabItemView, and forceRefresh to prevent
future regressions. Adds typing-latency-sensitive paths to CLAUDE.md
pitfalls section so agents know the constraints before editing.

* Add workspace palette actions and fix release autosave typing guard

Add Move Up/Down/Top, Close Other/Above/Below, Mark Read/Unread to
Cmd+Shift+P command palette and a Workspace submenu in the menu bar.

Fix recordTypingActivity() being gated behind #if DEBUG, which prevented
release builds from honoring the typing quiet period in autosave.
2026-03-11 17:54:02 -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
Lawrence Chen
879fb05969 Clarify source-shape test policy 2026-03-09 17:07:38 -07:00
Lawrence Chen
76f53aaf90 Build universal GhosttyKit for Release 2026-03-08 04:21:23 -07: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
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
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
26bef7316e
Fix custom notification sound staging reliability (#919) 2026-03-04 19:19:07 -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
Lawrence Chen
56f184d02e
Add debug logging for cmd+click link handling (#777)
* Add debug logging for cmd+click link handling

Logs every decision point in the link opening pipeline:
- mouseDown/mouseUp: modifier keys, click count, position
- resolveTerminalOpenURLTarget: input URL, classification (external/embedded/fallback)
- OPEN_URL action handler: routing decision (cmuxBrowser disabled, external, whitelist miss, embedded browser pane)

All logs are #if DEBUG only via dlog().

* Update tagged build link format for Claude Code cmd+clickability

Claude Code gets a markdown link with the real derived-data path
(file:///tmp/cmux-<tag>/Build/Products/Debug/cmux%20DEV%20<tag>.app)
which is cmd+clickable in cmux. Codex keeps the original format.

* Add equal sign separators to Claude Code build link format

* Fix cmd+click URL buffer overread in OPEN_URL handler

cmux was using String(cString:) to decode the URL from
GHOSTTY_ACTION_OPEN_URL, which reads until a null terminator.
The C struct provides both a pointer and a length field (url + len),
and the pointer is not guaranteed to be null-terminated. This caused
cmux to read past the URL bytes into adjacent memory, producing
corrupted URLs like "https://example.comcom" and multi-URL
concatenations.

Fix: use Data(bytes:count:) with the length field, matching how
vanilla Ghostty decodes the same struct in Ghostty.Action.swift.

* Address review feedback: extract debugModifierString helper
2026-03-02 21:47:24 -08:00
Lawrence Chen
919f77b6dc
Add setting to hide Cmd-hold shortcut hints (#765)
* Add setting to hide Cmd-hold shortcut hints

* Bump bonsplit for Cmd-hold pane hint toggle

* Document tagged app link format in agent notes

* Disable Ctrl pane hints when hold-hints toggle is off
2026-03-02 19:56:27 -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
6800cd44bb WIP: advance ssh remote workspace proxying 2026-02-28 17:05:55 -08:00
Lawrence Chen
8caa5e9c91
Bump version to 0.61.0 (#470) 2026-02-25 02:18:51 -08:00
Lawrence Chen
f366fb0b00 Fix terminal Cmd+F overlay layering and add regression guardrails 2026-02-22 15:25:30 -08:00
Lawrence Chen
4cbdd999d8 Socket CLI: prevent focus stealing + add rename-tab and focus regressions 2026-02-21 02:21:27 -08:00
Lawrence Chen
39b110d3b3 Move report_pwd fast path off main-thread sync 2026-02-21 01:01:56 -08:00
Lawrence Chen
a5c7600458 Harden drag overlay routing and add terminal overlay regression probes 2026-02-20 19:58:58 -08:00
Lawrence Chen
b17249fa30 Fix test command: allowAll socket mode + correct socket path
Tests run via SSH and aren't cmux descendants, so cmuxOnly mode
rejects the connection. Also fix socket path from /tmp/cmux.sock
to /tmp/cmux-debug.sock for debug builds.
2026-02-20 02:07:28 -08:00
Lawrence Chen
442eb1f01d Rename test targets to cmuxTests and cmuxUITests 2026-02-18 21:19:56 -08:00
Lawrence Chen
6748c202f2
Fix sidebar drag-and-drop broken by FileDropOverlayView (#76)
* Fix sidebar drag-and-drop broken by FileDropOverlayView

The FileDropOverlayView (added in 9fd3cc2) sits on the window's theme
frame above the content view. Its hitTest returned self for all events,
causing AppKit to route drag sessions to the overlay instead of the
content view where SwiftUI lives. AppKit walks UP the superview chain
from the hit-tested view, never checking siblings — so SwiftUI's
.onDrop handlers for sidebar tab reordering were never reached.

Three changes fix this:

1. Smart hitTest: check NSPasteboard(name: .drag) for .fileURL and only
   return self during Finder file drags. Return nil otherwise so mouse
   events and internal drags pass through to the content view.

2. Custom UTType for sidebar drags: replace the fragile UTType.plainText
   hack with a proper com.cmux.sidebar-tab-reorder type registered in
   Info.plist. Uses visibility: .ownProcess since it's internal-only.

3. Narrow overlay registration: only register for .fileURL instead of
   .fileURL + .URL + .string. The broad .string type collided with
   text-based drag payloads.

* Add custom UTType Info.plist pitfall to CLAUDE.md
2026-02-18 17:20:22 -08:00
Lawrence Chen
3b4c6f124b Add submodule safety rule to CLAUDE.md
Instructs AI agents to always push submodule commits to remote main
before updating the parent pointer, preventing orphaned commits.
2026-02-17 22:14:32 -08:00
Lawrence Chen
6d6efb6b60 Reversion all 1.x.x to 0.x.x for pre-launch versioning 2026-02-17 18:31:05 -08:00
Lawrence Chen
484b66c8ac
Fix terminal keys swallowed after opening browser (#45)
* Fix terminal keys (arrows, Ctrl+N/P) swallowed after opening browser

After a browser panel is shown, SwiftUI's internal focus system activates
and its _NSHostingView starts consuming arrow keys and other non-Command
key events via performKeyEquivalent, preventing them from reaching the
terminal's keyDown handler.

Fix: In the NSWindow performKeyEquivalent swizzle, when GhosttyNSView is
the first responder and the event has no Command modifier, route directly
to the terminal's performKeyEquivalent — bypassing SwiftUI's view hierarchy
walk entirely.

Also clear stale browserAddressBarFocusedPanelId when a terminal surface
has focus, preventing Cmd+N from being eaten by omnibar selection logic
after focus transitions away from a browser.

Adds DEBUG-only keyboard event ring buffer (KeyDebugLog) that dumps to
/tmp/cmux-key-debug.log for diagnosing future key routing issues.

* Fix split focus and Cmd+Shift+N swallowed after opening browser

Split focus: capture the source terminal's hostedView before bonsplit
mutates focusedPaneId, so focusPanel moves focus FROM the old pane
instead of from the new pane to itself. Also retry ensureFocus when the
new terminal's view has no window yet (matching the existing retry
pattern for isVisibleInUI).

Cmd+Shift+N: after WKWebView has been in the responder chain, SwiftUI's
internal focus system can intercept Command-key events in the content
view hierarchy (returning true) without firing the CommandGroup action
closure. Fix by dispatching Command-key events directly to NSApp.mainMenu
when the terminal is first responder, bypassing the broken SwiftUI path.
Also add Cmd+Shift+N to handleCustomShortcut so it's customizable and
doesn't depend on SwiftUI menu dispatch at all.

* Unified debug event log: merge key/mouse/focus into /tmp/cmux-debug.log

- Delete KeyDebugLog, MouseDebugLog, klog(), mlog() from AppDelegate
- Replace all klog/mlog calls with dlog() (provided by bonsplit)
- Remove debugLogCallback wiring from Workspace
- Add focus change logging: focus.panel, focus.firstResponder,
  split.created, focus.moveFocus
- Add import Bonsplit where needed for dlog access
- Fix stale drag state on cancelled tab drags (bonsplit submodule)

* Fix split focus stolen by re-entrant becomeFirstResponder during reparenting

During programmatic splits (Cmd+D / Cmd+Shift+D), SwiftUI reparents the old
terminal view, which fires becomeFirstResponder → onFocus → focusPanel for the
OLD panel, stealing focus from the newly created pane.

Add programmaticFocusTargetPanelId guard to suppress re-entrant focusPanel
calls for non-target panels during split creation.

Also document the unified debug event log in CLAUDE.md.

* Clear stale title/favicon when browser navigation fails

When a page fails to load (e.g. connection refused), the tab was still
showing the previous page's title and favicon. Now didFailProvisionalNavigation
resets pageTitle to the failed URL and clears faviconPNGData.

* Fix Cmd+N swallowed by browser omnibar and improve split focus suppression

- Only Ctrl+N/P trigger omnibar navigation, not Cmd+N/P (Cmd+N should
  always create new workspace regardless of address bar focus)
- Move split focus suppression from workspace-level guard to source:
  suppress becomeFirstResponder side-effects (onFocus + ghostty_surface_set_focus)
  directly on the old GhosttyNSView during reparenting, preventing both
  model-level and libghostty-level focus divergence
- Remove programmaticFocusTargetPanelId from Workspace.focusPanel

* Fix omnibar hang, WebView white flash, drag-over-browser, and idle CPU spin

- Omnibar: first click selects all without entering NSTextView tracking loop;
  subsequent clicks have 3s synthetic mouseUp safety net to prevent hang
- WebView: set underPageBackgroundColor to match window so new browsers don't
  flash white before content loads
- Drag/drop: register custom UTType (com.splittabbar.tabtransfer) in Info.plist
  so WKWebView doesn't intercept tab drags; override registerForDraggedTypes
  on CmuxWebView as belt-and-suspenders
- CPU: fix infinite makeFirstResponder loop in controlTextDidEndEditing by
  checking both the text field and its field editor (the actual first responder)
2026-02-17 03:21:08 -08:00
Lawrence Chen
2bae2ca2f0 scripts: require --tag for debug reload 2026-02-14 03:13:10 -08:00
Lawrence Chen
2db074b03b
Bump version to 1.25.0 (#33)
Fix blank terminal on macOS 26 and macOS 15:
- Add macOS 26 guard to two additional code paths that set window non-opaque
- Fix NSVisualEffectView z-order: add to themeFrame instead of contentView
- Align sidebarBlendMode defaults between @AppStorage and UserDefaults
- Add read_screen socket command and blank screen regression test
- Add reloads.sh staging script
2026-02-11 16:24:31 -08:00
Lawrence Chen
9817d131f8
Release v1.23.0 (#31)
* Rename cmuxterm to cmux across entire codebase

- Rename GitHub repos: manaflow-ai/cmuxterm -> manaflow-ai/cmux,
  manaflow-ai/homebrew-cmuxterm -> manaflow-ai/homebrew-cmux
- Rename bundle IDs: com.cmuxterm.app -> com.cmux.app
- Rename CLI: CLI/cmuxterm.swift -> CLI/cmux.swift
- Rename homebrew submodule: homebrew-cmuxterm -> homebrew-cmux
- Update all socket paths: /tmp/cmuxterm*.sock -> /tmp/cmux*.sock
- Update all GitHub URLs, DMG names, Sparkle URLs
- Update all source files, scripts, tests, docs, CI workflows

* Bump version to 1.23.0
2026-02-09 15:30:43 -08:00
Lawrence Chen
e9c5917c66
Fix zsh autosuggestions shared history in cmuxterm (#26)
- Restore real ZDOTDIR early in zsh startup so HISTFILE uses user history\n- Preserve user ZDOTDIR without treating Ghostty injected ZDOTDIR as user\n- Add regression tests and terminfo overlay for bright colors
2026-02-09 02:35:20 -08:00
Lawrence Chen
b3c2a8c7c3 Document --tag flag for parallel builds in CLAUDE.md 2026-02-05 23:06:48 -08:00
Lawrence Chen
c52d5afa53 claude 2026-02-01 21:59:01 -08:00
Lawrence Chen
e234123c17 Include local changes 2026-01-30 16:46:30 -08:00
Lawrence Chen
ad86227571 Add changelog and release command
- Add CHANGELOG.md with version history
- Add changelog page to docs site
- Add /release command for preparing releases
2026-01-29 17:58:10 -08:00
Lawrence Chen
e743498fe1 Handle Sparkle updater cache and bump version 2026-01-28 23:30:59 -08:00
Lawrence Chen
0959648643 Bump version and use ghostty fork 2026-01-28 22:40:03 -08:00
Lawrence Chen
a0bf5dfc84 Add cmuxterm CLI and socket control modes 2026-01-28 21:19:48 -08:00
Lawrence Chen
03ee628fb6 Add mock update feed UI tests 2026-01-28 03:22:37 -08:00
Lawrence Chen
3877dc2d98 Rename app to cmuxterm 2026-01-28 02:38:24 -08:00
Lawrence Chen
0441efc675 Improve update UI error details 2026-01-28 01:49:02 -08:00
Lawrence Chen
e3ee246930 Add Sparkle auto-update flow and titlebar update UI 2026-01-26 17:25:34 -08:00
Lawrence Chen
b0c61f7d6c Ship DMG releases and enhance tab actions 2026-01-26 14:48:08 -08:00
Lawrence Chen
4102567054 Fix release workflow for cmux 2026-01-26 03:39:53 -08:00
Lawrence Chen
f275782a9c Disable native tabbing and polish notifications 2026-01-26 03:28:54 -08:00
Lawrence Chen
8320d5805a Rename to cmux and add About panel 2026-01-26 03:05:03 -08:00
Lawrence Chen
cd0f6200c0 Fix Ctrl+C/D handling and add Unix socket control API for testing
Key changes:
- Fix keyboard input handling for control characters in GhosttyTerminalView
  - Set consumed_mods correctly (exclude Ctrl/Cmd from consumed mods)
  - Send unmodified character text for Ctrl+key combinations
  - Add unshifted_codepoint support for proper key encoding

- Add TerminalController with Unix socket API (/tmp/ghosttytabs.sock)
  - Commands: send, send_key, list_tabs, new_tab, close_tab, select_tab
  - Supports ctrl-c, ctrl-d, ctrl-z, enter, tab, escape, etc.

- Add Python test client and automated test suite
  - tests/ghosttytabs.py - Python client library
  - tests/test_ctrl_socket.py - Main Ctrl+C/D test suite (4 tests)
  - tests/test_signals_auto.py - Standalone PTY signal tests

- Update CLAUDE.md with socket API documentation and testing guide
- Update .gitignore for Python cache files

This fixes Ctrl+C/D not working in apps like claude-code, btop, opencode
while continuing to work in simpler apps like htop.
2026-01-22 02:20:51 -08:00
Lawrence Chen
c5bd543fe0 Initial commit: macOS terminal app with vertical tabs using libghostty
Features:
- Vertical tabs sidebar with SwiftUI
- Terminal emulation via GhosttyKit.xcframework (libghostty)
- Keyboard shortcuts: Cmd+T/N, Ctrl+Shift+` (new tab), Cmd+W (close),
  Cmd+Shift+[/], Ctrl+Tab (navigation), Cmd+1-9 (jump to tab)
- Reads Ghostty config from ~/Library/Application Support/com.mitchellh.ghostty/config
- Metal-based rendering
2026-01-22 01:16:24 -08:00