* Add `cmux omo` command for OpenCode + oh-my-openagent integration Same pattern as `cmux claude-teams`: creates a tmux shim so oh-my-openagent's TmuxSessionManager spawns agents as native cmux splits instead of tmux panes. Sets TMUX/TMUX_PANE env vars, prepends shim to PATH, and execs into opencode. Closes https://github.com/manaflow-ai/cmux/issues/2085 * Auto-install oh-my-opencode plugin when running cmux omo Before launching opencode, cmux omo now: - Checks if oh-my-opencode is registered in ~/.config/opencode/opencode.json - If not, creates/updates the config with the plugin entry - Checks if the npm package is installed in node_modules - If not, runs bun add (or npm install) to install it - Then proceeds with tmux shim setup and exec * Use shadow config dir to avoid modifying user's opencode setup Instead of writing directly to ~/.config/opencode/opencode.json, cmux omo now creates a shadow config at ~/.cmuxterm/omo-config/ that layers oh-my-opencode on top of the user's existing config. Symlinks node_modules, package.json, bun.lock, and plugin config from the original dir. Sets OPENCODE_CONFIG_DIR to the shadow directory. Running plain `opencode` remains unaffected. * Add Agent Integrations docs section with Claude Code Teams and oh-my-opencode pages Adds sectioned sidebar navigation to the docs site. The new Agent Integrations section contains separate pages for cmux claude-teams and cmux omo, documenting usage, tmux shim mechanics, directory layout, environment variables, and the shadow config approach. Both pages include a nightly-only warning. Full English and Japanese translations, nav item keys added to all 19 locales. * Remove uppercase from sidebar section headers * Add more spacing above and below sidebar section headers * Enable tmux mode in oh-my-opencode config, improve docs - cmux omo now writes tmux.enabled=true to the shadow oh-my-opencode.json config. Without this, oh-my-openagent's TmuxSessionManager won't spawn visual panes even though $TMUX is set (the config defaults to false). - Nightly warnings now link to /nightly instead of generic text. - Added "What you get" section to oh-my-opencode docs explaining the visual pane behavior (auto-layout, idle cleanup, queueing). - Added tmux.enabled step to first-run and how-it-works sections. * Add terminal-notifier shim to route oh-my-openagent notifications to cmux oh-my-openagent sends macOS notifications via terminal-notifier (args: -title <t> -message <m> [-activate <id>]). The shim in ~/.cmuxterm/omo-bin/terminal-notifier intercepts these calls and routes them through cmux notify, so notifications appear in cmux's sidebar panel instead of as raw macOS notifications. * Add pane geometry to tmux-compat for oh-my-openagent grid planning oh-my-openagent's TmuxSessionManager needs pane geometry (columns, rows, position, window dimensions) to decide where to spawn agent panes. Without this data, agents run headlessly. Server side: - pane.list v2 response now includes pixel_frame, cell_size, columns, rows per pane, plus container_frame at the top level - Uses BonsplitController.layoutSnapshot() for pixel geometry and ghostty_surface_size() for terminal grid dimensions CLI side: - tmuxEnrichContextWithGeometry() computes character-cell positions from pixel frames and cell dimensions for tmux format variables (pane_width, pane_height, pane_left, pane_top, pane_active, window_width, window_height) - list-panes now resolves pane targets (%uuid) via tmuxResolvePaneTarget instead of failing with "Workspace not found" - display-message enriched with geometry for format strings like #{pane_width},#{window_width} - tmux -V now returns "tmux 3.4" (needed by oh-my-openagent's tmux-path-resolver verification) * Add socket tests for tmux-compat pane geometry 6 tests verifying the geometry enrichment works end-to-end: - pane.list returns pixel_frame, columns, rows, cell_size, container_frame - tmux -V returns version string - list-panes -F renders geometry format variables as integers - list-panes -t %<uuid> resolves pane targets - display -p renders pane_width and window_width - After split, two panes have different positions and halved widths All 6 pass on macmini (cmux-macmini). * Handle tmux -V in shim script directly (no socket needed) oh-my-openagent's tmux-path-resolver runs tmux -V to verify the binary works. The __tmux-compat handler requires a socket connection, which may not be established at verification time. Handle -V in the bash shim directly to avoid the socket dependency. * Lower default tmux pane min widths for cmux omo oh-my-openagent defaults: main_pane_min_width=120, agent_pane_min_width=40, requiring 161+ columns. Most terminal windows are narrower, causing decideSpawnActions to return canSpawn=false and defer agents forever. cmux omo now sets: main_pane_min_width=60, agent_pane_min_width=30, main_pane_size=50, requiring only 91 columns. Also moved tmux -V handling into the bash shim to avoid needing a socket connection for the version check. * Resolve merge conflicts with main (main-vertical layout, focus param) - Keep upstream main-vertical layout anchoring from #2119 - Keep upstream focus param (v2Bool) instead of no_focus - Combine with our -d flag handling: -d sets focus=false - Include customCommands nav item from main * Implement select-layout equalize and resize-pane absolute width When oh-my-openagent spawns agent panes, it calls select-layout main-vertical after each split to redistribute panes evenly, then resize-pane -x <columns> to set the main pane width. Both were previously no-ops, causing cascading uneven splits. Server side: - Add workspace.equalize_splits v2 API that calls the existing TabManager.equalizeSplits (sets all dividers to 0.5) CLI side: - select-layout now calls workspace.equalize_splits before tracking main-vertical state - resize-pane -x <columns> without directional flags now computes the pixel delta from current to desired width and resizes accordingly * Fix equalize to use proportional divider positions The previous equalize set all dividers to 0.5, which in a right- recursive binary tree (from successive splits) gives 50/25/12.5/6.25% instead of equal sizes. New algorithm counts leaf panes on each side of each split and sets the divider to N_left / (N_left + N_right). For 5 panes in a chain: 1/5, 1/4, 1/3, 1/2, giving each pane exactly 20%. * Fix select-layout main-vertical to only equalize vertical splits The proportional equalize was treating the top-level horizontal split (main vs agent column) the same as vertical splits, setting the main pane to 1/6 of the window with 5 agents. For main-vertical layout, only equalize vertical splits (the agent column), leaving the horizontal main/agent divider untouched. The subsequent resize-pane -x handles the main pane width. workspace.equalize_splits now accepts an optional orientation filter ("vertical" or "horizontal") to scope which splits get equalized. * Re-equalize agent column after kill-pane * Address PR review comments - Fix cmux omo --help: remove omo from the help-bypass guard so --help shows usage text instead of trying to launch opencode - Don't overwrite unreadable opencode.json: fail with an error instead of silently resetting to empty config - Drain installer pipes concurrently before waitUntilExit to prevent deadlock from full pipe buffers during bun/npm install --------- Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com> |
||
|---|---|---|
| .claude/commands | ||
| .github | ||
| AppIcon.icon | ||
| Assets.xcassets | ||
| CLI | ||
| cmuxTests | ||
| cmuxUITests | ||
| daemon/remote | ||
| design | ||
| docs | ||
| ghostty@bc9be90a21 | ||
| GhosttyTabs.xcodeproj | ||
| homebrew-cmux@a5f372ecfa | ||
| node_modules | ||
| Resources | ||
| scripts | ||
| skills | ||
| Sources | ||
| tests | ||
| tests_v2 | ||
| vendor | ||
| web | ||
| .gitignore | ||
| .gitkeep | ||
| .gitmodules | ||
| .vercelignore | ||
| AGENTS.md | ||
| bun.lock | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| cmux-Bridging-Header.h | ||
| cmux.entitlements | ||
| CONTRIBUTING.md | ||
| ghostty.h | ||
| LICENSE | ||
| package.json | ||
| Package.resolved | ||
| Package.swift | ||
| PROJECTS.md | ||
| README.ar.md | ||
| README.bs.md | ||
| README.da.md | ||
| README.de.md | ||
| README.es.md | ||
| README.fr.md | ||
| README.it.md | ||
| README.ja.md | ||
| README.km.md | ||
| README.ko.md | ||
| README.md | ||
| README.no.md | ||
| README.pl.md | ||
| README.pt-BR.md | ||
| README.ru.md | ||
| README.th.md | ||
| README.tr.md | ||
| README.vi.md | ||
| README.zh-CN.md | ||
| README.zh-TW.md | ||
| THIRD_PARTY_LICENSES.md | ||
| TODO.md | ||
cmux
A Ghostty-based macOS terminal with vertical tabs and notifications for AI coding agents
English | 日本語 | Tiếng Việt | 简体中文 | 繁體中文 | 한국어 | Deutsch | Español | Français | Italiano | Dansk | Polski | Русский | Bosanski | العربية | Norsk | Português (Brasil) | ไทย | Türkçe | ភាសាខ្មែរ
▶ Demo video · The Zen of cmux
Features
Notification ringsPanes get a blue ring and tabs light up when coding agents need your attention |
|
Notification panelSee all pending notifications in one place, jump to the most recent unread |
|
In-app browserSplit a browser alongside your terminal with a scriptable API ported from agent-browser |
|
Vertical + horizontal tabsSidebar shows git branch, linked PR status/number, working directory, listening ports, and latest notification text. Split horizontally and vertically. |
|
- Scriptable — CLI and socket API to create workspaces, split panes, send keystrokes, and automate the browser
- Native macOS app — Built with Swift and AppKit, not Electron. Fast startup, low memory.
- Ghostty compatible — Reads your existing
~/.config/ghostty/configfor themes, fonts, and colors - GPU-accelerated — Powered by libghostty for smooth rendering
Install
DMG (recommended)
Open the .dmg and drag cmux to your Applications folder. cmux auto-updates via Sparkle, so you only need to download once.
Homebrew
brew tap manaflow-ai/cmux
brew install --cask cmux
To update later:
brew upgrade --cask cmux
On first launch, macOS may ask you to confirm opening an app from an identified developer. Click Open to proceed.
Why cmux?
I run a lot of Claude Code and Codex sessions in parallel. I was using Ghostty with a bunch of split panes, and relying on native macOS notifications to know when an agent needed me. But Claude Code's notification body is always just "Claude is waiting for your input" with no context, and with enough tabs open I couldn't even read the titles anymore.
I tried a few coding orchestrators but most of them were Electron/Tauri apps and the performance bugged me. I also just prefer the terminal since GUI orchestrators lock you into their workflow. So I built cmux as a native macOS app in Swift/AppKit. It uses libghostty for terminal rendering and reads your existing Ghostty config for themes, fonts, and colors.
The main additions are the sidebar and notification system. The sidebar has vertical tabs that show git branch, linked PR status/number, working directory, listening ports, and the latest notification text for each workspace. The notification system picks up terminal sequences (OSC 9/99/777) and has a CLI (cmux notify) you can wire into agent hooks for Claude Code, OpenCode, etc. When an agent is waiting, its pane gets a blue ring and the tab lights up in the sidebar, so I can tell which one needs me across splits and tabs. Cmd+Shift+U jumps to the most recent unread.
The in-app browser has a scriptable API ported from agent-browser. Agents can snapshot the accessibility tree, get element refs, click, fill forms, and evaluate JS. You can split a browser pane next to your terminal and have Claude Code interact with your dev server directly.
Everything is scriptable through the CLI and socket API — create workspaces/tabs, split panes, send keystrokes, open URLs in the browser.
The Zen of cmux
cmux is not prescriptive about how developers hold their tools. It's a terminal and browser with a CLI, and the rest is up to you.
cmux is a primitive, not a solution. It gives you a terminal, a browser, notifications, workspaces, splits, tabs, and a CLI to control all of it. cmux doesn't force you into an opinionated way to use coding agents. What you build with the primitives is yours.
The best developers have always built their own tools. Nobody has figured out the best way to work with agents yet, and the teams building closed products definitely haven't either. The developers closest to their own codebases will figure it out first.
Give a million developers composable primitives and they'll collectively find the most efficient workflows faster than any product team could design top-down.
Documentation
For more info on how to configure cmux, head over to our docs.
Keyboard Shortcuts
Workspaces
| Shortcut | Action |
|---|---|
| ⌘ N | New workspace |
| ⌘ 1–8 | Jump to workspace 1–8 |
| ⌘ 9 | Jump to last workspace |
| ⌃ ⌘ ] | Next workspace |
| ⌃ ⌘ [ | Previous workspace |
| ⌘ ⇧ W | Close workspace |
| ⌘ ⇧ R | Rename workspace |
| ⌘ B | Toggle sidebar |
Surfaces
| Shortcut | Action |
|---|---|
| ⌘ T | New surface |
| ⌘ ⇧ ] | Next surface |
| ⌘ ⇧ [ | Previous surface |
| ⌃ Tab | Next surface |
| ⌃ ⇧ Tab | Previous surface |
| ⌃ 1–8 | Jump to surface 1–8 |
| ⌃ 9 | Jump to last surface |
| ⌘ W | Close surface |
Split Panes
| Shortcut | Action |
|---|---|
| ⌘ D | Split right |
| ⌘ ⇧ D | Split down |
| ⌥ ⌘ ← → ↑ ↓ | Focus pane directionally |
| ⌘ ⇧ H | Flash focused panel |
Browser
Browser developer-tool shortcuts follow Safari defaults and are customizable in Settings → Keyboard Shortcuts.
| Shortcut | Action |
|---|---|
| ⌘ ⇧ L | Open browser in split |
| ⌘ L | Focus address bar |
| ⌘ [ | Back |
| ⌘ ] | Forward |
| ⌘ R | Reload page |
| ⌥ ⌘ I | Toggle Developer Tools (Safari default) |
| ⌥ ⌘ C | Show JavaScript Console (Safari default) |
Notifications
| Shortcut | Action |
|---|---|
| ⌘ I | Show notifications panel |
| ⌘ ⇧ U | Jump to latest unread |
Find
| Shortcut | Action |
|---|---|
| ⌘ F | Find |
| ⌘ G / ⌘ ⇧ G | Find next / previous |
| ⌘ ⇧ F | Hide find bar |
| ⌘ E | Use selection for find |
Terminal
| Shortcut | Action |
|---|---|
| ⌘ K | Clear scrollback |
| ⌘ C | Copy (with selection) |
| ⌘ V | Paste |
| ⌘ + / ⌘ - | Increase / decrease font size |
| ⌘ 0 | Reset font size |
Window
| Shortcut | Action |
|---|---|
| ⌘ ⇧ N | New window |
| ⌘ , | Settings |
| ⌘ ⇧ , | Reload configuration |
| ⌘ Q | Quit |
Nightly Builds
cmux NIGHTLY is a separate app with its own bundle ID, so it runs alongside the stable version. Built automatically from the latest main commit and auto-updates via its own Sparkle feed.
Report nightly bugs on GitHub Issues or in #nightly-bugs on Discord.
Session restore (current behavior)
On relaunch, cmux currently restores app layout and metadata only:
- Window/workspace/pane layout
- Working directories
- Terminal scrollback (best effort)
- Browser URL and navigation history
cmux does not restore live process state inside terminal apps. For example, active Claude Code/tmux/vim sessions are not resumed after restart yet.
Star History
Contributing
Ways to get involved:
- Follow us on X for updates @manaflowai, @lawrencecchen, and @austinywang
- Join the conversation on Discord
- Create and participate in GitHub issues and discussions
- Let us know what you're building with cmux
Community
Founder's Edition
cmux is free, open source, and always will be. If you'd like to support development and get early access to what's coming next:
- Prioritized feature requests/bug fixes
- Early access: cmux AI that gives you context on every workspace, tab and panel
- Early access: iOS app with terminals synced between desktop and phone
- Early access: Cloud VMs
- Early access: Voice mode
- My personal iMessage/WhatsApp
License
cmux is open source under AGPL-3.0-or-later.
If your organization cannot comply with AGPL, a commercial license is available. Contact founders@manaflow.com for details.