Coding agents
Pi
Minimal terminal coding agent wired to Melious through a provider entry — one env var, no plugin
Pi is a minimal, MIT-licensed terminal coding harness from earendil-works/pi. Its core stays deliberately small and everything else is an extension — skills, prompt templates, custom tools, AGENTS.md context. Sessions are tree-structured, so you can branch mid-conversation and switch back, and /model swaps the active model at any point without restarting. Melious isn't one of its built-in providers, so you declare us once in models.json — after that, export a key and our tool-capable chat models show up in the picker.
Setup
Skip the steps with the Melious CLI
The CLI installs pi, points it at us, and launches it with the environment already set. One command.
melious tools install pi
melious launch piIt writes ~/.melious/tool-configs/pi/models.json and points pi at that directory with PI_CODING_AGENT_DIR, so your own ~/.pi/agent — settings, sessions, credentials — is never touched.
The first launch in a project asks Trust this workspace? — the agent runs as you, with your Melious key — and defaults to no. Workspace trust covers what a grant means and how to revoke it. Melious also sets PI_TELEMETRY=0 and PI_SKIP_VERSION_CHECK=1, and updates go through melious tools update pi.
Install pi
npm install -g --ignore-scripts @earendil-works/pi-coding-agent--ignore-scripts stops a dependency's install script from running with your privileges. Pi doesn't need one.
Requires Node.js 22.19 or newer. After install, pi is on your PATH.
Add your key
export MELIOUS_API_KEY=sk-mel-<YOUR_API_KEY>Or run /login inside pi, pick Melious, and paste the key — pi writes it to ~/.pi/agent/auth.json with 0600 permissions. Stored credentials win over the environment variable, so /login is the one to reach for when you switch between keys.
Declare Melious in models.json
Pi has no built-in Melious provider, so this entry is what makes us show up at all. Write ~/.pi/agent/models.json:
{
"providers": {
"melious": {
"name": "Melious",
"baseUrl": "https://api.melious.ai/v1",
"api": "openai-completions",
"apiKey": "$MELIOUS_API_KEY",
"compat": { "supportsDeveloperRole": false },
"models": [
{
"id": "<MODEL_ID>",
"name": "<Display Name>",
"reasoning": true,
"contextWindow": 203000,
"maxTokens": 203000
}
]
}
}
}The $ prefix on apiKey matters: pi reads $MELIOUS_API_KEY as an environment variable and a bare MELIOUS_API_KEY as the literal key text. supportsDeveloperRole: false is the one compatibility flag we need — we take system, user, assistant, function and tool roles, and reject OpenAI's newer developer role. Everything else in pi's OpenAI-compatible path works unchanged.
Model entries here don't inherit context or pricing from anywhere, so spell out contextWindow and maxTokens per model; without them pi assumes 128000 and 16384. Check the models hub for the real numbers. Add as many entries as you want — one per Melious model you plan to use.
Run pi
pi/model (or Ctrl+L) lists every Melious model; Enter in that picker saves the highlighted one as your startup default. From the shell, pi --list-models melious prints what's available and pi --provider melious starts a session pinned to us. Model references are melious/<MODEL_ID> wherever pi asks for one.
Picking a model
Your models.json decides what the picker holds — pi fetches nothing on its own. List every Melious model you want there, and filter the catalog to ones that serve chat and handle tool calls, the two things a coding agent needs. glm-5.1 is a solid all-rounder; qwen3-coder-next is a good deal cheaper if your work is mostly code and you don't need a reasoning model.
Pi's thinking-level picker offers seven levels — off, minimal, low, medium, high, xhigh, and max — on any model you mark "reasoning": true. Which of them actually change the request depends on the model. Sending an explicit "none" silences some of our models and is ignored by others, so going non-reasoning is the reliable path to no thinking at all.
Browse melious.ai/hub/models for current IDs, context windows, and capability flags.
Steering routing
Append a routing flavor to the model ID:
pi --model melious/glm-5.1:eco:speed— latency-biased provider selection:price— cheapest available provider:eco— greenest energy mix- (no suffix) — balanced, our default
Pi reads a colon as a thinking level first — melious/glm-5.1:high sets effort — and falls back to treating an unrecognized suffix as part of the model ID. So a flavor works, but pi prints Warning: Model "glm-5.1:eco" not found for provider "melious". Using custom model id. on the way through. The request itself is fine.
One catch worth knowing: that fallback borrows its metadata from the first entry in your Melious model list. Flavor that model itself and the context window and pricing are correct. Flavor any other model and pi sizes and prices it as if it were the first one, which throws off the context meter and the session cost readout.
To fix that, and to get the flavored entry into the /model picker, declare it in ~/.pi/agent/models.json. New entries are added to what's already there rather than replacing it, so the rest stay put:
{
"providers": {
"melious": {
"compat": { "supportsDeveloperRole": false },
"models": [
{
"id": "kimi-k3:eco",
"name": "Kimi K3 (eco)",
"reasoning": true,
"contextWindow": 1000000,
"maxTokens": 1000000
}
]
}
}
}The compat block is not optional here. It has to be repeated on any second models.json write, because pi doesn't merge it across entries — without it pi sends a developer role and we reject the request with Invalid role 'developer'.
What's different
- The model list is yours to keep current. Pi doesn't ship a Melious catalog and doesn't fetch one, so a model we add today won't appear until you add it to
models.json. The Melious CLI writes that file from the live/v1/modelson every launch, which is the way around it. - Costs are shown in USD. Pi's session cost readout is dollar-denominated and we price in EUR, so the rates in your
models.jsonare converted figures. Your usage dashboard is the euro-accurate source. - Tool calling on supported models only. Pi sends OpenAI-shape
tool_callsto our Chat Completions endpoint. Only list models that handle tools — check_meta.capabilities.function_callingonGET /v1/models?include_meta=truefirst. - No explicit cache control. There's no field to mark a prefix as cacheable. Transparent prefix caching still happens on our side and comes back as
usage.cached_tokens, billed at the cheaper cache-read rate. See Models. - Custom response fields. With
api: "openai-completions", non-streamed responses and the final usage chunk of a stream carryenvironment_impactandbilling_cost, though pi's UI doesn't surface them — they're aggregated in your usage dashboard.
When it breaks
Error: unknown tool: pi— your Melious CLI predatespisupport, which arrived in v0.2.0. Update the CLI, or follow the manual setup above.pi --list-models meliousis empty — either~/.pi/agent/models.jsonis missing the provider entry above, or no key resolved. Pi hides models it can't authenticate.MELIOUS_API_KEYset but pi still won't authenticate — a stored credential beats the environment variable. Run/logoutand pick Melious to drop it, or/login meliousto replace it.Model "<MODEL_ID>:eco" not found ... Using custom model id— expected when you append a routing flavor. The request works; the context meter and cost readout borrow the first list entry's numbers. Declare the flavored ID inmodels.jsonto make them accurate.- Rate limit errors during long sessions — you're on a plan with a per-minute token cap and the session's context is big. Rate limits explains which plan lifts which limit.
Errors and retry patterns: Errors.