Self-contained Anthropic auth for the pi coding agent using your existing Claude Code credentials — no separate login or API key needed.
pi install git:github.com/fdietze/pi-claude-auth@main
Restart pi, pick a model with /model (or Ctrl+L). Done — your Claude Code
credentials are already seeded.
This fork is distributed as source on the
mainbranch, not npm.@maintracks the latest; for an exact, reproducible pin append a commit SHA (@<sha>) instead.
Claude Code must be installed and authenticated first.
The extension reads from your macOS Keychain entry
Claude Code-credentials. Runclaudeat least once so the entry exists. On Linux/Windows,~/.claude/.credentials.jsonis used instead.
claude at least once), and the claude
command on your PATH — the extension delegates every token refresh to itnpm install -g --ignore-scripts @earendil-works/pi-coding-agent)pi install git:github.com/fdietze/pi-claude-auth@main
pi clones main into ~/.pi/agent/git/ and loads the extension straight from
src/index.ts (it has no runtime dependencies). Use -l for a project-local
install.
Add to ~/.pi/agent/settings.json (global) or .pi/settings.json (project):
{
"packages": ["git:github.com/fdietze/pi-claude-auth@main"]
}
Then just run pi. The extension loads automatically.
The extension is a plain source tree with no runtime dependencies, so a Nix
setup consumes it directly — no npm, no pi package manager. Add it as a
flake = false input and link its src/ into pi's extension directory:
# flake.nix
inputs.pi-claude-auth = {
url = "github:fdietze/pi-claude-auth";
flake = false;
};
# home-manager
home.file.".pi/agent/extensions/pi-claude-auth".source =
"${inputs.pi-claude-auth}/src";
nix flake update then upgrades the extension with every other input. pi loads
src/index.ts from the linked directory on startup.
Paste this into any LLM agent (pi, Claude Code, Cursor, etc.):
Install the pi-claude-auth package and configure it by following:
https://raw.githubusercontent.com/fdietze/pi-claude-auth/main/installation.md
Reinstall to pull the latest main:
pi install git:github.com/fdietze/pi-claude-auth@main
After installation, run:
pi config
You should see the extension listed:
git:github.com/fdietze/pi-claude-auth@main (user)
Extensions
[x] src/index.ts
Then start pi and pick any Claude model with /model. If it responds, auth is
working.
Run pi, then pick a Claude model with /model (or Ctrl+L). The extension has
already seeded your Claude Code credentials, so there is nothing else to do — no
/login, no API key. When the token expires, pi asks the claude CLI to
refresh it; Claude Code stays the only writer of your credentials.
If your Claude Code login expires or is revoked, pi shows
"Claude Code login expired or revoked. Run claude and log in, then retry."
until you do. Nothing is retried in the meantime — the retry happens by itself
once Claude Code has written new credentials.
If your Claude Code credentials aren't OAuth-based, the extension stays out of the way and pi falls through to its standard Anthropic auth.
There are several good community projects solving Anthropic auth for pi (see Acknowledgements). Here's what makes this one different:
/login, no API key. Install and go./login when you have multiple accounts (Pro, Max, etc.).claude CLI to refresh, so the
single-use refresh token is never redeemed twice (which would revoke the
session and log you out of Claude Code).claude
refreshes.If you prefer a browser-based OAuth flow or need relay/caching features, check out pi-anthropic-oauth or @cortexkit/pi-anthropic-auth — both are solid options.
16 supported models. Run pnpm run test:models to verify against your account.
| Model |
|---|
| claude-haiku-4-5 |
| claude-haiku-4-5-20251001 |
| claude-opus-4-0 |
| claude-opus-4-1 |
| claude-opus-4-1-20250805 |
| claude-opus-4-20250514 |
| claude-opus-4-5 |
| claude-opus-4-5-20251101 |
| claude-opus-4-6 |
| claude-opus-4-7 |
| claude-opus-4-8 |
| claude-sonnet-4-0 |
| claude-sonnet-4-20250514 |
| claude-sonnet-4-5 |
| claude-sonnet-4-5-20250929 |
| claude-sonnet-4-6 |
The extension checks these in order:
Claude Code-credentials* entries — multiple accounts
are detected automatically)~/.claude/.credentials.json (fallback, works on all platforms)If you have multiple Claude Code accounts authenticated on macOS, the extension detects all of them from the Keychain automatically. Each account is labeled by its subscription tier (Claude Pro, Claude Max, etc.).
To switch accounts:
/login
Select the anthropic provider, then pick the account you want. Your selection
is persisted across sessions in ~/.pi/agent/claude-account-source.txt. If only
one account is found, the picker is skipped.
| Problem | Solution |
|---|---|
| "No Claude Code credentials found" | Run claude to authenticate with Claude Code first |
| "Keychain is locked" | Run security unlock-keychain ~/Library/Keychains/login.keychain-db |
| "Claude Code login expired or revoked" | Run claude and log in. pi picks the new credentials up by itself |
| "Another pi process is refreshing" | Transient: another pi instance holds the refresh lock. Send the request again |
OAuth refresh failed ... 400 invalid_request_error from a session/subagent | That pi session did not load this extension, so it hit pi's built-in refresh on the empty stored token. Load the extension in every pi session that uses these credentials, including subagents (e.g. add it to actor-subagents' child-extensions.json) |
| Not working on Linux/Windows | Ensure ~/.claude/.credentials.json exists. Run claude to create it |
| Keychain access denied | Grant access when macOS prompts you |
| Keychain read timed out | Restart Keychain Access (can happen on macOS Tahoe) |
| Package not updating | Reinstall at the ref: pi install git:github.com/fdietze/pi-claude-auth@main |
The Claude Code version is pinned to 2.1.280 for billing header computation.
If billing reverts to extra usage after a Claude Code update, override:
export ANTHROPIC_CLI_VERSION=<new-version>
or reinstall to pull the latest main:
pi install git:github.com/fdietze/pi-claude-auth@main
If you hit auth errors that are hard to reproduce, enable debug logging to capture the full auth flow:
export PI_CLAUDE_AUTH_DEBUG=1
Restart pi and reproduce the issue. The extension writes structured JSON logs to
~/.pi/agent/pi-claude-auth-debug.log. All secrets (tokens, API keys) are
automatically redacted — the log file is safe to share when reporting an issue.
To write logs to a custom path:
export PI_CLAUDE_AUTH_DEBUG=/tmp/pi-claude-auth-debug.log
Disable when done:
unset PI_CLAUDE_AUTH_DEBUG
| Variable | Description | Default |
|---|---|---|
PI_CODING_AGENT_DIR | pi's config directory (where auth.json lives) | ~/.pi/agent |
PI_CLAUDE_AUTH_DEBUG | Enable diagnostic logging (1 for default path, or a custom file path) | disabled |
ANTHROPIC_CLI_VERSION | Claude CLI version for billing headers | 2.1.160 |
This is a pi extension (packaged as a pi package) that sources Anthropic credentials from Claude Code instead of asking you to log in again. The governing rule: Claude Code is the only writer of its credentials, pi only reads them. Claude's OAuth refresh tokens are single-use, so a second party redeeming one gets the whole session revoked server-side — that is what logs you out of Claude Code.
On startup it reads your Claude Code OAuth tokens from the macOS Keychain (or
~/.claude/.credentials.json on other platforms) and seeds them into pi's
~/.pi/agent/auth.json under the anthropic provider — without the refresh
token, so no pi process can ever redeem it. pi then uses those credentials with
zero separate login.
When the token is within five minutes of expiry, pi calls this extension's refresh hook, which:
~/.pi/agent/claude-refresh.lock),claude -p "only say OK" --model haiku --effort low once,
which makes Claude Code refresh and store its own tokens, and re-reads them.
ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN are stripped from that run:
the CLI would authenticate with them instead of the Claude Code login, and
the refresh would silently change nothing.Other pi processes watch the credential source while they wait, so they pick up
the result without starting a second claude.
When a refresh changes nothing, that is recorded in
~/.pi/agent/claude-refresh-futile.json together with the credential state it
was tried for. The same state is never asked about twice — no subprocess, no
network, no timer. The state changes when Claude Code writes new credentials or
when the token crosses its expiry, and only then is a refresh attempted again.
While the credentials are expired and a refresh has already proved futile, pi
tells you to run claude.
Claude Code-credentials* Keychain entries on macOS (labeled by
subscription tier), falling back to ~/.claude/.credentials.jsonstat),
so a refresh by Claude Code or another pi process is picked up immediately.
The Keychain has no cheap equivalent, so those sources are re-read on expiry~/.pi/agent/auth.json with { type: "oauth", access, refresh: "", expires } under anthropic, holding the same <file>.lock directory pi's
own locking uses, and replacing the file through a renameanthropic OAuth provider override via
pi.registerProvider("anthropic", { oauth }):
login reads the Keychain/file (no browser) and exposes an account picker
when multiple accounts existrefreshToken delegates to the claude CLI under the refresh lockgetApiKey only reads; it never triggers a refreshA delegated refresh refreshes whichever account the claude CLI itself is
logged into. If you selected a different Keychain account via /login and it
expires, pi cannot refresh it: it falls back to another Claude Code account that
is still valid (for this session only, your /login choice is kept), and
otherwise asks you to run claude for that account.
The extension seeds an anthropic entry in ~/.pi/agent/auth.json, and a
stored credential outranks ANTHROPIC_API_KEY. Run /logout and pick
anthropic after removing the package, or start pi once with the extension
still installed and Claude Code logged out — it then removes its own entry.
This is a fork of
@pankajudhas81/pi-claude-auth
by Pankaj Udhas. It adds concurrency-safe auth.json writes based on
#3 by
@itsmingjie, shell-free credential subprocess
calls (execFileSync) from
@ftriquet's hardening audit, macOS multi-account
Keychain disambiguation from
#5 by
@mattsegura, and bumps the pinned Claude Code
version. All credit for the original design belongs upstream.
The upstream project is motivated by and copies patterns from opencode-claude-auth by Griffin Martin. That project solved the same problem for opencode — reusing Claude Code OAuth credentials so you don't need a separate login. We adopted the same approach (Keychain reading, token refresh, credential seeding) and adapted it for pi's extension API.
The community has built several other great solutions worth checking out:
pi-anthropic-oauth by
Leo Henon — a browser-based OAuth flow for pi. Uses a local callback server
for a full OAuth dance via /login anthropic. Different approach from ours
(browser login vs. Keychain reading), well-maintained, and popular (39 stars).
If you prefer authenticating directly through Anthropic's login page rather
than piggybacking on Claude Code credentials, this is a great choice.
@cortexkit/pi-anthropic-auth
by ismeth / CortexKit — a shared-core monorepo supporting both pi and OpenCode
through @cortexkit/anthropic-auth-core. Offers advanced features like relay
proxying via Cloudflare Workers, prompt caching controls (/claude-cache),
quota management, fast-mode for Opus, and routing strategies. The most
feature-rich option in this space (1,540 downloads/mo). If you need caching,
relay, or quota features, check this one out.
All three projects (and ours) exist because the community wants to use pi with Claude Pro/Max subscriptions. Different approaches, same goal. Pick whichever fits your workflow best.
This extension uses Claude Code's OAuth credentials to authenticate with Anthropic's API. Anthropic's Terms of Service state that Claude Pro/Max subscription tokens should only be used with official Anthropic clients. This extension exists as a community workaround and may stop working if Anthropic changes their OAuth infrastructure. Use at your own discretion.
MIT
TypeScript
98.9%
Self-contained Anthropic auth for the pi coding agent using your existing Claude Code credentials — no separate login or API key needed.
pi install git:github.com/fdietze/pi-claude-auth@main
Restart pi, pick a model with /model (or Ctrl+L). Done — your Claude Code
credentials are already seeded.
This fork is distributed as source on the
mainbranch, not npm.@maintracks the latest; for an exact, reproducible pin append a commit SHA (@<sha>) instead.
Claude Code must be installed and authenticated first.
The extension reads from your macOS Keychain entry
Claude Code-credentials. Runclaudeat least once so the entry exists. On Linux/Windows,~/.claude/.credentials.jsonis used instead.
claude at least once), and the claude
command on your PATH — the extension delegates every token refresh to itnpm install -g --ignore-scripts @earendil-works/pi-coding-agent)pi install git:github.com/fdietze/pi-claude-auth@main
pi clones main into ~/.pi/agent/git/ and loads the extension straight from
src/index.ts (it has no runtime dependencies). Use -l for a project-local
install.
Add to ~/.pi/agent/settings.json (global) or .pi/settings.json (project):
{
"packages": ["git:github.com/fdietze/pi-claude-auth@main"]
}
Then just run pi. The extension loads automatically.
The extension is a plain source tree with no runtime dependencies, so a Nix
setup consumes it directly — no npm, no pi package manager. Add it as a
flake = false input and link its src/ into pi's extension directory:
# flake.nix
inputs.pi-claude-auth = {
url = "github:fdietze/pi-claude-auth";
flake = false;
};
# home-manager
home.file.".pi/agent/extensions/pi-claude-auth".source =
"${inputs.pi-claude-auth}/src";
nix flake update then upgrades the extension with every other input. pi loads
src/index.ts from the linked directory on startup.
Paste this into any LLM agent (pi, Claude Code, Cursor, etc.):
Install the pi-claude-auth package and configure it by following:
https://raw.githubusercontent.com/fdietze/pi-claude-auth/main/installation.md
Reinstall to pull the latest main:
pi install git:github.com/fdietze/pi-claude-auth@main
After installation, run:
pi config
You should see the extension listed:
git:github.com/fdietze/pi-claude-auth@main (user)
Extensions
[x] src/index.ts
Then start pi and pick any Claude model with /model. If it responds, auth is
working.
Run pi, then pick a Claude model with /model (or Ctrl+L). The extension has
already seeded your Claude Code credentials, so there is nothing else to do — no
/login, no API key. When the token expires, pi asks the claude CLI to
refresh it; Claude Code stays the only writer of your credentials.
If your Claude Code login expires or is revoked, pi shows
"Claude Code login expired or revoked. Run claude and log in, then retry."
until you do. Nothing is retried in the meantime — the retry happens by itself
once Claude Code has written new credentials.
If your Claude Code credentials aren't OAuth-based, the extension stays out of the way and pi falls through to its standard Anthropic auth.
There are several good community projects solving Anthropic auth for pi (see Acknowledgements). Here's what makes this one different:
/login, no API key. Install and go./login when you have multiple accounts (Pro, Max, etc.).claude CLI to refresh, so the
single-use refresh token is never redeemed twice (which would revoke the
session and log you out of Claude Code).claude
refreshes.If you prefer a browser-based OAuth flow or need relay/caching features, check out pi-anthropic-oauth or @cortexkit/pi-anthropic-auth — both are solid options.
16 supported models. Run pnpm run test:models to verify against your account.
| Model |
|---|
| claude-haiku-4-5 |
| claude-haiku-4-5-20251001 |
| claude-opus-4-0 |
| claude-opus-4-1 |
| claude-opus-4-1-20250805 |
| claude-opus-4-20250514 |
| claude-opus-4-5 |
| claude-opus-4-5-20251101 |
| claude-opus-4-6 |
| claude-opus-4-7 |
| claude-opus-4-8 |
| claude-sonnet-4-0 |
| claude-sonnet-4-20250514 |
| claude-sonnet-4-5 |
| claude-sonnet-4-5-20250929 |
| claude-sonnet-4-6 |
The extension checks these in order:
Claude Code-credentials* entries — multiple accounts
are detected automatically)~/.claude/.credentials.json (fallback, works on all platforms)If you have multiple Claude Code accounts authenticated on macOS, the extension detects all of them from the Keychain automatically. Each account is labeled by its subscription tier (Claude Pro, Claude Max, etc.).
To switch accounts:
/login
Select the anthropic provider, then pick the account you want. Your selection
is persisted across sessions in ~/.pi/agent/claude-account-source.txt. If only
one account is found, the picker is skipped.
| Problem | Solution |
|---|---|
| "No Claude Code credentials found" | Run claude to authenticate with Claude Code first |
| "Keychain is locked" | Run security unlock-keychain ~/Library/Keychains/login.keychain-db |
| "Claude Code login expired or revoked" | Run claude and log in. pi picks the new credentials up by itself |
| "Another pi process is refreshing" | Transient: another pi instance holds the refresh lock. Send the request again |
OAuth refresh failed ... 400 invalid_request_error from a session/subagent | That pi session did not load this extension, so it hit pi's built-in refresh on the empty stored token. Load the extension in every pi session that uses these credentials, including subagents (e.g. add it to actor-subagents' child-extensions.json) |
| Not working on Linux/Windows | Ensure ~/.claude/.credentials.json exists. Run claude to create it |
| Keychain access denied | Grant access when macOS prompts you |
| Keychain read timed out | Restart Keychain Access (can happen on macOS Tahoe) |
| Package not updating | Reinstall at the ref: pi install git:github.com/fdietze/pi-claude-auth@main |
The Claude Code version is pinned to 2.1.280 for billing header computation.
If billing reverts to extra usage after a Claude Code update, override:
export ANTHROPIC_CLI_VERSION=<new-version>
or reinstall to pull the latest main:
pi install git:github.com/fdietze/pi-claude-auth@main
If you hit auth errors that are hard to reproduce, enable debug logging to capture the full auth flow:
export PI_CLAUDE_AUTH_DEBUG=1
Restart pi and reproduce the issue. The extension writes structured JSON logs to
~/.pi/agent/pi-claude-auth-debug.log. All secrets (tokens, API keys) are
automatically redacted — the log file is safe to share when reporting an issue.
To write logs to a custom path:
export PI_CLAUDE_AUTH_DEBUG=/tmp/pi-claude-auth-debug.log
Disable when done:
unset PI_CLAUDE_AUTH_DEBUG
| Variable | Description | Default |
|---|---|---|
PI_CODING_AGENT_DIR | pi's config directory (where auth.json lives) | ~/.pi/agent |
PI_CLAUDE_AUTH_DEBUG | Enable diagnostic logging (1 for default path, or a custom file path) | disabled |
ANTHROPIC_CLI_VERSION | Claude CLI version for billing headers | 2.1.160 |
This is a pi extension (packaged as a pi package) that sources Anthropic credentials from Claude Code instead of asking you to log in again. The governing rule: Claude Code is the only writer of its credentials, pi only reads them. Claude's OAuth refresh tokens are single-use, so a second party redeeming one gets the whole session revoked server-side — that is what logs you out of Claude Code.
On startup it reads your Claude Code OAuth tokens from the macOS Keychain (or
~/.claude/.credentials.json on other platforms) and seeds them into pi's
~/.pi/agent/auth.json under the anthropic provider — without the refresh
token, so no pi process can ever redeem it. pi then uses those credentials with
zero separate login.
When the token is within five minutes of expiry, pi calls this extension's refresh hook, which:
~/.pi/agent/claude-refresh.lock),claude -p "only say OK" --model haiku --effort low once,
which makes Claude Code refresh and store its own tokens, and re-reads them.
ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN are stripped from that run:
the CLI would authenticate with them instead of the Claude Code login, and
the refresh would silently change nothing.Other pi processes watch the credential source while they wait, so they pick up
the result without starting a second claude.
When a refresh changes nothing, that is recorded in
~/.pi/agent/claude-refresh-futile.json together with the credential state it
was tried for. The same state is never asked about twice — no subprocess, no
network, no timer. The state changes when Claude Code writes new credentials or
when the token crosses its expiry, and only then is a refresh attempted again.
While the credentials are expired and a refresh has already proved futile, pi
tells you to run claude.
Claude Code-credentials* Keychain entries on macOS (labeled by
subscription tier), falling back to ~/.claude/.credentials.jsonstat),
so a refresh by Claude Code or another pi process is picked up immediately.
The Keychain has no cheap equivalent, so those sources are re-read on expiry~/.pi/agent/auth.json with { type: "oauth", access, refresh: "", expires } under anthropic, holding the same <file>.lock directory pi's
own locking uses, and replacing the file through a renameanthropic OAuth provider override via
pi.registerProvider("anthropic", { oauth }):
login reads the Keychain/file (no browser) and exposes an account picker
when multiple accounts existrefreshToken delegates to the claude CLI under the refresh lockgetApiKey only reads; it never triggers a refreshA delegated refresh refreshes whichever account the claude CLI itself is
logged into. If you selected a different Keychain account via /login and it
expires, pi cannot refresh it: it falls back to another Claude Code account that
is still valid (for this session only, your /login choice is kept), and
otherwise asks you to run claude for that account.
The extension seeds an anthropic entry in ~/.pi/agent/auth.json, and a
stored credential outranks ANTHROPIC_API_KEY. Run /logout and pick
anthropic after removing the package, or start pi once with the extension
still installed and Claude Code logged out — it then removes its own entry.
This is a fork of
@pankajudhas81/pi-claude-auth
by Pankaj Udhas. It adds concurrency-safe auth.json writes based on
#3 by
@itsmingjie, shell-free credential subprocess
calls (execFileSync) from
@ftriquet's hardening audit, macOS multi-account
Keychain disambiguation from
#5 by
@mattsegura, and bumps the pinned Claude Code
version. All credit for the original design belongs upstream.
The upstream project is motivated by and copies patterns from opencode-claude-auth by Griffin Martin. That project solved the same problem for opencode — reusing Claude Code OAuth credentials so you don't need a separate login. We adopted the same approach (Keychain reading, token refresh, credential seeding) and adapted it for pi's extension API.
The community has built several other great solutions worth checking out:
pi-anthropic-oauth by
Leo Henon — a browser-based OAuth flow for pi. Uses a local callback server
for a full OAuth dance via /login anthropic. Different approach from ours
(browser login vs. Keychain reading), well-maintained, and popular (39 stars).
If you prefer authenticating directly through Anthropic's login page rather
than piggybacking on Claude Code credentials, this is a great choice.
@cortexkit/pi-anthropic-auth
by ismeth / CortexKit — a shared-core monorepo supporting both pi and OpenCode
through @cortexkit/anthropic-auth-core. Offers advanced features like relay
proxying via Cloudflare Workers, prompt caching controls (/claude-cache),
quota management, fast-mode for Opus, and routing strategies. The most
feature-rich option in this space (1,540 downloads/mo). If you need caching,
relay, or quota features, check this one out.
All three projects (and ours) exist because the community wants to use pi with Claude Pro/Max subscriptions. Different approaches, same goal. Pick whichever fits your workflow best.
This extension uses Claude Code's OAuth credentials to authenticate with Anthropic's API. Anthropic's Terms of Service state that Claude Pro/Max subscription tokens should only be used with official Anthropic clients. This extension exists as a community workaround and may stop working if Anthropic changes their OAuth infrastructure. Use at your own discretion.
MIT
TypeScript
98.9%