Recipes

Running locally

Your machine, your API keys, your MCP connections.

Two entry points, and they produce the same directory. Start with Pi to write the files yourself, or use the Introspection plugin to have a coding agent build them with you.

Start with Pi

Install the extension once, then point Pi at any recipe directory. Clone one that already runs, read it, then change the parts where your work is different.

pi install npm:@introspection-ai/recipes   # once per machine

git clone https://github.com/introspection-recipes/template-claude
pi --recipe ./template-claude

That one has no dependencies, so there is nothing to install inside it. To start from nothing instead, the two files in the smallest recipe are the entire requirement: no build step, no install store, no publish command. Requires Node.js 24 or later and Pi ^0.82.

Start with Introspection

Install the CLI, then run setup. Setup prepares Pi, the compatible Recipes extension, and the Introspection plugin for every detected Codex and Claude Code host. It shows the complete plan and asks before changing anything; Pi remains an independent, user-owned command.

npm install --global @introspection-ai/cli
introspection setup

After setup finishes, open the repository where the recipe should live in Codex or Claude Code and describe the agent you need. A new task discovers the installed workflow automatically. The plugin defines the job with you, creates or migrates the smallest useful recipe, proves it in fresh Pi sessions, and returns the local run command.

Build me an agent that <describe your agent>

Setup also reports the installed skills directory. The coding agent that ran setup can load the relevant SKILL.md from that path and continue in the current session; later tasks discover it automatically.

Model API keys

Locally, credentials come from your environment. A recipe never names an environment variable, which is why the same package also runs on a host that supplies credentials another way. The variable is derived from the provider in ai.model.

Provider prefixReads
anthropic/ANTHROPIC_API_KEY or ANTHROPIC_OAUTH_TOKEN
openai/OPENAI_API_KEY
google/ or gemini/GEMINI_API_KEY
openrouter/OPENROUTER_API_KEY
anything else<PROVIDER>_API_KEY
export ANTHROPIC_API_KEY='sk-ant-…'
pi --recipe .
// From your own process, omit credentials to read the same variables.
const handle = await createAgentSession({ recipe, agentName: "agent" });

A missing key is a launch failure, not a failure three tool calls in. Credential resolution happens before the session starts and raises RecipeCredentialError naming the provider it wanted.

MCP endpoints

The package declares which servers a recipe may use. Where those servers actually live is local configuration, because it differs per machine and per environment.

.pi/mcp.local.json
{
  "servers": [
    {
      "id": "contacts",
      "transport": "streamable_http",
      "url": "https://contacts.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${CONTACTS_MCP_TOKEN}"
      }
    }
  ]
}

Header values stay environment references and resolve at launch, so no token is ever written into the workspace. Export it first:

export CONTACTS_MCP_TOKEN='…'
pi --recipe .
// The same file, read explicitly instead of by convention.
await createAgentSession({
  recipe,
  agentName,
  mcpBindingsPath: ".pi/mcp.local.json",
});

OAuth servers

Declare auth: "oauth" on a local server definition to enable it.

.pi/mcp.local.json
{
  "servers": [
    {
      "id": "linear",
      "transport": "streamable_http",
      "url": "https://mcp.linear.app/mcp",
      "auth": "oauth",
      "oauthClientSecretEnv": "LINEAR_OAUTH_CLIENT_SECRET",
      "oauthRedirectUrl": "http://127.0.0.1:8787/callback"
    }
  ]
}

A recipe session uses cached credentials only and never opens a browser. That is deliberate: an agent cannot authenticate itself into a system you had not already connected. Complete or refresh the flow yourself and retry. A launch projects your local definitions into .pi/mcporter.json, so authenticate against that:

npx mcporter auth linear --config .pi/mcporter.json

Until then the agent gets a deployment-neutral message telling it to ask you to authenticate outside the session and retry, reported by mcp run --json-errors as authentication_required.

What to commit

FileCommit it?
.pi/mcp.local.jsonNo. It carries your endpoints and tokens
.pi/mcp.local.example.jsonYes, when a binding template helps the next person
.pi/mcporter.jsonNo. A launch regenerates it
Everything else in the recipeYes. That is the deliverable

Environment variables inside a run

recipe-owned tools receive the selected path and agent as PI_RECIPE_DIR and PI_AGENT_NAME. PI_ASK_USER_AUTO_APPROVE makes interactions resolve without a human, which is what you want in CI.