@vanillagreen/pi-claude-bridge 2.0.0 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,18 +3,20 @@
3
3
  Works with OAuth subscription, no API key, no errors.
4
4
 
5
5
  ![Claude bridge demo response](https://raw.githubusercontent.com/vanillagreencom/vstack/main/pi-extensions/pi-claude-bridge/assets/bridge-demo.png)
6
- ![Claude Bridge settings panel](https://raw.githubusercontent.com/vanillagreencom/vstack/main/pi-extensions/pi-claude-bridge/assets/settings-panel.png)
6
+ ![Pi Claude settings panel](https://raw.githubusercontent.com/vanillagreencom/vstack/main/pi-extensions/pi-claude-bridge/assets/settings-panel.png)
7
7
 
8
- Run Claude Code as a Pi provider. Adds `claude-bridge/*` models to `/model` while keeping Pi's tools and TUI.
8
+ Run Claude Code as the `pi-claude` Pi provider while keeping Pi's tools and TUI.
9
9
 
10
10
  Forked from [`elidickinson/pi-claude-bridge`](https://github.com/elidickinson/pi-claude-bridge). This fork removes the AskClaude tool and adds opt-in forwarding for Pi prompt context.
11
11
 
12
12
  ## Highlights
13
13
 
14
- - `claude-bridge/claude-fable-5`, Opus 5, Opus 4.8, Opus 4.7, Opus 4.6, Sonnet 5, Sonnet 4.6, and Haiku in `/model`. `/model opus` selects Opus 5; older Opus releases stay selectable by full ID.
14
+ - `pi-claude/claude-fable-5`, Opus 5, Opus 4.8, Opus 4.7, Opus 4.6, Sonnet 5, Sonnet 4.6, and Haiku in `/model`. `/model opus` selects Opus 5; older Opus releases stay selectable by full ID.
15
15
  - Pi tool calls run on Pi; Claude Code handles reasoning.
16
16
  - Tool-use turns block until Pi-delivered tool results reach Claude Code, including persistent subagent panes.
17
- - Session continuity across normal turns, `/compact`, tree navigation, and abort recovery.
17
+ - Parallel conversations and subagents keep independent request, abort, tool-loop, and Claude-session state.
18
+ - Session continuity across normal turns, `/compact`, tree navigation, abort recovery, and account-profile changes.
19
+ - Optional companion integration for usage-aware subscription account rotation without copying the bridge engine.
18
20
  - Thinking-level forwarding with summarized Opus thinking display.
19
21
  - Optional Claude effort overrides (`xhigh` → `max` for Opus 4.8).
20
22
  - MCP isolation and Claude cloud-MCP suppression to keep tokens lean.
@@ -23,9 +25,7 @@ Forked from [`elidickinson/pi-claude-bridge`](https://github.com/elidickinson/pi
23
25
 
24
26
  ## Install
25
27
 
26
- Requires pi ≥ 0.81 (bridge 2.x registers through pi's native provider API, so pi shows the
27
- Claude models only while a Claude account is actually connected). On older pi, install
28
- `@vanillagreen/pi-claude-bridge@1.x` instead.
28
+ Requires pi ≥ 0.81 (bridge 2.x registers through pi's native provider API, so pi shows the Claude models only while a Claude account is actually connected). On older pi, install `@vanillagreen/pi-claude-bridge@1.x` instead.
29
29
 
30
30
  Via [npm](https://www.npmjs.com/package/@vanillagreen/pi-claude-bridge):
31
31
 
@@ -44,170 +44,75 @@ Restart Pi after installation.
44
44
 
45
45
  ## Prompt context
46
46
 
47
- Default behavior matches upstream: append `AGENTS.md` plus Pi's skills block to Claude Code's `claude_code` preset prompt.
47
+ Default behavior matches upstream: append your context file plus Pi's skills block to Claude Code's `claude_code` preset prompt. The context file is the nearest one found walking up from the working directory, falling back to `<PI_CODING_AGENT_DIR>/AGENTS.md`. Within each directory the bridge follows Pi's own order — `AGENTS.override.md`, then `AGENTS.md`, then `AGENTS.MD` — so an `AGENTS.override.md` replaces `AGENTS.md` in the same directory, exactly as it does for Pi itself. `CLAUDE.md` is deliberately not forwarded: Claude Code already loads it natively, so forwarding it would apply the same context twice.
48
48
 
49
49
  Extra Pi context is off by default. Enable per item in the extension manager when you want Claude Code to see prompt blocks that other Pi extensions add to your session. Forwarded blocks are wrapped in explicit XML tags so Pi 0.75+ project-context boundaries do not bleed into adjacent sections.
50
50
 
51
51
  ## Settings
52
52
 
53
- Open `/extensions:settings`; settings appear under the **Claude Bridge** tab.
53
+ Open `/extensions:settings`; settings appear under the **Pi Claude** tab. Project settings in `.pi/settings.json` apply only after Pi marks the workspace trusted; before trust, vstack Pi extensions read user/global settings only. The bridge also reads `claude-bridge.json` (`~/.pi/agent/claude-bridge.json`, and `.pi/claude-bridge.json` in a trusted project). Settings the bridge takes from one of those files are shown with the file that supplies them, so the editor reports the value the bridge resolves rather than the default. Changing the setting in the editor writes Pi settings, which take precedence over `claude-bridge.json`.
54
54
 
55
- Project settings in `.pi/settings.json` apply only after Pi marks the workspace trusted; before trust, vstack Pi extensions read user/global settings only.
55
+ | Group | Setting | What it does |
56
+ | --- | --- | --- |
57
+ | General | Enable Pi Claude provider | Register `pi-claude/*` models. Reload required. |
58
+ | Base prompt | Forward AGENTS.md + skills | Append the nearest context file (`AGENTS.override.md`, `AGENTS.md`, or `AGENTS.MD`) and Pi's skills block. |
59
+ | Pi prompt context | Forward APPEND_SYSTEM.md | Forward project/global `APPEND_SYSTEM.md` content. |
60
+ | Pi prompt hooks | Forward project agents hook | Forward `pi-agents-tmux` Project Agents/Subagents list. |
61
+ | Pi prompt hooks | Forward task panel hook | Forward `pi-task-panel` workflow reminders. |
62
+ | Pi prompt hooks | Forward caveman hook | Forward `pi-caveman` response-style directives. |
63
+ | Claude Code | Strict MCP config | Block filesystem MCP auto-loads; Pi owns tools. |
64
+ | Claude Code | Fast mode | Enable Claude Code fast mode for bridge requests when the selected model and account support it. |
65
+ | Claude Code | Force Claude effort | Override Pi's thinking-level mapping for every Pi Claude request. `none` keeps Pi's selected level; `max` sends Claude Code `--effort max`. |
66
+ | Claude Code | Model effort overrides | JSON object mapping model IDs to Claude Code efforts, e.g. `{"claude-opus-4-8":"max"}`. Per-model entries beat the global force setting. |
67
+ | Claude Code | Claude executable path | Explicit `claude` binary path; empty auto-detects. |
56
68
 
57
- ### General
58
-
59
- | Setting | What it does |
60
- | --- | --- |
61
- | Enable Claude bridge provider | Register `claude-bridge/*` models. Reload required. |
62
-
63
- ### Base prompt
64
-
65
- | Setting | What it does |
66
- | --- | --- |
67
- | Forward AGENTS.md + skills | Append AGENTS.md and Pi's skills block. |
68
-
69
- ### Pi prompt context
70
-
71
- | Setting | What it does |
72
- | --- | --- |
73
- | Forward APPEND_SYSTEM.md | Forward project/global `APPEND_SYSTEM.md` content. |
74
-
75
- ### Pi prompt hooks
76
-
77
- | Setting | What it does |
78
- | --- | --- |
79
- | Forward project agents hook | Forward `pi-agents-tmux` Project Agents/Subagents list. |
80
- | Forward task panel hook | Forward `pi-task-panel` workflow reminders. |
81
- | Forward caveman hook | Forward `pi-caveman` response-style directives. |
82
-
83
- ### Claude Code
84
-
85
- | Setting | What it does |
86
- | --- | --- |
87
- | Strict MCP config | Block filesystem MCP auto-loads; Pi owns tools. |
88
- | Allow extra usage helper | Let the bridge launch Claude Code's `/extra-usage` flow when extra usage is required. Billing/admin approval still happens in Claude's browser page. |
89
- | Fast mode | Enable Claude Code fast mode for bridge requests when the selected model supports it. |
90
- | Force Claude effort | Override Pi's thinking-level mapping for every claude-bridge request. `none` keeps Pi's selected level; `max` sends Claude Code `--effort max`. |
91
- | Model effort overrides | JSON object mapping model IDs to Claude Code efforts, e.g. `{"claude-opus-4-8":"max"}`. Per-model entries beat the global force setting. |
92
- | Claude executable path | Explicit `claude` binary path; empty auto-detects. |
93
-
94
- Pi 0.80.6 and newer expose native `max` thinking. Fable 5, Opus 5, and Sonnet 5 bridge metadata forward both `xhigh` and `max`; the generic bridge fallback also maps `max` directly. **Force Claude effort** and **Model effort overrides** remain available when one bridge model needs a different fixed effort. For example, to force only Opus 4.8 to `max`:
95
-
96
- ```json
97
- {"claude-opus-4-8":"max"}
98
- ```
99
-
100
- Keys may be bare model IDs (`claude-opus-4-8`), `claude-bridge/<id>`, or `*` for all bridge models. Values are `low`, `medium`, `high`, `xhigh`, or `max`.
69
+ Pi 0.80.6 and newer expose native `max` thinking. Fable 5, Opus 5, and Sonnet 5 bridge metadata forward both `xhigh` and `max`; the generic bridge fallback also maps `max` directly. **Force Claude effort** and **Model effort overrides** remain available when one bridge model needs a different fixed effort — for example `{"claude-opus-4-8":"max"}` to force only Opus 4.8. Keys may be bare model IDs (`claude-opus-4-8`), `pi-claude/<id>`, or `*` for all bridge models. Values are `low`, `medium`, `high`, `xhigh`, or `max`.
101
70
 
102
71
  ### Connectors
103
72
 
104
73
  Turn this on and the model can use whatever your Claude account already has connected — the same connectors you use in the Claude app, now inside Pi:
105
74
 
106
- - **Gmail** search mail, read threads and messages.
107
- - **Google Calendar** — check calendars and events.
108
- - **Google Drive** — find and read files.
109
- - **Slack** — search and read channels, threads, canvases, and people.
110
- - **Jira and Confluence** — search and read issues, pages, and spaces.
111
- - Anything else on the account (Figma, org-specific connectors) works the same way — nothing to configure per connector.
75
+ **Gmail** (search mail, read threads and messages), **Google Calendar** (check calendars and events), **Google Drive** (find and read files), **Slack** (search and read channels, threads, canvases, and people), **Jira and Confluence** (search and read issues, pages, and spaces). Anything else on the account (Figma, org-specific connectors) works the same way — nothing to configure per connector.
112
76
 
113
- Sessions are **read-only** by default: the model can look things up, but cannot send, post, or change anything unless you explicitly turn writes on below.
77
+ Sessions are **read-only** by default: the model can look things up, but cannot send, post, or change anything unless you explicitly turn writes on. Search/read/fetch/list tools stay available while mutating tools are denied, fail-closed across every connector on the account.
114
78
 
115
- Connector tools run inside Claude Code rather than in Pi, so Pi shows the model's answer but no tool card for the lookup itself. (Before this was handled, Pi showed a card claiming `Tool not found` for calls that had actually succeeded so an answer built on real data looked invented.)
79
+ Connector tools run inside Claude Code rather than in Pi, so Pi shows the model's answer but no tool card for the lookup itself. Each lookup is still recorded in the session file as a `claude-bridge-connector-call` entry the tool name, whether it succeeded, and how many bytes came back, never the contents. So "did it really look that up?" has an answer even though nothing is drawn in the transcript.
116
80
 
117
- Each of those lookups is still recorded in the session file as a `claude-bridge-connector-call` entry the tool name, whether it succeeded, and how many bytes came back, never the contents. So "did it really look that up?" has an answer even though nothing is drawn in the transcript.
81
+ `/pi-claude:connectors` lists the Claude account's installed claude.ai connectors by asking the account, not the model, so the answer is complete by construction.
118
82
 
119
- That entry needs a pi session to be written into. A host that embeds the bridge **without** one loading it through a bare resource loader, so `extensionApi` is undefined gets no record at all, and nothing in the bridge can tell. Such a host can install its own destination:
120
-
121
- ```ts
122
- import { setConnectorCallAuditSink } from "@vanillagreen/pi-claude-bridge";
123
-
124
- setConnectorCallAuditSink((record) => myOwnAuditTrail(record)); // pass undefined to clear
125
- ```
126
-
127
- The sink **adds** a destination; it never replaces the session entry. A session-backed host that installs one gets both, so turning it on can never cost you the record you already had. Same payload-free shape as the entry (`name`, `toolUseId`, `outcome`, and where known `byteSize` / `childSessionId` / `reason`), and the same never-fails-a-turn rule: a sink that throws is caught and dropped. It is process-global, like the bridge's other host handles, so a host running several conversations in one process must route by `childSessionId` itself.
128
-
129
- Extension-manager settings use flat package-scoped keys:
130
-
131
- ```json
132
- {
133
- "vstack": {
134
- "extensionManager": {
135
- "config": {
136
- "@vanillagreen/pi-claude-bridge": {
137
- "enableConnectors": true,
138
- "connectorWriteMode": "deny"
139
- }
140
- }
141
- }
142
- }
143
- }
144
- ```
145
-
146
- Legacy `.pi/claude-bridge.json` configuration keeps these options nested under `provider`. Environment variables work with either format. Connectors remain off by default so Pi owns tool execution.
83
+ Extension-manager settings use flat package-scoped keys under `vstack.extensionManager.config["@vanillagreen/pi-claude-bridge"]` in `settings.json`. Legacy `claude-bridge.json` configuration nests these options under `provider` (prompt-context flags under `promptContext`); the flat keys are accepted there too. Environment variables work with either format. Connectors remain off by default so Pi owns tool execution.
147
84
 
148
85
  | Extension-manager key | Env var | Values | Default | What it does |
149
86
  | --- | --- | --- | --- | --- |
150
87
  | `enableConnectors` | `CLAUDE_BRIDGE_ENABLE_CONNECTORS` | `true`/`false` | off | Expose the account's connectors to the model (env OR config enables). |
151
88
  | `connectorWriteMode` | `CLAUDE_BRIDGE_CONNECTOR_WRITE` | `deny`/`allow` | `deny` | When connectors are enabled, whether their WRITE tools are exposed. |
152
89
 
153
- For both, the env var wins over config. `connectorWriteMode` only matters when connectors are enabled. Any value other than exactly `allow` is treated as `deny` (fail-closed).
154
-
155
- With `connectorWriteMode: "deny"` (the default), connector sessions are **read-only**: search/read/fetch/list tools stay available, while mutating tools are denied twice — the known write tools are removed from the model's tool list, and a runtime hook blocks any connector tool classified as a write at call time, regardless of permission mode. Classification is fail-closed across every connector on the account: a connector tool counts as a write unless its name begins with a known read verb, so not-yet-known write tools and future connectors are denied by the same rule.
156
-
157
- Set `allow` only for a one-shot write-executor session that has already obtained explicit user approval — never for an interactive connector chat.
90
+ For both, the env var wins over config. `connectorWriteMode` only matters when connectors are enabled. Any value other than exactly `allow` is treated as `deny` (fail-closed); set `allow` only for a one-shot write-executor session that has already obtained explicit user approval — never for an interactive connector chat.
158
91
 
159
- > **`allow` is per-process, not global.** A host's approved-write executor should set `CLAUDE_BRIDGE_CONNECTOR_WRITE=allow` in the **child env of a dedicated one-shot process** that runs the single approved write and exits. Do not set `connectorWriteMode: "allow"` in persistent `settings.json` (or `allow` process-globally) for a shared/long-lived sidecar that would make every connector session in that process write-capable, defeating the approval gate.
92
+ > **User scope + env only.** These two keys are resolved from user-scope configuration (`<PI_CODING_AGENT_DIR>/settings.json`, `<PI_CODING_AGENT_DIR>/claude-bridge.json`) and the env vars — never from a project's checked-in `.pi/settings.json` or `.pi/claude-bridge.json`, even when the project is trusted for ordinary options. Connectors expose live account data (mail, calendar, files), so a repo you clone must not be able to switch them on or un-gate their writes just by being the cwd.
160
93
 
161
- ### Isolated mode (embedding hosts)
162
-
163
- Host apps that embed the bridge and own every config dir explicitly can set `CLAUDE_BRIDGE_ISOLATED=1` in the bridge process env. Isolated mode disables every cwd/home discovery fallback so nothing outside the host-owned dirs is read:
164
-
165
- - no `AGENTS.md` discovery, including cwd ancestors and the shared `<PI_CODING_AGENT_DIR>/AGENTS.md`;
166
- - no extension-manager overlay from `<PI_CODING_AGENT_DIR>/settings.json`;
167
- - no project `.pi/settings.json` / `.pi/claude-bridge.json` reads (even for trusted projects);
168
- - no project `.pi/APPEND_SYSTEM.md`;
169
- - no `$PATH` search for the `claude` executable — the host either pins `pathToClaudeCodeExecutable` or gets the Claude Agent SDK's bundled default.
170
-
171
- Bridge settings come only from the authoritative `<PI_CODING_AGENT_DIR>/claude-bridge.json`; logs still resolve under `PI_CODING_AGENT_DIR`. Normal Pi CLI usage (flag unset) is unchanged.
94
+ Connectors mode also makes the child Claude Code resolve its filesystem settings (with them off, the child runs fully isolated). Only **user-scope** settings are loaded; project/local scope (a checkout's `.claude/settings.json`) is deliberately excluded. Setting `provider.settingSources` in bridge config still overrides this verbatim, but listing `"project"`/`"local"` there reopens that surface — only do it for checkouts you trust.
172
95
 
173
96
  ### Fable 5 and Opus 5 caveat
174
97
 
175
- The bridge registers `claude-bridge/claude-fable-5`, `claude-bridge/claude-opus-5`, `claude-bridge/claude-sonnet-5`, and `claude-bridge/claude-opus-4-8` even when Pi's Anthropic model registry has not shipped those entries yet. Fable 5 and Opus 5 both run classifiers that can decline a turn, so for each of them the bridge asks Claude Code to use Opus 4.8 as the availability fallback and preserves Claude Code's content-safety fallback events so Pi labels rerouted turns as Opus 4.8. Content-safety fallback still depends on Claude Code's own Fable 5 support; use Claude Code 2.1.170 or newer, and set `ANTHROPIC_DEFAULT_FABLE_MODEL` / `ANTHROPIC_DEFAULT_OPUS_MODEL` yourself when routing provider-specific model IDs through Bedrock, Vertex, or Foundry.
176
-
177
- ## Connector inventory
98
+ The bridge registers `pi-claude/claude-fable-5`, `pi-claude/claude-opus-5`, `pi-claude/claude-sonnet-5`, and `pi-claude/claude-opus-4-8` even when Pi's Anthropic model registry has not shipped those entries yet. Fable 5 and Opus 5 both run classifiers that can decline a turn, so for each of them the bridge asks Claude Code to use Opus 4.8 as the availability fallback and preserves Claude Code's content-safety fallback events so Pi labels rerouted turns as Opus 4.8. Content-safety fallback still depends on Claude Code's own Fable 5 support; use Claude Code 2.1.170 or newer, and set `ANTHROPIC_DEFAULT_FABLE_MODEL` / `ANTHROPIC_DEFAULT_OPUS_MODEL` yourself when routing provider-specific model IDs through Bedrock, Vertex, or Foundry.
178
99
 
179
- `/claude-bridge:connectors` lists the Claude account's installed claude.ai connectors by asking the account, not the model, so the answer is complete by construction.
100
+ ## Multiple subscription profiles
180
101
 
181
- `listAccountConnectors()` is the programmatic form for host apps. Import it from the package's `./connector-inventory` entry point:
102
+ An optional companion extension can provide account profiles through the bridge's versioned account-router integration. For each fresh Claude request, the bridge launches the Agent SDK subprocess with the selected profile's `CLAUDE_CONFIG_DIR`; Claude session files, connector inventory, and resume IDs remain account-scoped. When an account reports a rejected rate limit (or another classified pre-output failure), the bridge rebuilds the Claude session from Pi history under the next profile and retries the prompt — but never once text, thinking, a Pi tool call, or a child-executed connector call has begun, so a request cannot duplicate tool side effects on another account. The companion owns profile metadata, utilization ranking, and cooldown persistence; the bridge remains the SDK/stream/session engine.
182
103
 
183
- ```ts
184
- import { listAccountConnectors, resolveClaudeOAuth } from "@vanillagreen/pi-claude-bridge/connector-inventory";
185
- ```
186
-
187
- The same functions are re-exported from the package root for consuming apps whose vendored `package.json` uses a closed exports map (`{".": "./bundle/index.js"}`), which blocks every subpath:
188
-
189
- ```ts
190
- import { listAccountConnectors } from "@vanillagreen/pi-claude-bridge";
191
- ```
104
+ ## Account usage and rate limits
192
105
 
193
- It returns a discriminated result: on success `{ ok: true, complete: true, connectors }`, and on any transport or protocol failure `{ ok: false, reason }`. An account with no connectors is a successful empty list; a failure is never reported as an empty inventory. Credentials resolve from `CLAUDE_CONFIG_DIR` before `$HOME`, so a host running one sidecar per Claude account reads the right account.
106
+ Extra Usage is owned by Claude's account settings. The bridge neither changes that setting nor blocks Claude Code's native account behavior if the account has Extra Usage enabled on claude.ai, the child Claude Code uses it normally. If Claude rejects a request because the current allowance is exhausted, a managed account router treats it as a model-scoped limit and can try another account.
194
107
 
195
- ## Extra usage and rate limits
196
-
197
- Claude Code's `/extra-usage` local command works through the Claude Agent SDK. In Pi, use `/claude-bridge:extra` to run that flow from claude-bridge. Persist automatic launch on extra-usage errors with **Allow extra usage helper** in `/extensions:settings`.
198
-
199
- When Claude Code reports a rate-limit reset time, the bridge shows one clear `[rate-limit]` warning with timezone context and avoids repeating the same error line. If `pi-qol` is installed, it can use the reset time to resume later.
200
-
201
- Allowed-warning rate-limit events are filtered before user notification. The bridge normalizes unambiguous numeric utilization (`0 < value < 1` as fractional, `1 < value <= 100` as percent), suppresses low or unit-ambiguous values such as exact `1`, and only shows a neutral warning at 80%+ instead of claiming an unverified `% used` value. Check Claude Code `/usage` for exact allowed-warning utilization.
108
+ When Claude Code reports a rate-limit reset time, the bridge shows one clear `[rate-limit]` warning with timezone context and avoids repeating the same error line. If `pi-qol` is installed, it can use the reset time to resume later. Allowed-warning rate-limit events are filtered before user notification: the bridge shows a neutral warning at 80%+ utilization instead of claiming an unverified `% used` value. Check Claude Code `/usage` for exact allowed-warning utilization.
202
109
 
203
110
  If Claude Code accepts a turn but produces no visible output, the bridge returns a retryable assistant error with a backoff hint instead of leaving Pi stuck waiting. Tune the first-output timeout with `CLAUDE_BRIDGE_STREAM_IDLE_TIMEOUT` (bare numbers are seconds; suffixes `ms`, `s`, and `m` are accepted). Default: `90s`; set `0` to disable.
204
111
 
205
112
  ## Debugging
206
113
 
207
- Set `CLAUDE_BRIDGE_DEBUG=1` to write bridge logs to `<agent dir>/claude-bridge.log` and per-query Claude Code CLI logs under `<agent dir>/cc-cli-logs/`, where `<agent dir>` is `PI_CODING_AGENT_DIR` when set, else `~/.pi/agent`. Override the exact files with `CLAUDE_BRIDGE_DEBUG_PATH` / `CLAUDE_BRIDGE_DIAG_PATH`.
208
-
209
- Tool-result integrity problems are surfaced even when debug logging is off. Pi shows an error notification, writes a diagnostic file to `<agent dir>/claude-bridge-diag.log`, and appends a `claude-bridge-integrity` custom entry to the pi session transcript (compact metadata only — never tool output), so lost or mismatched tool output stays analyzable from the session file alone.
114
+ Set `CLAUDE_BRIDGE_DEBUG=1` to write bridge logs to `<agent dir>/claude-bridge.log` and per-query Claude Code CLI logs under `<agent dir>/cc-cli-logs/`, where `<agent dir>` is `PI_CODING_AGENT_DIR` when set, else `~/.pi/agent`. Override the exact files with `CLAUDE_BRIDGE_DEBUG_PATH` / `CLAUDE_BRIDGE_DIAG_PATH`. Startup failures include the resolved Claude executable and working directory, which makes missing binaries and wrong launch directories easier to fix.
210
115
 
211
- Startup failures include the resolved Claude executable and working directory, which makes missing binaries and wrong launch directories easier to fix.
116
+ Tool-result integrity problems always surface as a Pi error notification plus a `claude-bridge-integrity` custom entry in the pi session transcript (compact metadata only — never tool output), so lost or mismatched tool output stays analyzable from the session file alone. The on-disk diagnostic file (`<agent dir>/claude-bridge-diag.log`) is written only with `CLAUDE_BRIDGE_DEBUG=1` — like every other bridge disk log, it is opt-in.
212
117
 
213
- Contributor-facing stream, tool-result, and startup diagnostics are documented in [`DEVELOPMENT.md`](./DEVELOPMENT.md).
118
+ Embedding hosts, contributor-facing stream/tool-result/startup diagnostics, and the host-side connector APIs are documented in [`DEVELOPMENT.md`](./DEVELOPMENT.md).
@@ -15,9 +15,12 @@ function connectorServerNamespace(connectorName) {
15
15
  function credentialCandidatePaths(env = process.env) {
16
16
  const roots = [];
17
17
  const configDir = env.CLAUDE_CONFIG_DIR?.trim();
18
- if (configDir) roots.push(configDir);
19
- const home = env.HOME?.trim();
20
- if (home) roots.push(`${home}/.claude`, home);
18
+ if (configDir) {
19
+ roots.push(configDir);
20
+ } else {
21
+ const home = env.HOME?.trim();
22
+ if (home) roots.push(`${home}/.claude`, home);
23
+ }
21
24
  const seen = /* @__PURE__ */ new Set();
22
25
  const paths = [];
23
26
  for (const root of roots) {