---
title: "starbridge-mod"
url: "https://claudemods.dev/zh-tw/builds/starbridge-mod-b2ab70"
source: "https://github.com/T0mSIlver/starbridge/tree/main/mod"
source_type: "github"
repo: "https://github.com/T0mSIlver/starbridge/tree/main/mod"
author: "T0mSIlver"
author_handle: "T0mSIlver"
stars: 1
category: "工作流程與 CI"
categories: ["workflow"]
tags: ["claude-code", "hooks", "human-in-the-loop", "mod", "starbridge", "workflow"]
permission_level: 3
scan_complete: true
install: "claude plugin marketplace add T0mSIlver/starbridge\nclaude plugin install starbridge-mod"
added: "2026-10-09T05:19:32.754Z"
updated: "2026-10-09T08:24:02Z"
locale: "zh-tw"
content_locale: "zh-tw"
---

# starbridge-mod

將擁有者的 Starbridge 回答提交到提出要求的 Claude Code 工作階段中。一個 Claude Code 模組：無法載入模組的組建會跳過它，而 starbridge 外掛繼續運作。

## Description

# 適用於 Claude Code 的 Starbridge 模組

當擁有者回答一個決策時，此模組會將回答提交到提出要求的 Claude Code
工作階段中，如同 `starbridge wait` 列印的那一行：

```
Answer to d_Xk3… (Merge #12 now?): Merge
```

它可在終端機、桌面應用程式的程式碼標籤頁和遠端控制中運作。

## 安裝

從 Starbridge 市集安裝它，位於 `starbridge` 外掛旁邊
（`plugin/README.md`）：

```bash
claude plugin install starbridge-mod@starbridge --scope user
```

拒絕模組的 Claude Code 組建或組織會跳過此外掛並
保留技能；此時回答會等待，直到某個工作階段執行 `starbridge answers`。
要在單一工作階段中試用簽出：`claude --plugin-dir mod`。

## 運作方式

此模組不持有任何金鑰。每個互動式工作階段會選擇兩條路徑之一，並在代理啟動或停止時切換。

### 透過代理

當機器的代理（`starbridge agent`，PROTOCOL.md，「本機代理 API」）
在其 unix 通訊端上回應時，每個工作階段透過 `$.http.fetch` 與其通訊：

- 每個工作階段 id 呼叫一次 `POST /v1/sessions/<id>/hello`，攜帶工作階段的
  工作目錄。
- 背靠背呼叫 `GET /v1/sessions/<id>/events?wait=25`，在來自模組的呼叫
  的 30 秒限制內。代理只會將工作階段所提問的決策的回答交給該工作階段。
- 模組提交每個事件的那一行，然後透過
  `POST /v1/sessions/<id>/ack` 確認；代理會再次交付未確認的事件。
  它會跳過不知道的事件類型。
- 工作階段結束時呼叫 `POST /v1/sessions/<id>/bye`。

通訊端為 `$STARBRIDGE_AGENT_SOCKET`，否則對於預設設定目錄為
`$XDG_RUNTIME_DIR/starbridge/agent.sock`，
否則為設定目錄中的 `agent.sock`，與 CLI 的計算方式一致；在 Windows 上
（`OS=Windows_NT`），則是設定目錄中的連接埠檔案 `agent.port`，其中
列出回送連接埠以及每次呼叫攜帶的權杖（PROTOCOL.md）。426（代理使用
另一個 API 修訂版）或無法連線的呼叫會將工作階段送到 CLI 路徑。

### 透過 CLI

在沒有 agent 時，或設定 `STARBRIDGE_NO_AGENT=1` 時，mod 會執行 CLI，並每 30 秒檢查一次
agent。

- 每個互動式工作階段都會執行 mod，但每台機器只有一個工作階段進行輪詢：
  持有 `~/.config/starbridge/mod-poller.json` 中租約的工作階段。它連續執行
  `starbridge answers --session <id> --wait 25`，這使來自 mod 的呼叫
  保持在 30 秒限制以下。
- 其他工作階段會監看 `state.json`。當它變更時，它們會執行 `starbridge
  answers --session <id>`，這只會讀取本機狀態。
- `answers` 只會傳回該工作階段所提出、且沒有任何
  `wait` 列印過的決策答案。mod 會提交每一行，然後用
  `starbridge answers --session <id> --ack <ack>` 確認它；CLI 會把
  未確認的行再次交出。
- 沒有輪詢的工作階段也會在 `state.json` 未變更時每 30 秒執行一次 `answers`，
  以防有變更未被看到。
- 當工作階段結束時，它會放棄租約，另一個工作階段開始
  輪詢。

在兩條路徑上，`/clear` 或 `/resume` 之後，mod 都會使用新的工作階段
id；在 `/clear` 期間到達的行會以未確認狀態等待舊
工作階段。發生錯誤後，mod 會等待 2 秒，之後每再發生一次錯誤等待時間加倍，最多一分鐘，
並在狀態列中顯示錯誤，直到一次
呼叫成功。

## Pi

`pi/starbridge.ts` 是與 Pi 擴充功能相同的應答迴圈。它隨儲存庫的 Pi 套件以及 `starbridge` 技能一起提供。`starbridge setup` 會將它安裝到
它所執行的 CLI 的發行標籤，即 `v` 加 `starbridge --version` 所列印的內容：

```bash
pi install git:github.com/T0mSIlver/starbridge@v<version>
```

在互動式或 RPC Pi 工作階段中，它會將每個答案作為使用者訊息提交，
這會在 Pi 閒置時啟動一個回合，並在它忙碌時在目前回合之後執行。它也會將外掛的規則（`plugin/hooks/rule.md`）加入 Pi 的系統
提示中。`pi -p` 不會取得迴圈，因此那裡的 `starbridge ask` 會告訴 agent
去 `starbridge wait`。

安裝 [pi-permission-system](https://github.com/gotgenes/pi-packages/tree/main/packages/pi-permission-system)
後，`pi/permissions.ts` 會在其授權器鏈中註冊一個 `starbridge` 連結，
擁有者透過在其
`config.json` 中設定 `"authorizerChain": ["starbridge"]` 來啟用它（`starbridge config permissions on` 會提議加入它）。當規則說 `ask` 時，該連結會像 Claude Code 的掛鉤一樣執行 `starbridge hook permission
--agent pi`，並傳回裝置的允許（僅限本次
呼叫：該鏈從不允許連結為工作階段允許）或拒絕及
其訊息。同時，Pi 會顯示「在此回答」，這會從裝置那裡取回提示，
並開啟 pi-permission-system 自己的對話方塊。當 `starbridge config permissions` 關閉、
機器未配對或伺服器不回答時，以及 570 秒後，該連結會立即
遵從該對話方塊。

## opencode

`opencode/starbridge.ts` 是與 opencode 外掛相同的應答迴圈。
`starbridge setup` 會將它，連同它從 `hooks/` 匯入的檔案與規則，複製到
`~/.config/opencode/starbridge/`，並讓
`~/.config/opencode/plugins/starbridge.ts` 指向它。

opencode 不給指令工作階段 id，所以外掛的 `shell.env` 鉤子會為它們設定
`STARBRIDGE_OPENCODE_SESSION` 與該工作階段的標題，並啟動該工作階段的迴圈。每個
應答透過 `promptAsync` 送入：閒置的工作階段會開始一輪，忙碌的工作階段會在下一步
接收它。`opencode run` 沒有迴圈，所以 `starbridge ask` 會叫那裡的 agent 執行
`starbridge wait`。規則透過 `experimental.chat.system.transform` 寫入
系統提示。

每個 `permission.asked` 事件都會執行 `starbridge hook permission --agent
opencode`，當 `starbridge config permissions` 關閉時它會立刻結束。
同時 opencode 的對話框保持顯示：裝置的應答透過 opencode 的回覆路由送出，
鍵盤上的應答會停止 CLI，從而在裝置上確認該提示。
裝置能看到 Allow 核准的內容：`bash` 的指令；`edit` 的路徑與 diff，這是其
edit、write 與 apply_patch 工具所詢問的，還包括移動會把檔案帶到何處以及
補丁會刪除哪些檔案；來自其 shell 的 `external_directory` 詢問的目錄與指令。
其他權限會顯示其模式與中介資料。MCP 工具呼叫只顯示工具名稱，因為 opencode 的
權限事件不帶其任何引數。超過 8,000 個字元時，CLI 會截斷最長的字串並說明
這一點。

每個 `question.asked` 事件（opencode 的 `question` 工具的一次呼叫）都會執行
`starbridge hook question --agent opencode`，它會將每個問題連同其標籤作為選項
張貼，並在所有答案都到齊後印出這些答案。外掛透過
`POST /question/{id}/reply` 送出它們。鍵盤上的應答或 Esc
（`question.replied` 或 `question.rejected`）會停止 CLI，從而在裝置上確認這些
問題。

## 開發

```bash
pnpm --filter @starbridge/mod test
```

`e2e/run.ts` 透過 tmux 中的真實 Claude Code 工作階段驅動每個案例：閒置、回合中、`/clear` 和 `/resume`、熱重載、伺服器中斷，以及同時兩個工作階段。它針對隨機埠（`--local`）上的伺服器應用程式執行，或針對帶有測試裝置（`e2e/device.ts`）和本機 CLI 設定的真實伺服器執行。它需要 `claude`、`tmux` 和 `starbridge` 在 `PATH` 上，並為每個案例印出一行計時。使用 `--agent` 時，它會在整個執行過程中執行 `starbridge agent`，最後一行檢查每個工作階段是否透過它應答。

測試針對 CLI、真實代理和真實伺服器執行兩條路徑，`@starbridge/server/test-support` 會在隨機埠上啟動它們。`hooks/agent.ts` 是代理路徑，`hooks/poller.ts` 是 CLI 路徑，`hooks/switch.ts` 選擇其中一個，`hooks/register.ts` 將它們連接到引擎。CI 對所有檔案進行型別檢查，但 `register.ts` 除外。要對 `register.ts` 進行型別檢查，請載入一次 mod，以便引擎將其型別寫入 `.claude-plugin/types/`，然後執行 `tsc -p tsconfig.engine.json`。

## Install

```
claude plugin marketplace add T0mSIlver/starbridge
claude plugin install starbridge-mod
```

## Original README

# Starbridge mod for Claude Code

When the owner answers a decision, this mod submits the answer into the Claude
Code session that asked, as the line `starbridge wait` prints:

```
Answer to d_Xk3… (Merge #12 now?): Merge
```

It works in the terminal, the desktop app's Code tab and Remote Control.

## Install

Install it from the Starbridge marketplace, beside the `starbridge` plugin
(`plugin/README.md`):

```bash
claude plugin install starbridge-mod@starbridge --scope user
```

A Claude Code build or organization that refuses mods skips this plugin and
keeps the skill; answers then wait until a session runs `starbridge answers`.
To try a checkout in one session: `claude --plugin-dir mod`.

## How it works

The mod holds no keys. Each interactive session picks one of two paths, and
switches when the agent starts or stops.

### Through the agent

When the machine's agent (`starbridge agent`, PROTOCOL.md, "Local agent API")
answers on its unix socket, each session talks to it with `$.http.fetch`:

- `POST /v1/sessions/<id>/hello` once per session id, with the session's
  working directory.
- `GET /v1/sessions/<id>/events?wait=25` back to back, under the 30 s limit on
  calls from a mod. The agent hands the session only the answers to the
  decisions it asked.
- The mod submits each event's line, then confirms it with
  `POST /v1/sessions/<id>/ack`; the agent hands an unconfirmed event over
  again. It skips event types it does not know.
- `POST /v1/sessions/<id>/bye` when the session ends.

The socket is `$STARBRIDGE_AGENT_SOCKET`, else
`$XDG_RUNTIME_DIR/starbridge/agent.sock` for the default config directory,
else `agent.sock` in the config directory, as the CLI works it out; on Windows
(`OS=Windows_NT`), the port file `agent.port` in the config directory, which
names the loopback port and the token every call carries (PROTOCOL.md). A 426 (the
agent speaks another API revision) or a call that cannot connect sends the
session to the CLI path.

### Through the CLI

With no agent, or with `STARBRIDGE_NO_AGENT=1`, the mod runs the CLI and checks
for the agent every 30 s.

- Every interactive session runs the mod, but only one per machine polls: the
  session holding the lease in `~/.config/starbridge/mod-poller.json`. It runs
  `starbridge answers --session <id> --wait 25` back to back, which stays
  under the 30 s limit on calls from a mod.
- The other sessions watch `state.json`. When it changes, they run `starbridge
  answers --session <id>`, which reads local state only.
- `answers` returns only answers to decisions that session asked and that no
  `wait` has printed. The mod submits each line, then confirms it with
  `starbridge answers --session <id> --ack <ack>`; the CLI hands an
  unconfirmed line over again.
- A session that does not poll also runs `answers` every 30 s when
  `state.json` has not changed, in case a change went unseen.
- When a session ends, it gives up the lease and another session starts
  polling.

On both paths, after a `/clear` or a `/resume` the mod uses the new session
id; a line that arrives during a `/clear` waits, unconfirmed, for the old
session. After an error the mod waits 2 s, then twice as long after each
further error, up to a minute, and shows the error in the status line until a
call succeeds.

## Pi

`pi/starbridge.ts` is the same answer loop as a Pi extension. It ships in the
repository's Pi package with the `starbridge` skill. `starbridge setup` installs it at the
release tag of the CLI it runs, `v` and what `starbridge --version` prints:

```bash
pi install git:github.com/T0mSIlver/starbridge@v<version>
```

In an interactive or RPC Pi session it submits each answer as a user message,
which starts a turn when Pi is idle and runs after the current one when it is
busy. It also adds the plugin's rule (`plugin/hooks/rule.md`) to Pi's system
prompt. `pi -p` gets no loop, so `starbridge ask` tells the agent there to
`starbridge wait`.

With [pi-permission-system](https://github.com/gotgenes/pi-packages/tree/main/packages/pi-permission-system)
installed, `pi/permissions.ts` registers a `starbridge` link in its authorizer
chain, which the owner turns on with `"authorizerChain": ["starbridge"]` in its
`config.json` (`starbridge config permissions on` offers to add it). When a rule says `ask`, the link runs `starbridge hook permission
--agent pi`, as Claude Code's hook does, and returns the devices' allow (this
call only: the chain never lets a link allow for the session) or deny with
their message. Meanwhile Pi shows "Answer here", which takes the prompt back
from the devices and opens pi-permission-system's own dialog. The link defers
to that dialog at once while `starbridge config permissions` is off, the
machine is not paired or the server does not answer, and after 570 s.

## opencode

`opencode/starbridge.ts` is the same answer loop as an opencode plugin.
`starbridge setup` copies it, with the files it imports from `hooks/` and the
rule, into `~/.config/opencode/starbridge/`, and points
`~/.config/opencode/plugins/starbridge.ts` at it.

opencode gives commands no session id, so the plugin's `shell.env` hook sets
`STARBRIDGE_OPENCODE_SESSION` and the session's title for them, and starts that
session's loop. Each answer goes in with `promptAsync`: an idle session starts
a turn, a busy one takes it at its next step. `opencode run` gets no loop, so
`starbridge ask` tells the agent there to `starbridge wait`. The rule goes into
the system prompt through `experimental.chat.system.transform`.

Each `permission.asked` event runs `starbridge hook permission --agent
opencode`, which exits at once while `starbridge config permissions` is off.
opencode's dialog stays up meanwhile: the devices' answer is sent through
opencode's reply route, and an answer at the keyboard stops the CLI, which
settles the prompt on the devices.
The devices see what an Allow approves: the command for `bash`; the paths and
the diff for `edit`, which its edit, write and apply_patch tools ask, with
where a move takes a file and which files a patch deletes; the directories
and the command for an `external_directory` ask from its shell. Other
permissions show their patterns and metadata. An MCP tool call shows only the
tool's name, since opencode's permission event carries none of its arguments.
Past 8,000 characters the CLI cuts the longest string and says so.

Each `question.asked` event (a call of opencode's `question` tool) runs
`starbridge hook question --agent opencode`, which posts each question with its
labels as options and prints the answers once all are in. The plugin sends them
through `POST /question/{id}/reply`. An answer or Esc at the keyboard
(`question.replied` or `question.rejected`) stops the CLI, which settles the
questions on the devices.

## Develop

```bash
pnpm --filter @starbridge/mod test
```

`e2e/run.ts` drives real Claude Code sessions in tmux through each case:
idle, mid-turn, `/clear` and `/resume`, a hot reload, a server outage, and two
sessions at once. It runs against the server app on a
random port (`--local`), or against a real server with a test device
(`e2e/device.ts`) and this machine's CLI config. It needs `claude`, `tmux` and
`starbridge` on `PATH`, and prints one row of timings per case. With
`--agent` it runs `starbridge agent` for the whole run, and a last row checks
that every session answered through it.

The tests run both paths against the CLI, a real agent and the real server,
which `@starbridge/server/test-support` starts on a random port.
`hooks/agent.ts` is the agent path, `hooks/poller.ts` the CLI path,
`hooks/switch.ts` picks one, and `hooks/register.ts` connects them to the
engine. CI type-checks all but `register.ts`. To type-check `register.ts`,
load the mod once so the engine writes its types to `.claude-plugin/types/`,
then run `tsc -p tsconfig.engine.json`.
