Commit graph

79 commits

Author SHA1 Message Date
Austin Wang
8193e55dae
Fix background terminal startup for unfocused workspaces (#920) 2026-03-04 19:21:32 -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
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
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
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
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
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
168e6b9b25
Auto-heal missing CLI listener socket (#679)
* Auto-heal missing CLI socket listener

* Add Sentry socket listener breadcrumbs and failure capture
2026-02-28 01:19:38 -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
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
Austin Wang
c51171294e
Merge pull request #590 from manaflow-ai/fix/issue-582-sidebar-branch-refresh
fix: keep sidebar git branch updates responsive after sleep/wake
2026-02-26 15:27:21 -08:00
austinpower1258
6b85265255 fix: avoid blocking git branch socket updates on main thread 2026-02-26 15:21:27 -08:00
Lawrence Chen
847ce008ed
Restore lazy keychain reads for socket password (#589)
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
2026-02-26 15:16:27 -08:00
Lawrence Chen
f28eb00b31 Merge remote-tracking branch 'origin/main' into feature/sidebar-pr-metadata
# Conflicts:
#	Sources/ContentView.swift
#	Sources/Workspace.swift
2026-02-24 20:49:29 -08:00
Lawrence Chen
e4f351027c fix(sidebar): normalize escaped newlines in markdown blocks 2026-02-24 20:39:52 -08:00
Lawrence Chen
513e9aa607 feat(sidebar): add markdown blocks, provider labels, and fine-grained toggles 2026-02-24 20:38:07 -08:00
Lawrence Chen
f2ecb4877b feat(sidebar): add generic metadata rows and commands 2026-02-24 20:19:38 -08:00
Austin Wang
32b17e8926
Merge pull request #451 from manaflow-ai/cmux/terminal-render-z-order
Fix terminal blanking after full-surface horizontal tab drop
2026-02-24 16:03:41 -08:00
Lawrence Chen
2877531ea2
Auto-focus omnibar when focusing blank browser surfaces (#448)
* Auto-focus omnibar when focusing blank browser surfaces

* Fix browser omnibar autofocus across pane and palette paths

* Fix Cmd+P switcher omnibar autofocus timing
2026-02-24 16:00:03 -08:00
austinpower1258
f33d65f986 Fix terminal blanking after full-surface tab drops 2026-02-24 16:00:00 -08:00
Lawrence Chen
6eeca9c5da Merge remote-tracking branch 'origin/main' into pr-317-session-persistence
# Conflicts:
#	Sources/AppDelegate.swift
#	Sources/cmuxApp.swift
2026-02-23 14:58:16 -08:00
Lawrence Chen
8d03657c94
Command palette caret uses white tint (#361)
* Set command palette caret tint to white

* Add command palette window actions and shortcut sync
2026-02-23 04:08:01 -08:00
Lawrence Chen
5d63c5f035
Add command palette (Cmd+Shift+P) (#358)
Implements a VS Code-style command palette with fuzzy search,
workspace/surface switching, rename mode, and keyboard navigation.

Closes https://github.com/manaflow-ai/cmux/issues/133
2026-02-23 03:26:36 -08:00
Vadim Kostin
2d454df50f feat(sidebar): show linked pull request metadata 2026-02-23 10:45:36 +08:00
Lawrence Chen
927b0eb2d1 Implement session persistence pass 1 with multi-window restore 2026-02-22 15:39:59 -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
645c7f76ea Start workspace command process before workspace is opened 2026-02-21 05:06:29 -08:00
Lawrence Chen
9653113920 Queue workspace command input before surface attach 2026-02-21 04:57:46 -08:00
Lawrence Chen
a1e05fab84 Improve CLI workspace command responsiveness 2026-02-21 04:37:32 -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
e74f67d369 Merge remote-tracking branch 'origin/main' into issue-230-cli-unix-socket-lag
# Conflicts:
#	Sources/TerminalController.swift
2026-02-21 01:39:04 -08:00
Lawrence Chen
39b110d3b3 Move report_pwd fast path off main-thread sync 2026-02-21 01:01:56 -08:00
Lawrence Chen
167431b786 Avoid main-thread hops for explicit socket scope 2026-02-20 23:58:47 -08:00
Lawrence Chen
a2c39802d1 Merge origin/main into feat-sidebar-branch-refresh-on-close 2026-02-20 23:36:11 -08:00
Lawrence Chen
68cf29cd2d Deduplicate high-frequency socket metadata updates 2026-02-20 23:30:59 -08:00
Lawrence Chen
ede5b701bb
Fix Mark Tab as Unread no-op on focused tab (#249)
* Fix manual unread clear race on focused tab

* Add mark-as-read tab action and show ring for manual unread

* Flash then clear manual unread on tab focus
2026-02-20 23:07:52 -08:00
Lawrence Chen
60e7aeeb16 Fix stale sidebar git branch after split close 2026-02-20 21:47:06 -08:00
Lawrence Chen
d977477d5c Resolve tab actions by tab_id aliases 2026-02-20 20:13:36 -08:00
Lawrence Chen
a5360adb38 Unify tab/workspace action naming in CLI and socket 2026-02-20 20:13:36 -08:00
Lawrence Chen
10e44396df Add tab/workspace action APIs and consistent naming 2026-02-20 20:13:36 -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
9388358914 Merge remote-tracking branch 'origin/main' into fix-dragdrop-overlay 2026-02-20 19:53:45 -08:00
Lawrence Chen
cf767cf9af Fix bonsplit drag routing and pin submodule commit 2026-02-20 18:47:34 -08:00
Lawrence Chen
d9b7511b07
Implement pane.resize divider control and verify in tmux matrix test (#223) 2026-02-20 18:40:37 -08:00
Lawrence Chen
23979d8c02 Merge origin/main into fix-dragdrop-overlay 2026-02-20 18:29:36 -08:00
Lawrence Chen
6cb282bf09
tmux compat: implement issue-153 command set with matrix tests (#221)
* Add tmux rename-window workspace compatibility

Implement workspace.rename in the v2 API and wire CLI commands rename-workspace/rename-window with help text.

Add a regression test that validates API and CLI rename parity plus error handling.

Refs: https://github.com/manaflow-ai/cmux/issues/153

* Add full tmux compatibility command matrix and regression coverage
2026-02-20 18:22:26 -08:00
Lawrence Chen
7dbd7811df Fix workspace routing for surface.read_text
Addresses review feedback from https://github.com/manaflow-ai/cmux/pull/219 by resolving read-screen targets against requested workspace/surface instead of the selected workspace.
2026-02-20 16:31:48 -08:00
Lawrence Chen
146ac253af Harden file-drop routing for local tab drags 2026-02-20 16:27:12 -08:00
Lawrence Chen
b163c2bbf3 Expose production read-screen capture APIs
Implements capture-pane parity item from https://github.com/manaflow-ai/cmux/issues/153 by shipping production read-screen support from https://github.com/manaflow-ai/cmux/issues/152.
2026-02-20 16:22:33 -08:00