Skip to content

Pi

Pi support runs through Claudette’s bundled Pi SDK harness, not through the Pi RPC server. Claudette ships a compiled Bun sidecar that embeds @earendil-works/pi-coding-agent; the Rust app talks to that sidecar over a small JSONL protocol and maps Pi session events into the same chat, tool-call, permission, stop, and attention UI used by Claude Code and Codex.

This is a production provider path. It is always available in normal builds and is not hidden behind Experimental settings. Distributions that need to ship without Pi can drop the pi-sdk cargo feature at build time — see Building without the Pi harness.

  1. Install Pi (the pi CLI is optional but useful for pi auth and pi /login outside Claudette).
  2. Launch Claudette and open Settings > Models > Pi. The card now embeds a per-provider configuration list (see Configuring providers below) — configure GitHub Copilot, OpenRouter, OpenAI, Anthropic, Google Gemini, DeepSeek, and a handful of others without leaving Claudette.
  3. The model list refreshes automatically after each configure / sign-in round-trip. Use Refresh models to force a re-discovery if you change credentials outside Claudette.
  4. Pick a Pi model as the default in Settings > Models > Default model, or choose one per chat from the model picker.

The Pi card does not need a base URL or a card-level API key — keys are scoped per provider via the inline list.

The Pi card surfaces a curated list of providers Pi knows how to talk to:

  • Default visible — GitHub Copilot (OAuth, supports GHES), OpenRouter, OpenAI, Anthropic, Google Gemini, DeepSeek (API keys).
  • More providers… disclosure — xAI, Groq, Cerebras, Mistral, Fireworks, OpenCode Zen (API keys).
  • Env-only — Amazon Bedrock, Google Vertex AI, Azure OpenAI — these need too many environment variables to model in a dialog; the row links to Pi’s docs and reflects the configured state once the env vars are set.

For each row:

  • API-key providers open a Configure dialog where you paste the key. A “Keep this key private to Claudette” checkbox controls storage scope:
    • Unchecked (default) → key is written to Pi’s ~/.pi/agent/auth.json. Visible to the terminal pi CLI too.
    • Checked → key is stored in Claudette’s OS keychain under bucket piProviderSecrets and pushed to the harness as the matching env var (e.g. OPENROUTER_API_KEY) at spawn time. Invisible to terminal pi.
  • OAuth providers (currently GitHub Copilot) open a Sign in modal that drives Pi’s device-code flow. For Copilot the modal prompts for an optional GitHub Enterprise Server domain, displays the verification URL + user code, and closes when Pi reports success.
  • Env-only providers open the relevant Pi docs page in a browser; the row’s status dot turns green once Pi detects the env vars on next refresh.

The card also shows a per-row source label once configured (via auth.json, via $OPENROUTER_API_KEY, via models.json, …) so you can tell which credential path Pi will actually use.

OpenRouter-backed Pi turns report per-turn token usage and cost in the chat footer and the composer usage meter. Claudette also polls OpenRouter’s /credits endpoint with the OpenRouter key configured for Pi and shows remaining / used credits next to the local token totals when the call succeeds.

Claudette owns the Pi process lifecycle:

  • Rust adapter: src/agent/pi_sdk.rs starts the sidecar, correlates JSONL requests, and converts Pi events into Claudette AgentEvents.
  • Bun sidecar: src-pi-harness/ imports AuthStorage, ModelRegistry, SessionManager, DefaultResourceLoader, and createAgentSession from @earendil-works/pi-coding-agent.
  • Model discovery: Settings calls Pi’s ModelRegistry.getAvailable() through the sidecar and stores the returned model ids/context windows in Claudette’s backend settings.
  • Session persistence: each Claudette chat gets a Claudette-owned Pi session directory under the app data directory. Resetting or deleting the chat remains authoritative from Claudette’s point of view.
  • Packaging: the sidecar is compiled and staged with the other Tauri external binaries. The build also stages Pi package metadata so the SDK can resolve its bundled assets at runtime.

Pi’s default mutating tools are not exposed directly. Claudette registers custom Pi tools instead:

  • read/search/list tools can execute in read-only permission modes.
  • bash/write/edit tools emit a Claudette tool_request.
  • approval and denial flow through the same pending-permission cards, cleanup auto-deny, stop/reset draining, and notification attention path used by other harnesses.

The visible transcript shows Pi tool calls through Claudette’s native tool-call UI rather than as raw sidecar logs.

Pi models appear under a Pi group in the chat model picker. The picker splits Pi’s registry into one sub-section per real provider (Anthropic, OpenAI, Google, Mistral, Ollama, LM Studio, …) so the list stays scannable when Pi returns hundreds of entries. Each sub-section shows a few primary models with a Show all (N)… disclosure for the rest, and the picker’s top search filters across every section at once.

Per-session choice is persisted with the same keys as other harnesses:

  • model:<session_id>
  • model_provider:<session_id> with provider value pi

Default Pi selection uses the existing global model settings:

  • default_model
  • default_agent_backend

Anthropic via Pi is blocked for Claude subscription users

Section titled “Anthropic via Pi is blocked for Claude subscription users”

When the local Claude CLI is signed in with an OAuth subscription token (claude auth status reports authMethod: oauth_token), Claudette hides Pi’s Anthropic sub-section in the picker and the Rust resolver also refuses any chat-send that would route an anthropic/* model through Pi (ensure_anthropic_not_routed_through_pi_via_oauth in src-tauri/src/commands/agent_backends/runtime_dispatch.rs). The block exists so Claude OAuth tokens never leave the Claude CLI subprocess. Non-Anthropic Pi sub-sections (OpenAI, Google, Ollama, …) continue to work normally.

Beyond the dedicated Pi card, Ollama, LM Studio, OpenAI API, Custom OpenAI, and Codex Native can also be routed through the Pi harness via Settings > Models > $(card) > Runtime. The default for Ollama and LM Studio is now Pi (Claude CLI is the optional fallback). For Codex Native and the OpenAI cards, the default stays unchanged and Pi is opt-in. The provider prefix that Pi expects (ollama/, lmstudio/, openai/) is prepended automatically when Claudette dispatches the chat. See the Runtime row on each card.

  • /model lists Pi models when they are available and accepts provider-qualified ids such as pi/openai/gpt-5.4.
  • /login for a Pi-selected chat opens the Pi provider picker modal (Pi is multi-provider, so /login doesn’t blind-launch one OAuth flow the way it does for Codex or Claude Code — you pick which provider to configure).
  • /permissions keeps controlling Claudette’s permission mode for Pi, Claude Code, and Codex.

Pi sessions surface the same end-of-turn affordances as the Claude CLI gateway:

  • Auto-compaction is visible. When Pi’s native context manager fires compaction_start for any trigger — manual /compact, threshold (the keepRecentTokens budget), or overflow (context window exhausted) — the chat flips to Compacting context… instead of leaving a generic spinner. On success the compact_boundary divider renders the pre/post token counts and the meter resets to the post-compaction baseline; on auto-compaction failure the status returns to Running without a divider so the surviving turn keeps streaming.
  • The context meter shows end-of-turn occupancy. The meter reads AgentSession.getContextUsage() (Pi’s own end-of-turn context size + the model’s actual context window) rather than a cumulative tally across the agent loop’s internal LLM rounds. A 136 k turn on a 272 k model reads ~50%, not 1100%.

Pi tool calls — including the shell-backed bash and Pi’s exec tools — resolve as soon as the spawned command exits, even when the command backgrounded a descendant that inherited stdout / stderr (a typical example is bash -c "codex exec …", where the Codex CLI forks helper processes that hold the inherited pipe open). If you press Stop on the chat, the running command is cancelled via the abort signal. There is no automatic per-command timeout; pressing Stop is the only way to cancel a genuinely stuck command.

Refresh models returns only the seed models. Make sure pi auth has been run and provider configuration exists in Pi. Then click Refresh models again.

A write or shell command is waiting. Approve or deny the Claudette permission card in the chat timeline. Pi mutating tools intentionally wait on Claudette approval.

claudette-pi-harness not installed in a dev build. Launch via ./scripts/dev.sh (not bare cargo tauri dev). The launcher stages the Bun-compiled sidecar into src-tauri/binaries/ and, on macOS, mirrors it into the dev .app’s Contents/MacOS/ so the resolver’s current_exe.parent() lookup succeeds the same way it does in a release build. If you must run cargo tauri dev directly for some reason, export CLAUDETTE_PI_HARNESS=$(pwd)/src-tauri/binaries/claudette-pi-harness-$(rustc -vV | awk '/host:/ {print $2}') to point the resolver at the staged binary. Release builds stage everything automatically.