@thoth-agents/pi-claude-bridge
Pi extension that uses Claude Code (via Agent SDK) as a model provider and adds an AskClaude tool.
Package details
Install @thoth-agents/pi-claude-bridge from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@thoth-agents/pi-claude-bridge- Package
@thoth-agents/pi-claude-bridge- Version
0.4.0- Published
- Nov 4, 2026
- Downloads
- 1,254/mo · 135/wk
- Author
- eremesng
- License
- MIT
- Types
- extension
- Size
- 1.2 MB
- Dependencies
- 1 dependency · 4 peers
Pi manifest JSON
{
"extensions": [
"./dist/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@thoth-agents/pi-claude-bridge
Pi extension that integrates Claude Code via the Agent SDK. Originally based on claude-agent-sdk-pi by Prateek Sunal.
This is a vendored, Thoth-maintained copy of elidickinson/pi-claude-bridge, synced through upstream 0b41f78 (0.9.3 plus unreleased fixes), from the previous df964a9 base; the local package version is independent.
- Provider — Use Opus/Sonnet/Haiku as models in pi, with all tool calls flowing through pi's TUI
- AskClaude tool — Delegate tasks or questions to Claude Code when using another provider
FYI: Anthropic announced and then unannounced a change to how you would be billed for tools that use the Agent SDK like this one. It currently uses your regular subscription quota just like Claude Code.
Install
- Install the extension:
pi install npm:@thoth-agents/pi-claude-bridge - Log in to Claude Code with your Claude subscription: run
claudeand type/login. The bridge uses Claude Code's login, not pi's/login. - In pi, pick a
claude-bridge/...model with/model, not ananthropic/...model.
Install this bridge manually; the Thoth installer does not manage it.
Requires Pi >=1.5.0 and Node >=22.19.0.
Development Pi SDK/TUI dependencies are pinned to 1.5.0 in the root workspace lockfile.
Provider
Use /model to select any Claude model in pi-ai's catalog, e.g. claude-bridge/claude-fable-5-1, claude-bridge/claude-opus-5, or claude-bridge/claude-haiku-4-5.
Behind the scenes, pi's tools are bridged to Claude Code but everything works like normal in pi. Bash commands get Claude Code's 120-second default timeout at execution when no timeout is provided; the default is not saved in pi's history. Skills are forwarded to Claude Code's system prompt, and steering mid-turn reaches Claude at the next tool boundary.
Progress updates: Claude 5 progress updates between tool calls arrive from Anthropic as signed reasoning (thinking) blocks. The bridge recognizes the narration kind named in their signatures and shows them in Pi as normal assistant text, then replays them to Claude Code as the original signed blocks so this display change does not affect session reuse or caching. During streaming, it holds short blocks privately until it can classify them, so an update never appears as reasoning first; blocks whose signatures cannot be decoded, or that grow beyond 800 characters before closing, stay reasoning. The nonstreaming fallback classifies completed blocks without a length limit. Switching between claude-bridge models keeps the signed replay. Provider adapters that strip foreign signatures, such as Pi's own Anthropic or OpenAI providers, send these updates to their models as plain text. This ports upstream PR #212 (issue #211), not yet merged upstream.
Orca terminals: When ORCA_PANE_KEY or ORCA_TERMINAL_HANDLE is non-empty, native claude / claude.exe launches (provider, summaries, AskClaude and quota) use a neutral cc-bridge-runtime sibling with the original extension. This prevents Orca from mistaking the bridge child for the foreground agent. The bridge reuses an alias only when its bigint file identity matches the current executable; otherwise it replaces it atomically with a hardlink. It never copies the executable. If hardlinking or replacement fails, it launches the original unchanged. Resolution is cached until the Pi process restarts. Summary and quota calls keep the SDK's built-in launcher, setting only pathToClaudeCodeExecutable to the alias of the configured or SDK-default native binary; native stderr draining, callbacks and failure diagnostics are preserved. The provider and AskClaude spawn through the bridge's exit-observing QueryProcess, which waits for the child to close before it records or forks session state. AskClaude resolves its alias separately and keeps a bounded stderr tail for failure diagnostics. If default binary resolution fails, SDK options stay unchanged. Outside Orca, other executables (including Node/Bun), and bare/relative commands are unchanged; the bridge does not guess cwd/PATH resolution.
Dynamic appended instructions: On a resumed provider query, only added or changed projected append blocks (extension instructions, context files, or skills), plus removed block keys, are sent through query-scoped UserPromptSubmit hook context. The delimited update supersedes the same-keyed earlier blocks; unlisted blocks remain in effect. This includes restoration to a previous value and removal of all appended instructions. Unchanged content adds nothing. Blocks are line-start XML-like elements keyed by tag and optional path/name, comment regions (<!-- name:start -->…<!-- name:end -->), and ordinal free-text runs. The project_context wrapper and its immediate children are keyed independently, so changing one project_instructions file does not resend the others. Duplicate keys, unbalanced boundaries, or reordered retained blocks trigger a full replacement instead of a potentially misleading delta.
Claude Code 2.1.286 persists each hook additionalContext value over 10,000 JavaScript string-length units to a file and shows only a 2,000-character preview (exactly 10,000 stays inline; there is no limit override). The bridge caps each framed value at 9,000 .length units, splitting larger updates among several callbacks labeled Part i/n. Each callback is one-shot, including during steering. Effective state advances only after all parts return context. Skipped/failed delivery retries; partial delivery marks the baseline uncertain, forcing a full current replacement on the next query—even if it equals the old effective append. Only complete delivery clears uncertainty. Sessions written from Pi history start new recording epochs; resumes and forks from retained Claude Code records keep the recorded base and only the refreshes those records carry (see Resume across Pi restarts). Child and ephemeral sessions remain isolated. If hook registration fails, the query proceeds without refresh. Refresh applies between provider queries, not between tool turns or to AskClaude's separate native-tool prompt.
Cache preservation: Within a running process, systemPrompt still passes the current append with the claude_code preset and does not opt out of recording. A resumed or forked recording keeps its original recorded append instead. SDK 0.3.286 sdk.d.ts:2356–2382 documents that resumed queries use the recorded prompt verbatim. Installed CLI 2.1.286 embedded-source inspection at offsets 216482599 and 212825463 shows hook context becoming new trailing meta-user reminders, not rewritten earlier messages. Thus refresh leaves the recorded tools/system/history prefix byte-identical and adds only new-turn tail context within an active recording epoch. Offline regressions consume SDK user input and snapshot request content under a simulated CC recording boundary; they are not live cache-hit telemetry.
Resume across Pi restarts
Before each fresh query, the bridge compares per-message content digests of Pi's
history with its last recording. Matching history continues from the recorded Claude
Code records, including after a restart, /resume, or /reload, without re-importing
that history. Edits, rewinds and interruptions can retain records up to the last valid
cut before the first difference, then fork or write that prefix plus only the differing
remainder to a new Claude Code session id. Existing Claude Code transcripts are never
rewritten or deleted. Retaining the prefix can preserve a warm prompt cache, but does
not extend its TTL.
The bridge atomically saves per-Pi-session state under
~/.pi/agent/claude-bridge/sessions/ (honoring PI_CODING_AGENT_DIR) after the
Claude Code child exits. It records session pointers, cwd, model, content digests,
record IDs/cut positions and appended-instruction state; treat it as private session
state. Reuse is not restricted to clean completions: recorded progress after an
interruption can still be retained. Concurrent use of one Pi session by multiple
bridge processes is unsupported.
When no usable recording exists — no saved state, an unrecognized format, a changed
model or working directory, a missing transcript or no valid cut — the bridge writes
Pi's history into a new Claude Code session. After upgrading from the old checkpoint
format, each continuing session needs this one-time history rebuild, which can cost
prompt cache. Old claude-bridge/session-checkpoints files are ignored and left in
place: they are not read, migrated or deleted.
Appended-instruction state follows the records retained, including across Pi restarts. A resume keeps the latest recorded effective value; a fork or recorded-prefix rewrite keeps the original system append and only refreshes carried by retained records. A refresh cut away is delivered again when needed; a retained refresh is not resent when the current instructions match it. Missing, invalid or inconsistent append evidence on retained records triggers delivery of the full current appended instructions. Writing a session from Pi history starts a new epoch with the current appended instructions in its system prompt and no prior refreshes.
Tool schemas: Plain object schemas pass through unchanged. Object-only root anyOf/oneOf unions (including roots already declaring type: "object", object allOf variants and local $ref variants) are advertised under a required input property, preserving variants and root metadata/definitions. The bridge unwraps that envelope before passing arguments to Pi and re-wraps Pi history for Claude; an ordinary tool's own input field is untouched. Other non-object schemas are omitted rather than failing the request, with one warning per tool per session: a UI notification, or stderr in headless children, also recorded in claude-bridge-diag.log in pi's agent dir. Pi still validates calls against the original schema.
The model list comes from pi-ai's Anthropic catalog automatically — when pi-ai adds a new Claude model, it appears in /model after updating the package, no bridge update needed. Dated snapshot ids (e.g. claude-opus-4-5-20251101) are not shown.
1M Context: The bridge requests 1M context for Fable 5/5.1, Opus 5.5/5/4.8/4.7, and Sonnet 5.5/5 on either configured plan. Availability still depends on account entitlement: Fable 5 is unavailable on Pro without Extra Usage (both bare and [1m] variants were rejected with "Fable 5 requires usage credits"); Fable 5.1 was not re-probed and its entitlement remains unverified. Opus 4.6 gets 1M only on a Max plan or with Extra Usage, and Sonnet 4.6 only with Extra Usage — set provider.plan and/or provider.longContextExtraUsage as described in Configuration. Unknown or unmeasured models default to 200K context.
Displayed costs use pi-ai catalog prices as API-equivalent estimates, not subscription billing.
Rate limits and /claude quota
Claude SDK rate-limit events are reported synchronously to the process-wide
@thoth-agents/pi-core provider-limits registry as claude-bridge observations.
Each report carries the producing query's Pi session id (including child sessions,
AskClaude and summaries), utilization as a 0..1 fraction and reset time in Unix
milliseconds. Rate-limit warnings identify when requests beyond the plan limit are
being billed to Extra Usage.
Run /claude quota to show current plan usage: 5-hour and weekly windows,
Opus/Sonnet and model-specific windows when available, plus extra usage.
Percentages are shown directly from the response's 0–100 scale; reset times are
shown in your local timezone. The command reuses the bridge's working directory
and configured Claude Code executable. Only its child environment omits
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, since Claude Code treats usage fetching
as non-essential traffic; normal queries keep it disabled. The command sends
no prompt, enables no tools and closes its short-lived CLI query on every exit
path. It times out after 30 seconds. Nothing is fetched periodically or added to
sidebar quota state.
Experimental: this uses the SDK's
usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET({ skipBehaviors: true })
control request. Its API and response shape may change. If the method is missing,
update the Claude Agent SDK and Claude Code. Plan data is unavailable for API-key,
Bedrock and Vertex authentication (or missing Claude profile scope); the command
explains this instead of showing zero usage. If authentication is eligible but
Claude Code returns no usage data, the command reports that the usage request
failed or returned nothing and suggests trying again later. Timeout and request
failures are also reported explicitly. If another extension registers /claude, startup warns once
with its command/source; resolve the duplicate rather than relying on Pi's
suffixed or shadowed command names.
Opt-in live append-refresh test
Requires installed workspace dependencies, writable Claude Code session state, and the operator's Claude login. The probe activates the real bridge provider in-process and runs real SDK queries; it needs no global Pi CLI/shim and supports Windows. From the repository root in PowerShell:
$env:CLAUDE_BRIDGE_TESTING_PROMPT_REFRESH = "1"
pnpm --filter @thoth-agents/pi-claude-bridge exec node --import tsx tests/int-append-instructions.mjs
Remove-Item Env:CLAUDE_BRIDGE_TESTING_PROMPT_REFRESH
In Bash, use CLAUDE_BRIDGE_TESTING_PROMPT_REFRESH=1 pnpm --filter @thoth-agents/pi-claude-bridge exec node --import tsx tests/int-append-instructions.mjs.
Optional: CLAUDE_BRIDGE_TESTING_PROMPT_REFRESH_MODEL=<model-id> (e.g. claude-sonnet-4-6, without a provider prefix) selects the probe model (default Haiku 4.5); CLAUDE_BRIDGE_TEST_LOG_DIR selects the retained log directory. No alternate provider is needed.
The probe uses real lifecycle captures in a temporary working directory, a static block over 10,000 characters, and a small sentinel block beyond the first 2,000 characters. It runs three prompts: initial A, changed B with delivery disabled by the test-only CLAUDE_BRIDGE_TESTING_DISABLE_APPEND_REFRESH seam, then B with delivery enabled. SDK session IDs and bridge REUSE markers rule out rebuild or compaction. PASS requires the disabled prompt to still report A (active recording), the enabled model response to report B, actual changed-block delivery without resending the static block, and every delivered context value to be ≤9,000 .length units. Recording inactive, unreliable control answers, or unproven reuse report INCONCLUSIVE, exit 2; live acceptance remains unrun, not passed. A proven control followed by failed delivery exits 1. Without opt-in it skips and makes no model calls. Do not set the delivery-disable seam in normal use.
AskClaude Tool
Deprecated: AskClaude is a legacy tool and may be removed in a future release. The Claude Code provider remains supported. Pi subagent extensions can provide similar delegation.
Opt-in: set askClaude.enabled to true (see Configuration). Available when using any non-claude-bridge provider. Pi's LLM can delegate tasks to Claude Code and wait for it to answer a question or perform a task. Examples of how to use:
- "Ask Claude to plan a fix"
- "If you get stuck, ask claude for help"
- "Ask claude to review the plan in @foo.md, implement it, then ask an isolated=true claude to review the implementation"
- "Ask claude to poke holes in this theory"
Delegated calls don't read global CLAUDE.md files or Claude Code's skill listing, and always get Claude Code's own system prompt.
AskClaude calls/results render through the theme's Render KIT when present,
discovered through @thoth-agents/pi-core at render time. Without the kit, they
keep native Pi rendering; there is no dependency on @thoth-agents/pi-thoth-theme.
Parameters
prompt— the question or task for Claude Codemode—read(default, read files and search/fetch on web),none, orfull(read+write+bash, disable this mode withallowFullMode: falsein config)model—opus(default),sonnet,haiku, or a full model IDthinking— effort level:off,minimal,low,medium,high,xhigh.minimalmaps to SDKlow,xhightomax;offomits effort (Claude Code's default).isolated— whentrue, Claude gets a clean session with no conversation history (default:false)
Configuration
Config: ~/.pi/agent/claude-bridge.json (global) or the project Pi config directory, usually .pi/claude-bridge.json (project; merged over global except for provider). A project file cannot set provider options, including the Claude Code executable path or metered-billing opt-ins; put them in the global file. Claude Code loads only user settings (~/.claude/settings.json), not project or local settings.
{
"askClaude": {
"enabled": true,
"allowFullMode": true,
"defaultIsolated": false,
"description": "Custom tool description override"
},
"provider": {
"plan": "max",
"longContextExtraUsage": false,
"strictMcpConfig": true,
"pathToClaudeCodeExecutable": "/home/you/.nix-profile/bin/claude"
}
}
askClaude:
enabled— register the AskClaude tool (defaultfalse). The first TUI use shows a one-time deprecation warning; execution remains available.name— override the tool's pi-side name (default"AskClaude")label— override the TUI label (default"Ask Claude Code")description— override the tool description. Default whenallowFullMode: true: "Delegate to Claude Code for a second opinion or analysis (code review, architecture questions, debugging theories), or to autonomously handle a task. Defaults to read-only mode — use full mode when the user wants to delegate a task that requires changes. Prefer to handle straightforward tasks yourself."defaultMode—"read"(default),"none", or"full"defaultIsolated— start each call in a fresh session (defaultfalse)allowFullMode— allowmode: "full"; setfalseto lock it outappendSkills— forward pi's skills block into the system prompt (defaulttrue)
provider:
plan(default"pro") — set to"max"if you have a Max (or Team Premium/Enterprise) Anthropic plan. This enables Opus 4.6 with 1M context without Extra Usage; measured Opus 4.7/4.8/5/5.5 already get 1M on either configured plan.longContextExtraUsage— set totrueto enable 1M context models even if they cost money through Extra Usage on your plan. It enables Sonnet 4.6 with 1M on every plan and Opus 4.6 with 1M on Pro. Not needed for the measured Opus 4.7/4.8/5/5.5 models.forceTwoHundredK— array of model ids to pin to 200K context (bare id, no[1m]suffix). Use if pi-ai declares a model at 1M but Claude Code won't serve it on your plan.strictMcpConfig— block MCP servers from~/.claude.json/.mcp.json(defaulttrue). Cloud MCP (Gmail/Drive via claude.ai OAuth) is always blocked.autoMemoryEnabled— enable Claude Code's auto-memory system (defaultfalse)pathToClaudeCodeExecutable— path to theclaudebinary. Useful if your OS/filesystem has the SDK's bundled musl/glibc binaries in a place where they can't run. For example, with Nix you can set the binary to e.g."/home/you/.nix-profile/bin/claude".
Notices: the startup notice points out when provider.plan is unset and records startupNoticeShown in the global config. There's also a deprecation notice on first use of AskClaude that records its display date as askClaudeDeprecationShown.
Extension providers and models.json: pi's modelOverrides in ~/.pi/agent/models.json apply to extension-registered providers like claude-bridge, keyed by the model id shown in /model (opening /model reloads the file). For example, to give Pi a 400K window for a bridge model:
{
"providers": {
"claude-bridge": {
"modelOverrides": {
"claude-opus-5-5": { "contextWindow": 400000 }
}
}
}
}
This only changes Pi's context meter and auto-compaction threshold (contextWindow - reserveTokens); the Claude model actually served (200K or [1m]) still follows provider.plan, provider.longContextExtraUsage, and provider.forceTwoHundredK. Do not set a window larger than the served model's real capacity.
Claude Code's environment: Claude Code inherits pi's environment. For variables only bridge requests should get (a proxy, a gateway, Bedrock settings), add an env object to a claude-bridge credential in ~/.pi/agent/auth.json; its values override pi's, and an empty value removes the variable. Extensions calling a bridge model can pass env per request the same way. CLAUDE_CONFIG_DIR, HOME and USERPROFILE can't be set there (the turn fails), since the bridge reads Claude Code's session files through pi's own values. The bridge sets its non-essential-traffic flag only in the Claude Code child and strips inherited Claude Code session markers, leaving pi's own environment unchanged.
This example sends bridge requests through a proxy and keeps an exported gateway (issue #107) away from Claude Code, so it uses your Claude login:
{
"claude-bridge": {
"type": "api_key",
"key": "not-used",
"env": {
"HTTPS_PROXY": "http://127.0.0.1:8080",
"ANTHROPIC_BASE_URL": "",
"ANTHROPIC_API_KEY": "",
"ANTHROPIC_AUTH_TOKEN": ""
}
}
}
Tests
Install from the thoth-agents repository root with pnpm install (this package is a pnpm workspace member). pnpm --filter @thoth-agents/pi-claude-bridge run test:unit runs offline tests. pnpm --filter @thoth-agents/pi-claude-bridge run test adds integration tests that hit APIs; set CLAUDE_BRIDGE_TESTING_ALT_MODEL in .env.test for the alt-provider smoke test.
Integration tests spawn real pi and Claude Code subprocesses and need write access to ~/.claude — a sandbox that blocks it makes --resume fail with No conversation found with session ID.
Debugging
Set CLAUDE_BRIDGE_DEBUG=1 to enable debug output:
- Bridge log at
claude-bridge.login pi's agent dir (PI_CODING_AGENT_DIR, default~/.pi/agent) — provider calls, session sync decisions, tool results, CC stderr. Override location withCLAUDE_BRIDGE_DEBUG_PATH. - Per-query CC CLI logs at
cc-cli-logs/<timestamp>-<tag>-<seq>.login the same directory — the subprocess's own debug stream; tag isprovideroraskclaude. Shows CC's view of session loading, API requests, and tool calls.
When filing a bug about a session-resume failure (e.g. "No conversation found"), the most useful attachments are the syncResult: lines from the bridge log plus the matching cc-cli-logs/ file for the failing query.
Compatibility with other extensions
Which injection routes reach Claude Code
The bridge forwards pi's structured parts — project context files, skills, custom prompt, appended instructions, custom prompt sections (systemPromptOptions.sections), and selected non-hidden tools' toolGuidelines — and drops the rest. Tool guidelines are trimmed, deduplicated bullets in a final <tool_guidelines> section (omitted when empty). An explicit sections.rules override replaces generated tool guidance; a custom sections.tool_guidelines override also takes precedence. Pi's default rules/tool sections and promptGuidelines are not forwarded; explicit section overrides are preserved. Measured against the request body (diag/capture-proxy.mjs):
| Route | Reaches Claude Code |
|---|---|
before_agent_start -> message |
Yes, as literal prompt text in the user turn |
context editing the last user message |
Yes, as literal prompt text |
--append-system-prompt |
Yes, with pi's appended instructions |
context_with_system editing the system message |
Yes when it wraps pi's prompt; the turn fails when it replaces one |
before_agent_start -> systemPromptOptions.sections |
Yes, one <name> block per section |
before_agent_start -> systemPrompt |
No, dropped |
Two traps. Returning systemPrompt from before_agent_start makes pi replace the whole system prompt, discarding any context_with_system edit in the same run — only one reaches the request. And system-prompt edits work by wrapping: replacing pi's prompt leaves the bridge with nothing to match, so it refuses the turn rather than send Claude Code a request missing your context files, skills and custom instructions. The error names the closest known prompt and where it diverged.
To add instructions, use message, context, or a system-message edit that keeps pi's prompt intact.
Hooks written for Claude Code
~/.claude/settings.json hooks fire inside bridge turns, so a hook injecting Claude-specific guidance duplicates what pi's extensions already provide. A project's .claude/settings.json and .claude/settings.local.json are not loaded, so that repo's hooks, apiKeyHelper and env do not run. pi sets PI_CODING_AGENT=true for child processes, including the Claude Code child; a hook can skip itself on that:
[ -n "$PI_CODING_AGENT" ] && exit 0
Hooks do not fire on isolated summary queries.
Compaction and branch summaries
pi runs compaction and branch summaries natively. The bridge routes their cacheRetention: "none" calls to isolated Claude Code queries, leaving the live session untouched until pi completes the history rewrite. Other extensions can provide summaries through pi's hooks.
System prompt rejections
Other extensions can change the system prompt. When the result still contains pi's built-in system prompt text, or the two documentation paths that Anthropic looks for (docs/custom-provider.md in the same prompt with docs/packages.md), the bridge stops the turn instead of sending it, since Anthropic may otherwise bill these requests as Extra Usage. Fix the source extension before retrying; CLAUDE_BRIDGE_DEBUG=1 writes the full prompt to the bridge log when this happens.
Plan usage for footers and quota extensions
Alongside /claude quota and immediate pi-core provider-limit observations, the bridge exposes plan usage to footer/quota extensions. Claude Code sends a rate_limit_event when a usage window changes, and the bridge passes it to pi's after_provider_response event as anthropic-ratelimit-unified-* headers. Events are not tied to one response: one that arrives after a turn has ended on a tool call is reported on the next provider call, and only the latest is kept for this header channel. The pi-core registry still receives every event immediately. The headers use the names that the Anthropic API uses (for example anthropic-ratelimit-unified-5h-utilization). The bridge sends only the headers that it can make from the event: the status, the reset time, the representative claim, the overage status and reset, and the utilization and reset of each window. The status code is always 200. An extension that reads these headers for the built-in anthropic provider can also accept claude-bridge without other changes.
Using claude bridge with @gotgenes/pi-subagents
Requires the following in ~/.pi/agent/subagents.json:
{"promptInheritance": {"claude-bridge": "portable"}}
Known issues
Edits far back in history can still cost cache. The unchanged prefix is retained, but Anthropic's cache lookup has a limited lookback. A long rewritten suffix can prevent reuse of an earlier cache entry. With no usable recording, writing Pi history into a new session can also miss the prompt cache.
File snapshots in rewritten history can be lost. Native records before the matching point keep their attachments. A rewritten suffix carries @file expansions, but not snapshots Claude Code recorded after editing files; the tool calls and results remain in pi's history.
System prompt recording is account-dependent. The bridge keeps Claude Code's default recording and refreshes changed projected appends through new-turn hook context, not by replacing the recorded prompt. Prefix preservation depends on active recording; where CC has not enabled it, changing the append can still change the rendered system prompt. Arbitrary replacement prompts outside Pi's structured capture are not supported.
Exported Anthropic environment variables override the Claude Code child (issue #107). An exported ANTHROPIC_BASE_URL, ANTHROPIC_API_KEY, or ANTHROPIC_AUTH_TOKEN redirects Claude Code to that gateway and every turn fails with its auth error. Unset them for the pi process, or blank them in a claude-bridge credential's env (see Configuration).