Skip to content

v3.1.0

Choose a tag to compare

@github-actions github-actions released this 11 Jun 23:07
· 62 commits to main since this release

Headline: wmux panes and sidebars are now extensible by third-party UI plugins running in sandboxed iframes under the same permission stack as MCP plugins; the workspace sidebar shows live zero-config context (git branch, PR status, process-scoped listening ports, latest notification); and standard terminal notification escape sequences (OSC 9/777/99) are parsed into first-class events. Plus a batch of rendering and MCP-routing fixes. All features dogfood-verified on a live build.

Added

  • Workspace context sidebar (X1): live git branch, PR status, scoped listening ports, and latest notification per workspace — zero config. The sidebar now shows each workspace's git branch via an fs.watch on .git/HEAD (no polling; linked worktrees detected and marked), the current branch's PR number/state/CI checks from a 5-minute gh cache (silently absent when gh isn't installed; click opens the PR), listening TCP ports matched against each pane's own process tree (previously the port list was machine-global — every workspace showed the same first-20 ports), and a one-line summary of the latest terminal notification. All context flows through the existing workspace.metadata.changed event, so MCP clients and plugins see the same data the sidebar does.
  • UI plugin host: sandboxed sidebar panels, status-bar widgets, pane badges, and palette commands. Drop a bundle in ~/.wmux/plugins/<name>/ with a manifest.json and wmux hosts its UI in a sandboxed iframe (opaque origin, no network — the postMessage bridge is the only channel out). Plugin RPCs dispatch through the same permission stack as MCP plugins (trust DB, capability enforcement, approval prompts), with new capabilities ui.sidebar / ui.statusbar / ui.pane-decoration / ui.commands / notifications.read. Includes a reference plugin under examples/plugins/hello-panel. Verified end-to-end on a live build (approval flow → mount → bridge RPC → pane badge).
  • Terminal desktop notifications (OSC 9 / OSC 777 / OSC 99) are now parsed and surfaced as events. Programs that emit the standard notification escape sequences — iTerm2-style OSC 9, urxvt OSC 777;notify, and the kitty OSC 99 desktop-notification protocol (including chunked and base64 payloads) — produce a new notification.received event on the event bus (pollable via wmux_events_poll) in both daemon and local PTY modes. ConEmu's OSC 9 progress subcommands no longer trigger spurious toasts, and notification text is sanitized and length-capped. Groundwork for the attention-ring / toast-routing notification system.

Fixed

  • surface_list / pane.list no longer report a stale, workspace-wide cwd for every surface. Each surface's own live working directory (OSC 7 / prompt scrape) is now authoritative; the workspace-level metadata cwd — which is just whichever active surface last changed directory — is only a fallback. Previously that single path was stamped onto every surface in the workspace.
  • Panes no longer turn into X-boxes or blank out after splitting / tab-switching through many content-heavy panes in a long session. xterm's WebglAddon.dispose() detaches the renderer but never frees the underlying WebGL2 context, so split/tab churn accumulated zombie contexts past Chromium's ~16-context cap, force-evicting a live pane's context. Every addon teardown now force-releases its GL context immediately via WEBGL_lose_context.loseContext(). (#199, resolves #197)
  • Non-selected panes no longer render garbled or blank glyphs when switching pane selection. After long use with content-heavy panes, switching the selected pane could corrupt the other panes. xterm's WebGL addon shares one glyph texture atlas across every same-config terminal (CharAtlasCache); the focus/visible defensive repaint called clearTextureAtlas(), which empties that shared atlas and rebuilds only the newly-focused pane — the siblings kept stale per-cell texture coordinates and sampled an emptied/repositioned atlas. The repaint now does a full-range refresh() only and never touches the shared atlas; the earlier "garbled glyphs after a burst" case (#166) was already covered by the burst-path refresh, which never cleared the atlas. (#196, resolves #191)
  • MCP workspace-identity resolution no longer blocks the event loop. The identity PID-tree walk used a synchronous execFileSync per ancestor; it now walks the tree with async execFile, preserving the resolution result and the source invariant. (#195, resolves #194)
  • Playwright auto-open is pinned to the calling session's workspace. browser.open without an explicit workspaceId opened the browser in whichever workspace happened to be active; the engine now resolves the calling session's workspace and fails closed instead of falling back to the active one. (#193, resolves #190)
  • Esc now reaches the terminal under a CJK IME. While a CJK IME composition was active (keyCode 229), xterm dropped the Esc keystroke; wmux now matches the physical key code and injects Esc directly, the same class of fix as the Ctrl+J newline issue. (#189)

Contributors

  • @zer0ken — WebGL context-leak fix (#199), shared-atlas pane-corruption fix (#196), non-blocking MCP identity walk (#195), and Playwright workspace pinning (#193).
  • @snowyukitty — CJK IME Esc fix (#189).

What's Changed

  • fix(terminal): send Esc under a CJK IME (keyCode 229) by @snowyukitty in #189
  • macOS support: substrate를 Windows 수준으로 (focus/CLI/격리/zsh OSC133/agent detection) by @openwong2kim in #192
  • fix(mcp): pin Playwright auto-open to the calling session's workspace (#190) by @zer0ken in #193
  • fix(mcp): walk the identity PID tree with async execFile, not blocking execFileSync (#194) by @zer0ken in #195
  • fix(terminal): stop non-selected panes garbling on pane-selection switch (#191) by @zer0ken in #196
  • fix(terminal): release WebGL contexts on teardown to stop split-churn X-boxes (#197) by @zer0ken in #199

Full Changelog: v3.0.0...v3.1.0