omp
One provider block in models.yml, one key, every model, pay as you go.
At the end you have omp, the terminal coding agent from the oh-my-pi project, on one provider block at https://api.uplinkswitch.com/v1, with one API key from the console and any model id on the list, Claude included. Each request bills per token to the prepaid balance behind that key, no subscription, and the live table below is what one agent step costs on each model today.
Before you start
You need omp installed (curl -fsSL https://omp.sh/install | sh on macOS and Linux), an account on the console with credit on it, and one key created there. Create the key for omp alone, so its requests sit apart from any other tool on the Usage page. Nothing is installed on the UplinkSwitch side: the base URL and the key are the whole configuration.
Where the settings are
Custom providers live in ~/.omp/agent/models.yml (models.yaml is read only when the .yml file is absent). Its root holds providers and nothing else.
The default model is a separate setting: modelRoles.default in ~/.omp/agent/config.yml for every project, or <repo>/.omp/config.yml for one. omp reads the project file from the directory you launch it in and does not search parent directories. Read 2026-10-28 from omp.sh/docs/custom-models and docs/settings.
The provider block
api: openai-completions sends /v1/chat/completions to baseUrl, which is the format every chat model here answers. apiKey is the name of an environment variable, not the key itself. The two headers let the gateway attribute the traffic to omp on the Usage page. The limits under each model are the developer's published figures from the live catalog, so omp trims the conversation before the model refuses it.
# ~/.omp/agent/models.yml
providers:
uplinkswitch:
baseUrl: https://api.uplinkswitch.com/v1
api: openai-completions
apiKey: UPLINKSWITCH_API_KEY
headers:
HTTP-Referer: https://uplinkswitch.ai
X-Title: omp
models:
- id: claude-sonnet-5-5
name: Claude Sonnet 5.5
input: [text, image]
contextWindow: 1000000
maxTokens: 128000
- id: claude-opus-5-5
name: Claude Opus 5.5
input: [text, image]
contextWindow: 1000000
maxTokens: 128000
- id: gpt-6.1-sol
name: GPT-6.1 Sol
input: [text, image]
contextWindow: 1050000
maxTokens: 128000
- id: gemini-3.1-pro-preview
name: Gemini 3.1 Pro Preview
input: [text, image]
contextWindow: 1048576
maxTokens: 65536
- id: deepseek-v4-pro-0813
name: DeepSeek V4 Pro 0813
contextWindow: 1048576
maxTokens: 393216
- id: kimi-k3
name: Kimi K3
input: [text, image]
contextWindow: 1048576
maxTokens: 1048576Every id under models shows up in /model as uplinkswitch/<id>. Any id on the Models page can be added the same way. A model entry can also carry reasoning: true and a thinking block for effort controls, and a cost block with input, output, cacheRead and cacheWrite per million tokens for omp's own cost line; omp needs all four, and the console bills the live price either way.
The key
Export the variable in the shell that launches omp, or put it in a .env file. omp loads .env from the current directory, ~/.omp/agent, ~/.omp and your home directory, in that order, with an exported value winning over all of them.
export UPLINKSWITCH_API_KEY="sk-uplink-live-..."
omp# ~/.omp/agent/.env
UPLINKSWITCH_API_KEY=sk-uplink-live-...A value starting with ! runs a shell command and uses its output as the key, for a secret manager. --api-key on the command line overrides apiKey for one run and is not saved.
Which model to pick
Tool calling works on every chat model here, and omp's agent needs it for every file read, edit and command, so no id in the block is a dead end. Input price decides the session cost, because omp sends the conversation and every tool result back on each step; pick by the input column below. Set the default once:
# ~/.omp/agent/config.yml (or <repo>/.omp/config.yml)
modelRoles:
default: uplinkswitch/claude-sonnet-5-5Or start omp, run /model and assign a model to Default. /switch (Alt+P) changes only the current session; --model on the command line wins over everything. --slow, --smol and --plan override the thorough, lightweight and planning roles with any uplinkswitch/<id>. The uncensored coding builds go in the same block, billed per token.
What an omp step costs
One agent step at 40,000 input tokens and 1,500 output tokens, which is a task that has read a few files and run a command or two. Nothing is counted at the cached rate.
| Model | Input / 1M | Output / 1M | Cached input / 1M | Under list | One step, 40,000 in + 1,500 out |
|---|---|---|---|---|---|
| Claude Sonnet 5.5 | $1.20 | $3.00 | $0.075 | 40% on input | $0.0525 |
| Claude Opus 5.5 | $2.80 | $10.00 | $0.15 | 30% on input | $0.127 |
| GPT-6.1 Sol | $0.60 | $3.00 | $0.06 | 70% on input | $0.0285 |
| Gemini 3.1 Pro Preview | $1.20 | $7.20 | $0.12 | 40% on input | $0.0588 |
| DeepSeek V4 Pro 0813 | $0.792 | $1.188 | $0.0625 | 40% on input | $0.0335 |
| Kimi K3 | $0.90 | $4.50 | $0.12 | 70% on input | $0.0428 |
USD per million tokens, live from GET /v1/catalog. Under list: against the developer’s own published input price. The last column is the step above at this base URL, nothing at the cached rate.
Claude Sonnet 5.5 is $0.0525 for that step here, and a ten-step task is $0.525. Cached input bills at the cache-read rate in the table by itself; there is no switch to set. The Claude Code pricing post works a day and a month of agent steps at these rates.
Check it
omp models uplinkswitch lists the ids from the block; a bad field prints models.yml validation failed with its name. The second line sends one request in print mode:
omp models uplinkswitch
omp -p --model uplinkswitch/claude-sonnet-5-5 "Reply with only OK"From a shell, the same key should list the models:
curl https://api.uplinkswitch.com/v1/models -H "Authorization: Bearer $UPLINKSWITCH_API_KEY"The request shows on the console Usage page within seconds, with its tokens and its charge, recorded with omp as the app.
Errors you will see
401 invalid_api_key: the key is wrong or revoked, or the variable named inapiKeyis not set in the shell that launched omp. A name omp cannot find is sent as the literal key. Export it, or check the.envpath, and copy the key again from the console.402 insufficient_balance: the balance does not cover the request. Top up in the console.402 monthly_limit_reached: the key hit the monthly spend limit you set on it. Raise it in the console, or wait for the first of the month.404 model_not_found: the id undermodelsis not on the Models page at this base URL. Copy it from the page rather than typing it: a dot, a dash or a date suffix out of place is enough.403 scope_denied: the key carries a model allowlist and this id is not on it. Pick an allowed id or use a key without the limit.429 rate_limited: the key hit its requests-per-minute or concurrency limit. The response carriesretry-afterin seconds. Wait that long and resend.- The provider is missing from
/model: the file ismodels.yml, notconfig.yml, andbaseUrlends in/v1. Runomp models uplinkswitchfor the failing field.
Good to know
- Only the ids you list are offered.
discoverywithtype: openai-models-listcan readGET /v1/modelsinstead, which brings in every chat id at once;omp models refresh uplinkswitchre-reads it. - A model omitted from a field defaults to text-only input, a 128,000 context window and 16,384 output tokens, which is why the block above fills them from the catalog.
--modelsrestricts what Ctrl+P cycles through, by the sameprovider/idselectors.- The same key works in OpenCode, Claude Code and Cline on the same balance. A key per tool keeps the spend apart on the Usage page.
Questions
Get a key in the console: prepaid credit, no subscription, 30-day price lock.