Generate Oh My Pi models.yml and settings.yml: define a custom provider and route the default, smol, plan and commit roles to different models. Free.
Oh My Pi — the omp coding agent — makes a design choice most agents do not: it splits which providers exist from which model does which job. Providers are declared in ~/.omp/agent/models.yml. Routing lives in ~/.omp/agent/settings.yml. This generator writes both, side by side, updating live as you type. It runs entirely in your browser with no upload step.
That split is the whole point of the tool. Most agents give you one model setting and you live with it: pay for a frontier model on every turn, including the ones that write a commit message. Oh My Pi lets you route a commit message to something cheap and a planning turn to something expensive, in four lines of YAML. Getting those four lines right is what this generator is for.
Oh My Pi runs on Bun, and the custom-provider feature in models.yml requires Bun 1.3.14 or newer — the tool states this in the form itself. Two install routes are offered:
| Route | Command |
|---|---|
| Bun | bun install -g @oh-my-pi/pi-coding-agent |
| curl | curl -fsSL https://omp.sh/install | sh |
If provider declarations appear to be ignored after you write models.yml, check your Bun version before you debug the YAML.
The first tab writes a providers map with a single named entry. Fill in a provider name, choose an API type, give it a base URL, pick an auth style, and you get something like:
# ~/.omp/agent/models.yml
providers:
my-gateway:
baseUrl: https://gateway.example.com/v1
api: openai-completions
apiKey: "${MY_GATEWAY_API_KEY}"
discovery:
type: openai-models-list
The api field is the protocol the endpoint speaks, and Oh My Pi supports five natively rather than forcing everything through an OpenAI-compatible shim:
| Value | What it targets |
|---|---|
openai-completions | OpenAI-compatible chat completions — vLLM, proxies, gateways, most self-hosted servers |
openai-responses | OpenAI's Responses API |
anthropic-messages | The Anthropic Messages API directly |
google-generative-ai | The Gemini API |
google-vertex | Google Vertex AI |
Being able to name the native protocol matters when you are pointing at a first-party endpoint rather than a compatibility layer — you get the provider's own request shape rather than whatever a translation layer chose to drop.
This is the detail most likely to catch you out. With API-key auth, the generator does not write your key. It writes a shell-expansion reference whose variable name is computed from the provider name you typed: uppercased, with every run of non-alphanumeric characters replaced by an underscore, leading and trailing underscores stripped, and _API_KEY appended.
| Provider name you type | Variable the file expects |
|---|---|
my-gateway | MY_GATEWAY_API_KEY |
internal.llm | INTERNAL_LLM_API_KEY |
vllm prod | VLLM_PROD_API_KEY |
| (left blank) | MY_GATEWAY_API_KEY, from the my-gateway fallback |
So rename the provider and the expected variable changes with it. Export the matching variable in your shell and the file itself never contains a secret, which makes it safe to commit to a dotfiles repository.
The two other auth choices skip that entirely. none writes auth: none and is what you want for a local server that does not authenticate. oauth writes auth: oauth and defers to a browser flow instead of a static key.
One conditional line: the discovery block with type: openai-models-list is only written for openai-completions. That is the endpoint that exposes a models-list route Oh My Pi can enumerate, so the agent can discover what the gateway serves rather than making you list every model by hand. The other four API types do not get it.
The second tab writes a modelRoles map. Four roles are exposed, each taking a provider/model string:
| Role | Used for | Placeholder shown |
|---|---|---|
default | Standard turns — the bulk of the work | anthropic/claude-sonnet-4-5 |
smol | Cheap subagents | openai/gpt-4.1-mini |
plan | Planning mode | anthropic/claude-opus-4-5 |
commit | Commit messages | openai/gpt-4.1-mini |
Leave a field blank and the generator writes its placeholder, so the file is always complete and valid. The economic logic behind the split is straightforward once it is laid out: plan gets the strongest model because a bad plan wastes every turn that follows it; default gets a capable mid-tier model because it runs most often; smol and commit get something small because summarising a diff or fanning out a subagent does not need a frontier model. If you route all four to the same model you have Oh My Pi configured as an ordinary single-model agent — which works, but leaves its main advantage unused.
The form's own help text notes that a role string can carry an effort suffix, in the range :low through :xhigh — so anthropic/claude-opus-4-5:xhigh for the plan role expresses "the biggest model, thinking hardest, but only where planning happens". The generator passes whatever you type through verbatim, so suffixes are supported by typing them.
The link between them is the prefix. A role value of vllm-prod/qwen3-coder means "the model qwen3-coder, reached through the provider called vllm-prod" — and vllm-prod has to be a name omp recognises, either one of its built-in providers or the one you declared in models.yml. That is the entire contract between the files, and it is why the placeholders in the routing tab use built-in prefixes like anthropic/ and openai/: those work without declaring anything.
Which gives you a useful sequencing rule. If you only want to route between providers omp already knows about, you can ignore the models.yml tab entirely and write just settings.yml. You only need the provider tab when you are adding an endpoint omp has no built-in knowledge of — a self-hosted server, a corporate gateway, an inference proxy, a router in front of several vendors.
The generator writes one provider per file, which covers the common case. Adding a second is a matter of copying the indented block under providers: and giving it a different key; the map takes as many entries as you like. Remember that each one derives its own API-key variable name from its key, so two providers means two exports.
The base URL field takes whatever your endpoint expects, and the placeholder https://gateway.example.com/v1 reflects the most common shape. For openai-completions endpoints the /v1 suffix is the convention almost every compatible server follows — vLLM, LM Studio, Ollama's compatibility surface, and most proxies all serve the OpenAI routes below /v1. Omitting it is the usual cause of a 404 on every request while the host itself is plainly reachable.
The native API types are a different matter: an anthropic-messages or google-vertex endpoint has its own path convention, so take the base URL from that provider's own documentation rather than assuming /v1. Leave the field blank and the generator writes the placeholder so the YAML stays valid while you go and find the real value.
The final toggle, on by default, appends:
retry:
modelFallback: true
This lets omp fall back to another model when one errors, rather than dropping the turn. With four roles pointing at potentially four different providers, any single provider's rate limit or outage would otherwise stall you; fallback is what makes a multi-provider setup more resilient than a single-provider one rather than four times as fragile. Turn it off if you need to know for certain which model produced a given output — benchmarking, auditing, or reproducing a bug report.
Declare a provider named vllm-prod with API type openai-completions and base URL http://10.0.0.9:8000/v1, auth by API key. Then set default to vllm-prod/qwen3-coder, leave plan pointed at anthropic/claude-opus-4-5, and leave smol and commit on their mini defaults. You now have the routine coding turns running on your own hardware at no per-token cost, the planning turn on a frontier model where it earns its price, and the throwaway work on something cheap — with VLLM_PROD_API_KEY exported in your shell and no secret in either file.
~/.omp/agent/models.yml, not ~/.omp/models.yml.provider/model must match a provider omp knows — either a built-in one or the name you declared in models.yml. A typo in the prefix is not a YAML error.discovery block is only emitted for openai-completions; the other API types do not use it.Both files have copy and download buttons, and Reset returns the form to defaults. Note what this tool does not produce: there is no project context file and no MCP picker here, so — unlike the Claude Code, Codex and Gemini generators — there is no AI-assist panel anywhere in it. Every line of both outputs is deterministic YAML assembled from your inputs.