pi-anthropic-link1.1.0
Companion pi extension for the built-in Anthropic provider (registers zero chat providers): the wallet (real rate limits, real token usage, real dollar cost from the Admin API, org/workspace/API-key browsing), the half-price Message Batches tools (anthrop
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-anthropic-link
A pi extension that manages your Anthropic account and exposes Anthropic's bulk-processing API to the agent — while leaving pi's built-in Anthropic chat support completely alone.
The first-principles explanation
Anthropic's API is really two APIs behind one door:
- Talk to Claude — the Messages API. Send a prompt, stream a reply, attach images, tools, thinking. This is the chat brain.
- Talk to Anthropic about your account — how fast am I allowed to go (rate limits)? What did I actually spend (real dollars, not estimates)? And a bulk side-entrance: the Batches API, which will do up to 100,000 Claude requests for half price… if you can wait up to a day.
pi already has a native, first-class connector for #1 — streaming, thinking, prompt caching, tool calling, Claude Pro/Max subscription auth, the works. A second chat connector would be strictly worse than the one pi ships with.
pi has nothing for #2. It can't see your rate limits. Its /cost shows
estimates computed from list prices — never your real bill. It cannot
submit a batch at all. That gap — and only that gap — is what this
extension fills.
So the mental model:
pi native = the brain. It talks to Claude. pi-anthropic-link = the wallet and the batch pipeline. It talks to Anthropic about your account — and hands the agent a half-price bulk queue for work that can wait.
They never overlap, never conflict, and this extension registers zero chat
providers: your /model list stays exactly as pi native built it.
What lives where
| Anthropic API surface | pi native | this extension | nobody — rejected forever |
|---|---|---|---|
| Send messages, stream replies, thinking, caching | ✅ the whole job | — | — |
| Images in chat | ✅ inline base64, already works | — | — |
Claude Pro/Max subscription (/login OAuth) |
✅ | — | — |
| Model list & prices | ✅ shipped catalog | — | — |
Per-message estimated cost (footer, /cost) |
✅ | — | — |
| Your real rate limits (req/min, input tok/min per model group) | ❌ | ✅ status bar + account panel | — |
| Your real usage (tokens by model/day, cache breakdown) | ❌ | ✅ account panel | — |
| Your real bill (actual USD from the cost report) | ❌ | ✅ account panel + bar | — |
| Claude Code usage stats (sessions, commits, PRs) | ❌ | ✅ account panel | — |
| Batches — bulk jobs at 50% off | ❌ | ✅ anthropic_batch_submit / _check tools + TUI browser |
— |
| Count tokens before sending | ❌ | 🟡 small pre-flight tool | — |
| Server-side tools (Anthropic-hosted web search, code execution, sandbox bash) | ❌ | — | ✅ rejected: your local bash and search tools are better and free |
| Files API, Memory Stores, hosted Agents/Sessions | ❌ | — | ✅ rejected: org-infrastructure / niche / churn-heavy |
(Rejected rows are decisions, not deferrals — see "What it never does" below.)
The tools it exposes
anthropic_batch_submit — a half-price bulk queue
Why it exists. Interactive Claude calls are full price. The Batches API runs up to 100,000 requests / 200 MB as one job, billed at 50% off input and output tokens, against rate limits that don't touch your interactive traffic. Anthropic charges full price for exactly the work this makes half-price — the extension exists to put that discount in reach.
What it's for. Bulk, independent, latency-tolerant work — the three words that decide every use:
- classify / summarize / extract structured data from hundreds of documents or logs
- eval runs — one prompt across many inputs, or many prompt variants
- translation, tagging, dedup triage at scale
- a review or doc-generation pass over every file matching a pattern
What it is not for — the caveats the tool itself spells out.
- Turnaround is up to 24 hours. Often much faster, never guaranteed. The tool description says this loudly, because the model choosing the tool only knows what the description tells it: never batch anything you need in this conversation.
- Single-turn only. Each request in a batch is one complete standalone
Messages call — there is no agentic loop inside a batch (a
tool_useresponse can't be continued). Multi-step work stays in pi's interactive loop at full price. - API-key billed. Subscription plans (Pro/Max) do not cover batches — no API key, no batch tool.
anthropic_batch_check — the other half of the workflow
Batches are asynchronous by nature, so the pattern is submit → note the
batch id → go live your life → check later (even in a later session). While
running: progress counts (processing / succeeded / failed). On completion:
full JSONL results written to disk, each keyed by your custom_id with its
own usage numbers, results kept ~31 days. Batches can also be cancelled.
🟡 anthropic_count_tokens — the pre-flight check
"Will this prompt fit the context window?" before you build it. Marked conditional: pi's footer already shows live context usage, so this earns its slot only if it turns out useful.
Both batch tools are model-agnostic
A registered pi tool is account-scoped, not model-scoped: if you're
chatting with a local lemonade model and say "batch-summarize these 500
transcripts with Claude," the agent calls anthropic_batch_submit and it
bills your Anthropic account — no Anthropic model needs to be active in pi.
Same pattern as your existing ollama_web_search and lemonade tools.
The status bar
While an anthropic-provider model is active, a single extra row
appears below the editor (pi's setWidget / belowEditor — the built-in
footer is never touched; the row disappears the instant you switch models):
🅐 anthropic · lim 50 req/min · 400k tok/min · $41.20 today
lim …— your real rate limits for the active model's group, from the Admin API$… today— your real spend, the one number pi's footer can never show (it only estimates)- honest degraded states:
no admin keywhen the wallet has no key, and last-known values under anofflinemarker
What it deliberately does not repeat: tok/s, per-turn cost, context usage — pi's own footer already shows those. The bar shows only what pi can't.
The two-key situation (the one real caveat)
Anthropic splits its API behind two separate keys, by design:
| Key | Powers | This extension's stance |
|---|---|---|
API key / OAuth (ANTHROPIC_API_KEY, /login) |
Chat + the batch tools | Nothing new to set up — the extension resolves it through pi's existing auth chain, the same credential pi already uses |
| Admin API key (created separately in the Admin Console) | Only the wallet: rate limits, usage, real cost, org browsing | The one new credential — and it's optional |
The admin key is separate on Anthropic's side, deliberately: it can be read-only, scoped to a single workspace, and revoked without touching your coding sessions. Nothing can collapse two keys into one.
Why optional is okay: without the admin key, everything still works —
the batch tools, the count tool, the whole extension. Only the account
surfaces degrade, and they degrade honestly: the bar shows a no admin key marker and the setup panel says exactly where to add one. Never a
cryptic 401, never fake data.
Billing nuance worth knowing up front: Pro/Max subscription auth covers chat. The batch tools (and billed server tools generally) are API-key billed — so subscription-only users get the wallet from the admin key alone, and full batch value requires an API key.
/anthropic-setup
One command, one navigable TUI (the family rule), read-mostly by design:
| Menu | What you see / do |
|---|---|
| Account status ⭐ | Live panel: rate limits per model group, real token usage by model/day with cache breakdown, real dollar cost report, Claude Code usage stats — refreshes while open, n/p cycles workspaces |
| Admin key setup | First-run item: paste the admin key, verify live, see your org name |
| Organization & workspaces | List workspaces, set the active one, browse members (read-only) |
| API keys | List org API keys — masked; rename (confirm-gated) |
| Batches | Browser: list batches with live status/counts, view requests, retrieve results, cancel/delete (gated) |
| Account settings | Endpoint paths, timeouts, poll cadences — config, applied immediately |
| Documentation | Browse snapshotted OpenAPI ground truth + on-demand spec-freshness check (see below) |
Configuration
Everything lives in ~/.pi/agent/anthropic.json — every endpoint is a
*Path key, created as a commented starter on first run, failing loudly if
broken, JSONC comments allowed, TUI edits applying immediately with no
/reload.
What it never does (rejected, not deferred)
- Registers or replaces a chat provider — impossible to disable pi's built-in, and pointless: you'd trade the best connector in the harness for a worse one
- Server-side web search / code execution / sandbox bash — your local tools are free and run on your real machine; Anthropic's are billed and sandboxed
- Files API, Memory Stores, hosted agents & Sessions streaming — niche, churn-heavy, and covered by pi's local equivalents
- Model discovery — pi's shipped catalog is richer than the listing endpoint
Keeping the specs honest
This extension is built against a snapshot of Anthropic's OpenAPI spec (see Ground truth below), and Anthropic's API moves. So on startup, the extension quietly checks the upstream spec files for changes — in two stages, so documentation churn never cries wolf:
- stage 1 compares each snapshotted yaml in
docs/against the upstream file via git blob SHA (the local file's SHA is computed at runtime, the remote SHA comes from GitHub's API; nothing big is downloaded). Matching SHAs end the check. - stage 2 runs only for files whose SHA drifted: the upstream yaml is
downloaded and compared against the local snapshot as a semantic
fingerprint — canonicalized structure with prose (
description,summary,title), examples, and ordering removed — and the drift is classified:- cosmetic — nothing semantic changed: the file is silently auto-re-synced so ground truth stays current. No warning.
- additive — only new surface upstream (new endpoints/schemas):
a quiet info notice at startup (new surface can't break anything
you use today) plus full status in
/anthropic-setup→ Documentation; an extension update may adopt the new surface when convenient. - changed — something was removed or altered (endpoint, parameter, request/response shape): a startup warning naming the concrete differences — the extension may be out of date.
- the check is fire-and-forget, never blocks startup, runs at most once a day, and is silent on network failure
- disable with
"specCheck": falsein the config
Ground truth
The OpenAPI snapshots in this extension's docs/ folder are taken from the
api-evangelist/anthropic
repo (OpenAPI 3.2 conversions of the official Anthropic API):
- Messages / batches / count_tokens: https://github.com/api-evangelist/anthropic/blob/main/openapi/anthropic-messages-api-openapi.yml
- Admin usage: https://github.com/api-evangelist/anthropic/blob/main/openapi/anthropic-usage-api-openapi.yml
- Cost report: https://github.com/api-evangelist/anthropic/blob/main/openapi/anthropic-cost-api-openapi.yml
- Organizations (rate limits, workspaces, API keys): https://github.com/api-evangelist/anthropic/blob/main/openapi/anthropic-organizations-api-openapi.yml
- Models: https://github.com/api-evangelist/anthropic/blob/main/openapi/anthropic-models-api-openapi.yml
Extension version & provider API
This extension's version (version in package.json) and the provider API
it was built and verified against are recorded together in the provider
block of package.json — neither the Messages API nor the (beta-gated) Admin
API self-reports a version number, so the peg is the docs snapshot date plus
live-behavior confirmation. The account status panel shows the extension
version and the ground-truth verdict in its header.
On update, keep these in lockstep (all record the same fact):
versioninpackage.json— the extension release- the
providerblock inpackage.json(apiVerifiedAgainst,specSnapshot) — what that release was verified against - re-sync
docs/in the extension folder from upstream (/anthropic-setup→ Documentation → Spec freshness → Re-sync) - the behavior-reference dates in
docs/behavior.md - this README's version claims (the sections above)
A release that skips any of these is lying somewhere — the spec-freshness check (see Keeping the specs honest) is what catches #3 drifting silently.
Development
npm run check # typecheck (requires TypeScript: npx -y tsc)
npm test # unit tests (pure functions; no network, no API key)
npm run smoke:live # live smoke against the real API (keys from the environment)
The package ships raw TypeScript sources (no build step), so module imports
use .ts extensions. npm test registers a TS loader (scripts/ts-loader.mjs)
that prefers node's native --experimental-strip-types but falls back to
jiti — the same loader pi itself uses for extensions — on node builds without
embedded TypeScript support.
Manual smoke checklist
Run through these after any change to the wallet or batch paths (the live script below automates most of it):
- First run / no config — delete
~/.pi/agent/anthropic.json, start pi: a commented starter is created, an info notice points at/anthropic-setup, and the batch tools register (with a notice if no Messages key is resolvable). - Broken config — write garbage into
anthropic.json, restart pi: a loud error banner names the file and the fix, and nothing registers. - Admin-key wizard —
/anthropic-setup→ Admin key setup → paste a realsk-ant-admin…key: it verifies live against/organizations/meand shows your org name. Then check Account status shows rate limits, usage buckets, real cost, and Claude Code stats; pressn/pto cycle workspaces (needs >1 workspace). - Batch lifecycle — with
ANTHROPIC_API_KEYexported, ask the agent to submit a tiny 2-request batch; note the id; check withanthropic_batch_check(in-progress counts → results written toanthropic-batches/once ended); confirm the batch browser in/anthropic-setup→ Batches lists it, cancel and delete work (delete is typed-phrase gated).npm run smoke:liveautomates the full loop. - Degraded mode — remove the admin key from the config (and unset
ANTHROPIC_ADMIN_API_KEY): everything else works; the status bar showsno admin key, the account panel shows the honest markers — never a cryptic 401, never fake data. - Spec freshness —
/anthropic-setup→ Documentation → Spec freshness shows per-file status. To exercise the tiers: append a comment line to anydocs/*.yml, delete~/.pi/agent/cache/pi-anthropic-link/spec-check.json, restart pi — nothing warns (cosmetic drift: the file is silently re-synced; the comment is gone afterwards). To see the warning path instead, make a semantic edit (e.g. change a parameter'stype:in any docs yaml): the startup warning names the drifted file and the concrete difference; Re-check now confirms, Re-sync re-downloads the yamls (and says the code was NOT updated). Restore the tampered file afterwards (or use Re-sync).