Running 15 Claude Code Sessions at Once
TL;DR: Ten or more parallel Claude Code sessions work if you treat them as a small distributed system: ownership by function, one writer (a governance session) for shared rules and hooks, approval never relayed, repeat mistakes turned into guard hooks. Assumptions are verified before a human is asked, and no Claude-generated edit ships unreviewed, with GitOps as the record.
This is an opinionated write-up of what worked for me as a solo DevOps engineer, in one company's setup. Treat it as experience to weigh, not as the one right answer.
---
Why: what goes wrong with an "octopus"
I run 10–15 sessions at once in cmux, one per task. I'm the only DevOps engineer, so all are mine. Failures:
- File collisions. Two sessions edit one rule file at once. git add -A swept another session's edits into the wrong commit; staging explicit paths doesn't help, since a plain git commit takes the whole index.
- Relayed "approvals". A tells B "the user approved this"; B can't verify it, A can't transfer it.
- Worktree sprawl, stale state. About 18 worktrees across two repos; a sweep couldn't tell "abandoned" from "mid-task". A peer's "it's merged" can precede the merge.
- Context loss on compaction. A brief lives only in the sender's transcript, so it vanishes when both sides compact.
- Hook fixes racing. One session's regex fix undid another's; the suite stayed green, each fix tested only on its own case.
What: the setup
flowchart LR
subgraph cmux["cmux window"]
S1["Session: task A<br/>worktree A"]
S2["Session: task B<br/>worktree B"]
S3["Session: task C<br/>worktree C"]
G["Governance delegate<br/>(owns global rules + hooks)"]
end
S1 -- "SendMessage: brief" --> G
S2 -- "SendMessage: blocked by guard X" --> G
G -- "result + 'you can close your side'" --> S1
S3 <-- "collision notice" --> S2
U(("Human")) -. "approves in EACH session" .-> S1 & S2 & S3 & G
| Piece | Rule |
|---|---|
| cmux workspaces | one per session; worktrees named <session>--<desc>, so git worktree list shows owners. |
| One session = one task = one worktree/branch/PR | launch at the parent directory of all repos, never inside a worktree: it breaks on removal and can't switch repos. |
| Local task list, T<n> ids | created before investigating. T<n>, never #<n> (a GitHub reference; a hook enforces it). |
| Governance delegate | one long-lived session owns all shared-config writes, found by role, never by name. |
| Single owners | hook repair → the delegate, wherever the hook fired; machine-wide worktree removal → one sweep owner; a repo's .claude/, PRs and tickets → the session working it. SendMessage crosses ownership boundaries; it doesn't offload your own work. |
From about 57 real cross-session messages: finding a defect doesn't make it yours to fix, and being handed a fix doesn't make it yours to approve.
How
1. One dedicated session owns the global rules and hooks
The global CLAUDE.md, pattern docs, hooks, tests and settings are shared; two writers on one rule is a silent race. So one dedicated session writes there and takes no feature work. Others send it a brief for any wrong rule, hook defect or missing guard, create a local task, and never edit inline.
The boundary is mechanical: global config is one directory symlinked into ~/.claude/, so readlink -f tells you (plan files exempt).
2. Delegation moves the work, never the approval
Every brief says: "Nothing below is pre-approved; route every approval through the user in your own session." A harness timeout isn't approval. A peer's word counts when it restricts you ("these worktrees are still mine"), never when it widens what you may do.
3. A brief is a hypothesis, and the receiver files its own ticket
A good brief states: kind (request, finding, FYI); approval status; evidence (exact command or file:line); what was ruled out; what is deliberately not proposed; constraints the receiver can't see; disk state.
The receiver creates the local task and ticket, and the ticket id goes inside the brief; a message is not a tracking system. The receiver verifies conclusion and mechanism separately: a peer once rightly called a worktree safe to remove, for a reason that was impossible.
4. Many sessions on one repo: each knows its co-workers by name
Several sessions on one repo is fine, each on its own worktree, if each gets, at start, the list of its peers by name and what each owns. Then a session that finds work belonging to a peer's piece delegates it there instead of duplicating it, and interconnected changes land in the right order. Before touching a shared path, announce your workstream, ticket, the exact meeting path, and the peer's likely surprise.
5. Order the delegate's queue
Hooks, then rules, then other substantive work, worktree cleanup last. A broken hook hits every session; a broken rule only its readers.
6. When a guard blocks you with no legitimate way through
Send the delegate the command, the guard, its exact message, and what you tried. Then stop: "blocked" is a complete answer. Repackaging the command into a script, reading the refusal's hint as permission, and narrowing the guard yourself are ruled out.
7. No Claude-generated edit goes unreviewed by a human
Nothing a session writes reaches a shared branch, cluster or cloud project until a human has read it.
- Sessions stop at "ready for review". They open the PR; I read the diff and merge. A session never merges, even if its own option said so.
- No hand changes to live systems. Mutating kubectl, console edits and Terraform applies are blocked or handed to me as a command; clusters change only via a reviewed commit.
- GitOps is the second check. Git records every change; ArgoCD shows drift from git. To check what slipped past review, I compare the two, not a session's summary.
The cost: review is the tiring bottleneck; small PRs and summaries of what was tested, not edited, help. A session 95% right ships its 5% wrong unnoticed.
8. Verify before you ask: a non-negotiable global rule
Asking about a flag that doesn't exist turns approval into fact-checking. So the global "verify, don't claim" rule makes asking the gate: verify every load-bearing assumption before putting a change or an option list to me, attach the evidence, and mark anything unsettled as unverified. Three sources, strongest first:
1. The real environment. Read-only commands (describe, get, --dry-run=server, a live metrics or logs query); a live counter-example beats any document.
2. Authoritative documentation or source, at the version actually deployed. Docs via a lookup tool, not memory; upstream source at the release tag you run, not main; --help on the exact subcommand.
3. Online research, as corroboration when the first two are silent.
A proposal claims a blast radius; a conclusion like "impossible" needs a search for a working instance. A silent authoritative source is my decision, never a gap to guess.
A hook enforces the query part. The version clause came from fact-checking this series: a checker proposed a migration flag that upstream main has but the target release lacks, and that isn't equivalent to the documented one. Only per-tag source showed that.
The payoff: fewer, evidence-backed questions and fewer false results in PRs and docs.
9. Sessions have priorities: visit the urgent ones more often
An incident outranks a doc tidy-up. A waiting session is stalled, so a rarely visited one runs at my response rate. I visit urgent sessions far more often and answer questions as they arrive.
Having ADHD really helps here: jumping between many short threads is how my attention works anyway. Every session also writes for it: action first, open questions restated in full, one next step.
Rule layering: where knowledge goes
| Layer | Holds | Test |
|---|---|---|
| Global CLAUDE.md | Short non-negotiables pointing to detail docs | Loaded every session; characters cost tokens |
| Global pattern/workflow/troubleshooting docs | Examples, command lists | Default home for anything over one line |
| In-repo .claude/ + CLAUDE.md | Team-visible conventions | Would a teammate's agent act wrongly without it? |
| Per-user memory | Facts about this human | Agent-behaviour lessons are not personal |
- Copy, never point. A team repo never references a personal KB file teammates lack; copy the content (a hook rejects personal-KB paths).
- If you broke an existing rule, extend its doc, never memory: a silent rule lets the next session repeat the breach.
Guard hooks as enforcement
About 49 hook files, 57 test files:
| Class | Example |
|---|---|
| Block mutating kubectl | reads, diff, --dry-run=server, ArgoCD sync patches allowed. |
| Block commits/edits on main | team repos need a worktree; personal exempt. |
| Require full PR URLs | a bare #123 can't be opened from a terminal. |
| Prevent scratch files in /tmp | it vanishes mid-session. |
| Require query verification | denies PromQL/LogQL/SQL in a doc unless that exact query ran live this session: a documented join had never matched a row. |
| Stop-time push check | blocks ending a turn with unpushed commits or a PR-less branch, in every worktree the session itself edited or committed to (checking only the current repo once missed one). |
The enforcement ladder, weakest first: prose in a doc → a hook that blocks the call → removing the option entirely. A bare-name permissions.deny entry removes a whole tool from Claude's context; a scoped rule like Bash(rm *) only blocks matching calls.
Use PreToolUse (exit 2 blocks; PostToolUse cannot): a post-edit CLAUDE.md size warning only watched it grow; denying the projected size in PreToolUse fixed it.
Hooks are code: test-first, every time
A broken hook blocks work everywhere or silently stops guarding, so hooks get strict TDD:
1. Write the failing test first. Every hook has a suite in hooktests/; each new case (an input to deny, a near-miss to allow) goes in first.
2. Prove it goes RED. Run the new cases against a copy of the hook from before the change; a test passing against the old hook may not exercise the branch.
3. Make it GREEN, then run the whole suite. One runner executes every suite, a syntax sweep, and a check that every registered hook path resolves (a parsing hook can be dead if unregistered); per-fix spot checks caused the racing failure.
4. A hook change without a test change is denied by a commit guard, so time pressure can't skip it.
- Fail open on unparseable input or a missing jq; an over-broad Bash guard also removes file search. The exception is a guard on an irreversible action (see the update below).
Team rules (in-repo)
- Branches <ticket>/<type>/<desc>, never commit to main, Conventional Commits without scopes (on squash-merge repos the PR title's type is the release bump).
- Each repo has a KB index (.claude/README.md) and its own hooks in .claude/settings.json, so the team runs them too. Quote SKILL.md descriptions: unquoted ones hid 9 of 14 skills from a stricter-YAML agent.
Cost: model routing
- Opus primary plans, synthesises and reviews; cheaper worker subagents execute in parallel. Routine work: Sonnet primary, with an Opus oracle for hard decisions. Never downgrade reasoning on risky or irreversible decisions.
- Context isolation saves the most: one misconfigured autocompact threshold (a 1M-context session compacting only at about 800k tokens) outweighed everything else.
Pros / cons
| Pros | Cons |
|---|---|
| Real parallelism, full context each | Coordination overhead: briefs, notices, a queue |
| One writer removes write races | Delegate is a bottleneck; you still approve everything |
| Hooks catch repeat mistakes everywhere | Hooks need tests; a bad hook blocks every session |
| Review plus GitOps catches what guards miss | Reviewing every PR is the real, tiring bottleneck |
When not to do this: one or two sessions, or no shared global config.
Gotchas
- After removing a worktree, re-list and tell the owning session, or its next command fails.
- A session's readable name needs a cmux call; the environment holds only UUIDs.
- cmux's default next/previous-workspace shortcut crosses groups; since 0.64.23, bind Next/Previous Workspace in Group.
Takeaways
1. One dedicated session writes global rules and hooks; approval is never relayed; the receiver files the ticket.
2. Copy team knowledge into the repo; memory holds only facts about the human.
3. Climb the ladder: doc, PreToolUse deny, remove the option; hooks are test-first with a proven RED.
4. A human reviews every change; git plus ArgoCD's diff shows nothing slipped past.
5. Verify before asking: live environment, docs or source, then the web.
6. Name each session's co-workers; visit urgent sessions often.
References
- Claude Code hooks reference (exit codes): code.claude.com
- Claude Code permissions (permissions.deny): code.claude.com
- cmux changelog (0.64.23): github.com/manaflow-ai/cmux/blob/main/CHANGELOG.md
Update, 12 October 2026: what changed after publishing
Readers' comments on this article led straight to fixes. Thank you to everyone who took the time to write.
Prompted by readers:
- I replayed my real commands against the guards. One reader measured which risky commands their agents actually ran, instead of the ones they feared. I did the same: about 30,000 shell commands from my sessions held 161 destructive git commands, and none of my guards blocked any of them. Most named explicit files, a session throwing away its own edit. Seven were checkout or restore with no real path (git checkout -- ., git restore .), which in a shared checkout also drops every other session's uncommitted work, with no undo. A new guard blocks only that form; explicit paths stay allowed. Covering all 161 would have fired constantly and been muted within a day.
- Guards now count their own runs and blocks. Another reader keeps per-lesson counters to see whether a lesson holds. I adopted the run-and-block half: every guard logs each run and each block, so whether it still earns its place is decided from counts, not impressions. I did not adopt retiring a guard after a quiet stretch. A quiet guard may simply be working.
- "Have you retired a guard yet?" Once. A nudge hook fired on 20% of 3,583 replayed commands, so it was retired for being wrong too often, not for being quiet. Its own tests had all passed, because every case was one where it should fire.
Other corrections since publishing:
- Guards on irreversible actions now fail closed. Claude Code added onFailure: "block" to hook registrations, so a guard that can't run, times out or crashes denies the action instead of letting it through. I set it only where a miss can't be undone: mutating kubectl, Terraform applies, secret access, mutating SQL, and pointing prod at a branch. Never on Edit or Write: a failing guard there would block its own repair. Everything else still fails open, because stopping every session over a recoverable mistake is the wrong trade.
- The stop-time push check now covers only worktrees the session itself changed. It used to check any branch mentioned in the transcript, which flagged other sessions' work.
---
I wrote this article with the help of Claude, an AI assistant. I reviewed and edited it by hand, and it is based on my own hands-on experience.
1 reaction · 12 comments
cmux: A Ghostty-based macOS terminal with vertical tabs and notifications for AI coding agents (28k stars)
What it does
All text below is quoted directly from the project README.
>A Ghostty-based macOS terminal with vertical tabs and notifications for AI coding agents
Features:
- Notification rings: Panes get a blue ring and tabs light up when coding agents need your attention
- Notification panel: See all pending notifications in one place, jump to the most recent unread
- In-app browser: Split a browser alongside your terminal with a scriptable API ported from agent-browser
- Vertical + horizontal tabs: Sidebar shows git branch, linked PR status/number, working directory, listening ports, and latest notification text. Split horizontally and vertically.
- SSH: cmux ssh user@remote creates a workspace for a remote machine.
- Claude Code Teams: cmux claude-teams runs Claude Code's teammate mode with one command. Teammates spawn as native splits with sidebar metadata and notifications. No tmux required.
- Browser import — Import cookies, history, and sessions from Chrome, Firefox, Arc, and 20+ browsers so browser panes start authenticated
- Custom commands — Define project-specific actions in cmux.json that launch from the command palette
- Programmable — 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/config for themes, fonts, and colors
- GPU-accelerated — Powered by libghostty for smooth rendering
- Open source — Free and GPL-licensed
>Open the .dmg and drag cmux to your Applications folder. cmux auto-updates via Sparkle, so you only need to download once.
Repository
manaflow-ai/cmux
Repository stats
|Metric|Value|
|:-|:-|
|Stars|27,946|
|Forks|2,466|
|Last release|v0.65.0 (2026-10-05)|
|Languages|Swift 60.7%, Rust 11.4%, TypeScript 9.8%|
|Contributors|247|
|AI contributor accounts (Claude / Codex / Cursor / Copilot)|Claude: 3,064, Codex: 13, Copilot: 5, Cursor: 2|
|AI co-authored commits|Claude: 2,625, Codex: 20, Copilot: 5, Cursor: 2|
Main contributor
|Field|Value|
|:-|:-|
|Name|Lawrence Chen|
|GitHub|@lawrencecchen|
|Commits to this repo|7,242 (top contributor)|
|Company / Location|@manaflow-ai, sf|
|X / Twitter|@lawrencecchen|
|Followers|323|
|Public repos|187|
|On GitHub since|2019-08-11|
7 points
Mentions
cmuxについて雑に呟いたら、issueが立っていた。すごい。AIで改善活動してる! cmux#33707
If you are using cmux like me know the latest build and the nightly one still ships with eMudhra root certs. I have reported a bug at cmux#25452
颜值非常高的 Claude 终端! 高效的跨Agent协同 侧边栏任务分组和状态呈现 manaflow-ai/cmux t.co
非常好用的 Claude 终端!!! 能够同时运行非常多个 CLI,而且侧边栏还有对应的状态变更,你可以同时在多个不同的任务之间来回切换。 能够同时在这个终端里面用 Claude Code、Codex 还有 Antigravity 的 CLI,强烈建议大家去使用! manaflow-ai/cmux t.co
エージェント用 IDE を3つ試して、今さら cmux を使い始めた cmux は少し前に話題になっていたターミナルで、自分もそのとき一度試してみました。ただ、乗り換えるどころか使い始めるところまでも行きませんでした。通知が来たワークスペースがサイドバーの一番上に勝手に並び替わるのが合わなかったですし、当時 tmux で悩んでいた通知まわりのことも cmux にしたからといって解決しませんでした。サイドバーの表示をすっきりさせられることも知らなかったので、そのままやめています。 それから数か月たって、Claude Code を並列に回す道具をあらためて探しました。エージェント用の IDE を3つ試して、結局たどり着いたのが一度やめた cmux でした。 普段は Claude Code のセッションを同時に10本近く立ち上げています。1つの作業に対して複数のセッションを立てることもありますし、コードを変えずに調べるだけのセッションもかなりの数あります。 これまでは tmux の中で動かしていました。入力待ちのセッションを探すために recon という tmux 用のツールを入れたこともあります。以下は cmux 0.65.0(2026年10月時点)で確認した内容です。 エージェント用 IDE を3つ試した 試したのは Orca、T3 Code、Superset の3つで、どれも brew で入ります。 stablyai/orca pingdotgg/t3code superset-sh/superset brew install --cask stablyai/orca/orca brew install --cask t3-code brew install --cask superset 最初は Superset がいいかなと思っていました。サイドバーでセッションをグループにまとめる機能は、Orca より Superset のほうが使いやすかったです。ただ、ターミナルのスクロールがガタガタで、製品としてまだ頼りない感じがしました。スクロールの粗さは issue(#5364)にも上がっています。 Orca は多機能ですが、いろいろやりすぎている印象でした。過去のセッションの履歴を見られる機能はちょっと羨ましかったです。 T3 Code はターミナルではなく GUI で Claude Code を動かすツールで、ほかの2つと違ってタブの機能がありません。自分の設定の分け方とも相性が悪かったです。自分は仕事用と個人用で Claude Code の設定ディレクトリ(CLAUDE_CONFIG_DIR)を分けているのですが、T3 Code から起動すると仕事のリポジトリでも個人用の設定で動いていて、Claude の認証エラーも出ました。 3つを触っていて一番引っかかったのは、セッションをまとめる単位が git worktree になっていることでした。グループを作るのもサイドバーに並べるのも、worktree があることが前提の設計に見えました。worktree を勝手に作らない設定自体は、Orca などにもあります。 自分の場合、コードを変えるなら worktree を切ったほうがいいとは思っています。ただ、調べるだけのセッションも多いですし、調査を複数同時に走らせることもあります。それを1セッション1 worktree にすると、仕事のリポジトリは大きくて動かすのに依存パッケージのインストールも要るので、10本近く並べるとディスクを食いすぎます。worktree は必要になったら作るぐらいでよくて、最初から作られなくていいです。 結局 IDE ではなく、ターミナルに戻ってきました。これ tmux で十分じゃないか、と一度は思ったくらいです。 ターミナルに戻ってから何が欲しいのかを考えると、イメージしていたのは Edge などのブラウザにある縦タブでした。セッションが縦に並んでいて、グループにまとめられて、作業中か入力待ちかも分かる、という形です。 tmux に縦タブに当たる機能があるか、似たツールがあるかを調べてもらって、候補に残ったのが herdr と cmux でした。herdr は以前も試しています。左に worktree の一覧があって、それとは別にタブでウィンドウを持つ形になっているのが個人的にいまいちでした。 cmux はワークスペースがサイドバーに縦に並び、グループにもまとめられます。worktree を勝手に作ることもありません。その日のうちに入れて、並べていたセッションを全部 cmux に移しました。 cmux の設定 前回やめた理由だった並び替えは、設定1つで止められました。~/.config/cmux/cmux.json で reorderOnNotification を "off" にすると、通知が来ても並びが変わらなくなります。既定値では、通知が来たワークスペースが上へ移動します。 ~/.config/cmux/cmux.json "app": { "accentColor": "cmux", "commandPaletteSearchesAllSurfaces": true, "reorderOnNotification": "off" }, サイドバーも、ブランチ・PR・ワークスペースの説明の表示を切って、エージェントの状態と通知のメッセージだけが見えるようにしています。 ~/.config/cmux/cmux.json "sidebar": { "compactAgentStatus": false, "showNotificationMessage": true, "showBranchDirectory": false, "showPullRequests": false, "showWorkspaceDescription": false }, commandPaletteSearchesAllSurfaces はコマンドパレットで全部のタブ(cmux の用語ではサーフェス)を検索できるようにする設定です。最初に試したときは、サイドバーをここまでスッキリさせられることを知りませんでした。 tmux との違い cmux でやっていることを tmux でできないかというと、全然そんなことはありません。グループは tmux のセッションやウィンドウで作れます。自分の中では、tmux で横に並べていたタブを縦にしたのが cmux、という理解です。 はっきり違うと感じたのは、ターミナルの中でブラウザを開けることで、これは自分の中ではわりと大きいです。 もう1つ、tmux より cmux のほうが Claude Code が他のペインを操作しやすい気がしていました。気のせいか気になったので Claude Code に調べてもらったところ、cmux の内部で何か特別な最適化をしているわけではないそうです。違いは、エージェント向けの道具が本体に同梱されていることでした。 cmux guide(cmux --skill も同じ)で、エージェント向けの手順書が出る。自分の位置を cmux identify --json で調べ、画面を読んでから送り、また読む、という流れまで書いてある cmux の中のターミナルには CMUX_WORKSPACE_ID と CMUX_SURFACE_ID が入っていて、cmux send や cmux read-screen は対象を省くとそこを使う 別のエージェントには cmux agent message で話しかけられる。ドキュメントには、相手のターミナルに直接打ち込まずにこれを使うよう書いてある 画面を読む read-screen は tmux の capture-pane -p と、送る send / send-key は send-keys と同じことをしているそうです。tmux だと他のペインの指定先はエージェントが自分で調べることになるので、違いはそこを迷わずに済むところだ、というのが調べてもらった結論でした。 まだ慣れていないところ 不満がないわけではありません。一番困っているのは未読の扱いです。作業が終わったワークスペースには青い未読の印が付くのですが、そのワークスペースを開くと消えてしまいます。一度覗いてそのまま別の作業に移ると、どこで何をすればいいのかをまだ見失います。 青い表示には未読以外の意味もあります。Claude Code に調べてもらったところ、ターンが終わったあとも、裏で待ち処理を動かしているセッションは青い Waiting のまま残るそうです。色だけでは見分けられず、アイコンや文字で判断する必要があります。 ショートカットや名前にもまだ慣れていません。cmux はウィンドウの中にワークスペース、その中にペイン、ペインの中にサーフェスという階層で、tmux の呼び方とは違います。慣れないので、サーフェスの作り方や移動、コピーモードでの範囲選択など、cmux 固有の操作を早見表にまとめました。 完全に移行したわけではなく、tmux もまだ使っています。
「判断」は自分、「作業」は AI。cmux × Claude Code で実装を並列化しつつ「理解を手放さない」開発フロー AI に並列で作業させて生産性を上げるメリットは享受しつつ、何をするかは自分で決めて、できたものは自分が読んでから通す、という形にしたくて、cmux(AI エージェントを並列で動かすターミナル)と Claude Code でワークフローを組みました。 特別なことはしていませんが、本記事ではその仕組みを紹介します。 全体像 システムの中核は、ターミナルのタブを「司令塔」と「ワーカー」に完全に分離することです。単一の Claude Code に全てを任せるとコンテキストが混ざって精度が落ちるため、物理的に頭脳を切り離します。 司令塔タブ: システム全体を横断するドキュメントの「正本」リポジトリを開いておくタブ。自分(人間)は基本的にここに常駐します ワーカータブ: 実際のコード変更を行うタブ。1タスク = 1 worktree = 1タブの原則で、Claude Code を独立して走らせます 司令塔には、自分の隣に交通整理だけをする Claude のセッションを1本置いています。 ワーカータブでの作業が完了した際や、人間の判断(承認やエラー対応)が必要になった際は、司令塔タブにいる自分に1行で報告が来るように運用しています。 ワークフロー 今日1日行うタスクを司令塔タブで選択し、以下の流れで並列実装を走らせます。繰り返す手順は、その都度指示するのをやめてスキルにしてあります。 1.【人間】設計と指示書の作成 AIに丸投げするのではなく、何をもってゴールとするのか(完了条件)の判断は人間がします。司令塔タブで明確な指示書を作成し、ワーカーに渡します。 とはいえ、仕様を1から自分で書いているわけではありません。何をしたいかというゴールを明確にして渡して、あとは AIに設計してもらいます。それをそのまま承認するのではなく、なぜそのような実装プランにしたかの根拠をいまのコードの状態と、公式ドキュメントや最新のベストプラクティスも引いてきてもらって、説明してもらい、理解してから承認するようにしています。なんか良さそうだから承認するではなくて、根拠を理解してから承認している形です。決まったものは issue に書いて、それを仕様の正本にします。 2.【AI】1タスク1タブでの並列実装 ワーカータブの Claude Code に指示を投げ、draft PR の作成まで自走させます。AI が自走している間、私はその他の作業を行います。 draftPR完了の報告は、レビュースキルを通し、直し終わってからするようにさせています。 3.【人間】PR の確認とマージ AI が draft PR を作成したら、最終的な確認とマージは必ず自分の手で行います。 確認は2つです。差分の理解と動作確認です。 差分の読み方で決めているのは、細かいコードの書き方は見ないということです。何をしているかを理解するようにしています。 動作確認は、実際に動くのを自分で確かめてからマージします。ここは今後 AI に任せていきたいところですが、現状は自分の手でやっています。 まとめ 現状、最初の実装前の設計の部分と最終的なマージ前の確認作業は自分に残して、作業だけを AI に並列で任せるこのワークフローを進めています。 AI にコードを委譲しきってしまうことに少しでも不安を感じている方の、参考に少しでもなれば幸いです。
Running 15 Claude Code Sessions at Once TL;DR: Ten or more parallel Claude Code sessions work if you treat them as a small distributed system: ownership by function, one writer (a governance session) for shared rules and hooks, approval never relayed, repeat mistakes turned into guard hooks. Assumptions are verified before a human is asked, and no Claude-generated edit ships unreviewed, with GitOps as the record. This is an opinionated write-up of what worked for me as a solo DevOps engineer, in one company's setup. Treat it as experience to weigh, not as the one right answer. --- Why: what goes wrong with an "octopus" I run 10–15 sessions at once in cmux, one per task. I'm the only DevOps engineer, so all are mine. Failures: - File collisions. Two sessions edit one rule file at once. git add -A swept another session's edits into the wrong commit; staging explicit paths doesn't help, since a plain git commit takes the whole index. - Relayed "approvals". A tells B "the user approved this"; B can't verify it, A can't transfer it. - Worktree sprawl, stale state. About 18 worktrees across two repos; a sweep couldn't tell "abandoned" from "mid-task". A peer's "it's merged" can precede the merge. - Context loss on compaction. A brief lives only in the sender's transcript, so it vanishes when both sides compact. - Hook fixes racing. One session's regex fix undid another's; the suite stayed green, each fix tested only on its own case. What: the setup flowchart LR subgraph cmux["cmux window"] S1["Session: task A<br/>worktree A"] S2["Session: task B<br/>worktree B"] S3["Session: task C<br/>worktree C"] G["Governance delegate<br/>(owns global rules + hooks)"] end S1 -- "SendMessage: brief" --> G S2 -- "SendMessage: blocked by guard X" --> G G -- "result + 'you can close your side'" --> S1 S3 <-- "collision notice" --> S2 U(("Human")) -. "approves in EACH session" .-> S1 & S2 & S3 & G | Piece | Rule | |---|---| | cmux workspaces | one per session; worktrees named <session>--<desc>, so git worktree list shows owners. | | One session = one task = one worktree/branch/PR | launch at the parent directory of all repos, never inside a worktree: it breaks on removal and can't switch repos. | | Local task list, T<n> ids | created before investigating. T<n>, never #<n> (a GitHub reference; a hook enforces it). | | Governance delegate | one long-lived session owns all shared-config writes, found by role, never by name. | | Single owners | hook repair → the delegate, wherever the hook fired; machine-wide worktree removal → one sweep owner; a repo's .claude/, PRs and tickets → the session working it. SendMessage crosses ownership boundaries; it doesn't offload your own work. | From about 57 real cross-session messages: finding a defect doesn't make it yours to fix, and being handed a fix doesn't make it yours to approve. How 1. One dedicated session owns the global rules and hooks The global CLAUDE.md, pattern docs, hooks, tests and settings are shared; two writers on one rule is a silent race. So one dedicated session writes there and takes no feature work. Others send it a brief for any wrong rule, hook defect or missing guard, create a local task, and never edit inline. The boundary is mechanical: global config is one directory symlinked into ~/.claude/, so readlink -f tells you (plan files exempt). 2. Delegation moves the work, never the approval Every brief says: "Nothing below is pre-approved; route every approval through the user in your own session." A harness timeout isn't approval. A peer's word counts when it restricts you ("these worktrees are still mine"), never when it widens what you may do. 3. A brief is a hypothesis, and the receiver files its own ticket A good brief states: kind (request, finding, FYI); approval status; evidence (exact command or file:line); what was ruled out; what is deliberately not proposed; constraints the receiver can't see; disk state. The receiver creates the local task and ticket, and the ticket id goes inside the brief; a message is not a tracking system. The receiver verifies conclusion and mechanism separately: a peer once rightly called a worktree safe to remove, for a reason that was impossible. 4. Many sessions on one repo: each knows its co-workers by name Several sessions on one repo is fine, each on its own worktree, if each gets, at start, the list of its peers by name and what each owns. Then a session that finds work belonging to a peer's piece delegates it there instead of duplicating it, and interconnected changes land in the right order. Before touching a shared path, announce your workstream, ticket, the exact meeting path, and the peer's likely surprise. 5. Order the delegate's queue Hooks, then rules, then other substantive work, worktree cleanup last. A broken hook hits every session; a broken rule only its readers. 6. When a guard blocks you with no legitimate way through Send the delegate the command, the guard, its exact message, and what you tried. Then stop: "blocked" is a complete answer. Repackaging the command into a script, reading the refusal's hint as permission, and narrowing the guard yourself are ruled out. 7. No Claude-generated edit goes unreviewed by a human Nothing a session writes reaches a shared branch, cluster or cloud project until a human has read it. - Sessions stop at "ready for review". They open the PR; I read the diff and merge. A session never merges, even if its own option said so. - No hand changes to live systems. Mutating kubectl, console edits and Terraform applies are blocked or handed to me as a command; clusters change only via a reviewed commit. - GitOps is the second check. Git records every change; ArgoCD shows drift from git. To check what slipped past review, I compare the two, not a session's summary. The cost: review is the tiring bottleneck; small PRs and summaries of what was tested, not edited, help. A session 95% right ships its 5% wrong unnoticed. 8. Verify before you ask: a non-negotiable global rule Asking about a flag that doesn't exist turns approval into fact-checking. So the global "verify, don't claim" rule makes asking the gate: verify every load-bearing assumption before putting a change or an option list to me, attach the evidence, and mark anything unsettled as unverified. Three sources, strongest first: 1. The real environment. Read-only commands (describe, get, --dry-run=server, a live metrics or logs query); a live counter-example beats any document. 2. Authoritative documentation or source, at the version actually deployed. Docs via a lookup tool, not memory; upstream source at the release tag you run, not main; --help on the exact subcommand. 3. Online research, as corroboration when the first two are silent. A proposal claims a blast radius; a conclusion like "impossible" needs a search for a working instance. A silent authoritative source is my decision, never a gap to guess. A hook enforces the query part. The version clause came from fact-checking this series: a checker proposed a migration flag that upstream main has but the target release lacks, and that isn't equivalent to the documented one. Only per-tag source showed that. The payoff: fewer, evidence-backed questions and fewer false results in PRs and docs. 9. Sessions have priorities: visit the urgent ones more often An incident outranks a doc tidy-up. A waiting session is stalled, so a rarely visited one runs at my response rate. I visit urgent sessions far more often and answer questions as they arrive. Having ADHD really helps here: jumping between many short threads is how my attention works anyway. Every session also writes for it: action first, open questions restated in full, one next step. Rule layering: where knowledge goes | Layer | Holds | Test | |---|---|---| | Global CLAUDE.md | Short non-negotiables pointing to detail docs | Loaded every session; characters cost tokens | | Global pattern/workflow/troubleshooting docs | Examples, command lists | Default home for anything over one line | | In-repo .claude/ + CLAUDE.md | Team-visible conventions | Would a teammate's agent act wrongly without it? | | Per-user memory | Facts about this human | Agent-behaviour lessons are not personal | - Copy, never point. A team repo never references a personal KB file teammates lack; copy the content (a hook rejects personal-KB paths). - If you broke an existing rule, extend its doc, never memory: a silent rule lets the next session repeat the breach. Guard hooks as enforcement About 49 hook files, 57 test files: | Class | Example | |---|---| | Block mutating kubectl | reads, diff, --dry-run=server, ArgoCD sync patches allowed. | | Block commits/edits on main | team repos need a worktree; personal exempt. | | Require full PR URLs | a bare #123 can't be opened from a terminal. | | Prevent scratch files in /tmp | it vanishes mid-session. | | Require query verification | denies PromQL/LogQL/SQL in a doc unless that exact query ran live this session: a documented join had never matched a row. | | Stop-time push check | blocks ending a turn with unpushed commits or a PR-less branch, in every worktree the session itself edited or committed to (checking only the current repo once missed one). | The enforcement ladder, weakest first: prose in a doc → a hook that blocks the call → removing the option entirely. A bare-name permissions.deny entry removes a whole tool from Claude's context; a scoped rule like Bash(rm *) only blocks matching calls. Use PreToolUse (exit 2 blocks; PostToolUse cannot): a post-edit CLAUDE.md size warning only watched it grow; denying the projected size in PreToolUse fixed it. Hooks are code: test-first, every time A broken hook blocks work everywhere or silently stops guarding, so hooks get strict TDD: 1. Write the failing test first. Every hook has a suite in hooktests/; each new case (an input to deny, a near-miss to allow) goes in first. 2. Prove it goes RED. Run the new cases against a copy of the hook from before the change; a test passing against the old hook may not exercise the branch. 3. Make it GREEN, then run the whole suite. One runner executes every suite, a syntax sweep, and a check that every registered hook path resolves (a parsing hook can be dead if unregistered); per-fix spot checks caused the racing failure. 4. A hook change without a test change is denied by a commit guard, so time pressure can't skip it. - Fail open on unparseable input or a missing jq; an over-broad Bash guard also removes file search. The exception is a guard on an irreversible action (see the update below). Team rules (in-repo) - Branches <ticket>/<type>/<desc>, never commit to main, Conventional Commits without scopes (on squash-merge repos the PR title's type is the release bump). - Each repo has a KB index (.claude/README.md) and its own hooks in .claude/settings.json, so the team runs them too. Quote SKILL.md descriptions: unquoted ones hid 9 of 14 skills from a stricter-YAML agent. Cost: model routing - Opus primary plans, synthesises and reviews; cheaper worker subagents execute in parallel. Routine work: Sonnet primary, with an Opus oracle for hard decisions. Never downgrade reasoning on risky or irreversible decisions. - Context isolation saves the most: one misconfigured autocompact threshold (a 1M-context session compacting only at about 800k tokens) outweighed everything else. Pros / cons | Pros | Cons | |---|---| | Real parallelism, full context each | Coordination overhead: briefs, notices, a queue | | One writer removes write races | Delegate is a bottleneck; you still approve everything | | Hooks catch repeat mistakes everywhere | Hooks need tests; a bad hook blocks every session | | Review plus GitOps catches what guards miss | Reviewing every PR is the real, tiring bottleneck | When not to do this: one or two sessions, or no shared global config. Gotchas - After removing a worktree, re-list and tell the owning session, or its next command fails. - A session's readable name needs a cmux call; the environment holds only UUIDs. - cmux's default next/previous-workspace shortcut crosses groups; since 0.64.23, bind Next/Previous Workspace in Group. Takeaways 1. One dedicated session writes global rules and hooks; approval is never relayed; the receiver files the ticket. 2. Copy team knowledge into the repo; memory holds only facts about the human. 3. Climb the ladder: doc, PreToolUse deny, remove the option; hooks are test-first with a proven RED. 4. A human reviews every change; git plus ArgoCD's diff shows nothing slipped past. 5. Verify before asking: live environment, docs or source, then the web. 6. Name each session's co-workers; visit urgent sessions often. References - Claude Code hooks reference (exit codes): code.claude.com - Claude Code permissions (permissions.deny): code.claude.com - cmux changelog (0.64.23): github.com/manaflow-ai/cmux/blob/main/CHANGELOG.md Update, 12 October 2026: what changed after publishing Readers' comments on this article led straight to fixes. Thank you to everyone who took the time to write. Prompted by readers: - I replayed my real commands against the guards. One reader measured which risky commands their agents actually ran, instead of the ones they feared. I did the same: about 30,000 shell commands from my sessions held 161 destructive git commands, and none of my guards blocked any of them. Most named explicit files, a session throwing away its own edit. Seven were checkout or restore with no real path (git checkout -- ., git restore .), which in a shared checkout also drops every other session's uncommitted work, with no undo. A new guard blocks only that form; explicit paths stay allowed. Covering all 161 would have fired constantly and been muted within a day. - Guards now count their own runs and blocks. Another reader keeps per-lesson counters to see whether a lesson holds. I adopted the run-and-block half: every guard logs each run and each block, so whether it still earns its place is decided from counts, not impressions. I did not adopt retiring a guard after a quiet stretch. A quiet guard may simply be working. - "Have you retired a guard yet?" Once. A nudge hook fired on 20% of 3,583 replayed commands, so it was retired for being wrong too often, not for being quiet. Its own tests had all passed, because every case was one where it should fire. Other corrections since publishing: - Guards on irreversible actions now fail closed. Claude Code added onFailure: "block" to hook registrations, so a guard that can't run, times out or crashes denies the action instead of letting it through. I set it only where a miss can't be undone: mutating kubectl, Terraform applies, secret access, mutating SQL, and pointing prod at a branch. Never on Edit or Write: a failing guard there would block its own repair. Everything else still fails open, because stopping every session over a recoverable mistake is the wrong trade. - The stop-time push check now covers only worktrees the session itself changed. It used to check any branch mentioned in the transcript, which flagged other sessions' work. --- I wrote this article with the help of Claude, an AI assistant. I reviewed and edited it by hand, and it is based on my own hands-on experience.
我觉得,终端终于开始为 agent 时代重做了 同时开一堆 Claude Code 会话,哪个在等你确认 找半天吧 cmux:macOS 原生终端,agent 要确认窗口直接亮蓝环 git 分支/PR/端口钉死在标签栏,tmux 那套是给人用的 manaflow-ai/cmux t.co
cmux: A Ghostty-based macOS terminal with vertical tabs and notifications for AI coding agents (28k stars) What it does All text below is quoted directly from the project README. >A Ghostty-based macOS terminal with vertical tabs and notifications for AI coding agents Features: - Notification rings: Panes get a blue ring and tabs light up when coding agents need your attention - Notification panel: See all pending notifications in one place, jump to the most recent unread - In-app browser: Split a browser alongside your terminal with a scriptable API ported from agent-browser - Vertical + horizontal tabs: Sidebar shows git branch, linked PR status/number, working directory, listening ports, and latest notification text. Split horizontally and vertically. - SSH: cmux ssh user@remote creates a workspace for a remote machine. - Claude Code Teams: cmux claude-teams runs Claude Code's teammate mode with one command. Teammates spawn as native splits with sidebar metadata and notifications. No tmux required. - Browser import — Import cookies, history, and sessions from Chrome, Firefox, Arc, and 20+ browsers so browser panes start authenticated - Custom commands — Define project-specific actions in cmux.json that launch from the command palette - Programmable — 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/config for themes, fonts, and colors - GPU-accelerated — Powered by libghostty for smooth rendering - Open source — Free and GPL-licensed >Open the .dmg and drag cmux to your Applications folder. cmux auto-updates via Sparkle, so you only need to download once. Repository manaflow-ai/cmux Repository stats |Metric|Value| |:-|:-| |Stars|27,946| |Forks|2,466| |Last release|v0.65.0 (2026-10-05)| |Languages|Swift 60.7%, Rust 11.4%, TypeScript 9.8%| |Contributors|247| |AI contributor accounts (Claude / Codex / Cursor / Copilot)|Claude: 3,064, Codex: 13, Copilot: 5, Cursor: 2| |AI co-authored commits|Claude: 2,625, Codex: 20, Copilot: 5, Cursor: 2| Main contributor |Field|Value| |:-|:-| |Name|Lawrence Chen| |GitHub|@lawrencecchen| |Commits to this repo|7,242 (top contributor)| |Company / Location|@manaflow-ai, sf| |X / Twitter|@lawrencecchen| |Followers|323| |Public repos|187| |On GitHub since|2019-08-11|
📡 被要求下架的聊天 App 衝上第一 | GitHub 每日爆紅 Top 5 (2026-10-07) 2026-10-07 GitHub 熱門專案 Top 5,倒數介紹,每個都講「適合誰用」和「為什麼值得關注」。 5. DuarteSantos8/openGym(6.9k stars)— 自架的健身與體重紀錄 App,一行 docker compose 就能跑,資料留在自己主機 DuarteSantos8/openGym 4. earthtojake/text-to-cad(18k stars)— 讓 AI agent 產出 STEP/STL/3MF 3D 模型,還會做可製造性檢查與工程圖 earthtojake/text-to-cad 3. cloudflare/security-audit-skill(26k stars)— Cloudflare 漏洞挖掘系統的起點,六階段 AI 資安稽核技能 cloudflare/security-audit-skill 2. manaflow-ai/cmux(28k stars)— 以 Ghostty 為核心、為 AI coding agent 設計的 macOS 終端機,垂直分頁加通知提醒 manaflow-ai/cmux 1. permissionlesstech/bitchat(36k stars)— 藍牙 mesh 離線聊天,有網路時改走 Nostr,不需帳號與手機號碼 permissionlesstech/bitchat #GitHub #開源 #程式設計 #AI工具 #資安