omp packages

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

prawnbear Published 10 days ago MIT ~437 downloads/mo

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.

Did it work for you?

Result

One report per person. A new report replaces your old one.

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:

  1. Talk to Claude — the Messages API. Send a prompt, stream a reply, attach images, tools, thinking. This is the chat brain.
  2. 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_use response 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 key when the wallet has no key, and last-known values under an offline marker

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": false in 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):


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

  1. version in package.json — the extension release
  2. the provider block in package.json (apiVerifiedAgainst, specSnapshot) — what that release was verified against
  3. re-sync docs/ in the extension folder from upstream (/anthropic-setup → Documentation → Spec freshness → Re-sync)
  4. the behavior-reference dates in docs/behavior.md
  5. 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):

  1. 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).
  2. Broken config — write garbage into anthropic.json, restart pi: a loud error banner names the file and the fix, and nothing registers.
  3. Admin-key wizard — /anthropic-setup → Admin key setup → paste a real sk-ant-admin… key: it verifies live against /organizations/me and shows your org name. Then check Account status shows rate limits, usage buckets, real cost, and Claude Code stats; press n/p to cycle workspaces (needs >1 workspace).
  4. Batch lifecycle — with ANTHROPIC_API_KEY exported, ask the agent to submit a tiny 2-request batch; note the id; check with anthropic_batch_check (in-progress counts → results written to anthropic-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:live automates the full loop.
  5. Degraded mode — remove the admin key from the config (and unset ANTHROPIC_ADMIN_API_KEY): everything else works; the status bar shows no admin key, the account panel shows the honest markers — never a cryptic 401, never fake data.
  6. Spec freshness — /anthropic-setup → Documentation → Spec freshness shows per-file status. To exercise the tiers: append a comment line to any docs/*.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's type: 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).