機能

Claude Codeの起動

最終更新日: 2026年10月19日
ccam 0.6.0とClaude Code 2.1.302で確認済み

このページは英語から機械翻訳されています。修正を歓迎します。 GitHubでこのページを編集

このページの内容

ccam workは、アカウントworkとしてClaude Codeを起動し、名前より後のものはすべてそのままclaudeに渡します。ターミナル、スクリプト、パイプで入力を渡す場合など、claudeと入力するあらゆる場所で使えます。

使い方

ccam work                        # Claude Code as the account work
ccam 2                           # the account with number 2 (see ccam list)
ccam work --resume               # claude --resume, as work
ccam work -p "fix the tests" --output-format json
cat log.txt | ccam work -p "find the cause"
ccam -p "summarise"              # no name: the default account
ccam use work                    # make work the default account
ccam run work --continue         # same as ccam work --continue
ccam                             # the picker on a terminal, the list otherwise
ccam --dry-run work -p hi        # print the command instead of running it

アカウントの名前か、ccam listに表示される番号を指定します。ccamは名前より後の引数を読まないので、ccam work --helpはClaude Codeのヘルプを表示します。名前の後の--は省略できます。標準入力、終了コード、シグナルはclaudeと同じように動作します。

最初の引数が-で始まり、ccam自身のフラグでない場合、ccamはすべての引数を付けてデフォルトのアカウントを起動します。デフォルトはccam useで設定したアカウントで、設定していない場合は番号が最も小さいアカウントです。

ピッカー

引数なしのccamは、標準入力と標準出力がターミナルであればピッカーを開き、そうでなければccam listを出力します。ピッカーには、各アカウントの番号、メールアドレス、5時間の使用量、最終使用日時、共有項目が表示されます。使用量は、各アカウントの応答があり次第表示されます。

キー 動作
Enter 選択したアカウントとしてClaude Codeを起動します
1~9 その番号のアカウントを起動します
Up/Down、k/j 選択を移動します
a ピッカーを閉じてccam addのウィザードを実行します
s 選択したアカウントの共有項目を編集します(Spaceかxで切り替え、Enterで適用、Escで戻ります)
d 選択したアカウントをデフォルトにします
r 短期キャッシュを使わずに使用量を取得し直します
q、Esc、Ctrl+C 終了します

ピッカーは操作を実行する前に閉じるので、Claude Codeが起動する前にターミナルは元の状態に戻ります。dや共有の変更の後は、ピッカーがもう一度開きます。共有を変更するときは、ccam shareと同じように、先に計画を表示して確認を求めます。

オプション

オプション 効果 デフォルト
--dry-run ccamが実行する環境変数とコマンドを表示して終了します オフ
-v、--version ccam <version>を表示します(最初の引数の場合のみ)
-h、--help ccam --helpやccam run --helpとして、ccamのヘルプを表示します

引数の規則:

  • ccamが自身のフラグを読むのは、アカウント名より前だけです。名前より後の引数は、--dry-runや--helpも含めてすべてClaude Codeのものです。
  • --dry-runは、ccam --dry-run work、ccam run --dry-run work、ccam --dry-run(デフォルトのアカウント)の形で使えます。拒否されることはなく、そのとおりに動作します。
  • ccam run <name|number> [claude args]は、ccam <name>の長い形式です。名前なしのccam runはデフォルトのアカウントを使います。
  • アカウント名にはadd、list、run、usageなどのccamのコマンド名を使えないので、ccam <word>が曖昧になることはありません。

ドライランは、そのままシェルに貼り付けられる1行を出力します。

$ ccam --dry-run work -p "fix the tests"
CLAUDE_CONFIG_DIR=/home/me/.local/share/ccam/profiles/work /home/me/.local/bin/claude --mcp-config=/home/me/.local/share/ccam/groups/default/mcp.json -p 'fix the tests'

しくみ

起動のたびに、コマンドラインからexecまで同じ手順をたどります。

各ボックスはその手順の実行中に強調表示され、その下の行は、Claude Codeが起動するときの環境変数と引数です。

  1. cmd/ccam/main.goがapp.Mainを呼び出します。ccamが別の名前で起動された場合、それはショートカットなので、直接起動処理に進みます。
  2. app.parseは、cobraが関わる前にos.Argsを調べます。cli.Executeに進むのは、ccam単体(ピッカー)、ccamのコマンド名(config.Reserved)、-h/--help、-v/--versionだけです。それ以外はすべて起動です。
  3. launcher.Launchが~/.config/ccam/config.tomlを読み込みます。解析するファイルはこれだけです。
  4. launcher.Prepareが名前か番号でアカウントを見つけ、先頭の--を1つ取り除き、ResolveClaudeでclaudeの実行ファイルを特定します。PATHの検索結果は、ファイルの更新日時とともに~/.local/state/ccam/claude-pathにキャッシュされるので、ccamが起動のたびにPATHを検索することはありません。ファイルが変更されたか、なくなった場合は、検索し直します。config.tomlのclaude_binのパスは、そのまま使われます。ループになるため、ccam自身であるclaudeは、inodeで比較して拒否します。
  5. checkLinksが、アカウントのフォルダー~/.local/share/ccam/profiles/<name>/を共有設定と比較します。使うshare.Checkはlstatとreadlinkだけを呼び出すので、システムコールは項目ごとに1回か2回です。足りないリンクはその場で作成します。データを失う可能性があるものがあれば、起動を停止します。
  6. applyMCPが共有MCPサーバーを追加します(後述)。
  7. session.Registerがセッションを記録します。ccamは、自身のPIDを名前とし、プロセスの開始時刻を内容とするマーカーを$XDG_RUNTIME_DIR/ccam/profile-<name>/<pid>(XDG_RUNTIME_DIRがない場合は~/.local/state/ccam/locks/)に書き込みます。会話履歴を共有するアカウントの場合は、まずhistoryCheckがhistory-<group>-<hash>(ハッシュは現在のフォルダーから求めます)で実行中のセッションを探し、そこにも登録します。execはPIDを変えないので、マーカーはそのままClaude Codeのプロセス自体を指すことになります。保持し続けるロックではなくマーカーを使うのは、Claude Codeが起動したプロセスがロックを引き継ぎ、セッション終了後もロックを持ち続けてしまうためです。
  8. Plan.Execがターミナルのタイトルをclaude · <name>に設定し(標準エラー出力がターミナルの場合)、起動時刻をfsyncなしで~/.local/state/ccam/last-used/<name>に書き込み、syscall.Execを呼び出します。

Claude Codeは、CLAUDE_CONFIG_DIRにアカウントのフォルダー、CCAM_PROFILEにアカウント名が設定された状態で実行されます。ccamは、これらの変数について引き継いだ値をすべて取り除きます。macOSでccam importで登録した~/.claudeフォルダーの場合は、CLAUDE_SECURESTORAGE_CONFIG_DIRにも空の値を設定します。これにより、そのアカウントと通常のclaudeが同じキーチェーンのログインを使います。

execを使う理由

syscall.Execはccamのプロセスをclaudeに置き換えます。そのため、ccamがメモリーに残ることはなく、キー入力、シグナル、終了コードはClaude Code自身のものになり、引数はシェルの文字列ではなく配列のまま保たれます。claude mcp addで追加したサーバーの検出など、セッション後に必要な処理は次の起動時に行います。ccamは.claude.jsonの更新日時を~/.local/state/ccam/mcp/<name>/seenと比較し、変更があった場合だけファイルを解析します。

コマンドラインの振り分け

3つのコマンドラインが、internal/appの中でそれぞれ別の経路をたどります。

ショートカットはargv[0]で、ccam <name>は最初の引数で判定され、どちらもsyscall.Execで終わります。cobraに到達するのは、ccam usageのようなccamのコマンドだけです。

共有MCPサーバー

デフォルトのflag戦略では、ccamはグループのMCPサーバーを引数としてClaude Codeに渡し、自分で指定した引数より前に置きます。

mcp.FlagArgsは、グループのmcp.jsonがある場合にだけ引数を返し、Plan.InsertArgsがそれをclaudeの直後に置きます。自分で指定した--mcp-configや--strict-mcp-configも、その上に追加で適用されます。Claude Codeの--mcp-configは複数の値を取るので、--mcp-config=<path>という1つの引数にしています。2つの引数に分けると、続くプロンプトも設定ファイルとして読まれてしまいます。

config.tomlでmcp_strategy = "sync"を設定すると、ccamは代わりにアカウントの.claude.jsonにサーバーを書き込みます。アカウントがすでに実行中の場合は、これをスキップします。

Remote Control

ccam work rc(またはccam work remote-control)は、workとしてClaude CodeのRemote Controlを起動します。claude remote-controlは動詞の前の--mcp-configを拒否し、動詞の後でも受け付けません。また、そのセッションはアカウントの.claude.jsonからしかMCPサーバーを読みません。そのため、ここではフラグ戦略の動作が異なります。

  1. remoteControlは、アカウントより後の引数のうち-で始まらない最初のものをClaude Codeの動詞とみなします。それがremote-controlかrcの場合、mcp.FlagArgsは何も追加しません。

  2. mcp.Syncedは、グループのmcp.jsonの更新日時をアカウントのsync-stampと比較します。.claude.jsonにグループの現在のサーバーがすでに入っている場合や、グループにサーバーがない場合は、確認せずにRemote Controlを起動します。

  3. それ以外の場合、ccamはセッションで使えなくなるサーバーの名前を示して確認します。

    ccam: Remote Control sessions only get MCP servers stored in account work's .claude.json, not the shared MCP servers (ctx, fs).
    Copy them into .claude.json (a backup is kept)? [y/N]
  4. yと答えると、mcp.Syncがsync戦略と同じ方法でサーバーをコピーします。Claude Codeのロックを取得し、バックアップを取ったうえで、アカウント自身のサーバーは残します。Nと答えた場合やターミナルがない場合は、それらのサーバーなしでRemote Controlを起動し、起動のたびにサーバーをコピーするmcp_strategy = "sync"を案内します。

ccamは、サーバーがコピーされるまでRemote Controlの起動のたびに確認し、コピーした後はグループのmcp.jsonが再び変わったときに一度だけ確認します。その後の通常の起動では.claude.jsonのコピーが--mcp-configより優先されるため、ccam mcp add、remove、importはほかのアカウントが持つコピーも更新します(共有MCPサーバー)。

10 msの予算

ccamがClaude Codeの起動前に追加する時間は、最大10 ms(p95)です。起動経路では、cobraのコマンドツリーの構築、Bubble Teaの起動、ネットワーク接続を一切行いません。また、パッケージのinit()関数の合計が5 msを超えるとTestPackageInitIsCheapが失敗します。scripts/perf-check.shはhyperfineでccam --dry-run work、ccam work、ショートカットを計測し、10 msを超えると失敗します。internal/launcherのBenchmarkLaunchPathは、これらの手順をループで実行します。手順ごとの時間を確認するには、CCAM_TRACE=1を設定します。

$ CCAM_TRACE=1 ccam --dry-run work >/dev/null
ccam trace: start                 2.830ms (total 2.830ms)
ccam trace: load config           0.397ms (total 3.227ms)
ccam trace: prepare               0.112ms (total 3.339ms)
ccam trace: check links           0.238ms (total 3.578ms)
ccam trace: prelaunch             0.083ms (total 3.661ms)

安全性と特殊なケース

  • 不明な名前や番号を指定するとno account "<name>"で停止し、ccam listを案内します。アカウントが1つもない場合は、ccam add <name>で追加するよう求めます。
  • 共有パスが通常のファイルになったり、間違った場所を指していたりする場合、ccamはstopped because of share link problems:で停止し、問題を一覧表示して、ccam doctor --fixを実行するよう求めます。起動経路でデータを移動することはありません。
  • このアカウントと会話履歴を共有する(同じグループの)別のClaude Codeが同じフォルダーで実行中の場合、ccamは履歴が混ざる可能性があることを警告し、Run anyway? [y/N]と尋ねます。ターミナルがない場合は、警告を表示して続行します。
  • --dry-runは、MCPの同期、新しいサーバーの通知、履歴の確認、セッションのマーカー、タイトル、最終使用日時をスキップし、execも行いません。共有リンクの確認は行い、通常の起動と同じように足りないリンクを作成します。
  • workがすでに実行中のときにccam work rcを実行すると、.claude.jsonには触れずにその旨を表示し、グループのサーバーなしでRemote Controlを起動します。サーバーをコピーするには、セッションが終了した後にもう一度実行してください。--dry-runではメッセージを表示するだけで、確認もコピーも行いません。
  • mcp_strategy = "sync"の場合、同期に失敗するとccam: MCP sync failed (launching anyway): …と表示され、Claude Codeはそれまでのサーバーで起動します。