Commit graph

77 commits

Author SHA1 Message Date
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
30bb74dc92 Merge branch 'pr-374-ssh-remote-cli-relay' into issue-151-ssh-remote-port-proxying
# Conflicts:
#	CLI/cmux.swift
#	Sources/ContentView.swift
#	Sources/GhosttyTerminalView.swift
#	Sources/Panels/TerminalPanel.swift
#	Sources/SocketControlSettings.swift
#	Sources/TabManager.swift
#	Sources/TerminalController.swift
#	Sources/Workspace.swift
#	daemon/remote/README.md
#	daemon/remote/cmd/cmuxd-remote/main.go
#	docs/remote-daemon-spec.md
#	tests_v2/test_ssh_remote_cli_metadata.py
2026-03-09 18:31:10 -07:00
Austin Wang
4ba967556e
Fix cmux --version memory blowup (#1121)
* Add version memory guard regression test

* Fix cmux --version plist lookup blowup
2026-03-09 16:35:05 -07:00
Lawrence Chen
e7c3961489
Revert "Add workspace pages in the titlebar (#1030)" (#1040)
This reverts commit 4de975e6a4.
2026-03-07 00:05:58 -08:00
Lawrence Chen
4de975e6a4
Add workspace pages in the titlebar (#1030)
* Add workspace pages in the titlebar

* Add workspace pages UI test target entry

* Relax workspace pages UI test titlebar checks

* Use page close button in workspace pages UI test

* Stabilize workspace pages UI test interruptions

* Skip page close confirms in UI tests

* Clean up superseded workspace handoffs

* Tighten page hint UI assertions

---------

Co-authored-by: cmux <cmux@cmuxs-Mac-mini.local>
2026-03-06 21:23:11 -08:00
Lawrence Chen
43f42b730c
Merge pull request #972 from manaflow-ai/task-browser-open-trailing-json-flags
Support trailing browser output flags
2026-03-05 22:39:14 -08:00
Lawrence Chen
ff428a7386
Merge pull request #973 from manaflow-ai/task-browser-goto-snapshot-after-parsing
Fix browser goto snapshot-after parsing
2026-03-05 22:39:10 -08:00
Lawrence Chen
0e7daae4a6 Merge remote-tracking branch 'origin/main' into task-browser-open-trailing-json-flags
# Conflicts:
#	CLI/cmux.swift
2026-03-05 20:03:19 -08:00
Lawrence Chen
085e192bca
Add diagnostics for empty browser snapshots (#977) 2026-03-05 20:01:05 -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
61792c3caf Fix browser goto snapshot-after parsing 2026-03-05 17:57:05 -08:00
Lawrence Chen
103f80fac2 Support trailing browser output flags 2026-03-05 17:56:37 -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
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
Lawrence Chen
bfe843f0bd
Clear sidebar notification when user submits prompt (#821)
* Clear sidebar notification when user submits prompt in Claude Code

Add UserPromptSubmit hook to the Claude Code wrapper that calls
`cmux claude-hook prompt-submit`. This clears the workspace notification
and sets status back to "Running" when the user addresses Claude's question,
so the "waiting for input" preview in the sidebar goes away.

Also adds --tab support to clear_notifications socket command and
--workspace support to the clear-notifications CLI command for
per-workspace notification clearing.

Closes https://github.com/manaflow-ai/cmux/issues/799

* Address review feedback: stricter error handling

- clear-notifications CLI: error on explicit --workspace failure instead of
  falling back to global clear. Env var still gracefully degrades.
- prompt-submit hook: propagate sendV1Command errors instead of swallowing
  with try?.
- clear_notifications socket: validate --tab flag is present before resolving,
  reject malformed args instead of falling back to selected tab.

* Gate env workspace fallback on windowId == nil in clear-notifications

Matches the pattern used by other CLI commands to avoid using
CMUX_WORKSPACE_ID from the caller shell when --window targets
a different window.
2026-03-03 18:48:32 -08:00
Lawrence Chen
fdc38a3326
Add external URL bypass rules for embedded browser opens (#768)
* Add external URL bypass rules for embedded browser opens

* Align open-wrapper external regex handling with app-side matcher
2026-03-02 17:50:34 -08:00
Lawrence Chen
f451766d12
Add cmux <path> to open directories and Homebrew binary stanza (#705)
* Add `cmux <path>` to open directories and Homebrew binary stanza

CLI: `cmux .` or `cmux /path/to/dir` opens a new workspace at the
given directory. If the app isn't running, it launches first and waits
for the socket. Also adds `--cwd` flag to `new-workspace`.

Server: `workspace.create` now accepts an optional `cwd` parameter,
passed through to `TabManager.addWorkspace(workingDirectory:)`.

Homebrew: adds `binary` stanza to the cask so `cmux` CLI is globally
available after `brew install --cask cmux`. Updated both the cask file,
the CI workflow template, and the manual release script so automated
version bumps preserve the stanza.

* Address review: validate cwd type, fix socket detection, propagate errors

- looksLikePath now also matches paths containing `/` (e.g. `foo/bar`)
- openPath uses socket connection attempt instead of fileExists to detect
  whether the app is running (Unix sockets may not appear on filesystem)
- launchApp/activateApp now throw instead of swallowing errors with try?
- Server validates that cwd param is a string, returns invalid_params error
  if wrong type is passed
2026-02-28 20:25:41 -08:00
Lawrence Chen
fff1cd786f Fix ssh workspace focus and harden remote daemon bootstrap paths 2026-02-28 19:56:11 -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
6800cd44bb WIP: advance ssh remote workspace proxying 2026-02-28 17:05:55 -08:00
Lawrence Chen
181574586e
Fix --help flag executing commands instead of showing help (#657)
* Fix --help flag executing commands instead of showing help (#650)

The --help check fell through to command dispatch when subcommandUsage
returned nil for a command. Now --help always returns before dispatch,
printing a generic fallback when no specific help text exists.

Also adds missing subcommandUsage entries for: new-window, list-panes,
list-pane-surfaces, surface-health, trigger-flash, list-panels,
focus-panel, set-app-focus, ping, capabilities, identify, list-windows,
current-window, refresh-surfaces, current-workspace, list-notifications,
clear-notifications.

Closes #650

* Document all flags and options in CLI --help output

Every subcommand's help text now shows all accepted flags, options,
environment variable fallbacks, and positional arguments matching the
actual dispatch code. Also adds help entries for commands that were
returning the generic fallback (list-workspaces, list-panes,
list-pane-surfaces, surface-health, trigger-flash, list-panels,
focus-panel, set-app-focus, etc.)

* Show 'Unknown command' for invalid commands, add legacy alias help

Unknown commands now show "Unknown command 'X'. Run 'cmux help' to see
available commands." instead of the misleading "No detailed help
available." Also adds help entries for legacy browser aliases
(open-browser, navigate, etc.) pointing to 'cmux browser --help'.

* Audit all 89 CLI commands for complete help coverage

- Add missing `help` subcommandUsage entry
- Expand id|ref → id|ref|index for move-workspace-to-window,
  close-workspace, select-workspace, rename-workspace
- Document CMUX_WORKSPACE_ID/CMUX_TAB_ID/CMUX_SURFACE_ID env var
  defaults in tab-action, rename-workspace
- Expand browser help: get (--selector, --attr, --property),
  find (--name, --exact, --index), network route (--abort, --body),
  open/open-split/new env var defaults
- Remove duplicate rename-window help case (now handled by
  rename-workspace combined case)
- Upgrade regression test to auto-extract dispatch+subcommandUsage
  switches and flag any commands missing help entries
2026-02-27 17:38:33 -08:00
Lawrence Chen
9ae737026d
Fix browser eval: await promises, always-on console hooks, undefined detection (#613)
- Wrap eval scripts in async IIFE that detects and awaits thenables,
  using callAsyncJavaScript when available (macOS 11+) (#603)
- Register console/error telemetry hooks as WKUserScript at document
  start so they survive navigation and are active before page JS (#604)
- Return typed envelope {__cmux_t, __cmux_v} from eval to distinguish
  undefined from no return value; CLI prints "undefined" (#605)
- Keep dialog hooks as lazy injection only (not document-start) to
  avoid suppressing WKUIDelegate native dialogs
- Add regression tests for async wrapper and undefined CLI rendering
2026-02-27 01:42:27 -08:00
Lawrence Chen
fdca658c80
Remove not_supported commands and legacy aliases from --help (#595)
Hide browser subcommands that always return not_supported on WKWebView
(viewport, geolocation, offline, trace, network, screencast, input)
and the legacy browser alias notice from the help output. Command
handlers remain for backwards compatibility.

Closes https://github.com/manaflow-ai/cmux/issues/593
2026-02-26 20:36:21 -08:00
Lawrence Chen
e74012a728
Add cmux tree command for full hierarchy view (#592)
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
2026-02-26 20:04:09 -08:00
Lawrence Chen
bcb6f49d6e
Fix CLI SIGPIPE exit on broken stdout pipes (#581) 2026-02-26 15:17:50 -08:00
Lawrence Chen
163f8572e4
Replace keychain password storage with file-based storage (#576)
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
2026-02-26 14:29:12 -08:00
Lawrence Chen
2714d07c9f Scope socket password keychain per debug run and harden CLI lookup 2026-02-25 00:30:39 -08:00
Lawrence Chen
f16d8f36e7 Merge remote-tracking branch 'origin/main' into pr-374-ssh-remote-cli-relay
# Conflicts:
#	CLI/cmux.swift
#	Sources/ContentView.swift
#	Sources/TerminalController.swift
#	Sources/Workspace.swift
2026-02-25 00:14:00 -08:00
Lawrence Chen
daa340fa87 Harden cmux ssh for mixed-version remote sessions 2026-02-24 22:09:27 -08:00
Lawrence Chen
2b7928aa60 Fix ssh terminfo spew by using RemoteCommand bootstrap 2026-02-24 21:53:35 -08:00
Lawrence Chen
4e5b5c8ee8 Make cmux available in cmux ssh sessions via ephemeral PATH bootstrap 2026-02-24 21:46:11 -08:00
Lawrence Chen
0f47ae3d1a Document cmux ssh focus-intent workspace selection 2026-02-24 21:30:57 -08:00
Lawrence Chen
c5f7217f85 Focus new workspace after cmux ssh and lock with regression test 2026-02-24 21:27:22 -08:00
Lawrence Chen
257afc0623 Fix SSH relay/socket regressions and restore session/focus contracts 2026-02-24 21:20:24 -08:00
Lawrence Chen
f7ef0707c2 Include commit metadata in cmux --version output 2026-02-24 20:51:43 -08:00
Lawrence Chen
db86d3e301 Broaden CLI socket telemetry and add restart listener command 2026-02-24 20:38:05 -08:00
Lawrence Chen
93c167ff02 Add Sentry breadcrumbs for claude-hook socket failures 2026-02-24 20:22:38 -08:00
Lawrence Chen
37be8efeb0 Print browser console/errors in non-JSON mode 2026-02-24 14:57:55 -08:00
Lawrence Chen
9db730718b Fix browser eval CLI output 2026-02-24 14:29:01 -08:00
Raghav Pillai
18700b0515 Add SSH reverse relay for local Unix socket
- Add support for spawning an SSH reverse relay that forwards a remote TCP port to a local cmux Unix socket
- Generate random ephemeral relay port and propagate via CLI, workspace config, and JSON payloads
- Start/monitor background relay Process in WorkspaceRemoteSessionController with stderr handling and auto-restart
- Filter probe-reported ephemeral ports and avoid treating relay ports as user service ports
- Create remote cmux symlink and write remote ~/.cmux/socket_addr for relay discovery
- Kill orphaned relay processes on startup to avoid conflicts
- Add helpers to check loopback port reachability and adjust forward/SSH options (ControlPath, ExitOnForwardFailure)
2026-02-23 18:24:25 +02:00
Lawrence Chen
f7457055f1
Add sidebar metadata CLI subcommands and API docs (#305)
* Add sidebar metadata CLI subcommands and API docs

Expose set-status, clear-status, list-status, set-progress,
clear-progress, log, clear-log, list-log, and sidebar-state as
proper CLI subcommands with --help support and usage() listing.
Previously these only existed as raw socket commands.

Also adds a "Sidebar metadata commands" section to the docs site
API reference page.

* Quote multi-word values in socket command strings

Fix set-progress --label and log message forwarding to properly
quote values before sending to the socket tokenizer. Without
quoting, multi-word labels like "Build step one" would be split
into separate tokens. Also quote --source values for consistency.

* Fix socket quoting: escape backslashes and quote status values

Add socketQuote() helper that escapes both backslashes and double
quotes before wrapping in quotes. Apply it to:
- set-status value (prevents --flags in values being parsed as options)
- set-status --icon and --color values
- set-progress --label
- log --source and message text

Fixes values like "pytest --maxfail=1" or "C:\new\build" being
mangled by the socket tokenizer.

* Escape newlines in socketQuote to prevent socket framing breakage

The socket protocol uses newline as message terminator, so embedded
newlines/carriage returns in values would truncate the command.

* Parse flags before positionals in set-status, clear-status, set-progress

Fixes flags-first invocation like `cmux set-status --workspace workspace:2
build compiling` which previously grabbed `--workspace` as the key.
Now all flags are extracted first, then positional args are validated.
2026-02-22 16:06:32 -08:00
Lawrence Chen
ea87076fe4 Fix CLI exit code on v1 auth errors 2026-02-22 01:37:42 -08:00
Lawrence Chen
a168182f54 Merge remote-tracking branch 'origin/main' into issue-296-access-control-modes
# Conflicts:
#	CLI/cmux.swift
2026-02-22 01:01:08 -08:00
Lawrence Chen
18550e5d1f Add expanded socket access modes with password auth
Implements https://github.com/manaflow-ai/cmux/issues/296 with new modes: off, cmuxOnly, automation, password, and allowAll.

Adds keychain-backed password storage, connection-level auth gates (v1 auth + v2 auth.login), settings UX with warning confirmation, CLI --password support, and regression tests.
2026-02-22 00:55:14 -08:00
Lawrence Chen
f184f882c0 Add CLI --version output and regression test 2026-02-22 00:16:01 -08:00
Austin Wang
740b4b11e5
Deduplicate branch context lines by directory (#288) 2026-02-21 17:45:52 -08:00
Lawrence Chen
4cbdd999d8 Socket CLI: prevent focus stealing + add rename-tab and focus regressions 2026-02-21 02:21:27 -08:00