Melious
Integrations

Pi

Minimal terminal coding agent — register Melious as a custom OpenAI-compatible provider via a TypeScript extension

Pi
by Mario Zechnerpi.dev

Pi is a minimal, MIT-licensed terminal coding harness from badlogic/pi-mono. It speaks 15+ providers out of the box and lets you wire in custom ones through TypeScript extensions rather than config files. Sessions are tree-structured (you can branch and switch mid-conversation), the agent surface is built around primitives — extensions, skills, prompt templates, AGENTS.md context — and /model swaps the active model at any point. Pointing it at Melious is a few lines of TypeScript dropped into ~/.pi/agent/extensions/melious.ts.

Setup

Install Pi

npm install -g @mariozechner/pi-coding-agent

This is the only documented install path right now. Requires Node.js. After install, pi is on your PATH.

Register Melious as a custom provider

Pi auto-discovers extensions from ~/.pi/agent/extensions/*.ts (global) and .pi/extensions/*.ts (project-local). Drop the file below in either location. Pi compiles and loads it on next launch — no extra config.

~/.pi/agent/extensions/melious.ts
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";

export default function (pi: ExtensionAPI) {
  pi.registerProvider("melious", {                              
    name: "Melious",                                            
    baseUrl: "https://api.melious.ai/v1",                       
    apiKey: "MELIOUS_API_KEY",                                  
    api: "openai-completions",                                  
    models: [                                                   
      {                                                         
        id: "<MODEL_ID>",                                       
        name: "<Display Name>",                                 
        reasoning: false,                                       
        input: ["text"],                                        
        cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, 
        contextWindow: 128000,                                  
        maxTokens: 4096
      }                                                         
    ]                                                           
  });
}

api: "openai-completions" tells Pi to send Chat Completions-shaped requests, which Melious serves natively. apiKey is an env var name — Pi reads MELIOUS_API_KEY from the environment at request time. List one entry per model you plan to use; the next step shows how to skip the manual list.

Or auto-populate models from /v1/models

The extension factory can be async. That lets you fetch our live model catalog and register every model in one go — no manual updates when we add or remove one:

~/.pi/agent/extensions/melious.ts
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";

export default async function (pi: ExtensionAPI) {
  const apiKey = process.env.MELIOUS_API_KEY;
  if (!apiKey) return;

  const res = await fetch("https://api.melious.ai/v1/models?include_meta=true", {
    headers: { Authorization: `Bearer ${apiKey}` },
  });
  const { data } = await res.json();

  pi.registerProvider("melious", {
    name: "Melious",
    baseUrl: "https://api.melious.ai/v1",
    apiKey: "MELIOUS_API_KEY",
    api: "openai-completions",
    models: data
      .filter((m: any) => m._meta?.type === "chat")             
      .map((m: any) => ({                                       
        id: m.id,                                               
        name: m._meta?.display_name ?? m.id,                    
        reasoning: m._meta?.capabilities?.reasoning ?? false,
        input: m._meta?.capabilities?.vision
          ? ["text", "image"]
          : ["text"],
        cost: {
          input: m._meta?.pricing?.input_per_1m ?? 0,
          output: m._meta?.pricing?.output_per_1m ?? 0,
          cacheRead: 0,
          cacheWrite: 0,
        },
        contextWindow: m._meta?.context_length ?? 128000,
        maxTokens: m._meta?.max_output_tokens ?? 4096,
      })),
  });
}

The factory runs at startup. Hot-reload from inside Pi via /reload after editing.

Authenticate and run

Export your key and launch:

export MELIOUS_API_KEY=sk-mel-<YOUR_API_KEY>
pi

/model inside the session lets you switch between any registered model. pi --list-models shows what got registered. pi --provider melious filters to just our models.

Picking a model

Pi has no built-in capability gating — every entry in your models array is selectable via /model. If you want Pi to label which can call tools or handle vision, set input: ["text", "image"] for vision models and rely on Pi's UI badges; for tool-use, the request will succeed or fail based on what the model actually supports server-side.

Browse melious.ai/hub/models for current IDs, context windows, and capability flags. The async factory above maps _meta.capabilities straight onto Pi's model entry.

Steering routing

Append a flavor suffix to the model id when you register it:

{ id: "<MODEL_ID>:eco", name: "<Display Name> (eco)", /* ... */ }
  • :speed — latency-biased provider selection
  • :price — cheapest available provider
  • :eco — greenest energy mix
  • (no suffix) — balanced, our default

Register one entry per flavor and switch via /model per session. See Routing for the full decision table.

What's different

  • Provider registration is code, not config. Pi's design choice — extensions are TypeScript, hot-reloadable, and live next to your other agent customisations (skills, prompt templates). No JSON to keep in sync with a config schema.
  • Model list is whatever you register. Pi doesn't auto-discover models from the provider endpoint unless your extension does it. The async-factory pattern above is the supported way.
  • Tool calling on supported models only. Pi sends OpenAI-shape tool_calls to our Chat Completions endpoint. Not every open-weight model handles tools — check _meta.capabilities.tool_use on GET /v1/models?include_meta=true or filter at melious.ai/hub/models.
  • Custom response fields. environment_impact and billing_cost ride on raw responses but Pi's UI doesn't surface them — they're logged on our side and aggregated in your usage dashboard.

When it breaks

  • Provider 'melious' not found — the extension didn't load. Check it's in ~/.pi/agent/extensions/ (or your project's .pi/extensions/), the file ends in .ts, and the default export is a function. Run pi --list-models to see what registered.
  • MELIOUS_API_KEY is not set — Pi reads the env var named in the apiKey field. Export it, or use pi --env-file <path> if you keep it elsewhere.
  • Async factory throws on startup — Pi loads extensions before the prompt. If your fetch against /v1/models fails (network, bad key), the provider doesn't register. Wrap in try/catch and fall back to a static models array if you want graceful degradation.
  • /model shows nothing under Melious — your models array is empty (the filter dropped everything). Inspect what /v1/models?include_meta=true returned and adjust the filter.

Errors and retry patterns: Errors.

On this page