Comment threads keep filing Pi as “another Claude Code substitute.” Install it and the omission is deliberate: no built-in sub-agent, no plan mode. What actually stings is a different lock-in. Your keys still live inside one vendor subscription, so swapping models means swapping the window, the permissions, and the whole workflow. This article tests whether what you lack in 2026 is a thicker IDE—or a minimal harness that can swap Claude, GPT, and Gemini, and sit inside a TypeScript repository.
As of September 16, 2026, Pi Coding Agent (npm: @earendil-works/pi-coding-agent) is a minimal terminal coding harness with four openings onto the same loop: an interactive TUI, print/JSON, RPC, and a TypeScript SDK. Below we split npm install, API keys and auth.json, switching across the three providers, and the path for writing the SDK into a repo—along the axes of entry, execution, and context. This is not another “who is smarter” review.
Why “one more IDE agent” cannot solve multi-model
Most teams in 2026 are not short of agents. They are short of a way to keep keys, models, and the execution host from collapsing into a single vendor product. Claude Code eats an Anthropic subscription. Codex CLI eats ChatGPT. Cursor hides model choice inside the editor account. You want Claude for an afternoon of architecture edits, Gemini for a night of test sweeps, and GPT for weekend commit notes—and every switch costs a new window, a new permission grant, and a new pile of context you cannot take with you.
That is not a model-quality problem. It is a product-shape problem. When the chat window, the billing account, and the tool loop are the same object, “try the other model” is not a one-line change. It is a migration. People then go shopping for the next IDE agent, hoping a thicker sidebar will finally let them keep one workflow while the backends rotate. The sidebar gets prettier. The keys stay locked.
Pi splits that assumption. Official positioning is a minimal harness: by default the model only gets read, write, edit, and bash. Features other products bake in—sub-agents, plan mode, permission gates, MCP—become extensions, Skills, or a Pi Package that you add when the workflow actually needs them. The model is a swappable backend, not the product itself. That sounds austere until you have lived through a quarter of “we standardized on one agent” and then a procurement freeze on that vendor’s next model family.
The asymmetric conclusion is this: the divide is not which of Claude, GPT, or Gemini is smarter, but whether the harness treats models as swappable execution backends and can embed in your own TypeScript project. What you should upgrade is the entry (CLI / SDK / RPC), credential layering, and an always-on execution node—not yet another thicker IDE. For a conceptual breakdown of “what a harness even is,” see Agent Harness, Explained: Omnigent in 2026. This piece only solves how to install Pi, attach three keys, and write the loop into a repo.
If you already live inside one official CLI and have no second bill, you can stop early and keep that CLI. Pi’s advantage only shows up when the second key exists, or when a reviewer script has to run without a human sitting in a chat box. The rest of this article assumes you want that option, even if week one only proves a single key.
What Pi is: four entry points of a minimal harness
Classify first, then talk commands. Pi is not another chat window. It is four ways to open the same agent loop. The classification axes are still entry, execution, context, and who it is for. Teams that skip this step usually install the TUI, never discover -p or the SDK, and then declare the tool “just a terminal Claude.” That is a usage error, not a product review.
| Tool / Form | Entry Point | Execution Capability | Context | Best For |
|---|---|---|---|---|
| Interactive TUI | pi; /model, /login, /tree | Read, write, and edit files; run bash; optional Skills / extensions | Session tree under ~/.pi/agent/sessions/; loads AGENTS.md | People who edit a repo daily and need to steer mid-task |
| Print / JSON | pi -p "…"; --mode json | One-shot tasks; fits scripts and CI | Sessions writable by default; --no-session if you want none | People stuffing an agent into a Makefile or GitHub Actions |
| RPC | stdin/stdout JSON protocol | Non-Node hosts drive the same loop | The host owns sessions and permissions | People embedding Pi in an existing gateway or desktop shell |
| TypeScript SDK | createAgentSession() / ModelRuntime | Same tools and model catalog as the CLI | Sees cwd and ~/.pi/agent by default; auth path is overridable | People writing review, fix, and patrol pipelines inside the repo |
The site states the philosophy without decoration: change the harness, not your workflow. Extensions are TypeScript modules that can register tools, slash commands, shortcuts, and TUI widgets. Skills load on demand so you do not blow the prompt cache on every launch. Packages install with pi install npm:@scope/pkg or pi install git:host/user/repo. Treat the capability list on pi.dev and the npm package notes as source of truth. Version numbers move; the command shape is more stable than “the model name from some Tuesday in March.”
That last point is easy to skip and expensive later. A README that hard-codes last month’s Opus snapshot will fail the first time the catalog refreshes. A README that says “export a key, run pi --list-models, then call the SDK with getAvailable()” still works after the refresh. The harness is the contract. The model ID is inventory.
Pi vs. closed agents: entry, execution, context
If a bake-off opens with “is Claude stronger than GPT?”, you have already missed the difference that will survive next quarter’s model card. Put Pi, an official CLI, and an IDE agent on one table. Align them on entry, execution, context, and audience. The ranking almost always flips. For a leaderboard-style write-up, see Best AI Coding Agent Ranking 2026. This article does not re-rank anyone. It only asks whether you should pull the keys out of the product.
| Tool / Form | Entry Point | Execution Capability | Context | Best For |
|---|---|---|---|---|
| Pi Coding Agent | TUI / -p / RPC / SDK | Four default tools plus optional extensions; models hot-swap | AGENTS.md, session tree, project .pi/ | People who need multi-model and want the agent written as a repo script |
| Claude Code / Codex CLI | Official terminal; subscription or vendor key | Deeply bound to the house model and house workflow | Vendor sessions and vendor rule files | People already bought into one house who only want the boxed experience |
| Cursor / IDE agent | Editor sidebar and inline diffs | Best file-edit feel; weak as a script | The open repo plus the editor account | People who interactively edit code and do not write pipelines |
| Homegrown function calling | Your own HTTP / JSON loop | Full control, but you rewrite tools and sessions | Your schema and your storage | When the product itself is an agent, not “an agent that writes code” |
How Claude Code and Codex trade off on a remote Mac is covered in Claude Code vs Codex: remote Mac development environments. Those pieces answer “which official CLI should I pick.” This one answers “once you already know you want multi-model and you want the loop inside TypeScript, how do you install the harness.”
A useful honesty check before you migrate: if your team’s only daily motion is “open the sidebar, accept the diff, push,” an IDE agent is still the right surface. Pi does not try to beat inline diffs. It tries to make the same tool loop callable from a Makefile, a GitHub Action, and a scripts/ file without cloning the chat UI three times. If you do not have that second surface, you are paying a harness tax for a flexibility you will not use.
npm install and API key setup
Global CLI: talk first, embed later
The official recommendation is a global install with --ignore-scripts. Normal Pi use does not depend on dependency install-lifecycle scripts; skipping them cuts a class of supply-chain surprise. Pin Node to whatever LTS you already run. The engine range declared in the package will move. Do not treat a minor version from a blog post as a contract with your platform team.
npm install -g --ignore-scripts @earendil-works/pi-coding-agent # or: pnpm add -g --ignore-scripts @earendil-works/pi-coding-agent # or: bun add -g --ignore-scripts @earendil-works/pi-coding-agent # installer alternative: curl -fsSL https://pi.dev/install.sh | sh pi --version
After install, do two things before you judge the product. Confirm pi is on PATH. Confirm the provider you intend to use has at least one key or one completed /login. Without credentials the TUI still opens, but the runnable items in the model catalog are empty. That empty catalog is the most common “it installed but nothing works” report, and it is not a bug in the harness.
If PATH is messy—nvm, fnm, Homebrew Node, and a CI image that still has an old global npm prefix—fix that before you debug models. which pi and pi --version should agree across a new shell. On a cloud Mac image, bake the Node version and the global prefix into the image instead of hoping each SSH session inherits your laptop’s nvm.
How to layer keys: environment variables, auth.json, one-shot overrides
Official credential resolution order is: command-line --api-key → ~/.pi/agent/auth.json → process environment variables → custom provider keys in models.json. In the TUI, /login writes OAuth or an API key into auth.json (file mode 0600). auth.json beats the environment, which fits “this machine lives on this key.” Environment variables fit CI and one-off experiments. SDK setRuntimeApiKey is an in-process override that does not hit disk, which fits tests and multi-tenant hosts.
That order is the whole security model in miniature. A developer laptop can keep long-lived keys in auth.json and never export them into a shell that might get pasted into a ticket. A GitHub Action should never have an auth.json in the checkout; it should inject Secrets as env vars for the length of the job. A host that runs reviews for several teams should use runtime keys and never share a home-directory file. Mixing those three patterns on one box is how keys leak—not because Pi is sloppy, but because the highest-priority source wins silently.
export ANTHROPIC_API_KEY=sk-ant-... export OPENAI_API_KEY=sk-... export GEMINI_API_KEY=... # auth.json key name is google pi # interactive: /login to pick a provider; /model or Ctrl+L to switch; Ctrl+S to save as the startup default
{
"anthropic": { "type": "api_key", "key": "sk-ant-..." },
"openai": { "type": "api_key", "key": "sk-..." },
"google": { "type": "api_key", "key": "..." }
}
The key field also accepts $ENV_VAR interpolation and command substitution such as !op read 'op://…' (cached in-process). On a remote or headless machine, browser-callback flows like OpenRouter often cannot complete; the official path is to paste the final redirect URL or authorization code back into the login prompt—especially common on an SSH cloud Mac. Use providers.md as the provider table, not a guessed key name from another SDK.
auth.json; the developer machine uses environment variables or 1Password. An SDK runtime key is for a single task. It is not “shared team config” you commit to git.
Wiring Claude, GPT, and Gemini
Pi keeps a “models that can run tools” catalog for each built-in provider. Configured catalogs refresh on their own; pi update --models forces a pull. Auth can be a subscription (Claude Pro/Max, ChatGPT Plus/Pro Codex, GitHub Copilot) or an API key. Switch with /model or Ctrl+L; cycle favorites with Ctrl+P. /scoped-models decides what that cycle contains.
The practical habit is to keep all three keys on the machine and a short scoped list of models you actually pay for. A twelve-item cycle sounds powerful and becomes a tax: people land on a reasoning-heavy snapshot for a “list the files” job and then wonder why the invoice moved. Scope the list. Keep the expensive model one /model away, not on the default keystroke.
| Provider | Environment variable | auth.json key | CLI entry | Best For |
|---|---|---|---|---|
| Anthropic Claude | ANTHROPIC_API_KEY | anthropic | pi --provider anthropic; /login can also use Pro/Max | People who want long-context architecture edits and will pay extra token usage |
| OpenAI GPT | OPENAI_API_KEY | openai | pi --model openai/gpt-4o; /login can also use a Codex subscription | People who already have an OpenAI bill and want to share the key with existing API scripts |
| Google Gemini | GEMINI_API_KEY | google | pi --provider google; use --list-models for concrete IDs | People who want a cheap repo sweep, or already have a Gemini console project |
pi --list-models claude pi --list-models gpt pi --list-models gemini pi --provider anthropic --thinking high "Refactor the loops in src/ into testable functions" pi --model openai/gpt-4o -p "Summarize this repo's entry modules in three sentences" pi --provider google -p "Read-only: list test files that are not covered" # switch inside the session — no reinstall # /model or Ctrl+L # Ctrl+P cycle the scoped list
Model IDs change when the catalog refreshes. Official examples have used spellings such as claude-opus-4-5, claude-sonnet-4-5, gpt-4o, and gpt-5.1. At install time, trust pi --list-models and the SDK’s getAvailable(). Do not bake a blog snapshot ID into a production script. Custom gateways (Ollama, vLLM, a company proxy) go through ~/.pi/agent/models.json, provided the other side speaks one of the OpenAI, Anthropic, or Google APIs. OAuth or a private protocol belongs in an extension. Do not fork the CLI to paper over a login flow.
If what you actually want is “I write the HTTP, I parse the JSON,” that is the function-calling layer, not the harness layer. Compare Function calling and the JSON API across OpenAI, Gemini, and Claude and GPT-5.6 API tutorial: calling, pricing, and models: those pieces teach you to hit the provider directly. This one teaches Pi to own the tool loop while you only swap the backend.
A clean acceptance test for “the backend really is swappable” is boring on purpose. Write one prompt—“list TypeScript entry files, do not edit”—and run it once per provider with the same AGENTS.md. If the three answers disagree about which files exist, you have a context problem, not a model-IQ problem. If they agree on the files and differ on taste, that is the point of a swappable backend. Keep the rules in the repo. Keep the taste in the model picker.
TypeScript project walkthrough
The CLI solves “a human directs from a terminal.” The SDK solves “a script in the repo can direct too.” The SDK ships in the same npm package; you do not install a second product. The minimum loop is: local dependency → three keys only in the environment → ModelRuntime picks a model → createAgentSession sends one read-only task → dispose().
Treat that loop as a product surface, not a demo. Once a script can open a session, choose a model, restrict tools, and exit cleanly, you can hang it off npm run review, a pre-push hook you only enable on a cloud node, or a scheduled Action. The temptation is to jump straight to “let it open PRs.” Resist it. A read-only script that prints a finding is an agent you can audit. A script with write and edit enabled “because we might need it” is an unsupervised intern with your git credentials.
npm init -y npm install @earendil-works/pi-coding-agent # add "type": "module" to package.json
import {
createAgentSession,
ModelRuntime,
SessionManager,
} from "@earendil-works/pi-coding-agent";
const runtime = await ModelRuntime.create();
if (process.env.ANTHROPIC_API_KEY) {
await runtime.setRuntimeApiKey("anthropic", process.env.ANTHROPIC_API_KEY);
}
if (process.env.OPENAI_API_KEY) {
await runtime.setRuntimeApiKey("openai", process.env.OPENAI_API_KEY);
}
if (process.env.GEMINI_API_KEY) {
await runtime.setRuntimeApiKey("google", process.env.GEMINI_API_KEY);
}
const preferred =
runtime.getModel("anthropic", "claude-opus-4-5") ??
runtime.getModel("openai", "gpt-4o") ??
(await runtime.getAvailable())[0];
if (!preferred) {
throw new Error("No available model: export one of the three keys first, or run pi --list-models");
}
const { session } = await createAgentSession({
model: preferred,
thinkingLevel: "low",
tools: ["read", "bash"],
sessionManager: SessionManager.inMemory(),
modelRuntime: runtime,
});
try {
session.subscribe((event) => {
if (
event.type === "message_update" &&
event.assistantMessageEvent.type === "text_delta"
) {
process.stdout.write(event.assistantMessageEvent.delta);
}
});
await session.prompt(
"Read-only: list the TypeScript entry files in the current directory, and point to the place most likely missing tests. Do not change files."
);
} finally {
session.dispose();
}
The sample deliberately shrinks tools to read + bash and keeps the session in memory, not on disk. A CI review script should not own write / edit by default. For a durable session, switch to SessionManager.create(process.cwd()). To share the same long-lived key as the CLI, do not call setRuntimeApiKey; let the runtime read ~/.pi/agent/auth.json. When you customize auth paths, point authPath / modelsPath at the application’s own directory so multiple services do not fight over one home-directory file. Event, steer, and follow-up semantics live in sdk.md.
AGENTS.md: write the repo rules once for every model
On launch, Pi concatenates ~/.pi/agent/AGENTS.md with parent-directory and current-directory AGENTS.md (or CLAUDE.md). If a layer has AGENTS.override.md, that layer loads only the override. This is the concrete landing spot for “swap the model, keep the rules”: Claude, GPT, and Gemini read the same entry points, test commands, and red lines. Replace the system prompt with .pi/SYSTEM.md; append with APPEND_SYSTEM.md.
# Rules this repo gives Pi - Package manager: npm. Do not switch to pnpm on your own. - Checks: npm test && npm run lint - Red lines: do not commit .env, auth.json, or *.pem - Read-only by default; use write/edit only when the user explicitly says files may be changed
Headless CI will not pop a project-trust dialog. When no saved trust decision exists, non-interactive mode follows the global defaultProjectTrust: ask (default) and never ignore project-level .pi/ resources; only always trusts them. One-shot overrides are --approve / --no-approve. When you drop Pi onto a self-hosted runner, bake the trust policy into the machine image before you debate models. For the layering of GitHub Actions and cloud Mac runners, see GitHub Actions macOS self-hosted runners and cloud Mac 2026.
Two versioning rules save pain. Humans use the global CLI and can float with npm update -g when they want new TUI behavior. Scripts lock the SDK version in the repo package.json so a Friday CLI upgrade does not change what CI does on Monday. Both may read ~/.pi/agent. Do not let a script’s runtime key silently override the machine’s long-lived key unless that is the documented contract for that job.
How to choose by scenario
The real question is not “should I install Pi.” It is which constraint comes first: interactive edits, an agent written as a script, or the boxed experience of one official CLI. If you cannot name that constraint, you will install everything and then blame the harness for being “too thin” in the editor and “too chatty” in CI.
| Your situation | Recommendation | Reason |
|---|---|---|
| Claude in the afternoon, Gemini at night, no window-switching | Pi TUI + three keys + /model | The divide is a swappable backend, not another IDE |
| Reviews / fixes must live as repo scripts | SDK as a project dependency; CI uses pi -p or tsx scripts/pi-review.ts | The entry is a script, not a chat box; the tool allowlist lives in code |
| Already bought into Claude or ChatGPT; only want the official workflow | Stay on Claude Code / Codex; do not pay a harness tax for “multi-model” | Without a second key, Pi’s advantage does not show up |
| The product itself needs a custom agent protocol | Function calling + your own sessions; Pi is at most an internal coding assistant | Pi is a coding harness, not your product runtime |
| Need the agent 24/7; a closed laptop lid kills it | Always-on cloud Mac + machine-level auth.json + print/SDK | Long tool loops hate sleep; the execution host fails before the model name does |
For the product judgment of “why a cloud Mac is the agent execution layer,” see Why Cloud Mac became the 2026 iOS dev default. This article fills in the layer that sits on that node: npm, keys, model switching, and TypeScript scripts.
Recommended stacks
Stacks can layer. Pi solves “a coding harness with swappable models.” It does not give you a Mac that never closes its lid, and it does not pay your three provider invoices. Pick a stack that matches the first constraint in the matrix, then add a second surface only after the first one is reproducible.
- Personal daily stack: global
pi+ANTHROPIC_API_KEYas the default + the other two keys on standby + a repoAGENTS.md. Switch models withCtrl+Lin the session. The rules do not switch. This is the cheapest way to feel the divide without writing a script. - TypeScript repo stack: the global CLI is for humans; a second copy of the SDK lives in
devDependenciesfor scripts. Reviews use read-only tools. File edits get a separate command that a human has to confirm. Lock the SDK version the same way you lock the test runner. - CI stack:
pi -por an SDK script + GitHub Actions Secrets + a self-hosted macOS runner. Freeze trust with--approve. Never print keys in logs. Prefer a machine image that already has Node, PATH, and file mode0600on anyauth.jsonyou keep off-repo. - Multi-provider gateway stack: one OpenRouter / Cloudflare AI Gateway key in front of several models; still switch with Pi’s
/model. Fits teams that do not want three first-party keys scattered on every laptop. You still need an allowlist and a bill owner—the gateway does not erase cost, it only centralizes it. - Minimal validation stack: install only the CLI, export only one key, run
pi -p "list the ts files in the current directory". Clear the four beats (install → credentials → one task → reproducible) before you add a second model or the SDK. If that one-liner fails, the rest of this article will not save you.
A multi-agent classroom or an IM digital twin is not Pi’s home field. Those need orchestration and a gateway—see What OpenMAIC’s rise means for multi-agent collaboration. Pi is for “the same read-edit-run loop, swap the backend, keep going.”
Common pitfalls
- Reading Pi as a free Claude Code clone. It deliberately skips sub-agents and plan mode. Add those with an extension or a Package if you need them. Do not complain that “the core is too thin” and then wait for the next IDE. Thin is the point: the loop stays embeddable.
- Stuffing three keys into one dotenv that will be committed. Developer machines use a shell profile or 1Password. CI uses Secrets. Shared machines use
auth.jsonat mode0600. An SDK runtime key does not hit disk and cannot replace a machine credential. If a key has ever lived in the repo, rotate it; do not “fix the gitignore and hope.” - Hard-coding a blog’s model ID into production. Catalogs refresh. Scripts should call
getAvailable()or--list-models, then fall back on a stable provider prefix. Snapshot IDs belong in a comment, not in arequired:field. - Giving the agent default
write/editin CI. Reviews and patrols use a read-only allowlist. File changes get a human latch. “The model is careful” is not a permission model. - Expecting a trust dialog in headless mode. Set
defaultProjectTrustor pass--approvefirst, or project-level Skills will not load and you will debug “why is CI dumber than my laptop” for a day. - Running a long SDK job on a laptop that sleeps. The session tree can resume, but side effects from a bash command interrupted by sleep do not roll back. Put long jobs on an always-on node. Lid-close is an infrastructure bug, not a model bug.
Implementation steps
- Write the non-negotiables: interactive only, scripts only, or both; whether week one must attach all three models; whether CI is allowed to write to disk. If you cannot answer those three, do not install yet—you will optimize the wrong surface.
- Install the CLI and do an empty run:
npm install -g --ignore-scripts @earendil-works/pi-coding-agent, thenpi --version, and confirm PATH in a fresh shell. - Attach only one key: export or
/login, thenpi -p "list the current directory". The acceptance bar is “reproducible,” not “a longer reply.” Save the exact command in the repo README. - Attach the second and third providers: add
OPENAI_API_KEY/GEMINI_API_KEY, run the same prompt with/modelor--provider, and confirm the rules come fromAGENTS.mdrather than from the model’s mood. - Write the SDK into the repo: project dependency plus one read-only
scripts/pi-review.ts. The tool allowlist is hardcoded. Fail the job if no model is available instead of silently skipping. - Pick the execution host: a laptop is fine for learning. CI and long jobs go on an always-on cloud Mac or a self-hosted runner. Redact logs. Keys never enter artifacts.
- Only then add extensions and observability: install a Package when you actually need plan mode, MCP, or a permission gate. Meter usage, failure fallback, and human takeover before you widen the tool list.
FAQ
How does Pi Coding Agent relate to Claude Code?
Claude Code is Anthropic’s official coding workflow: the model and the entry are the same product. Pi is a third-party minimal harness. It can use an Anthropic key or a Claude subscription, and it can also attach OpenAI and Gemini at the same time. It does not replace “deep official integration.” It replaces “switching models means switching the entire toolchain.” If you only have one Anthropic seat and you like that seat, keep Claude Code. If you already pay two bills and you want one AGENTS.md, Pi is the thinner layer in the middle.
Do I have to configure Claude, GPT, and Gemini at the same time?
No. One key is enough to pass the install acceptance test. The point of a second key is that the same AGENTS.md and the same tool allowlist can change backends per task. If you do not have a second bill, do not grow the ops surface for the slogan “multi-model.” Add the second provider the week you have a real reason—nightly cheap sweeps, a backup when one vendor rate-limits, or a review model that is not also the implementation model.
Will a global npm install fight the SDK in the project?
They will not steal the same command, but versions can drift. Convention: humans use the global CLI; scripts lock the version in the project package.json. When both read the same ~/.pi/agent, do not let a script’s runtime key overwrite the machine’s long-lived key unless that job is documented as ephemeral. If you need isolation, point the SDK at its own authPath and leave the CLI on the home-directory file.
Why is Gemini’s environment variable not GOOGLE_API_KEY?
The official table spells the Gemini API key as GEMINI_API_KEY, while the auth.json key is google. Vertex uses ADC plus project/region variables, which is not the same road as an AI Studio Gemini key. Trust providers.md. Do not guess key names from “what Google usually calls things.” Mixing Vertex ADC and an AI Studio key on one host is a common source of “it works in the TUI and fails in CI.”
Can I install on Windows or a headless cloud Mac?
Yes. The global npm package is cross-platform; the site also ships install.sh and a PowerShell installer. On a headless machine use pi -p, RPC, or the SDK—do not depend on the TUI. OpenRouter-style OAuth on SSH needs you to paste the callback. On a cloud Mac, freeze Node, PATH, and auth.json permissions before you debate models. A reproducible image beats a clever dotfiles repo that only works when you are logged in.
Why a cloud Mac at all? Isn’t npm on a laptop enough?
A laptop is enough to learn the commands. It is not enough for overnight reviews, a long fix that continues after the lid closes, or CI that must share an environment with Xcode and signing. Pi decoupled the model. Bash and the file tools are still bound to the machine that is running the process. If that machine sleeps, the loop sleeps. If that machine is a different OS than the one you ship, the agent is reviewing a fantasy.
Conclusion
A Pi Coding Agent setup tutorial looks like npm, environment variables, and three model IDs. What you actually have to land is a split: harness apart from model, keys apart from the repo, interactive entry apart from the script entry. The usage that still stands in September 2026 is global CLI for humans, SDK for the repo, AGENTS.md for every backend, and an always-on node for long jobs.
The asymmetric conclusion still holds: the divide is not which of Claude, GPT, or Gemini is smarter, but whether you can treat the model as a swappable backend and embed that loop in TypeScript. Clear one key and one pi -p first. Then add a second model and a TypeScript script. When you need an execution plane, move the process off a sleeping laptop onto a cloud Mac. Upgrade the entry, the credentials, and the node—not the next IDE agent.
Pi decoupled the model, but bash is still bound to that machine
SDK reviews, print-mode patrols, and overnight fixes all want a host that never closes its lid: a stable Node version, a reproducible PATH, auth.json locked down, logs you can audit. Hashvps provides native macOS cloud Macs with dedicated IPv4, so you can keep the Pi CLI, TypeScript scripts, and the Xcode toolchain on one always-on node—leave the model bill with the provider, leave execution in the data center.
Stabilize the agent’s execution plane first, then debate which model to swap — see Hashvps plans and regions, and decide npm, keys, and the cloud Mac node independently.