Codync
免費、開源的 1:1 替代方案,取代 Grok Bot 與 Muse。從 iPhone、Mac 或 Linux 桌面將 Claude Code、Codex、Cursor 與 40+ 程式碼代理人作為持續機器人傳訊。群組聊天、主題串…
AI 翻譯
One TUI for every AI coding agent session — Claude Code, Codex, Cursor, and more — in sync across every device.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗A cross-device tmux session manager for AI coding agents.
Run your coding agents from any device — even your phone.
ccmux is one TUI for every coding-agent session you've got running — Claude Code, Codex, Cursor, and more. If you've used tmux, the mental model is one sentence: ccmux is a tmux session manager built for coding agents. tmux keeps each session alive in the background; ccmux is the single dashboard over all of them — color-coded by what each agent is doing, on every device you own. Start, resume, and supervise them all from your Mac, your laptop, or your phone. No tmux session names to memorize, no claude --resume <hash> to type, no SSH-then-attach gymnastics. It runs over your tailnet and attaches over SSH or Mosh. Setup is one command.
curl -fsSL https://raw.githubusercontent.com/skzv/ccmux/main/scripts/install.sh | sh
ccmux setup
Drops ccmux + ccmuxd in ~/.local/bin. ccmux setup finishes first-run setup for Tailscale, agent CLIs, and the background daemon.
Other paths:
Homebrew (macOS, or Linuxbrew on Linux):
brew trust --tap skzv/tap
brew install skzv/tap/ccmux
Homebrew 6 refuses formulae from third-party taps until you vouch for the tap, so brew trust comes first — without it the install stops with Refusing to load formula skzv/tap/ccmux from untrusted tap skzv/tap. Once per machine. (It's skzv/tap, not skzv/homebrew-tap — Homebrew drops the prefix.)
From source: git clone https://github.com/skzv/ccmux.git && cd ccmux && make setup.
Works on macOS, Linux, and Windows via WSL2. Source builds require Go 1.26+.
It's 11pm. The session you started this morning on your Mac is still running — your laptop's lid has been closed for hours, but the daemon held a caffeinate lock and Claude kept thinking.
Your phone vibrates: Claude is asking a question. You tap the notification, you're attached. You answer, hit Ctrl-b d, lock the phone.
Tomorrow morning on the train, you open your laptop, type ccmux — the same session is right there, exactly where you left it. Three device transitions. Zero CLI commands.
That's ccmux. The same session, the same TUI, on every device. No host config, no session-name memory, no claude --resume. Just press Enter on the row you want.
Color-coded by state — active, idle, needs your input. The Devices panel shows every other ccmux-running machine on your tailnet right next to it. The usage panel tallies Claude's 5-hour quota and per-agent prompt counts. ccmux usage prints the same 5-hour block, and the daemon's API serves it to phones as claude_block. Live updates as each session moves through states.
The "start on Mac, continue on phone" loop, end to end:
your Mac — attach with Enter, detach with Ctrl-b d
your phone — same TUI, narrower (Blink, Termius, or the Moshi app)
tmux is the session store; ccmux is the lens. The phone-width layout collapses everything into a single scrollable column when ccmux runs in a narrow terminal. Mosh makes the connection survive cell→wifi roaming, lid-close, walking-out-of-range — so you can detach the phone on the train and reattach two stops later.
Open the Projects tab, press n. Pick which device should host the new project — local, or any reachable peer running ccmuxd on your tailnet. The remote daemon creates the directory natively and starts the agent. ccmux SSH-attaches you in. You never typed ssh, never typed mkdir, never typed tmux new-session.
The new-project form also picks the agent (Claude, Codex, Cursor, and more) for this project — the choice sticks at <project>/.ccmux/agent.
ccmux remembers every past Claude / Codex / Antigravity thread, sorted by recency. Press 2 for the Conversations screen, navigate, press Enter. The daemon resumes the agent with the correct session ID. You don't type claude --resume <hash> ever again.
Headless agent runs (claude -p, codex exec, SDK invocations) are filtered out by default so a scripted workflow doesn't drown the list — press H to toggle them back on.
Pick per project which AI runs it — ccmux works with Claude Code, Codex, Antigravity CLI, Gemini CLI, Cursor, pi, Grok, Muse Code, and more, speaking each one's launch and resume dialect. The choice is sticky, stored at <project>/.ccmux/agent. The dashboard, daemon state-detection, and dispatch all follow per-project. Press a in the Projects tab to switch the selected project's agent (cycles claude → codex → antigravity → cursor → pi → grok).
Dashboard rows on non-default agents get a small [codex], [antigravity], [cursor], [pi], or [grok] tag so a single glance tells you what's running where.
Gemini CLI and Antigravity CLI are separate agents in ccmux. Gemini remains available to Gemini Code Assist Standard/Enterprise customers and paid API users; see Google’s transition announcement.
Install with npm install -g @google/gemini-cli, sign in through gemini, then
run ccmux new gemini-demo --agent gemini or pick Gemini CLI in the project menu.
Existing .ccmux/agent files containing gemini launch Gemini again. Projects
explicitly set to antigravity continue to launch agy; use the Projects agent
picker to change them if needed.
ccmux reads Gemini’s JSON/JSONL history, previews, and token usage from
~/.gemini/tmp/. Resume uses gemini --resume <session-id> in the project directory
recorded by Gemini. If an old transcript has no recoverable project location,
open that project in Gemini CLI once to register it before resuming from ccmux.
Settings and authentication stay native: press e on the Gemini Agents tab to
edit ~/.gemini/settings.json, and use gemini to sign in. An optional
command setting selects a specific installation independently of Antigravity:
[agents.gemini]
command = "/absolute/path/to/gemini"
Install Meta's CLI with brew install --cask muse-code, then run muse login.
Start a fresh project with ccmux new muse-demo --agent muse, or select Muse Code
in the new-project form. Reopen a project to continue its latest session, or
choose an exact conversation in Conversations (ccmux resume <id> in the CLI).
Muse history, previews, search, message counts, and token usage come from native
session logs. Press / in Conversations to search project paths, previews, or IDs;
use ccmux list-conversations --query "cache" from the CLI. Child-agent usage is included once; unavailable cost is shown
explicitly. ccmux usage --json exposes the same recorded totals as the dashboard.
Deleting an inactive conversation removes its complete session and derived cache;
Muse's native locks protect active sessions and child agents.
Read the guide in English, 中文, Español, 日本語, 한국어, Français, Deutsch, Português, or Русский.
Per-project Notes tab — every .md file in the project, organized as a collapsible folder tree, with markdown rendered inline by Glamour. Folders open collapsed so a deep notes tree doesn't bury you: →/l expands a folder (or drills in), ←/h collapses it (or jumps out to the parent). Want it all open? Launch with ccmux --expand-notes or set [notes] expand_folders = true. Ripgrep-backed / search matches literal text, ignoring case (also available without ripgrep). Plain markdown on disk is the source of truth. No sync service. No cloud. Press e to edit a note in $EDITOR; ccmux reads notes, writing them is the agent's job.
Notes follow you across devices: press H to toggle which machine you're viewing notes from — the local box or any reachable ccmuxd peer on your tailnet. The list, preview, and search all re-scope to the selected device (read-only for remote). Scriptable too: ccmux notes list|read|search <project> [--host <name>].
One screen for "is my agent installed and signed in?" Per-agent CLI version, config root, login status, and a command palette to re-run setup or open the config directory.
Codex configuration, conversation history, and usage honor CODEX_HOME, falling back to ~/.codex when unset.
ccmux setup is the interactive wizard. It checks tmux / mosh / tailscale / claude / gh and offers to brew install whatever's missing. The first time you launch ccmux on an unconfigured machine it offers to run setup for you (decline once and it won't ask again; set CCMUX_NO_SETUP_NUDGE=1 to always skip the prompt). For dotfiles / provisioning, ccmux setup --yes runs non-interactively — it takes the recommended answer at every prompt (install deps, generate the SSH key, install the daemon autostart) and skips the integrations that can't be scripted (Moshi pairing, Tailscale/gh browser auth). ccmux doctor is the non-interactive health check — perfect for scripting or when something stops working.
Dashboard shows a banner when a new release lands. ccmux update git-pulls the checkout, rebuilds, reloads ccmuxd. Flags: --dry-run, --skip-pull, --no-restart. The Devices panel tags any tailnet peer running a behind-version of ccmuxd so you see at a glance which machines need an update.
The way to use ccmux on your phone today is the Moshi app. Moshi holds a Mosh connection to your Mac alive through roaming and lid-close, raises a real push notification when an agent needs you, and shows a live picker of your sessions — tap one and you're attached to ccmux's TUI on your phone.
ccmux moshi-setup
Installs moshi-hook on the Mac, runs Easy Pair (a QR code appears in your terminal — scan it with the Moshi iOS app, done), and wires the Claude Code hooks that turn needs_input events into categorized push notifications (approval_required vs task_complete). Tap the notification, the Moshi app shows your live tmux session list, pick one, attach, answer, detach. No tokens to copy.
Plain BEL fallback works in any iOS terminal client (Blink Shell, Termius) — you lose the categories, that's it. For headless / scripted setups: ccmux moshi-setup --token <token> bypasses the QR flow.
Building your own mobile client?
ccmuxdexposes an HTTP API (list / attach over a WebSocket PTY / send-keys / events / notes / usage, plus a pairing + push flow) — see the HTTP API reference.
# On the always-on Mac Mini:
ccmux daemon install # ccmuxd survives reboot
# edit ~/.config/ccmux/config.toml: listen_tailnet = true
# On the laptop — nothing to do:
ccmux # dashboard already lists the Mini
Every refresh, ccmux runs tailscale status --json, probes each online non-mobile peer for a ccmuxd /v1/health, and merges the responders into the host list. Install ccmux on a new device, start its daemon, and it shows up on every other device on your tailnet within seconds.
Peers with the same name stay separate. Device pickers and session confirmations include their addresses when names collide, so each action targets the selected machine.
The Devices panel on the Dashboard shows every device on your tailnet:
Attaching to an auto-discovered peer execs ssh -t <host> -- tmux attach -t <name> (cross-platform PATH prepend so Homebrew/Snap/Linuxbrew tmux is found). A host you've pinned with ccmux host add <name> <address> attaches with mosh instead — tolerates roaming and stalls (--mosh=false keeps it on plain ssh).
Manually pinning a host with
ccmux host addstill works — useful for non-Tailscale hosts, or to force a specific port:--portis the remote ccmuxd port (default 7474),--ssh-portits sshd port (default 22),--userthe SSH user (or write the address asuser@host). Ports go in the flags, not the address. Discovered hosts and pinned hosts coexist on the dashboard without duplicates.
~/.config/ccmux/config.toml — the knobs that matter:
lang = "zh" # UI language: "en" | "zh"; empty = follow $LANG
[projects]
root = "~/Projects" # where ccmux looks for projects
[daemon]
poll_interval_seconds = 2
idle_seconds_for_needs_input = 3
listen_tailnet = false # set true on your server-mode host
tailnet_port = 7474
[sleep]
mode = "safe" # "safe" | "dangerous" | "very_dangerous"
low_battery_cutoff = 20 # dangerous mode auto-downgrades below this
[notifications]
bell = true # ring local terminal BEL on needs_input
Notifications: the bell rings whenever an agent finishes a turn and waits for input (
needs_input) andbell = true, regardless of whether moshi-hook is paired. Typing into a prompt, resizing a pane or restarting the daemon doesn't ring it, and a restart (orccmux update) doesn't forget which sessions you've already looked at or how many prompts each has had. The audible chime at your desk and the push on your phone are complementary, not duplicates. Setbell = falseif you'd rather rely on phone pushes alone. An agent you start by hand in any tmux session (claudein a plain shell) is watched too, for as long as it runs. The exact rules are in the HTTP API reference under "What counts as a turn".
Sleep-mode notes:
safe—caffeinate -son macOS (Apple's policy keeps it AC-only).systemd-inhibit --what=sleep:idleon Linux.dangerous—caffeinate -d -i -m -son macOS, works on battery too. Daemon polls battery once a minute and downgrades tosafewhen belowlow_battery_cutoff(so a forgotten laptop doesn't run flat).very_dangerous— addssudo -n pmset -a disablesleep 1(macOS) /sudo -n systemctl mask sleep.target …(Linux). Requires passwordless sudo for the specific command; silently degrades todangerousif sudo prompts. Always reverted when ccmuxd exits cleanly.Example sudoers entry (run
sudo visudo -f /etc/sudoers.d/ccmux):# macOS %admin ALL=(ALL) NOPASSWD: /usr/bin/pmset -a disablesleep * # Linux %sudo ALL=(ALL) NOPASSWD: /bin/systemctl mask *, /bin/systemctl unmask *
projects.root and subscription.tier are also editable inline from the Settings screen — ↑/↓ to move, Enter to edit, e to open $EDITOR for the prose-heavy fields. After editing, run ccmux update to reload the daemon with the new config.
Comment the file however you like. When ccmux saves it (a Settings row, ccmux host add, ccmux language), it only touches the values that changed, so your comments, blank lines and key order stay where you left them. A setting you left out of the file stays out until you change it; the only line a save adds on its own is schema_version, the first time. ccmux host remove takes the comment above that [[host]] with it. Same for ~/.codex/config.toml when you flip YOLO or effort in the Codex tab.
Language / 语言: the TUI follows
$LANG/$LC_ALLby default (zh*→ Simplified Chinese, anything else → English). Setlang = "en"or"zh"to override — from config.toml or the Settings screen, where the switch applies immediately. Untranslated strings fall back to English.
~/Projects/api and ~/work/api) get separate sessions. Whichever started first keeps c-api, the other gets c-api-<tag>, and ccmux matches each one to its project by directorysafe, dangerous, very_dangerous (sudo-gated; system-wide override that survives lid-close)ccmux new <name> — creates the directory + starts the agent (--agent, else agents.default from config, else Claude). No CLAUDE.md, no docs/ tree, no git init. Bootstrapping is the agent's job. From a script (no terminal), new, resume and shell start the session and print created <name>; attach with: ccmux attach <name> instead of attaching.claude -p / SDK runs and codex exec invocations are filtered by default. Press H to toggle. Antigravity transcripts carry no headless tag, so those are always shown.n in Projects, pick a host, the remote daemon does the work.git · CLAUDE · docs/ tags tell you which dirs are real software projects vs scratch dirs.<project>/.ccmux/agent — sticky across sessions←/→a in Projects to switch the selected project's agent[codex], [antigravity], [cursor], [pi], or [grok] tagccmux doctor enumerates installed agents; setup wizard points at the right install command for eachdocs/01_Specs/02_Multi_Agent.mdccmux-mcp ships alongside ccmux in the same install — a Model Context Protocol server agents can plug into to see and act on every sessionccmux mcp register (also offered by ccmux setup), or by hand: claude mcp add --scope user ccmux -- ccmux-mcp. ccmux mcp unregister takes it out again (ccmux uninstall does that for you). Other MCP-aware clients: point a stdio server at the ccmux-mcp binarylist_sessions, read_pane, list_projects, list_conversations, get_usage, list_machines, notes ones, daemon health--allow-mutate exposes spawn_session, send_keys, kill_session — opt-in, hidden from tools/list until the flag is onCCMUX_HOST=mini.tail-xxxxx.ts.net:7474 ccmux-mcp points it at a tailnet peer's daemon — an agent on the laptop can drive sessions on the Mac minidocs/01_Specs/04_MCP_Server.md~/.claude/low / medium / high / xhigh / max) + alwaysThinkingEnabled toggle. Writes effortLevel to ~/.claude/settings.json so every new Claude Code session inherits your default.CLAUDE.md from the TUI.md file in the project, as a collapsible folder tree, rendered by Glamour→/← (or l/h) expand/collapse them — or open everything with ccmux --expand-notes/ search; plain markdown on disk is the source of truth (no required cloud)$EDITOR — ccmux reads your notes; writing them is the agent's jobH toggles which device's notes you're viewing (local or any tailnet peer); also via ccmux notes list|read|search --host <name>ccmux moshi-setup; scan the QR code with the Moshi app, you're paired. No token paste.moshi-hook plugging into Claude Code's hooks system (approval_required, task_complete)ccmux list, attach, kill and rename take --host <name> for any host you added with ccmux host add. ccmux kill --host mini api kills the mini's api session, not yoursccmux setup — interactive wizard, checks every dep, offers brew install for missing pieces; --yes runs it non-interactively for scripts, and the first launch on a fresh machine offers to run it for youccmux doctor — non-interactive health check (great for scripting)ccmux update — pulls the git checkout, rebuilds, reloads ccmuxdccmux uninstall — clean removal, never touches your projects; from Claude Code's config it only removes its own MCP entry? opens contextual key help on every screenh/j/k/l) and arrow keys both workccmux doctor tells you exactly which side is missing.Six hands-on walkthroughs. Each is self-contained — pick whichever maps to what you're trying to do.
The core loop: create → talk to your agent → take notes.
ccmux new auth-redesign # or: ccmux new auth-redesign --agent codex
That command does two things, and only two things:
~/Projects/auth-redesign/ — an empty directory.c-auth-redesign and starts your agent inside it (Claude by default).ccmux does not scaffold the project — no CLAUDE.md, no docs/ tree, no git init, no GitHub repo. Bootstrapping is the agent's job, done inside the session: run /init to have the agent write CLAUDE.md, openspec to set up specs, git init whenever you want version control. ccmux opens the door; what the project becomes is up to you and your agent.
To check on the session without joining the conversation: ccmux list. To attach: ccmux attach auth-redesign (any session name ccmux list prints works too). The session keeps running after you detach.
ccmux
The Dashboard shows all sessions, color-coded by state:
When a session transitions to needs_input, ccmuxd injects a terminal BEL. Any iOS terminal client that maps BEL→notification raises a push.
Useful keys on the Sessions screen:
Enter — attachx — kill the highlighted sessionR — rename? — full keymapSee the Mobile setup section above.
See the Config section above. ~/.config/ccmux/config.toml has the full set of knobs.
See the Multi-machine section above. Heavy users live in this flow: sessions on the Mini, clients on laptop/phone, no host config — auto-discovery handles it.
ccmux doctor # one-shot health check
ccmux update # git pull + rebuild + reinstall + restart daemon
ccmux uninstall # clean removal
ccmux update auto-detects your git checkout (defaults to ~/Projects/ccmux). Flags: --dry-run, --skip-pull, --no-restart.
ccmux uninstall # interactive: shows what it'll do, asks y/N
ccmux uninstall --yes # skip the prompt
ccmux uninstall --dry-run # preview only
What gets removed:
ccmuxd (SIGTERM)~/.local/bin/ccmux, ~/.local/bin/ccmuxd and ~/.local/bin/ccmux-mcp~/.local/state/ccmux/ (socket, logs)~/.local/share/ccmux/ (snapshots, daemon db)~/.config/ccmux/ (unless --keep-config)c-* session (unless --keep-chrome)ccmux MCP server entry in ~/.claude.json, if you registered one (backed up to ~/.claude/backups/ first) — otherwise Claude Code keeps trying to start the deleted ccmux-mcpWhat is never touched:
<project>/docs/~/.claude/ (Claude Code state + moshi-hook entries), apart from that one MCP entryTo also remove moshi-hook: brew services stop moshi-hook && brew uninstall moshi-hook && brew untap rjyo/moshi.
LAPTOP (client + local) MINI (local + server)
┌─────────────────────────────┐ ┌──────────────────────────────┐
│ ccmux TUI │ ──http──► ccmuxd HTTP │
│ ├─ local sessions ◄─unix──┤ tailnet │ ├─ sessions (mini-foo) │
│ │ • laptop-bar │ ────────► │ • mini-foo (active) │
│ │ • laptop-baz │ │ │ • mini-cas (waiting 🔔)│
│ └─ remote: mini │ │ └─ caffeinate -s while active
│ • mini-foo │ │ │
│ │ │ ccmuxd Unix socket │
│ │ │ (for local TUI on mini) │
└─────────────────────────────┘ └──────────────────────────────┘
▲
│ Mosh
│ (when phone connects)
┌────────┴──────────┐
│ iPhone (Moshi / │
│ Blink / Termius) │
└───────────────────┘
Full design: docs/02_Architecture/00_System_Design.md.
HTTP API (for integrators / mobile clients): docs/02_Architecture/05_HTTP_API.md.
TUI design system: docs/02_Architecture/04_TUI_Design_System.md.
Phasing in ROADMAP.md. Headline:
Infrastructure follow-ups tracked in docs/01_Specs/03_Testing_And_CI.md:
cmd/ccmux-stress/ harness for 20+ session loads, notification storms, 24h long-haul, with pprof + FD-leak detectioncmd/ccmux-crawl/ monkey-tester + native fuzzers + rapid property tests to find the bugs no human would think to tryAlpha. Core flows (attach, new, kill, notes, daemon, Moshi) work end-to-end. Expect rough edges; file issues. Wait for v0.1 if you want it for real work.
Standing on the shoulders of Charm:
Plus Cobra for the CLI surface and SQLite for daemon state.
Issues and PRs welcome. See CONTRIBUTING.md (TBD). The short version:
gofmt, go vet, staticcheckmake test (unit) and make test-e2e (integration — requires tmux)ccmux doctor outputdocs/01_Specs/01_Feature_Catalog.md firstFSL-1.1-MIT — Functional Source License with MIT future grant.
In plain English: you can use, modify, and redistribute ccmux freely for any purpose except offering it (or a substantially-similar feature set) as a competing commercial product or managed service. Two years after each release, that version automatically relicenses to plain MIT.
If you want to commercialize a derivative work sooner, get in touch.
The workflow this tool wraps was developed in public by the AI-first software engineering community over 2024–2026. Particular thanks to:
The TUI supports English, Simplified Chinese, Spanish, Japanese, Korean, French, German, Brazilian Portuguese, and Russian. Change the language immediately in Settings, or save a preference from the shell:
ccmux language # list codes and native language names
ccmux language ru # save Russian; reopen the TUI to apply
ccmux contribute # contribution and issue links
With no configured language, ccmux follows LC_ALL, then LANG, falling back to English. Website language choices are available in the top toolbar at ccmux.ai.
Found a bug or wording that could be clearer? Report it or submit a pull request. Translation improvements from native speakers are welcome.