pi-claude-bridge

Pi extension that uses Claude Code (via Agent SDK) as a model provider.

Packages

Package details

extension

Install pi-claude-bridge from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-claude-bridge
Package
pi-claude-bridge
Version
0.11.0
Published
Nov 6, 2026
Downloads
77K/mo · 20.1K/wk
Author
elidickinson
License
MIT
Types
extension
Size
428.5 KB
Dependencies
3 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./src/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-claude-bridge

npm version

Pi extension that integrates Claude Code via the Agent SDK. Originally based on claude-agent-sdk-pi by Prateek Sunal.

Use Opus/Sonnet/Haiku as models in pi, with all tool calls flowing through pi's TUI.

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

  1. Install the extension:
    pi install npm:pi-claude-bridge
  2. Log in to Claude Code with your Claude subscription: run claude auth login. The bridge uses Claude Code's login, not pi's /login.
  3. In pi, pick a claude-bridge/... model with /model, e.g. claude-bridge/claude-opus-5-5. Don't pick the anthropic/... models: those are pi's own Anthropic provider and don't go through Claude Code or your subscription.

Optional: to let other providers delegate tasks or questions to Claude Code, install the AskClaude tool: pi install npm:pi-claude-bridge-askclaude (askclaude/).

Requires pi 1.2.0 or newer to use all models (but should mostly work >=0.86.1).

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-5, or claude-bridge/claude-haiku-5-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 since pi's bash has none. Skills are forwarded to Claude Code's system prompt, and steering mid-turn reaches Claude at the next tool boundary.

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.

All current models run with 1M context. Opus 4.6 and Sonnet 4.6 need extra settings for 1M (see Configuration).

Configuration

Config: ~/.pi/agent/claude-bridge.json. There is no project config, so a cloned repo can't point the bridge at its own executable or turn on metered billing.

{
  "provider": {
    "strictMcpConfig": true,
    "pathToClaudeCodeExecutable": "/home/you/.nix-profile/bin/claude"
  }
}

provider:

  • strictMcpConfig — block MCP servers from ~/.claude.json / .mcp.json (default true). Cloud MCP (Gmail/Drive via claude.ai OAuth) is always blocked.
  • autoMemoryEnabled — enable Claude Code's auto-memory system (default false)
  • pathToClaudeCodeExecutable — path to the claude binary. 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".
  • 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.
  • plan (default "pro") — set to "max" on a Max (or Team Premium/Enterprise) plan to run Opus 4.6 with 1M context.
  • longContextExtraUsage — set to true to run Opus 4.6 (on Pro) and Sonnet 4.6 with 1M context, billed through Extra Usage.

Extension providers and models.json: pi's modelOverrides in ~/.pi/agent/models.json do not work correctly with pi-claude-bridge; they only apply to pi-side settings like compaction threshold. Overriding contextWindow or other fields requires editing src/models.ts directly — to pin a model to 200K, use provider.forceTwoHundredK instead.

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.

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

npm run test:unit for offline tests. npm 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.log in pi's agent dir (PI_CODING_AGENT_DIR, default ~/.pi/agent) — provider calls, session sync decisions, tool results, CC stderr. Override location with CLAUDE_BRIDGE_DEBUG_PATH.
  • Per-query CC CLI logs at cc-cli-logs/<timestamp>-<tag>-<seq>.log in the same directory — the subprocess's own debug stream; tag is provider (or askclaude for the AskClaude package). 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, and custom prompt sections (systemPromptOptions.sections) — and drops the rest. 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 a repo's hooks, apiKeyHelper and env never 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

The bridge does not show plan usage itself. 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. 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"}}

Session history

The bridge compares conversation content before each fresh query. Unchanged history resumes the Claude Code session. Tree navigation and history edits retain Claude Code's records up to the last safe matching point, then continue in a new session. /fork and clone start from the parent session's Claude Code records the same way. Model changes and changed instructions import pi's history into a fresh Claude Code session.

Session pointers, content digests and record IDs are saved under claude-bridge/sessions/ in pi's agent directory (PI_CODING_AGENT_DIR, default ~/.pi/agent). They let the bridge recover its matching prefix after a restart. Running the same pi session simultaneously in multiple bridge processes is unsupported.

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.

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.

Changed instructions cost a cache miss. When project context (AGENTS.md/CLAUDE.md), skills, or extension-written instructions change (for example, after an edit and /reload), the next turn imports the conversation into a new Claude Code session so the model sees them. That turn re-sends the conversation uncached and drops earlier thinking. An extension that rewrites its system prompt section every turn pays this on every turn.

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).