pai
    Preparing search index...

    Setting up coding agents

    This guide covers what pai setup changes for each coding agent, where it keeps the key, and how to undo it.

    For temporary agent configuration, use pai claude, pai codex or pai pi. See Run agents and choose how you pay. This guide covers permanent configuration changes and installing the agent skill.

    pai setup             # finds your agents, shows each file's changes, asks first
    pai setup --dry-run # shows the changes and writes nothing
    pai setup --yes # makes the changes without asking
    pai setup --model auto

    pai looks for each agent's folder in your home folder ( SETUP_AGENTS). For each one it finds, it installs the phantom-ai skill (if the agent reads skills) and points the agent's own model calls at Phantom AI. Before it writes anything it prints a diff of each file, with any key shown as sk-phantom-****, and asks Make these changes? [y/N]. Without a terminal to ask in, it stops and changes nothing; add --yes or --dry-run.

    Each agent starts on phantom-1 unless you pass --model ( SETUP_MODEL). With no key saved yet, setup installs the skills only and tells you to run pai login first.

    The older flags still run without asking: pai setup --agent <name> installs one agent's skill, --mcp adds the MCP server, and --agent <name> --provider points one agent at Phantom AI.

    pai writes what Vercel's vercel ai-gateway setup writes for each agent, with Phantom AI's addresses ( agentBaseUrl) and the key kept out of config files wherever the agent can read it some other way.

    Agent Found by What pai changes Address
    Codex ~/.codex (or $CODEX_HOME) config.toml: model_provider = "phantom", a [model_providers.phantom] table that reads the key from PHANTOM_API_KEY (env_key), the model, model_catalog_url, and [features] api_key_model_discovery = true; the key in the shell block /codex/v1
    Claude Code ~/.claude (or $CLAUDE_CONFIG_DIR) settings.json: apiKeyHelper runs pai key show; the env block sets ANTHROPIC_BASE_URL, CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1, ENABLE_TOOL_SEARCH, an empty ANTHROPIC_API_KEY, and ANTHROPIC_MODEL only with --model /claude-code
    opencode ~/.config/opencode/opencode.json (or $XDG_CONFIG_HOME) a phantom provider whose key is {env:PHANTOM_API_KEY}; model only with --model; the key in the shell block /coding-agent/v1
    Continue ~/.continue config.yaml: a model first in models: with apiKey: ${{ secrets.PHANTOM_API_KEY }}, and .onboarding_complete beside it; the key in the shell block /coding-agent/v1
    Goose ~/.config/goose (or $XDG_CONFIG_HOME) custom_providers/custom_phantom.json (api_key_env, a 1,000,000-token context limit for phantom-1), and GOOSE_PROVIDER and GOOSE_MODEL in config.yaml; the key in the shell block /coding-agent/v1/chat/completions
    Aider ~/.aider or ~/.aider.conf.yml ~/.aider.conf.yml: openai-api-base and model: openai/phantom-1; ~/.aider.model.metadata.json and ~/.aider.model.settings.yml for the context window and edit format; AIDER_OPENAI_API_KEY in the shell block /coding-agent/v1
    GitHub Copilot CLI ~/.copilot (or $COPILOT_HOME) the shell block only: COPILOT_PROVIDER_BASE_URL, COPILOT_PROVIDER_API_KEY, COPILOT_MODEL /coding-agent/v1
    Cline ~/.cline ~/.cline/data/settings/providers.json (mode 600): an OpenAI Compatible provider with the key, made the one Cline uses /coding-agent/v1
    Cursor ~/.cursor nothing; Cursor keeps models on its settings screen, so setup prints the steps and puts the key in the shell block to copy /cursor/v1
    pi ~/.pi the skill only

    Codex reads Phantom AI's model list (/codex/v1/models) only when its config has both model_catalog_url and api_key_model_discovery, so setup writes both. Vercel's setup leaves the model to you in Claude Code and opencode, and pai does the same unless you pass --model. Codex starts on phantom-1.

    Cline is the one agent whose config holds the key: it reads the key only from providers.json, with no variable or command to point it at. After pai rotate, run pai setup --agent cline --provider again. If Cline already has an OpenAI Compatible provider at another address, pai leaves it alone and says so.

    Apart from Cline, pai never writes the key into an agent's config file. Claude Code asks for it by running pai key show, which also works when you start Claude Code outside a terminal. The agents that read a variable get PHANTOM_API_KEY from a block pai adds to your shell's startup file ( shellBlock), as Vercel's setup does with its own key:

    $SHELL File
    zsh ~/.zshrc (or $ZDOTDIR/.zshrc)
    bash ~/.bash_profile on macOS, ~/.bashrc elsewhere
    fish config.fish in $XDG_CONFIG_HOME/fish, else ~/.config/fish
    anything else ~/.profile

    The block sits between # >>> pai setup >>> and # <<< pai setup <<<. When a shell starts, it leaves a PHANTOM_API_KEY you set yourself alone. Otherwise, on macOS, it reads the key from the Keychain item your login key points to; elsewhere, or with PHANTOM_KEY_NAME set, it runs pai key show. Open a new terminal after setup so the agents see the variable. Desktop apps started from the Dock don't read this file; Vercel's setup doesn't cover them either. Claude Code (through apiKeyHelper), Goose's desktop app (through config.yaml, once PHANTOM_API_KEY is set) and Cline don't depend on it for their settings.

    Because the block sets PHANTOM_API_KEY to your login key, pai rotate and pai burn treat that variable as the login key: rotate saves the new key as the login key, and burn forgets it.

    Like Vercel's setup, pai shows each file's changes before writing and copies each file it edits first. pai names the copy <file>.pai.bak, so it never overwrites a .bak of your own. Later runs keep that first copy as long as the file is still as pai left it. pai records each file it changed in setup-backups.json in the state folder ( applySetup).

    pai setup --provider off                 # remove what pai wrote, for every agent found
    pai setup --agent codex --provider off # for one agent
    pai setup --restore # put back the .pai.bak copies
    pai setup --restore --agent codex

    --provider off removes only what pai wrote. In TOML, YAML and shell files every line pai adds ends with # pai setup, and a line pai replaced stays above it as a comment starting # pai setup was:, which --provider off turns back into the line. JSON and JSONC files are edited with jsonc-parser, as in Vercel's setup: pai changes only the keys it sets, keeps comments, trailing commas, key order and indent, and formats only the text it adds, so --provider off gives back the same bytes. In them pai removes its own entries: the phantom provider, a model starting phantom/, Claude Code's apiKeyHelper and the variables it set, Cline's OpenAI Compatible provider at Phantom AI's address, and the Aider metadata entries marked "pai": true. Goose's custom_phantom.json is removed. Vercel's setup has no undo command; --provider off and --restore are pai's own.

    --restore copies each .pai.bak back and removes files pai created ( restoreSetup). It skips a file that changed after pai wrote it, since the copy would undo that change too. Codex adds [projects."..."] tables when you trust a folder, so its config often counts as changed. Use --provider off for such a file.

    pai checks each file before it changes anything, and skips an agent whose file it can't read: JSON with a syntax error (comments and trailing commas are fine), TOML that doesn't parse (pai checks TOML with smol-toml, the parser Vercel's setup uses, before and after each edit), a TOML key set in a way a line edit can't change, such as an inline table, YAML indented with tabs, a models: [...] list on one line, a top-level YAML key whose value runs over several lines, or a shell file with a # >>> pai setup >>> line and no end line. The output names the file and the reason, the exit code is 1, and the other agents are still set up. pai also skips a file that changed between the preview and the write.

    The supported setup interface is planSetup, previewSetup, applySetup, and restoreSetup. setupAgents combines planning and applying for callers that have already approved the changes.

    import { planSetup, previewSetup, applySetup } from '@connortessaro/pai';

    const plan = planSetup(process.env, { agent: 'codex', provider: true });
    console.log(previewSetup(plan));
    // After reviewing the preview:
    const result = applySetup(process.env, plan);

    A plan includes the skill, provider settings, and shell changes for the chosen agent. Applying it keeps backups and skips files that changed after planning. Use restoreSetup to undo those writes without overwriting later edits.

    Configuration editors, shell helpers, agent definitions, and their internal planning types remain exported for compatibility, with deprecation notices. Use the setup interface for new code; removal of compatibility exports belongs to a future major release. claudeProvider also remains callable: it changes only Claude settings and now uses the shared backup writer.