Skip to main content

Pi

Pi is a minimal, extensible terminal coding agent. It reads custom OpenAI-compatible providers from its own config, so — like OpenClaw, which is built on the same agent stack — it's a first-class connect target: the proxy writes the config for you.

Before you start

Do the shared setup from How-to guides first: the proxy must be running (zs-proxy proxy start) and funded (zs-proxy fund).

The quick way: zs-proxy connect pi

zs-proxy connect pi # configure Pi to use the proxy
zs-proxy connect pi --model qwen3-coder # ...and set it as the default model
zs-proxy connect pi --print # preview the merged config, write nothing

Pi keeps its provider catalog and its default-model setting in two files, so connect writes both (backing each original up to <file>.bak) and reports each path:

FileWhat connect writes
~/.pi/agent/models.jsonthe zerosignal provider, seeded with the live model catalog
~/.pi/agent/settings.jsondefaultProvider + defaultModel — only with --model

Your other Pi settings are preserved, and Pi keeps its own built-in providers alongside the zerosignal one — custom models are added by id, not swapped in for the built-in catalog.

What it writes to models.json:

{
"providers": {
"zerosignal": {
"name": "ZeroSignal",
"baseUrl": "http://127.0.0.1:9376/v1",
"apiKey": "zerosignal-local",
"api": "openai-completions",
"models": [ ]
}
}
}

baseUrl is your live proxy endpoint and apiKey is a placeholder the proxy ignores. models carries the live catalog — each entry gets its context window, max output tokens, input modalities, and (where priced) a cost block.

And, with --model, to settings.json:

{
"defaultProvider": "zerosignal",
"defaultModel": "qwen3-coder"
}
info

The default model is a bare id. Pi takes --provider and --model as separate flags and looks the model up inside the provider, so defaultModel is qwen3-codernot zerosignal/qwen3-coder like opencode and OpenClaw use. A slash-prefixed value silently resolves to nothing.

info

Pricing. connect seeds each priced model's cost (USD per 1M tokens) with the network's advertised rates grossed up by the protocol fee — what you actually pay — taken from the cheapest operator serving each model. Treat them as an estimate: the authoritative charge is metered and billed on-chain per request, and routing may land on a different-priced operator. Free or unpriced models keep a zeroed cost. See Pricing for the full model.

If Pi's config lives somewhere non-standard, point connect at it with PI_CODING_AGENT_DIR=/path/to/agent-dir (Pi's own variable — it names the directory, and connect writes both files into it), or override just models.json with --config-path.

Select the model and run

With --model the default is already set — just start Pi:

pi

Otherwise pick a zerosignal model with /model (or Ctrl+L) inside Pi, or name it on the command line:

pi --provider zerosignal --model qwen3-coder

Send a message — the first reply confirms the whole path (encrypt, pay, route) is working.

Troubleshooting

SymptomFix
connect says Pi wasn't detectedName it explicitly — zs-proxy connect pi configures the named tool even without detection, writing ~/.pi/agent/models.json.
Pi isn't using the proxyPick a zerosignal model with /model, and confirm the zerosignal provider exists under providers in ~/.pi/agent/models.json.
Pi starts on a different modelThe default lives in settings.json, not models.json — re-run zs-proxy connect pi --model <model>. Note Pi persists the model you pick with /model, which overwrites it.
Pi shows none of the network's modelsAn invalid models.json is rejected as a whole, not per-entry. Pi prints the schema error at startup; restore models.json.bak and re-run connect.
Connection refusedThe proxy isn't running or the base URL is wrong. Check curl http://localhost:9376/healthz and start it with zs-proxy proxy start.
Running Pi in a container? Nothing connectsSee the Docker note — use host.docker.internal and bind the proxy off loopback.
wallet_unfunded / payment errorsAdd funds with zs-proxy fund — see Wallet & funding.

What's next