CC Bridge

開発者向け

CC Bridge 開発者向けガイド

CC Bridge の API を使うと、ペアリング済みの PC やブラウザを、自分のプログラムや AI エージェント(Claude Code など)から操作できます。 認証、API、端末ごとに使えるツール、記録と安全装置、独自の端末をつなぐ方法をまとめています。

HTTPS と JSON Bearer トークン 操作はすべて監査ログに記録

しくみ

CC Bridge は 3 つの役割でできています。

コントローラーあなたのプログラムや AI エージェント。HTTPS の API で命令を送ります。
ブリッジcc-bridge.elc-gateway.com。命令と結果を中継し、すべての操作を記録します。
端末(ハンドラー)Windows・Mac のアプリと Chrome 拡張。ブリッジへ自分からつなぎに行きます。
  • 端末はブリッジへ外向きにつなぐので、端末側でポートを開けたり、公開 IP を用意したりする必要はありません。
  • API の 1 回の呼び出しが 1 つの命令です。端末が結果を返すまで応答を待ちます。
  • 端末・利用者はテナント(会社や部署の単位)に分かれていて、自分のテナントの外の端末は見えません。

はじめかた

  1. トークンを受け取る。管理者にコンソールの「利用者」で利用者を作ってもらい、アクセストークン(ccu_ で始まる文字列)を受け取ります。トークンは発行したときに一度だけ表示されます。
  2. 端末をつなぐ。インストールのページからアプリか Chrome 拡張を入れ、サインインするか接続コードで登録します。
  3. API を呼ぶ。まず、トークンの持ち主と操作できる端末を確かめます。
export CC_BRIDGE_URL=https://cc-bridge.elc-gateway.com
export CC_BRIDGE_TOKEN=ccu_...        # 管理者から受け取ったトークン

# トークンの持ち主と、操作できる端末
curl -s -H "Authorization: Bearer $CC_BRIDGE_TOKEN" $CC_BRIDGE_URL/api/whoami
curl -s -H "Authorization: Bearer $CC_BRIDGE_TOKEN" $CC_BRIDGE_URL/api/handlers

端末 ID(hdl_ で始まる文字列)は、一覧の handlerId です。コンソールの端末一覧でも、ID を押すとコピーできます。つながっている端末(connected: true)に命令を送ってみます。

curl -s -X POST $CC_BRIDGE_URL/api/handlers/hdl_0123456789abcdef/cmd \
  -H "Authorization: Bearer $CC_BRIDGE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"desktop.system.info","params":{}}'

認証と権限

すべての API に Authorization: Bearer <トークン> を付けます。トークンがない、または無効なときは 401 unauthorized が返ります。

役割操作できる端末
メンバー自分が所有する端末と、管理者に割り当ててもらった端末
テナント管理者同じテナントのすべての端末。端末の停止と再開もできます

操作できない端末を指定すると、存在しない端末と同じ 404 unknown-handler が返ります。ほかの人の端末があるかどうかは分からない作りです。端末が接続中でも、割り当てがなければ 404 です。自分の端末ではない PC を使うときは、管理者に端末の ID を伝えて割り当ててもらってください。GET /api/handlers に出てくる端末が、いま操作できる端末です。

  • トークンは環境変数などで渡し、コードやリポジトリには書かないでください。
  • 漏れたときは管理者に再発行を頼んでください。再発行すると、古いトークンはすぐに使えなくなります。
  • 同じトークンを複数のプログラムで使うときは、X-Session ヘッダーに見分けるための名前(40 文字まで)を付けてください。監査ログと、同時操作の知らせに出ます。

API

ベース URL は https://cc-bridge.elc-gateway.com です。{id} は端末 ID です。

端末

GET/api/whoami

トークンの持ち主。{ kind, userId, name }

GET/api/handlers

操作できる端末の一覧。{ handlers: [...] }

GET/api/handlers/{id}

1 台の詳細。connected・os・hostname・handlerVersion・tools(その端末で使えるツール)など

命令

POST/api/handlers/{id}/cmd

任意のツールを実行します。{ name, params, timeoutMs }。ツールは下の「ツール」を見てください。

POST/api/handlers/{id}/exec

コマンドを実行します(desktop.exec の近道)。{ cmd, cwd, timeoutMs, env } → { exitCode, stdout, stderr, durationMs }

POST/api/handlers/{id}/screenshot

画面を撮ります(desktop.screenshot の近道)。本文は desktop.screenshot の引数です。

ファイル

POST/api/handlers/{id}/fs/read

読む。{ path, encoding, maxBytes }。encoding は utf-8 か base64

POST/api/handlers/{id}/fs/write

書く。{ path, content, encoding, mkdirs, overwrite }。既にあるファイルは overwrite: true のときだけ上書きします

POST/api/handlers/{id}/fs/push?path=…&mkdirs=1&overwrite=1

大きなファイルを送ります。本文はバイト列そのまま(Content-Type: application/octet-stream)。4 MB ずつ中継し、最後に SHA-256 で照合します → { ok, path, bytes, sha256, verified }

GET/api/handlers/{id}/fs/pull?path=…

ファイルを受け取ります。応答の本文がファイルのバイト列です

# 送る(本文はファイルのバイト列そのまま)
curl -s -X POST "$CC_BRIDGE_URL/api/handlers/$ID/fs/push?path=C:/work/data.zip&mkdirs=1&overwrite=1" \
  -H "Authorization: Bearer $CC_BRIDGE_TOKEN" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @data.zip

# 受け取る
curl -s -o report.pdf "$CC_BRIDGE_URL/api/handlers/$ID/fs/pull?path=C:/work/report.pdf" \
  -H "Authorization: Bearer $CC_BRIDGE_TOKEN"

接続と記録

POST/api/handlers/{id}/test

ブリッジから端末への接続テスト。{ ok, results: { ws, tunnel, … } }

POST/api/handlers/{id}/update-check

端末に更新の確認を指示します。自動更新がオンの端末は、新しい版があれば入れ替わります

GET/api/handlers/{id}/audit?limit=200

その端末の監査ログ。{ audit: [...] }

登録と停止

POST/api/pair/{code}/approve

接続コード(ABCD-EFGH)を承認します。承認した端末はあなたの所有になります。/deny で拒否

POST/api/handlers/{id}/block

端末を停止します(テナント管理者)。すぐに切断し、/unblock するまで再接続を断ります

DELETE/api/handlers/{id}

ペアリングを解除します(所有者)。もう一度つなぐには登録し直しが必要です

近道の /exec・/screenshot・/fs/* は Windows・Mac のアプリ用です。Chrome 拡張には /cmd でツール名を指定して送ります。

応答とエラー

命令が成功すると、次の形で返ります。data の中身はツールごとに違います。

{
  "ok": true,
  "data": { "os": "windows", "hostname": "…", "cpu": { … }, "memory": { … } }
}

直近 60 秒以内に別のセッションが同じ端末を操作していると、contention が付きます。命令は実行されます(ロックではありません)。マウスやキーボードの操作がぶつかるおそれがある、という知らせです。

{
  "ok": true,
  "data": { … },
  "contention": {
    "others": [{ "actor": "user:usr_…(…)@nightly", "secondsAgo": 12 }],
    "warning": "この端末は直近60秒以内に他のセッション(…)も操作しています。…"
  }
}
状態error意味
400name-required など必要な項目がありません
401unauthorizedトークンがない、または無効です
404unknown-handler端末がない、または操作できません
409handler-not-connected端末がつながっていません(停止中を含む)
422ssh-sweep-blockedSSH を大量に試すコマンドを止めました(「記録と安全装置」)
501client-too-old端末のアプリが古く、その機能に対応していません
502command-timeout など時間切れ、または端末側のエラーです。error に理由が入ります

時間と大きさ

  • 命令の待ち時間は既定で 60 秒です。timeoutMs で変えられますが、途中の経路で 100 秒前後で切れることがあります。長い処理は 90 秒以内に分けるか、端末側で裏で動かして結果をファイルで受け取ってください。
  • JSON の本文は 32 MB までです。大きなファイルは fs/push と fs/pull を使ってください。

ツール

端末で使えるツールは、GET /api/handlers/{id} の tools に出ます。/cmd の name にツール名、params に引数を入れて呼びます。

Windows・Mac のアプリ

ツール主な引数内容
desktop.screenshotdisplay, region画面を PNG で返します(pngBase64・width・height)
desktop.mouse.movex, y, durationMsマウスを動かします
desktop.mouse.clickx, y, button, clicksクリックします
desktop.mouse.scrollclicks, x, yスクロールします
desktop.keyboard.typetext文字を入力します
desktop.keyboard.presskeysキーを押します。"enter" や ["ctrl","c"]
desktop.clipboard.read / writetextクリップボードを読む・書く
desktop.execcmd, cwd, timeoutMs, envコマンドを実行します
desktop.fs.read / write / statpath ほかファイルの読み書きと情報(stat は sha256 も返せます)
desktop.window.list / focustitleウィンドウの一覧と切り替え
desktop.screen.info—画面の大きさ・倍率・ディスプレイの数
desktop.locateImagetemplate, confidence画面の中から画像(PNG の base64)を探し、位置を返します
desktop.system.infoincludePublicIp, includeGpuOS・CPU・メモリなど
desktop.permissions.check—Mac で、入力と画面収録の許可が効いているか
  • desktop.exec はシェルを通しません。パイプや && を使うときは、["bash","-lc","…"] や ["powershell","-Command","…"] のようにシェルを明示してください。
  • マウス・キーボード・画面の操作は、1 台につき 1 つずつ順に実行されます。

Chrome 拡張

ツール主な引数内容
screenshottabId, format, fullPage, transferModeタブを撮ります
getDomselector, maxBytesページの HTML を取ります
click / type / pressKeyselector ほか要素を押す・入力する・キーを送る
scroll / waitForSelectorselector, timeoutMsスクロールする・要素が出るのを待つ
navigateurlページを開きます
executeJscode, world, timeoutMsページで JavaScript の式を実行し、値を返します
tabs.* / windows.* / tabGroups.*—タブとウィンドウの一覧・作成・切り替えなど
bookmarks.* / history.* / downloads.* / cookies.*—ブックマーク・履歴・ダウンロード・Cookie
clipboard.read / write, systemInfo—クリップボードとブラウザの環境
  • 操作の対象は、最後に使ったウィンドウで表示中のタブです。
  • 拡張 0.9.2 以降は、ページを扱うツール(screenshot・getDom・click・type・pressKey・scroll・waitForSelector・navigate・executeJs)に tabId を渡すと、そのタブを前面に出さずに操作します。人が別のタブを使っていても画面は切り替わりません。tabId は tabs.list で調べるか、tabs.create に active: false を付けて自分用のタブを作ってください。tabs.activate は人の画面を奪うので、見せたいときだけ使います。0.9.2 より前の拡張は tabId を無視して前のタブを操作してしまうため、ブリッジが 501 client-too-old で断ります。
  • 操作できるのはページのいちばん外側の枠だけです。ほかのサイトの iframe の中、chrome:// のページ、拡張機能のページ、PDF は操作できません。
  • screenshot などで画像を受け取るときは transferMode: "base64" を指定してください。
  • executeJs の既定(world: "DEBUGGER")では、Chrome の上部に「デバッグ中」の帯が出ます。

記録と安全装置

  • 監査ログ。送った命令は、誰が・いつ・どの端末に・何を(引数を含めて)送ったかが記録されます。結果の中身は記録しません。8KB を超える引数は、先頭 2KB と長さ・SHA-256 だけを記録します。パスワードなどの秘密は引数に入れないでください。記録は GET /api/handlers/{id}/audit で見られます。
  • 端末の停止。管理者やテナント管理者が端末を停止すると、その端末はすぐに切断され、再開されるまでつながりません。そのあいだの命令は 409 になります。
  • 緊急停止。管理者はすべての端末を一度に止められます。止まっているあいだは、どの端末にも命令は届きません。
  • SSH の連続実行を止める。ループの中の ssh や、同じ相手への繰り返しなど、SSH を大量に試すコマンドは実行前に止めて 422 を返します。
  • 同時操作の知らせ。ほかのセッションが同じ端末を操作していると、応答に contention が付きます。

AI エージェントから使う

Claude Code などの AI エージェントに使わせるときは、トークンを環境変数で渡し、使い方をプロジェクトの説明(CLAUDE.md など)に書いておきます。例:

## CC Bridge
- PC の操作は CC Bridge の API で行う。ベース URL は $CC_BRIDGE_URL、
  認証は "Authorization: Bearer $CC_BRIDGE_TOKEN"。
- 操作できる端末は GET /api/handlers。端末ごとに使えるツールは tools に出る。
- 命令は POST /api/handlers/<端末ID>/cmd に {"name": "<ツール名>", "params": {...}}。
- X-Session ヘッダーに作業名を付ける(同じトークンの別セッションと見分けるため)。
- パスワードなどの秘密は引数に入れない(引数は監査ログに残る)。
- 応答に contention が付いたら、ほかの人も同じ端末を操作している。画面操作は控える。

プログラムから呼ぶ

JavaScript(Node.js 18 以降):

const res = await fetch(`${process.env.CC_BRIDGE_URL}/api/handlers/${id}/cmd`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CC_BRIDGE_TOKEN}`,
    'Content-Type': 'application/json',
    'X-Session': 'nightly-report',     // 監査ログで自分の作業を見分ける名前
  },
  body: JSON.stringify({
    name: 'desktop.exec',
    params: { cmd: ['git', 'status', '--short'], cwd: 'C:/work/app', timeoutMs: 30000 },
  }),
});
const { ok, data, error } = await res.json();

Python(標準ライブラリだけ):

import json, os, urllib.request

req = urllib.request.Request(
    f"{os.environ['CC_BRIDGE_URL']}/api/handlers/{hid}/cmd",
    data=json.dumps({"name": "desktop.screenshot", "params": {}}).encode(),
    headers={
        "Authorization": f"Bearer {os.environ['CC_BRIDGE_TOKEN']}",
        "Content-Type": "application/json",
    },
)
with urllib.request.urlopen(req, timeout=90) as r:
    shot = json.load(r)["data"]          # pngBase64, width, height

独自の端末をつなぐ

配布しているアプリや拡張のほかに、自分で作ったプログラムを端末(ハンドラー)としてつなぐこともできます。

1. 接続コードで登録する

POST /device/code
{"handlerType":"my-handler","handlerName":"検査ラインの PC","os":"linux"}

→ {"device_code":"…","user_code":"ABCD-EFGH",
   "verification_uri":"https://cc-bridge.elc-gateway.com/activate","expires_in":600,"interval":3}

user_code を人に見せ、コンソールか /activate で承認してもらいます。そのあいだ interval 秒ごとに次を呼び、承認されたらトークンを受け取ります。コードの期限は 10 分です。

POST /device/token
{"device_code":"…"}

→ {"status":"pending","interval":3}
→ {"status":"approved","handler_token":"cch_…","handler_id":"hdl_…","handler_type":"my-handler"}

2. WebSocket でつなぐ

つないだら、まず自分の情報(handler-manifest)を送ります。命令(cmd)が届いたら、同じ cmdId で結果(result)を返します。

wss://cc-bridge.elc-gateway.com/ws?token=cch_…&handlerType=my-handler&handlerVersion=1.0.0

→ {"type":"handler-manifest","handlerType":"my-handler","handlerVersion":"1.0.0",
   "os":"linux","hostname":"line3-pc","tools":["my.hello"]}

← {"type":"cmd","cmdId":"c_…","name":"my.hello","params":{"to":"world"}}
→ {"type":"result","cmdId":"c_…","ok":true,"data":{"message":"hello, world"}}
→ {"type":"result","cmdId":"c_…","ok":false,"error":"理由"}
切断コード意味端末がすること
4401トークンが無効トークンを消し、登録し直します
4403停止中(端末の停止・緊急停止)トークンは残し、間をあけてつなぎ直します
4000ペアリング解除登録し直します
  • ブリッジは 25 秒ごとに WebSocket の ping を送ります。切れたら、1 秒から 30 秒まで間隔を延ばしながらつなぎ直してください。
  • 新しい版があると {"type":"update-available","version":"…"} が届きます。無視してもかまいません。

関連: インストール ・ リリースノート ・ コンソール ・ 質問や要望はメモを送るから。