手を動かして確かめる¶
実機で 1 周する手順。 上から順に打てば、ccs が本当に動くかを自分の目で確認できる。
各手順には「期待される出力」と「違ったときに見るところ」を付けた。
期待される出力は、すべてこのマシンで実際に上から順に走らせて得たもの
(UUID と時刻だけは毎回変わる)。信頼確認の 30 秒待ちも、/exit のあとに
ペインがシェルへ戻ることも、実機で確認した上で書いている。
所要時間はおよそ 15 分。途中でやめても、最後の「元に戻す」だけやれば跡は残らない。
0. 前提を確かめる¶
期待される出力(版は前後してよい):
1. 触る前の状態を控える¶
あとで「元に戻ったか」を確かめるため。 何も変わっていないことを最後に確認する。
期待される出力(まだ tmux を使っていなければ):
no server running on /private/tmp/tmux-501/default
ls: /Users/apple/.cc-scratch: No such file or directory
55
数字は控えておく
最後の数字(.projects の件数)を覚えておく。手順 9 以外では増えないはず。
2. 何も起きないことを確かめる¶
resolve は副作用が無い。まずここで、打ち間違いが安全に分かることを見る。
期待される出力:
続けて、曖昧なときに勝手に選ばないことを見る。
期待される出力(終了コードは 1):
ccs: IceCubesApp に当てはまるリポジトリが複数あります:
Dimillian/IceCubesApp
ken-ty/IceCubesApp
<owner>/<repo> の形で指定し直してください。
ここまでで tmux セッションは 1 つも立っていない。 確かめる:
→ no server running ... のまま。
3. 立てる¶
期待される出力(1 行の JSON。sessionId は毎回変わる):
{"slug":"x01","sessionId":"0ecd87dd-…","path":"/Users/apple/ghq/github.com/ken-ty/x01","tmux":"cc/x01","transcript":"/Users/apple/.claude/projects/-Users-apple-ghq-github-com-ken-ty-x01/0ecd87dd-….jsonl","created":true,"running":true}
見るところ:
createdがtruerunningがtrue- 数秒で返る(30 秒待たされたら手順 3 の下の「うまくいかないとき」へ)
30 秒待って「登録されませんでした」と言われた
ccs はペインの中身を見せてくれる。だいたいは次のどれか:
- 信頼確認で止まっている →
ccs attach x01して「1. Yes, I trust this folder」 - ログインが切れている →
ccs attach x01して/login - それ以外 → ペインの内容をそのまま読む
ccs はこのときセッションを消さない。 何に詰まったかを見られるようにするため。
諦めるときは ccs kill x01。
4. ハブから見えることを確かめる(ここが核心)¶
ccs を作った理由はこの 1 点。 立てたセッションに、このハブから指示を送れること。
ここで使う ListAgents と
SendMessage はシェルのコマンドではないので、
ターミナルではなくこのチャットで頼む。
ListAgents で今あるセッションを見せて
期待される結果: 一覧に x01 が interactive · idle として現れる。
続けて、実際に仕事を頼んでみる:
x01 のセッションに「このリポジトリの README の見出しだけ列挙して」と頼んで、結果を教えて
期待される結果: 数十秒で、x01 側が調べた内容が返ってくる。
ここが通れば、狙っていたものは動いている
ターミナルを 1 度も開かずに、新しいセッションを立てて仕事を頼み、結果を回収できた。
5. 乗り込んで、抜ける¶
期待される動き: Claude Code の画面に切り替わる。左下に x01 と出ている。
抜けるとき: Ctrl-b を押してから d(detach)。Ctrl-c や exit ではない。
detach と kill は違う
Ctrl-b d で抜けてもセッションは生き続ける。それが tmux を使っている理由。
畳みたいときだけ ccs kill を使う。
抜けたあと、生きていることを確かめる:
期待される出力:
SLUG STATUS SESSION ID PATH
x01 idle 0ecd87dd-cdb0-4835-add0-23e4c14b9b5f ~/ghq/github.com/ken-ty/x01
6. 二度立てても増えないことを確かめる¶
期待される出力: 手順 3 と同じ sessionId で、created が false。
打ち方を変えても同じになることも見る:
→ これも created:false、同じ sessionId。
tmux セッションが 1 本のままであること:
→ cc/x01: 1 windows … の 1 行だけ。
7. 止まったセッションの見え方¶
claude だけを終了させて、ペインが残っている状態を作る。
→ Claude Code の中で /exit(または Ctrl-d)。ペインはシェルに戻る。
→ Ctrl-b d で抜ける。
期待される出力:
SLUG STATUS SESSION ID PATH
x01 stopped 0ecd87dd-cdb0-4835-add0-23e4c14b9b5f ~/ghq/github.com/ken-ty/x01
見るところ: stopped になっても SESSION ID が出ている。
この UUID が同じ会話に戻る手掛かりで、ccs restore もこれを使う。
この状態で ccs new x01 を打つと、成功扱いにせず復帰コマンドを出す:
ccs: cc/x01 のペインは残っていますが、claude は動いていません。
乗り込んで、同じ会話を再開する:
ccs attach x01
claude --resume 0ecd87dd-cdb0-4835-add0-23e4c14b9b5f
畳んで立て直す: ccs kill x01 && ccs new x01
7.1 止まったセッションを戻す¶
ccs ls が stopped と言っている状態のまま、同じ会話で立て直す。
期待される出力(既定は見せるだけ。何も起きない):
立て直せるセッション:
x01 2026-08-22 13:45 0ecd87dd-cdb0-4835-add0-23e4c14b9b5f <会話の名前>
実行するには: ccs restore --yes
別の会話を選ぶ: ccs restore <slug> --list
見るところ: SESSION ID が戻す前と同じで、STATUS が stopped でなくなっている。
ここが違っていたら、戻ったように見えて別の会話が立っている。
ccs attach x01 で乗り込むと、前の会話がそのまま続いている(スクロールバックに
前のやり取りがある)。アプリの一覧では元の名前のまま戻る ── restore は
-n を渡さないので、会話に付いていた名前が消えない。
戻した会話は動き出すことがある
落ちる直前に続きがあった会話は、resume した瞬間に続きを走らせる。
ccs から止める手段は無いので、1 本ずつ戻したいときは名指しする
(ccs restore x01 --yes)。詳細は restore.md。
tmux ごと消えた場合(再起動の再現)も同じ手順で戻る。ccs kill x01 で畳んでから
ccs restore を打つと、x01 も候補に出る ── ghq 配下でも ccs が立てた印があれば
拾うため(印とは)。
8. 掃除する¶
まず見せるだけ:
期待される出力:
見るところ: 何も消えていない。 tmux ls で確かめてよい。
内容を確認してから実行:
期待される出力:
期待される出力:
9. 使い捨ての作業枠(何本でも立つ)¶
ここで ~/.claude.json に行が増える
枠を信頼済みにするのは ccs 自身(#6、
2026-08-18 の決定)。手順 1 で控えた .projects の件数が、立てた枠のぶんだけ増える。
期待される出力(stderr に 1 行、stdout に JSON):
ccs: ccs が発行した作業枠なので信頼済みにしました: /Users/apple/.cc-scratch/3f9a2c1b
{"slug":"tmp-1","sessionId":"…","path":"/Users/apple/.cc-scratch/1",…,"created":true}
信頼確認は出ない。 枠は ccs が作った空のディレクトリなので、確認が守ろうとしている
「知らないコード」がそこに無い。
続けてもう 1 本立てて、枠が増えることを確かめる:
期待される出力: tmp-1 と tmp-2 が両方 idle で出る。ここが詰まると
「使い捨てを何本も立てる」という枠の存在理由そのものが成り立たない。
短い綴りの ccs new tmp も同じ結果になる。ただし ghq に tmp という名前のリポジトリが
あるときだけは、どちらを指したか決められないので候補を出して止まる。
枠の割り当て方は変わる予定
~/.cc-scratch/1・~/.cc-scratch/2 という固定 8 枠は、セッションごとに一意な
ディレクトリを作る形へ変わる(ADR-0001)。
この手順で確かめているのは「使い捨ての場所が何本でも立ち、信頼確認が出ないこと」なので、
そこは変わらない。変わるのはパスと slug の見た目で、そのときはこの手順書も直す。
9.1 セッションが自分で終わる(ccs kill --self)¶
アプリでアーカイブしても tmux のセッションは残る。 アーカイブは会話一覧の操作で、
CLI のプロセスは生き続ける ── ccs ls の idle は誤読ではなく事実。実測
(2026-08-28、動いている 16 本)でレジストリのキーを全部並べても、archived に
当たるものは無かった。
| 見たもの | 値 |
|---|---|
| レジストリのキー | bridgeSessionId cwd entrypoint kind messagingSocketPath name nameSince nameSource peerFeatures peerProtocol pid pidDomain procStart sessionId startedAt status statusUpdatedAt tmux updatedAt version waitingFor |
status の値 |
idle 8 / waiting 6 / busy 1 / null 1 |
だから終わる意思のあるセッションが、自分で終わる。
<slug> は打たない ── 自分がどれかは $TMUX と $TMUX_PANE から決まる。
cc/ のペインを持たないセッションからも打てる。 アプリや VS Code から開いた
セッションは ccs 管轄外なので $TMUX からは決まらないが、--self が言っているのは
「自分が終わる」であって「ccs が立てたものを畳む」ではない。そちらは祖先の pid で
レジストリを引いて自分を特定し、tmux ではなく claude の pid に SIGTERM を送る。
CLAUDE_PIDは使わない。 claude は自分の pid を子プロセスへ渡すが(実測 2026-08-30)、env は継承されるので入れ子や古い値で他人を指しうる。ここは kill の宛先なので、取り違えると畳まれるのが他人のセッションになる- SIGKILL に昇格しない。 SIGTERM なら claude は会話ログを書き切る(§10)。
KILL で落とすと書き切られていない会話が残り、
--resumeで戻す先が壊れる
何が残るかを実測する(本物の claude が要る)¶
この節だけは fake claude では答えにならない。 スタブは自前で SIGHUP を trap しているので、本物が SIGHUP でどう片付けるかは本物でしか見えない。
まず 1 本立てて、何ができるかを控える。
ls ~/.claude/sessions/ | sort > /tmp/before-sessions.txt
ls /tmp/cc-socks/ | sort > /tmp/before-socks.txt
ccs new <target>
ls ~/.claude/sessions/ | sort > /tmp/after-sessions.txt
comm -13 /tmp/before-sessions.txt /tmp/after-sessions.txt
実測(2026-08-28): 1 セッションにつき 3 つできる。
つまり ~/.claude/sessions/<pid>.json、~/.claude/sessions/<pid>.<hash>.key、
/tmp/cc-socks/<pid>.sock。どれも ccs は作っていない ── claude 自身のもの。
畳んで、消えることを確かめる。
実測: tmux kill-session の SIGHUP で 3 つとも消えた。ただし即座ではない。
| いつ | プロセス | <pid>.sock |
<pid>.json / .key |
|---|---|---|---|
kill-session の直後 |
まだ生きている | 消えている | 残っている |
| 数秒後 | 消えた | 消えた | 消えた |
claude が終了しながら片付けるので、ccs が消して回る必要は無い。 逆に、
ccs が先回りして消すと、まだ生きているプロセスの足元を抜くことになる。
自分で終わるところまで通す¶
--self は「中から打つ」ので、外から ccs kill を撃つのとは別物。1 本立てて、
そのセッション自身に打たせる。
実測(2026-08-28、本物の claude で 1 本): セッションは自分を畳み、
~/.claude/sessions は 34 → 36 → 34、/tmp/cc-socks は 17 → 18 → 17 と
元に戻った。tmux セッションも残っていない。
報告は読めない
ccs kill --self は畳む前に「同じ会話に戻るには…」を出すが、打った本人は
それを読めない。 ペインごと消えるので、出力を受け取るはずのプロセスも
一緒に死ぬ(実測: 会話ログの末尾はツールの結果が書かれないまま終わっていた)。
読めるのは断られたときだけ ── そのときセッションは生きている。
戻り方が要るときは ccs restore を使う。
断られる経路¶
| 相手 | どうなるか |
|---|---|
| hub | 拒否(--force でも)。落とすとスマホから叩く経路が消える |
| 未コミットの変更がある作業ツリー | 拒否。ccs kill --self --force が要る |
| 作業中 | 止めない。 この ccs を動かしているのが自分なので、自分の status は必ず作業中になる |
| git の管理下でないところ(使い捨ての作業枠など) | 未コミットの門は掛からない |
worktree は消さない(ccs kill と同じ方針)。片付けは ccs gc の担当。
10. 元に戻す¶
期待される出力: 空になった枠のディレクトリも gc が消す。
親のディレクトリだけ残るので、それも消す:
期待される出力:
tmux ls にセッションが残っていても異常ではない
ここで確かめたいのは「ccs の跡が残っていないこと」なので、tmux ls ではなく
ccs ls で見る。ccs ls は cc/ が付いたセッションだけに絞るため、
自分で開いた作業用の tmux セッションを巻き込まない。
tmux ls を打つと、手順 8 で畳まなかったセッションや、この手順の外で立てた
ものがそのまま出る。tmux サーバは 1 本でも残っていれば動き続けるので、
no server running … が出るのは全部畳んだときだけ。
これは「手順 7〜8 で畳んだ x01 を、そのあと立て直したまま残している」状態。
畳むなら ccs kill x01、残すならそのままでよい。
ccs 自体を外すなら:
~/.claude.json について
手順 9 で増えた hasTrustDialogAccepted の行は残る。枠を次に使うときに確認が
出なくなるだけで、害は無いので消さなくてよい。気になるなら
jq 'del(.projects["'"$HOME"'/.cc-scratch/1"])' で消せるが、このファイルは
Claude Code の状態がまとめて入った 100KB 級のものなので、書き戻す前に
中身を確かめること。
11. hub を 1 周する(一部実施)¶
launchd の経路だけ実測した(2026-08-22 / macOS 15・Homebrew)
アプリ側の見え方(名前・offline の残り方・--resume での RC 張り直し)は
まだ。fake claude では確かめられないので、ここは未チェックのまま残す。
確かめたいこと:
- [ ] スマホ / デスクトップのアプリの一覧に
hubという名前で出るか (会話を数往復させても名前が変わらないか) - [ ]
ccs hub restartのあと、アプリの一覧に新しい hub が出て、古いものが offline で残り続けないか - [ ]
ccs hub restart --resumeで同じ会話に戻り、そのとき Remote Control が 張り直されるか - [ ]
remoteControlAtStartup: trueを設定している環境で、--remote-controlの 明示指定が二重登録にならないか - [x] launchd から起動した
ccs hub upが、手元と同じ tmux サーバに入るか
11.1 launchd の経路(実測済み)¶
ccs hub agent --print > ~/Library/LaunchAgents/local.ccs.hub.plist
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/local.ccs.hub.plist
tmux kill-server # tmux サーバごと落として、電源断と同じ状態を作る
結果: 入る。 launchctl が起動した ccs hub up は
/private/tmp/tmux-501/default ── 手元のシェルの tmux ls が見るのと同じ
ソケット ── に cc/hub を作り、ccs ls にも 1 本だけ出た。bridge も付いた。
ただし、素の -lc では PATH が足りずに死ぬ。 最初の設置では
~/.cc-hub/agent.log に依存不足だけが積まれた。
launchd が渡す PATH は /usr/bin:/bin:/usr/sbin:/sbin 相当で、-lc を付けても
読まれるのは /etc/zprofile(path_helper)と ~/.zprofile まで。~/.zshrc
は対話シェル専用なので読まれない。 Homebrew の既定の入れ方は
~/.zshrc に brew shellenv を書くので、/opt/homebrew/bin がそこで落ちる。
これを受けて ccs hub agent は、生成時に解決できた依存の在処を
EnvironmentVariables に焼き込むようにした。焼き込んだあとで
tmux kill-server → launchctl bootstrap を通したところ、上のとおり復帰した。
ユニットは生成した環境に紐づく
焼き込みなので、Homebrew の場所を変えたり claude を入れ直したりしたら
ccs hub agent --print で出し直して置き換える。
hub down のまま放置しない
paused がある間は自動起動も止まる。確認が終わったら ccs hub up --force。
元に戻す:
launchctl bootout gui/$(id -u)/local.ccs.hub
rm ~/Library/LaunchAgents/local.ccs.hub.plist
ccs hub down && rm -rf ~/.cc-hub # 中身を確かめてから
通ったかどうかの一覧¶
- [ ] 0. 依存が揃っている
- [ ] 2.
resolveが副作用なしで答え、曖昧なときは勝手に選ばない - [ ] 3.
ccs newが数秒で JSON を返す - [ ] 4. ハブの
ListAgentsに現れ、SendMessageで仕事を頼めた ← ここが本命 - [ ] 5.
Ctrl-b dで抜けてもセッションが生きている - [ ] 6. 二度立てても増えない(
created:false、同じsessionId) - [ ] 7.
stoppedでもSESSION IDが出る - [ ] 7.1
ccs restoreが同じsessionIdで立て直し、会話の名前も変えない - [ ] 8.
gcが既定では何も消さない - [ ] 9. 使い捨ての作業枠が、信頼確認なしで 2 本とも立った
- [ ] 9.1
ccs kill --selfで自分を畳め、~/.claude/sessionsと/tmp/cc-socksが元の件数に戻った - [ ] 9.1 管轄外(アプリや VS Code から開いたセッション)でも
ccs kill --selfが通り、cc/のペインを持たない相手を SIGTERM で畳めた(自動テストでは「殺したプロセスが 走り切れない」ところを再現できないので、ここだけが本当の確認になる) - [ ] 10. 元に戻せた
- [ ] 11. hub(未実施。fake claude では確かめられない部分)
4 が通れば、この道具が解こうとしていた問題は解けている。 他が引っかかっても、それは使い勝手の話。
うまくいかないときの見どころ¶
| 症状 | 見るところ |
|---|---|
ccs new が 30 秒待って失敗する |
ペインの中身が出るのでそれを読む。信頼確認かログイン切れが大半 |
ListAgents に出てこない |
ccs ls で idle か確かめる。stopped なら claude が落ちている(使い分け) |
attach から抜けられない |
Ctrl-b → d。Ctrl-c ではない |
ccs new --tmp が「枠が全部埋まっています」 |
ccs gc で状況を見る。中身のある枠は ccs が消さないので自分で確認する |
ccs new tmp が「同名のリポジトリもあります」 |
ghq に tmp がある。作業枠なら --tmp、リポジトリなら <owner>/tmp |
ccs kill が「作業中です」で止まる |
意図した動き。ccs attach で様子を見てから --force |
アプリでアーカイブしたのに ccs ls に残っている |
誤読ではない。 アーカイブは会話一覧の操作で、CLI のプロセスは生きている。そのセッションに ccs kill --self を打たせる(9.1) |
ccs kill --self が「未コミットの変更があります」で止まる |
意図した動き。git status --short を見てから --force |
ccs restore に戻したいものが出てこない |
ghq の外に立てたものは列挙しない(名指しで戻す)。印の無い会話(アプリ / VS Code から開いたもの)も出ない。古い会話は既定で 7 日まで(--all)。印とは |
ccs hub up が no-rc(10)で終わる |
Remote Control が付いていない。ccs config で CCS_REMOTE_CONTROL を見る。使わない環境なら off |
ccs hub up が needs-attention(15)で止まる |
再起動を繰り返している。ccs hub attach と ~/.cc-hub/hub.log を見る |
| 終了コードの意味 | 0 成功 / 1 失敗 / 2 使い方の誤り / 4 依存が無い / 10〜15 は hub の状態(hub) |
それでも分からなければ、このチャットにそのまま貼ってほしい。
ccs が出すメッセージは、次の手が分かるように書いてある。
書いていなかったとしたら、それはこちらの直すべき点。