TierMux Checking…

TierMux documentation

Introduction

TierMux is three things built on one dataset: a verified catalog of free-tier LLM providers and models, a free agentic coding assistant for VS Code, and a self-hosted gateway that serves inference from your own keys on your own infrastructure.

Every provider in the catalog has been verified with real requests. Capability flags — tool calling, image input, reasoning — are measured, not copied from a pricing page, and listings that stop answering are removed rather than left to fail silently. The catalog reflects what is callable today, not what was callable when it was indexed.

The API is read-only, needs no account and no key, and sends Access-Control-Allow-Origin: * on every response, so a browser can call it directly.

i
Nothing on this page requires an account. There is no TierMux login, no API key to request, and no rate limit beyond the 120-second cache on catalog responses. If a page tells you to sign up for TierMux, it is not us.

Quick start

Three entry points, depending on what you came for.

Code in your editor#

  1. Install the extension. In VS Code: Extensions (Ctrl Shift X) → search TierMux → Install. In Cursor, Windsurf, Antigravity, VSCodium or Trae, take the same build from Open VSX.
  2. Open it. Activity Bar → TierMux.
  3. Type. Four providers ship keyless, so the first message answers with no key, no account and no config.

That is the whole setup. Adding free keys comes later and is the single biggest upgrade you can make.

Read the catalog#

Every free reasoning model currently in the catalog, in three languages:

Shell curl + jq
curl -s "https://tiermux.mainulislam3057.workers.dev/models?tag=frontier" \
   | jq '.models[] | select(.pricing.free) | .model_id'

Full shapes are in the API reference and the object reference.

Run the gateway#

The gateway is in final testing and the public repo has not landed yet. This catalog already serves the exact configuration payload it consumes, so a gateway deployed on day one works against it with no extra setup. The full design is here →

Concepts

Six words that mean something specific in TierMux. Worth two minutes now.

TermWhereWhat it means
CatalogeverywhereThe verified list of providers and models this site publishes. Both products read it; neither of them hardcodes a model list, which is why a new free provider appears without a product update.
ProvidercatalogOne upstream API — Groq, Google AI Studio, Cerebras, a keyless router. Identified by provider_id. A provider has a base_url and is either keyless or takes a free key you get from its own portal.
ModelcatalogOne model on one provider. The same model name on two providers is two entries, because their context windows, limits and prices differ. That duplication is exactly what makes cross-provider failover possible.
Keylesscatalog, extensionA provider that answers with no key and no account. Four of them ship enabled, which is why the extension's first message works before you configure anything.
ChainextensionThe ordered list of model–provider pairs one turn may use. Built per message, one model per provider first, so it spans providers rather than burning one provider's whole list.
AutobothA model choice, not a mode: "you pick for me". Pin a specific model instead and the turn goes to exactly that model. Only auto triggers routing.
✓
Mode and model are independent. Mode decides what the agent may do; the model picker decides who does it. Ask + Auto, Agent + a pinned model, and every other combination are all valid.
01

VS Code extension

The editor product: install it, pick a mode, add free keys, and tune what the agent may do without asking.

VS Code extension

A free, open-source agentic coding assistant that pools 30+ free-tier providers into one self-healing surface. No subscription, no per-token bill, no TierMux server in the request path.

id mainul-islam.tiermux requires VS Code ^1.93 licence MIT telemetry none

Install#

One VSIX runs in VS Code and every VS Code fork. The only difference is which registry your editor reads:

EditorRegistryHow
VS CodeMarketplaceExtensions (Ctrl Shift X) → TierMux → Install, or from the Marketplace page ↗.
Cursor, Windsurf,
Antigravity, VSCodium, Trae
Open VSXSearch TierMux in the editor's extension pane, or install from Open VSX ↗.
anything elseeitherExtensions: Install from VSIX takes the downloaded file. Both registries serve the identical build.

First run#

The TierMux panel in the VS Code sidebar: brand header, a tip banner, a models-ready row, a recent-chat list, and the composer with mode and model pickers.

Activity Bar → TierMux, then type

That is the whole first run. The row above the composer reports how many models are ready and what routing is set to; the banner above it surfaces whatever free tier is currently worth knowing about.

  • Bottom-left picks the mode: Ask · Plan · Agent.
  • Next to it, the model picker — leave it on Auto, or click to pin one.
  • / runs a skill, @ attaches a file, the paperclip adds an image.
  • Shift Enter is a newline; Enter sends.
  • The footer counts lifetime tokens, requests, and what those turns would have cost on a paid API.

Modes and the model picker

Three modes, picked in the composer. Ask is the default.

ModeWrites?What happens
AsknoQ&A only. Streams answers with strictly read-only tools — reads, greps, git log — and touches nothing.
PlannoReads and searches read-only. runCommand is offered but every call is gated by an ask; mutating tools are absent and policy-denied. The turn ends with a structured plan card you approve, edit or reject.
AgentyesFull tool set — diffs you approve, terminal you approve, checkpoints with real undo.

An approved plan executes as one agent turn with its steps enumerated in the prompt. Progress survives a reload — there is a Resume button.

Auto is a model choice, not a mode#

The model picker sits next to the mode picker and defaults to Auto. Auto classifies your message — chat, coding, debug, plan, agent, vision, by regex, with no model call — then builds a chain and works down it. Pin a model instead and that turn goes to exactly that model, with no routing.

How a turn is routed#

The chain is: your pinned model if there is one, else the task table's pick, then every enabled model strongest-first — one model per provider first, so the chain spans providers instead of exhausting one. Then each upstream answer is given a fixed meaning:

The provider did thisTierMux does this
429Cools that key, tries your next key, then the next provider.
401 · 402 · 403Tries your other keys on that provider, then skips the platform for this turn.
404 model removedNext provider — and that model is skipped for 24 hours.
400 with tools offeredNext provider; the pair is marked tool-incompatible for 10 minutes.
5xx · timeout · headers then silenceNext provider.
200 but emptyNext provider. A blank reply is not an answer.
✓
“Why this model?” Every reply carries a popover naming the model that answered and how it was chosen — including which providers were tried and why they were passed over. If a turn surprises you, that is where the answer is.

Providers and keys

Optional, and the highest-leverage ten minutes you can spend on the extension. More keys means more headroom before a wall; unused keys just rest.

The Providers settings tab: a search box, an all-providers switch, and a list of providers with toggles, key fields and per-model capability badges.

⚙ gear → Providers

Click a provider to expand it. Paste a free key, then tick only the models you want in the chain. Enabled providers sort to the top.

  • The T V R badges on each model row mean tools, vision and reasoning — measured, not advertised.
  • Each model row can carry its own key, for providers that issue per-model credentials.
  • Providers marked keyless need nothing at all.
  • Skip this tab entirely and the keyless four still answer.

The keyless four#

Enabled out of the box, no account required: Kilo Gateway, OpenCode Zen, OVH AI Endpoints and Pollinations. This list is read from the live catalog.

Providers with a free key#

Every other provider issues free keys through its own portal. The live list, with a direct link to each portal, is in the provider directory further down this page — the get a key ↗ link in each row goes straight to the right signup.

✓
Two or three keys beats twenty. Add keys for a couple of providers beyond the keyless four and add a second key on the one you lean on hardest. Rotation across two keys on a busy provider removes more walls than a tenth provider you never reach.

Where keys live#

In VS Code's encrypted secret storage — not in settings.json, and not in your workspace. Requests go VS Code → provider, directly. There is no TierMux server in the path and nothing to opt out of.

MCP, skills and custom endpoints

Three more gear tabs. All optional; each one extends what a turn can reach.

The MCP settings tab, showing configured servers and a browsable registry of common MCP servers with one-click install.

MCP servers

+ Add server, or edit tiermux.mcpServers in settings.json directly. Every tool a connected server exposes becomes an agent tool for the rest of the session.

  • The registry below the list installs common servers — filesystem, GitHub, Fetch, Puppeteer — in one click.
  • Remote search defaults to the official MCP registry; point tiermux.mcpRegistrySearchUrl elsewhere, or blank it to disable remote search.
  • TierMux: Reconnect MCP Servers re-establishes them without a window reload.
The Skills settings tab: installed skills, a search box, and browsable skill cards each with a source link and an Install button.

Skills

A skill is a saved prompt you run as /name. Installed ones land in .agents/skills/, the cross-tool convention, so they are shared with other agent tools in the same workspace.

  • Browse the catalog, or point tiermux.skillRegistryUrl at your own list to replace it.
  • TierMux: Add Skill from GitHub installs one by URL.
!
Read the source before installing. A skill is a prompt that steers the agent, so it runs with the agent's permissions. Vendor repo on a card means only that it installs from the vendor's own repository — not that anyone reviewed it.
The custom endpoint form at the bottom of the Providers tab: name, base URL, endpoint type and an optional key, with a Save and fetch models button.

Custom endpoints

At the bottom of the Providers tab. Name, base URL, type, an optional key, then Save & fetch models.

  • OpenAI-style — Ollama, LM Studio, vLLM, LiteLLM, llama.cpp, Azure OpenAI.
  • Newer — the Responses API shape.
  • Anthropic-style — Claude-compatible endpoints.
  • Local servers are probed for their real context window rather than trusting the number they advertise.
The Usage tab: a token total ring, request count, estimated money saved, and a filterable per-model breakdown.

Usage

Lifetime tokens, request count and estimated money saved, broken down per model. Tracked locally on your machine and cleared only when you ask.

  • Useful for the question that actually matters: which free tier are you leaning on, and what happens the day it changes?
  • If one provider carries most of your traffic, that is the one to add a second key for.

Approvals and safety

The agent edits files and runs commands. What it may do without asking is yours to set, and the defaults ask.

The Others settings tab, with the utility model, inline completion model, write confirmation toggle and command approval mode.

⚙ gear → Others

  • Require write confirmation — a diff you approve before any file is written, created or deleted. On by default.
  • Command approval — always (ask every time, the default), allowlist (built-in safe prefixes plus your own), or off.
  • Utility model — the small one used for chat titles and commit messages.
  • Inline completions — off by default; ghost text is a high request volume against free-tier limits.
  • Diagnostic trace — turn it on when a turn feels slow and read the TierMux Diag output channel.

The rails that are not optional#

  • Every path argument is confined to the workspace. A tool call cannot escape it.
  • Checkpoints capture the before-content of a write before the mutation, so Undo genuinely restores rather than asking the model to reconstruct.
  • Stop really kills the shell — not just the stream.
  • After a turn edits files, your own verify command runs; a non-zero exit feeds the failure back for bounded fix-and-recheck rounds.
  • A turn that hits its step cap stops visibly and offers Continue with full memory. Nothing is redone.

Settings reference

Everything the extension contributes to settings.json, with its default. All of it is optional — the defaults are the recommended configuration.

Agent#

SettingDefaultWhat it does
tiermux.agent.requireWriteConfirmationtrueAsk before the agent writes, creates or deletes a file, and before inline chat applies an edit.
tiermux.agent.commandApproval"always"How runCommand is gated: always, allowlist, or off.
tiermux.agent.commandAllowlist[]Extra command prefixes auto-runnable in allowlist mode, on top of the built-in safe defaults — e.g. "php artisan migrate".
tiermux.agent.commandTimeoutMs120000Maximum time a single agent command may run before it is killed.
tiermux.agent.verifyCommand"auto"Command run after a turn edits files, to check the project still works. A non-zero exit triggers fix-and-recheck rounds.
tiermux.agent.verifyFixRounds1How many fix-and-recheck rounds a failing verify command may trigger.
tiermux.agent.maxStepsPerTurn50Hard ceiling on tool-loop steps in a single turn. 0 removes the ceiling.
tiermux.agent.maxConcurrentRuns3How many chat sessions may run their agent at once. Extra sends queue, to respect free-tier rate limits.
tiermux.agent.auditTodostrueBefore a turn ends, look for evidence of every todo it marked complete and hand back anything it cannot find.
tiermux.agent.autoCondensetrueCompact the conversation automatically as it approaches the routed model's context window.
tiermux.agent.autoCompactThreshold0.8Fraction of the context window at which that compaction fires.
tiermux.agent.autoCondenseTokenCap32000Absolute token ceiling for compaction targeting, even on a model advertising a much larger window. 0 disables the cap.
tiermux.agent.toolCompaction"light"Replace bulky tool results from earlier steps with a one-line summary before they re-enter context.
tiermux.agent.learnFromCorrections"ask"Carry what you corrected or rejected into .tiermux/memory.md so later sessions start knowing it.
tiermux.agent.diagTracefalseLog picker → router → provider → SDK into the TierMux Diag output channel.

Models, context and completions#

SettingDefaultWhat it does
tiermux.catalog.urlthis siteWhere the model catalog comes from. Point it at your own deployment to run a private catalog.
tiermux.models.autoEnableNewtrueEnable models newly discovered in the catalog. Models on providers you have not enabled stay inactive regardless.
tiermux.utilityModel"auto"Model for short utility tasks — chat titles, commit messages. auto prefers a strong keyless model so it works with no key.
tiermux.context.includeOpenEditorstrueSilently attach the active editor — the selection, or a slice around the cursor — and its live diagnostics each turn.
tiermux.context.ambientSliceRadius15Lines of context each side of the cursor. Lower means fewer tokens per turn, which helps against free-tier quotas.
tiermux.completions.enabledfalseCopilot-style inline ghost-text completions. Off by default: high request volume against free-tier rate limits.
tiermux.completions.model"auto"Model used for inline completions.
tiermux.completions.debounceMs350Debounce before requesting a completion.

Plans, skills and MCP#

SettingDefaultWhat it does
tiermux.plan.saveToFiletrueSave Plan-mode plans as markdown checklists you can read and edit.
tiermux.plan.folder".tiermux/plans"Workspace-relative folder those plan files are written to.
tiermux.mcpServers{}MCP stdio servers whose tools are exposed to the agent.
tiermux.mcpRegistryUrl""A custom curated MCP list that replaces the bundled one.
tiermux.mcpRegistrySearchUrlofficial registryRegistry queried by the MCP panel's remote search. Blank disables remote search.
tiermux.skillRegistryUrl""Replaces the live skill list with your own.
tiermux.skillRegistrySearchUrl"https://skills.sh"Directory searched by the Skills panel's remote box.
A conservative starting point settings.json
{
  "tiermux.agent.requireWriteConfirmation": true,
  "tiermux.agent.commandApproval": "allowlist",
  "tiermux.agent.commandAllowlist": ["npm test", "npm run build", "git status"],
  "tiermux.agent.verifyCommand": "npm test",
  "tiermux.context.ambientSliceRadius": 10
}

Commands

Everything in the Command Palette (Ctrl Shift P / Cmd Shift P) under TierMux:.

CommandShortcutWhat it does
Inline Chat (Edit at Cursor)Ctrl/Cmd+IEdit at the cursor without leaving the file.
Add Selection to ChatCtrl/Cmd+Shift+LPush the current selection into the panel as context.
New Chat—Start a fresh session.
Chat History—Searchable list of past chats — the last 50 per workspace.
Compact Conversation—Summarise older turns now instead of waiting for the auto-compact threshold.
Copy Handoff Note—Copy a summary of the session for a teammate or another tool.
Manage Models & Keys—Open the Providers tab directly.
Set API Key / Clear API Key—Add or remove a provider key without opening the panel.
Refresh Model Catalog—Re-fetch the catalog now rather than on its own schedule.
Reconnect MCP Servers—Re-establish MCP connections without reloading the window.
Explain / Fix / Refactor Selection—Selection-scoped actions on the current editor.
Generate Tests / Docs—Write tests or documentation for what is selected.
Fix with AI—Act on the diagnostic under the cursor.
Generate Commit Message—Write a commit message from the staged diff, using the utility model.
Toggle Inline Completions—Turn ghost text on or off for this window.
Edit Style & Tone Memory—Open the memory file the agent carries between sessions.
Add Skill from GitHub—Install a skill from a repository URL.
Verify Grounding—Re-check a claim in the last answer against the workspace.
Tips & Announcements—Read the catalog's announcement feed in the editor.

Troubleshooting

The failures people actually hit, and what each one means.

SymptomLikely causeWhat to do
Every turn is slow to startfree-tier time-to-first-tokenExpected; free tiers are slow to first token. Pin a fast model for quick questions, or enable more providers so routing has a fast one to reach for.
"All providers failed"no reachable model left in the chainThe error names each provider tried and why. Usually every enabled provider is rate-limited at once — add a key for one more provider, or wait out the window.
Tools are ignoredrouted to a model without tool callingCheck the T badge on the model in Providers. Tool-declaring requests are kept on tool-capable models, so this normally means every tool-capable model was unreachable.
A model vanished from the pickerremoved from the catalog, or quarantinedFree tiers disappear without notice; the catalog removes dead entries rather than caching them. A 404 also quarantines that pair for 24 h locally.
Key accepted but every call 401swrong provider, or a key scoped elsewhereKeys are per provider. Re-paste it on the right row, then use TierMux: Clear API Key to drop the old one.
Completions never appearoff by defaulttiermux.completions.enabled is false, deliberately — ghost text is high request volume against free quotas.
Agent stops mid-taskstep capIt stops visibly and offers Continue with full memory. Raise tiermux.agent.maxStepsPerTurn if it happens constantly.
Not in the extension panefork reads a different registryCursor, Windsurf, Antigravity, VSCodium and Trae read Open VSX ↗. Same build.
i
Before filing anything, turn on tiermux.agent.diagTrace and reproduce once. The TierMux Diag output channel then shows the full path — picker, router, provider, raw usage — which is usually the whole answer.
02

Gateway

The self-hosted endpoint: deploy it, connect your agents to it, and know what it does when an upstream misbehaves.

Gateway

A self-hostable LLM gateway that consumes this catalog and serves inference through your own provider keys, on your own infrastructure. TierMux maintains the catalog; nothing else leaves your deployment.

protocols OpenAI · Responses · Anthropic targets Workers + D1 · Docker/Node + SQLite state final testing
  • Speaks all three protocols over one endpoint — Claude Code, Codex CLI, Cline, Zed and the OpenAI Agents SDK connect directly.
  • Key rotation, circuit breakers, per-model quarantine, aliases, and an auto model that ranks on observed facts rather than a static list.
  • Prompts, responses, provider keys and routing state never leave the deployment. The only outbound call to TierMux is the public catalog fetch.
  • Migrations apply themselves on cold start. There is no migration command on either target — which is what makes the one-click deploy viable at all.
i
The public repo has not landed yet. This catalog already serves the exact configuration payload the gateway consumes, so a gateway deployed on day one needs no additional setup. Launch updates go to the announcements feed first.

Installing and updating

The wizard is the shortest route to both: it checks the machine, asks where the gateway should run, and either starts it here or deploys it to your own Cloudflare account. The same three steps update an existing deployment.

Start the wizard from the unzipped release
npm run setup

# or double-click:
#   macOS    start.command
#   Windows  start.bat

It serves one page on 127.0.0.1:8790 and opens it. Nothing is installed globally and no terminal work follows — the Worker bundle ships pre-built, so there is no wrangler and no build step.

1 · It checks the machine#

The wizard's first step, listing Node runtime, gateway bundle and network as ready.

Three requirements, checked for you

  • Node v22.5.0 or newer. The gateway stores data through Node's built-in SQLite, which landed in v22.5.0.
  • The gateway bundle. Pre-built and ready to deploy — the check reports its size.
  • Network. Only needed for the Cloudflare route; it confirms the Cloudflare API answers from here.

Roughly thirty models answer with no provider key at all, so you can test the gateway before adding any.

2 · You choose where it runs#

The wizard's second step, offering Cloudflare or this computer.

Both are free, and neither is permanent

  • Cloudflare — a Worker with a D1 database in your own account. Reachable from anywhere, and it stays up when this computer does not.
  • This computer — runs here on SQLite for as long as the window stays open. The quickest way to try it; you can deploy to Cloudflare later without losing anything.

3 · Deploying to Cloudflare#

The wizard's Cloudflare step, showing the three API token permissions and the token field.

One scoped API token, used once

Open Cloudflare API tokens ↗, then Create Token → Create Custom Token, and add exactly these three permissions:

ScopeResourceLevelWhy
AccountWorkers ScriptsEditUploads the Worker itself.
AccountD1EditCreates the database and binds it.
AccountAccount SettingsReadReads your account list and workers.dev subdomain.
i
The token stays on your computer, is held in memory for the length of the deploy, and is never written to disk. The wizard binds to 127.0.0.1 for the same reason — a process holding a Cloudflare token has no business being reachable from the network.

Cloudflare shows the token once. Paste it, verify, and the wizard creates the D1 database, uploads the script, and enables the workers.dev URL — with real upload progress rather than a spinner.

Updating an existing gateway#

The wizard's update pane: Update existing selected, with the token steps collapsed.

Same three steps, one toggle

On the last step, switch from Fresh install to Update existing. Only the Worker code is replaced — the database, the admin account, your provider keys and every issued API key stay exactly as they are.

The token walkthrough collapses to a show the steps link, because you have already made one; the same token works again.

Updating the other way round#

If you deployed from a fork rather than the wizard, or you run it in Docker, updating is the equivalent action in that world:

How you deployedTo updateWhat happens
Setup wizardRun it again, pick Update existingNew Worker code uploaded over the old one. Database untouched.
Deploy button / forkGitHub’s Sync fork buttonWorkers Builds redeploys on the push. Database untouched.
Dockerdocker compose pull && docker compose up -dState survives the recreate and every image update.
Nodegit pull && npm install && npm startSame database in DATA_DIR.
!
A code update is always your explicit action. The gateway will never fetch and run new code on its own — it holds your provider keys and proxies your traffic, so a self-updating gateway would be a supply-chain risk rather than a convenience. Schema changes ride along with the code and apply themselves at startup, so there is never a separate migration step.
✓
The catalog updates itself regardless. New providers and models arrive on a ~5 minute poll with no redeploy — that is data, not code. Updating the gateway is only ever about the gateway’s own code.

Deploying the gateway

Two targets, one source tree, one schema. D1's engine is SQLite, so the schema is genuinely shared — only the driver differs.

Cloudflare Workers + D1 one click
The Deploy button forks the repo into
your GitHub, provisions D1, deploys,
and wires up Workers Builds.

Every later push to your fork
auto-deploys.

Needs: a browser and a CF account.
Docker / Node + SQLite
docker compose up -d      # :8788/panel

npm install && npm start   # Node 22.5+

# Built-in node:sqlite — no compile
# step, no Redis, no Postgres.
# Config: PORT and DATA_DIR.

The packaged release ships a pre-built Worker bundle, so deploying needs neither wrangler nor a build step on the far end. State survives docker compose down and every image update.

First run#

  1. Open /panel. With no admin yet, you land on /panel/install.
  2. Set an admin username and password. That is the entire form. You are never asked where the catalog lives, because that is not yours to manage — it loads on its own.
  3. Install locks. /panel/install stops working, so nobody can claim the account after you.
  4. Add a provider key, then issue an API key. /v1/* refuses to serve until at least one API key exists. There is no open mode and no default password.
!
Code updates are always your explicit action. Cloudflare: GitHub's Sync fork button, and Workers Builds redeploys. Docker: docker compose pull && docker compose up -d. A gateway that holds your provider keys and proxies your traffic must never fetch and run new code on its own.

Agents and clients

Everything that has been connected to this gateway, and the three things each one asks for under its own set of names. Seventeen clients, one endpoint.

!
Claude Code is the exception. It appends /v1/messages itself, so its base URL must not end in /v1 — otherwise every call goes to /v1/v1/messages and 404s, which Claude Code then reports as “authentication failed”. Everything else in this table takes the /v1 form.
ClientProtocolBase URLConfig lives inKey supplied as
Claude CodeAnthropichttps://YOUR-DEPLOYMENT no /v1environmentANTHROPIC_AUTH_TOKEN
Codex CLIResponseshttps://YOUR-DEPLOYMENT/v1~/.codex/config.tomlenv_key → env var
PiOpenAIhttps://YOUR-DEPLOYMENT/v1~/.pi/agent/models.jsonapiKey: "$VAR"
Hermes AgentOpenAIhttps://YOUR-DEPLOYMENT/v1~/.hermes/config.yamlapi_key: "${VAR}"
ClineOpenAIhttps://YOUR-DEPLOYMENT/v1settings UIAPI Key field
Roo CodeOpenAIhttps://YOUR-DEPLOYMENT/v1settings UIAPI Key field
Kilo CodeOpenAIhttps://YOUR-DEPLOYMENT/v1Providers → Custom providerAPI key field
AiderOpenAIhttps://YOUR-DEPLOYMENT/v1flags or environmentOPENAI_API_KEY
GooseOpenAIhttps://YOUR-DEPLOYMENT/v1goose configureprompted
OpenHandsOpenAIhttps://YOUR-DEPLOYMENT/v1Settings → AdvancedAPI key field
ContinueOpenAIhttps://YOUR-DEPLOYMENT/v1config.yamlapiKey
Open WebUIOpenAIhttps://YOUR-DEPLOYMENT/v1Settings → ConnectionsAPI key field
ZedOpenAIhttps://YOUR-DEPLOYMENT/v1settings UIAPI key field
OpenCodeOpenAIhttps://YOUR-DEPLOYMENT/v1config fileAPI key field
DeepSeek harnessOpenAIhttps://YOUR-DEPLOYMENT/v1environmentOPENAI_API_KEY
OpenAI SDKOpenAIhttps://YOUR-DEPLOYMENT/v1codeapi_key=
curlall threehttps://YOUR-DEPLOYMENT/v1 / https://YOUR-DEPLOYMENT—Authorization: Bearer

The three values#

Whatever a client calls its fields, it is asking for the same three. Base URL turns up as “API endpoint”, “Custom URL” or “Provider API”; the provider type must be set to OpenAI Compatible before any of them take effect, because every other provider type ignores the URL and calls its own servers.

ValueWhat to useNotes
Base URLhttps://YOUR-DEPLOYMENT/v1Claude Code excepted, as above.
API keytmx_…Issued under Connect in your panel. Shown once; only its hash is stored.
ModelautoLets the gateway choose. Put a model id from your Models tab here instead to pin one.

Verifying a connection#

Before blaming the client, check the gateway answers. A 200 with a non-empty list means the URL, the key and the catalog are all good — so anything still broken is on the client's side of the wire.

Verify curl
curl -s -H "Authorization: Bearer tmx_your_key_here" \
  "https://YOUR-DEPLOYMENT/v1/models"
i
Your own deployment shows these steps with your real URL and key already filled in, under Connect in the panel. The full per-client walkthrough is on the gateway page →

Gateway routing and failure policy

A fixed, deterministic order — and a substitution is always announced, never silent.

  1. Exact alias — yours, panel-configured, resolves before model names
  2. Exact model_id
  3. Normalized key — deepseek/deepseek-v4:free and deepseek-v4 collide, which is what makes cross-provider fallback possible
  4. Wildcard match — deepseek/* style patterns
  5. Configured fallback alias
  6. auto — unknown names land here instead of dead-ending on a 404; x-tiermux-model and the response body both name what actually ran

Before any of it: requests declaring tools only reach tool-capable models, image-carrying requests only vision-capable ones, and prompts are steered away from models whose context window cannot hold them.

Failure policy#

Upstream resultWhat happens
400 · 413 · 415 · 422Caller's fault — returned verbatim, never retried.
401 · 403That key is parked 15 minutes; the request fails over.
402 · 404 · 405 · 501Fail over; the model–provider pair is remembered and skipped next time.
408 · 409 · 425Transient — fail over.
429That key is parked and the next takes over. Honours Retry-After; a "daily quota gone" body parks the key until midnight UTC. Never opens the circuit.
5xx · 529Counts toward two circuits — the provider's (5 consecutive) and that one model's (3). One broken model never takes its provider offline.
Stream dies before first tokenFalls over. HTTP 200 and headers are not a commitment.
Stream dies after first tokenNever falls over — switching mid-answer would duplicate generation and re-run tool calls. The failure is reported inside the stream.

The auto profiles, hedging, quota headroom and recovery windows →

03

Catalog API

The public data layer both products read. Five GET endpoints, open CORS, no key.

Catalog API — conventions

Five read-only endpoints. All are GET, all are CORS-enabled, and none of them takes an API key.

Base URL
https://tiermux.mainulislam3057.workers.dev

Authentication#

None. There is no key to obtain and no header to send. Every response carries Access-Control-Allow-Origin: * and Access-Control-Allow-Methods: GET, so browser code can call these endpoints directly with no proxy.

Caching and versioning#

The four catalog endpoints answer with Cache-Control: public, max-age=120. /api/service-status answers no-store, because a stale kill-switch read is worse than an extra request.

Every catalog response carries three fields at the top level:

FieldTypeMeaning
versionstringCatalog schema version, e.g. "1.6". Key your client's cache on this — a change means the shape may have moved.
last_updatedstringDate of the last catalog revision, YYYY-MM-DD — the newest change to any provider, model or announcement the response was built from. Currently "…".
last_synced_atstring | nullWhen the catalog was last verified against the providers, ISO 8601 UTC. The sync runs every five minutes; a value older than about fifteen minutes means it is stalled. Currently "…".
✓
Poll politely. The catalog re-syncs every five minutes and changes only when a provider's free tier does. A five-minute poll is generous; anything faster only ever reads the same 120-second cache. The gateway polls on roughly that cadence and keeps its last valid catalog if a fetch fails or comes back malformed.

Filtering#

Two query parameters exist across the API. Unknown parameters are ignored rather than rejected.

ParameterTypeAccepted by
tagstring/models and /catalog. One of frontier, strong, mid, small, unknown — the tier every model carries. A tag that matches nothing returns an empty list, not an error.
providerstring/models only. A provider_id such as google.
i
Only enabled entries are public. A disabled provider is absent, and so is every model on it, regardless of that model's own state. So enabled is always true in these responses — it is there for clients that also read an operator export, where it is not.
GET/modelsflat list

Every enabled model as a flat list, each entry joined with its provider. The endpoint most clients want.

cache public, max-age=120 auth none params tag, provider
Request
curl -s "https://tiermux.mainulislam3057.workers.dev/models?tag=reasoner&provider=google"

Response

200 real response, truncated to the first model
{
  "version": "1.6",
  "last_updated": "…",
  "last_synced_at": "…",
  "count": 9,
  "models": [
    {
      "model_id": "gemini-2.5-flash",
      "display_name": "Gemini 2.5 Flash",
      "enabled": true,
      "context_window": 1000000,
      "capabilities": { "tools": true, "vision": true, "reasoning": true },
      "tags": ["mid"],
      "limits": { "rpm": 15, "rpd": 1500 },
      "pricing": { "free": true, "input": 0.3, "output": 2.5 },
      "recommended": false,
      "provider_id": "google",
      "provider_display_name": "Google"
    }
  ]
}
FieldTypeNotes
countnumberLength of models after filtering, not the size of the catalog.
models[]Model[]See the object reference. On this endpoint only, each entry also carries provider_id and provider_display_name.
GET/providersdirectory

The provider directory with a model count per provider, and no model bodies. Use it to build a picker without downloading the whole catalog.

cache public, max-age=120 auth none params none
200 real response, truncated to one provider
{
  "version": "1.6",
  "last_updated": "…",
  "last_synced_at": "…",
  "count": 34,
  "providers": [
    {
      "provider_id": "google",
      "display_name": "Google",
      "base_url": "https://generativelanguage.googleapis.com/v1beta",
      "keyless": false,
      "key_url": "https://aistudio.google.com/apikey",
      "enabled": true,
      "model_count": 10
    }
  ]
}
i
key_url and docs_url are only present when set. Read them with a presence check, not a truthiness check on an assumed key.
GET/catalogeverything

Providers with their models nested, plus announcements, in one request. This is the payload shape the gateway consumes.

cache public, max-age=120 auth none params tag
200 shape only
{
  "version": "1.6",
  "last_updated": "…",
  "last_synced_at": "…",
  "announcements": [ { "id": 7, "title": "…", "details": "…" } ],
  "providers": [
    {
      "provider_id": "groq",
      "display_name": "Groq",
      "base_url": "https://api.groq.com/openai/v1",
      "keyless": false,
      "key_url": "https://console.groq.com/keys",
      "enabled": true,
      "models": [ { "model_id": "…", "capabilities": { … } } ]
    }
  ]
}

With ?tag=, models are filtered first and providers left with no matching model are dropped entirely — so the response never contains an empty models array you have to skip over.

✓
Prefer /models if you are going to flatten this anyway — it is a smaller response and already carries the provider name on each entry.
GET/announcementsfeed

Operator announcements: new providers, newly verified free tiers, removals, and product updates such as the gateway launch.

cache public, max-age=120 auth none params none
200
{
  "version": "1.6",
  "last_updated": "…",
  "last_synced_at": "…",
  "count": 3,
  "announcements": [
    { "id": 1, "title": "New provider verified", "details": "Plain text, newlines preserved." }
  ]
}

details is plain text, not HTML or markdown. Render it in a <pre> or escape it — the rendered feed at the bottom of this page does exactly that.

GET/api/service-statuskill switch

The cheapest possible read, carrying no catalog data. This is the endpoint automated clients should poll.

cache no-store auth none params none
200
{ "service_enabled": "1", "last_synced_at": "…" }

The value is the string "1" or "0", not a boolean. When it reports "0", the four catalog endpoints answer 503 until the operator flips it back. last_synced_at is the same field the catalog endpoints carry, so a client can watch for a stalled sync from this one cheap read.

!
Fail open, not closed. If this endpoint is unreachable, treat the service as up and keep serving from your last good catalog. A client that hard-fails on a network blip turns a catalog outage into your outage — the gateway takes exactly this approach.

Object reference

The two objects that appear across the API.

Model#

FieldTypeDescription
model_idstringThe id to send to the provider, verbatim. Unique only within a provider — the same id on two providers is two catalog entries.
display_namestringHuman label. Fall back to model_id if you need a guaranteed non-empty string.
enabledbooleanAlways true in public responses; disabled models are filtered out before serving.
context_windownumberTokens, as verified. May be 0 or null when the provider never disclosed one and probing was inconclusive.
capabilities.toolsbooleanTool/function calling works. Measured with a real call.
capabilities.visionbooleanAccepts image input.
capabilities.reasoningbooleanEmits reasoning output.
tags[]string[]Exactly one entry: the model's capability tier — frontier, strong, mid, small, or unknown when the id could not be resolved. The band is measured capability, so it is independent of parameter count and of pricing. Capabilities themselves are never tags; read capabilities.* instead.
limits.rpmnumberRequests per minute per key. null when the provider publishes none.
limits.rpdnumberRequests per day per key. Same nullability.
pricing.freebooleanCallable at no cost on this provider's free tier.
pricing.inputnumberUSD per million input tokens. null when unpriced.
pricing.outputnumberUSD per million output tokens.
recommendedbooleanOperator's pick among comparable entries. A ranking hint, not a capability.
provider_idstring/models only The owning provider.
provider_display_namestring/models only That provider's label.
!
pricing.free: true is not the same as "0.00 in, 0.00 out". Some providers list a zero price on a model that answers 429 requires_purchase until an account is funded. The free flag is set from what a real call returned, so trust the flag over the numbers.

Provider#

FieldTypeDescription
provider_idstringStable id — the value the provider query parameter takes.
display_namestringHuman label.
base_urlstringAPI root. Empty string when the provider is reached some other way.
keylessbooleanAnswers with no key and no account.
key_urlstringoptional Where a free key is issued. Absent when there is nothing to link to.
docs_urlstringoptional The provider's own API docs.
enabledbooleanAlways true in public responses.
model_countnumber/providers only Enabled models on this provider.
models[]Model[]/catalog only Nested models, without the two provider fields — you already know the provider.
i
The operator's private comments column on a provider is deliberately not in any public response. It holds maintenance notes that may name accounts or internal decisions.

Errors and status codes

Every error is JSON with a single error string. There are no error codes to switch on — the HTTP status is the contract.

StatusBodyWhen, and what to do
200the payloadNormal. An empty models or providers array is a 200, not a 404 — a filter that matches nothing is not an error.
404{"error":"Not found"}Unknown path — and also a known path with a method other than GET, because routes match on method and path together, so POST /models is a 404 rather than a 405. Check for a typo before assuming an outage; there are only five public endpoints.
503{"error":"Service is currently paused. Try again later."}The operator kill switch is off. Sent no-store. Keep serving your last good catalog and re-check /api/service-status on a slow timer.
500{"error":"…"}Unexpected. Retry once with backoff; if it persists, it is worth reporting.
Handling both failure modes JavaScript
async function loadCatalog(previous) {
  try {
    const res = await fetch(BASE + "/models");
    // 503 means paused, not broken: keep whatever you had.
    if (res.status === 503) return previous;
    if (!res.ok) throw new Error("HTTP " + res.status);
    const data = await res.json();
    // A malformed body must not replace a good catalog either.
    if (!Array.isArray(data.models)) throw new Error("bad shape");
    return data;
  } catch (err) {
    return previous;
  }
}

Rate limits#

There is no per-client rate limit on these endpoints and no 429. The 120-second cache is what protects the service, which is also why a tighter poll buys you nothing.

The limits on a model are a different thing entirely: those are the upstream provider's limits, per key, and they are the numbers your own client has to respect.

04

Directory

The live catalog, rendered from the same API this page documents.

Model directory

The complete model directory, generated live from the catalog on page load. Capability badges are measured per model: T tool calling, V image input, R reasoning output.

ModelProviderContextCapabilitiesPrice
Loading the catalog…

Provider directory

Every provider in the catalog, with its endpoint and key information. Keyless providers need no account; the others issue free API keys through their own portals — the get a key ↗ link goes straight there.

ProviderEndpointAccessModels
Loading the catalog…
05

Reference

Operator announcements and the questions that come up most.

Announcements

Catalog and product updates from the operator, newest first. The same feed is available as JSON at /announcements.

Loading announcements…

FAQ

Is there a rate limit on the catalog API?

No per-client limit and no 429. Responses are cached for 120 seconds, so polling faster than that reads the same bytes. Five minutes is a sensible cadence; the catalog itself re-syncs every five minutes.

Can I call this from a browser?

Yes. Every response sends Access-Control-Allow-Origin: *, so no proxy is needed. The page you are reading does exactly that — the directories above were fetched client-side.

A model in the catalog returned 429 immediately. Is the data wrong?

Probably not. limits.rpm and limits.rpd are per key, and a free tier's real headroom moves — a promotion can appear and vanish inside a day.

The catalog records what a real call returned at verification time. If a listing has genuinely stopped answering it gets removed on the next sync rather than cached; the fastest fix on your side is a second key, or a second provider.

Can I run my own catalog?

Yes, and both products support it. Point tiermux.catalog.url at your own deployment for the extension, or set the TIERMUX_CONFIG_URL deployment variable for the gateway. Serve the /catalog shape documented above and both will consume it.

Does the extension send anything to TierMux?

It fetches the catalog from this site. That is the only request in its direction, and it carries no identity, no prompt and no usage.

Inference goes VS Code → provider, directly. Keys live in VS Code's encrypted secret storage; chats are JSON files on your own disk. The gateway keeps the same rule on your infrastructure.

Why is the same model listed several times?

Because a model on two providers has two context windows, two rate limits and two prices — and on a given day one of them works while the other does not. Keeping them as separate entries is what makes cross-provider failover possible; collapsing them would throw away the only field that matters when one goes down.

Something missing here? The extension is open source — open an issue on GitHub ↗.