01 · Quickstart
From zero to your first running agent in about 5 minutes.
Prerequisites
| Dependency | Requirement | Notes |
|---|---|---|
| Node | >=22.19.0 | pi’s engines constraint; production images use node:24-bookworm-slim. Stick with Node at runtime (Bun is only used for the toolchain). |
| pnpm | 9.x (packageManager: [email protected]) | workspace monorepo. |
| pi config directory | ~/.pi/agent exists | Run pi once and log in so that auth.json / settings.json are generated. Or provide a provider key via environment variables (see below). |
Never installed pi? First run
npm i -g @earendil-works/pi-coding-agent(or follow its docs), then runpiand log in once.
Install & Run (Development Mode)
pnpm install
pnpm dev # next dev — http://localhost:3000Open the browser and enter a source in the agent source picker, in one of three forms:
- A directory containing
index.ts→ runs your custom agent (custom mode); - Any directory → general CLI mode (
pi --mode rpc); - A git source → resolved, then same as above.
Pick One from examples/ to Get Started
The repo’s examples/ directory ships several ready-to-point-at examples, organized by capability in the examples index. For your first run, we recommend either of these two introductory examples:
| Example | Best for | Notes |
|---|---|---|
examples/hello-agent | Your first run | A self-contained, minimal custom agent that exposes a single echo tool and does not load system tools or on-disk skills. |
examples/minimal-agent | Seeing the leanest entry | A skeleton with only the required fields of defineAgent(), handy for modeling your own entry file. |
For more examples organized by capability (attachments, AIGC, Web UI extensions, etc.), see the examples index.
Run the Example Agent in 5 Minutes
The following uses the minimal example examples/hello-agent:
// examples/hello-agent/index.ts (excerpt)
import { defineAgent } from "@blksails/pi-web-agent-kit";
import { defineTool } from "@earendil-works/pi-coding-agent";
import { Type } from "@earendil-works/pi-ai";
const echo = defineTool({
name: "echo",
label: "Echo",
description: "Echo the provided text back to the caller.",
parameters: Type.Object({ text: Type.String() }),
async execute(_id, params) {
return { content: [{ type: "text", text: params.text }], details: undefined };
},
});
export default defineAgent({
// model omitted → inherits the default provider/model from ~/.pi/agent/settings.json
systemPrompt: "You are hello-agent, a minimal pi-web example agent.",
customTools: [echo],
});The above is an excerpt. The real
examples/hello-agent/index.ts:1also setsnoTools: "builtin"andskills: () => ({ skills: [], ... }), making the example self-contained — it exposes only the customechotool and loads neither system built-in tools nor disk-discovered skills. The meaning of these two switches is covered in 07 · Custom Agent Development.
Steps:
- After
pnpm devstarts, open http://localhost:3000 - Enter the absolute path to
examples/hello-agentin the picker (the picker requires an absolute path; or setPI_WEB_DEFAULT_SOURCE, see below) - Enter the session and send a message → expected: you see a streaming reply
- Make it call the tool: send “use the echo tool to echo hello” (or a similar instruction) → expected: an
echotool card appears in the session
No reply / authentication error? Most likely the default provider/model has no valid key. First use the stub agent under “Offline Quick Verification” below to get the chain working; for authentication issues, see 18 · Troubleshooting / FAQ.
hello-agentdeliberately omitsmodel, letting it inherit the default provider/model from your pi login, so it works out of the box. To pin the model, addmodel: { provider, modelId }, but that provider must have valid authentication.
Configuration (Optional)
Credentials and defaults come from ~/.pi/agent by default (if you’ve logged in to pi, no environment keys are needed). To override, copy .env.local.example to .env.local. The most common ones:
# .env.local
PI_WEB_DEFAULT_SOURCE=/abs/path/to/examples/hello-agent # default source for the picker
PI_WEB_DEFAULT_CWD=/abs/path/to/workdir # default working directory for sessions
PI_WEB_DEFAULT_PROVIDER=openrouter # force the provider (otherwise from settings.json)
PI_WEB_DEFAULT_MODEL=anthropic/claude-sonnet-4.6 # force the model (value must match the provider)For the complete set of variables, see 05 · Configuration Reference.
Offline Quick Verification (No Model Quota Consumed)
You can verify the full chain without an LLM key (using a deterministic stub agent):
PI_WEB_STUB_AGENT=1 pnpm dev
# or run the offline Node-level streaming e2e:
pnpm e2e:nodeCommon Scripts at a Glance
| Command | Purpose |
|---|---|
pnpm dev | Dev server (next dev, :3000) |
pnpm build / pnpm start | Production build / start |
pnpm test | Tests for all workspace packages |
pnpm test:app | App-level vitest |
pnpm e2e | Playwright browser e2e |
pnpm e2e:node | Offline Node-level streaming e2e (stub agent) |
pnpm typecheck | Typecheck for all packages + app |
pnpm build:cli / pnpm start:cli | Build / start the global CLI (standalone, see 14 · CLI) |
Common First-Time Issues
- Don’t run
pnpm buildduring dev — it pollutes the shared.nextand causes webpack 500s. CLI/e2e builds use isolated directories (NEXT_DIST_DIR=.next-cli/.next-e2e). - Changed an injected route / config domain but the route didn’t take effect — the handler singleton is pinned on
globalThis, and hot reload does not refresh new routes, so you need to restart dev. - For more, see 18 · Troubleshooting / FAQ.
Next Steps
- Understand loading and session mechanics → 02 · Core Concepts
- Write your own agent → 07 · Custom Agent Development
- Integrate a custom model gateway → 06 · Providers and Models