コンテンツにスキップ

なぜ ccs が要るのか

ccs の中核は tmux new-session -d の 1 行に近い。実装は 設計調査 のとおり「足りない 4 つを埋めるだけ」で、 そう書くと必ず「手順書(skill)で足りたのでは」という疑問が出る。

この文書はその疑問に答える。素の Claude Code セッションで何が起きないかを 実測で示し、それを踏まえて tmux と CLI という選択の理由を書く。

計測日: 2026-08-18 / claude 2.1.233 / macOS。


1. 「新しいセッションを立てて」は素直には通らない

Claude Code のセッションに、新しい Claude Code セッションを立てさせたい。 素直に頼むと、次の 3 つのどれかに落ちる。

1.1 ツールから直接 claude を起動する → pty が無くて即死する

セッションのツールから起動したプロセスに pty が無い。この状態で対話モードの claude を起動すると、黙って --print モードに落ちてそのまま終了する。

$ tty
not a tty

$ claude -n ttytest --session-id <uuid>
Error: Input must be provided either through stdin or as a prompt argument when using --print

プロセスは残らない。対話セッションはそもそも存在できない。

1.2 これは「禁止」ではない

入れ子で claude を呼ぶこと自体は通る。同じ環境で -p を付ければ動く。

$ claude -p "reply with exactly: NESTED-OK"
NESTED-OK

つまり再帰的な起動を止めているポリシーは無い。 足りないのは pty を配る手段だけ。 ここを取り違えると、 「外から SSH で入る」ような別の問題を解きに行くことになる。

1.3 組み込みのツールには新規作成の口が無い

手段 なぜ届かないか
SendMessage 生きている既存セッション宛にしか送れない。 新しくは作れない
ListAgents 一覧するだけ
Agent ツール サブエージェントであって独立したセッションではない。ListAgents にも Remote Control にも現れず、終わればそこで消える
ツールから直接 claude §1.1 のとおり pty が無く即死する

claude agents --json も読み取り専用。新規作成だけが空白という状態が、 設計調査 §1 の表の「セッションの新規作成: 要る」に対応する。


2. 手で tmux を叩けば立つ。だが毎回同じ形では立たない

pty は tmux が配れる。実際、ccs を使わずに手順どおり叩けばセッションは立つ。

mkdir -p "$D"
U=$(uuidgen | tr 'A-Z' 'a-z')
tmux new-session -d -s manual-x -c "$D" sh -c "claude -n manual-x --session-id $U; exec /bin/zsh"

この手順を実際に踏んだところ、3 つで止まった。

2.1 workspace trust ダイアログで固まる

新しいディレクトリでは、起動直後に信頼確認が出る。

 Quick safety check: Is this a project you created or one you trust?

 ❯ 1. Yes, I trust this folder
   2. No, exit

デタッチ起動なのでペインを覗くまで気づけない。しかもこの間、セッションは ~/.claude/sessions/<pid>.json にすら現れない。外から見ると 「立ったのか、死んだのか、待っているのか」が区別できない。 tmux send-keys で手動承認して初めて起動が完了した。

2.2 cc/ を付け忘れると管理から外れる

ccs ls は cc/ 接頭辞の tmux セッションだけを扱う(設計調査 §4.2)。 手で立てた manual-x はこの名前空間の外にあり、一覧に出てこなかった。

出てこないということは、ccs kill も ccs gc も届かないということでもある。 放置されたまま残り、次に気づくのは tmux ls を直接叩いたときになる。

ここが厄介なのは、規約を知っていても外れることだ。 上の手順は規約を知ったうえで打ったのに、cc/ を落とした。

2.3 冪等でない

UUID・作業ディレクトリ・セッション名を毎回自分で決めることになる。 同じ名前で 2 回叩けば tmux が duplicate session で落ちる。 tmux new-session が返った時点ではまだ起動途中なので、 登録されるまで待つループも自分で書くことになる。


3. ccs が変えるのは「立つ」ではなく「毎回同じ形で立つ」

同じことを ccs で行うと 1 コマンドで、結果が 1 行の JSON で返る。

$ ccs new --tmp
ccs: ccs が発行した作業枠なので信頼済みにしました: /Users/apple/.cc-scratch/2e60932e
{"slug":"tmp-8","sessionId":"2e60932e-…","path":"/Users/apple/.cc-scratch/8",
 "tmux":"cc/tmp-8","transcript":"…/2e60932e-….jsonl","created":true,"running":true}
手で tmux を叩く ccs new
コマンド数 4(mkdir / uuidgen / tmux / send-keys) 1
trust ダイアログ 手で承認が要る。気づかないと固まる 事前に解決して起動する
置き場所・名前 自分で決める。衝突は自己責任 空き枠を選び、slug は冪等
ccs ls での可視性 出ない(管理・後片付けの外) 出る
起動完了の判定 自分で待つ 登録を待ってから返る(running)
出力 無し JSON

ccs の価値は「できないことをできるようにする」ことではない。 手で 4 コマンド叩けば立つ。価値は、毎回同じ形で立ち、立った後も管理下に残ることにある。


4. なぜ tmux なのか — pty のためだけではない

pty を配るだけなら他にも手はある(script、expect、疑似端末を張る自作プロセス)。 tmux を選ぶ理由は、セッションの寿命をどの GUI からも切り離せることにある。

  • 人間が乗り込める。 ccs attach <slug> で、AI が立てたセッションに人間がそのまま入る。 逆に、人間が始めた作業を SendMessage で AI に引き継ぐこともできる。 会話の主体を途中で交代できるのは、実体が端末セッションだからこそできる
  • 長時間走る。 ターミナルを閉じてもプロセスは残る。 数時間から数日かけて /loop を回す運用が前提にできる
  • デスクトップアプリから独立している。 アプリの再起動・更新・ウィンドウを閉じる操作に 巻き込まれない。切断の原因がひとつ減る

3 番目は Remote Control と組み合わせたときに効く。Remote Control は プロセスが生き続けていることを前提にしているので、 セッションの宿主が「閉じられうる GUI」であるかどうかが、そのまま切断の頻度になる。

未検証

「ターミナル常駐のほうが実際に切断が少ない」は、設計上そうなるという説明であって、 デスクトップアプリとの切断頻度を並べて測ったものではない。

その独立には代償がある — アプリからターミナルが見えない

同じ独立性が、Claude アプリからのターミナルアクセスを奪う。

ccs で立てたセッションを Claude アプリ(デスクトップ / モバイル)から開いても、 そのセッションが動いている端末の画面は出てこない。 アプリが自分で立てたセッションでは出るのに、ccs のものでは出ない。

レジストリ(~/.claude/sessions/<pid>.json)を全件見ると、entrypoint で綺麗に二分される。

entrypoint tmux フィールド 立てたのは
claude-desktop 無し デスクトップアプリ
claude-vscode 無し VS Code 拡張
cli 有り ccs(および手で叩いた tmux)

pty を持っている主体が違う。 アプリが立てたセッションは、アプリ自身が pty を作って claude を起動しているので、その端末に画面を出せる。ccs のセッションで pty を 持っているのは tmux サーバーで、アプリはそこへの handle を持っていない。

未検証

アプリがどの条件で端末の画面を出すかの実装は確認していない。 上はレジストリの形から立てた仮説にすぎない。

これは ccs 固有の欠陥ではない。 手で tmux new-session して立てたセッションも 同じ形(entrypoint: cli + tmux 有り)になり、同じ制約を受ける。 ただし ccs を使うと全セッションがこの状態になるので、実質的には ccs の制約として現れる。

いまの回避策と、その限界

したいこと 手段 限界
端末の画面を見る ccs attach <slug> 同じマシンのターミナルからしかできない
セッションに指示を出す SendMessage(ハブ経由) 会話は通る。シェルの生の出力は返らない
何が起きたか後から読む ~/.claude/projects/<cwd-slug>/<uuid>.jsonl 会話の記録であって端末の画面ではない

外出先でアプリしか持っていない状況では、端末に届く経路が無い。 ccs は「ハブから複数セッションを立てて回す」道具なので、 立てたものをモバイルから触るのは主要な使い方に含まれる。ここは埋める必要がある。

追跡は #19。


5. なぜ skill ではなく CLI なのか

§2 の手順は、そのまま手順書として書ける。それでも CLI にしてある理由は 3 つある。

手順書(skill) ccs(CLI)
trust の回避 手順としては書けるが、~/.claude.json を書く状態変更。冪等性と壊れた JSON の扱いは書き手任せ コードとして冪等。妥当性を確かめてから mv で置き換える
命名規約 守られる保証がない。 外れると管理から漏れる(§2.2) 強制される
出力 自然言語。読めるのは AI だけ JSON。人間・スクリプト・GUI から叩ける
テスト 無い bats + fake claude スタブ。本物の claude を起動せずに検証する

とくに 3 行目が、この先を決めている。

手順書は「AI に読ませるもの」で、CLI は「誰でも叩けるもの」。 セッションを AI だけが立てるなら手順書で足りた。 人間も、スクリプトも、GUI も同じ入口から立てるなら、コマンドである必要がある。


まとめ

  • 素の Claude Code セッションは、新しいセッションを立てられない。禁止ではなく、 pty が無く、組み込みに新規作成の口が無い(§1)
  • tmux を手で叩けば立つ。ただし trust で固まり、命名を外すと管理から漏れ、冪等でない(§2)
  • ccs が売るのは可能性ではなく再現性。同じ形で立ち、立った後も管理下に残る(§3)
  • tmux は pty のためだけではなく、attach・長時間稼働・GUI からの独立のために選んでいる(§4)
  • 手順書ではなく CLI なのは、入口を AI 以外にも開けておくため(§5)
  • ただし tmux による独立には代償がある。Claude アプリからは端末の画面が見えない(§4)