Providers Overview
Providers are the LLM inference backends meka uses to run your instructions. meka ships with five, each selectable as a profile type:
| Backend | Protocol | Endpoint | Auth |
|---|---|---|---|
anthropic-messages | Anthropic Messages | {base}/v1/messages | API key |
claude-subscription | Anthropic Messages | api.anthropic.com/v1/messages | Claude subscription |
openai-chat-completions | OpenAI Chat Completions | {base}/chat/completions | API key |
openai-responses | OpenAI Responses | {base}/responses | API key |
chatgpt-subscription | OpenAI Responses | chatgpt.com/backend-api/codex/responses | ChatGPT subscription |
A backend names the wire protocol, not a vendor. That is deliberate, and it cuts both ways. One vendor can serve several protocols: OpenAI publishes Chat Completions and Responses, and they are different request shapes, not options on one. One protocol is served by many vendors: /v1/messages is implemented by Anthropic, Amazon Bedrock, Databricks, LiteLLM and Ollama, so calling it “the Claude API” would misname it the moment you point it elsewhere.
The two subscription backends are the exception, and carry a vendor name instead. What you pick there is a billing relationship; the endpoint and the client shape come with it and are not yours to choose.
Synthetic is the clearest case for why this matters. One vendor, two protocols, two base URLs:
[providers.synthetic-claude]
type = "anthropic-messages"
base_url = "https://api.synthetic.new/anthropic/v1"
[providers.synthetic-gpt]
type = "openai-chat-completions"
base_url = "https://api.synthetic.new/openai/v1"
Configuring a Provider
Providers are configured as named profiles. The easiest way is meka provider add, which writes the
profile to the config file and stores the secret (API key or OAuth token) in the database:
$ meka provider add work --type claude-subscription --model claude-opus-5
This produces a [providers.work] entry in ~/.config/meka/config.toml:
default_provider = "work"
[providers.work]
type = "claude-subscription"
model = "claude-opus-5"
Selecting a Provider
A new session runs on the profile named by --provider <name>, else default_provider, else
the sole profile. Switch the default with meka provider use <name>:
meka --provider work # pick the profile this session starts on
meka provider use work # persist as default_provider
There is no environment-variable override for provider selection.
A resumed session ignores all three and runs on the profile it recorded, so meka -c stays
where the conversation was had whatever default_provider currently says. --provider on a resume
is not a per-run override either: it repins the session, rewriting the row so every later resume
keeps it. meka session list shows which profile each session runs on, which is the whole story: a
session records a profile name and nothing else. You can move a live session with /provider <name>
in the REPL, PATCH /v1/sessions/{id} over HTTP, or the Provider picker in an ACP client. See
Sessions.
Pointing a backend somewhere else
Every API-key backend takes a base_url, so the protocol you pick is independent of who serves it:
| Server | Chat Completions | Responses | Anthropic Messages |
|---|---|---|---|
| OpenAI | yes | yes | no |
| Anthropic | no | no | yes |
| Ollama | yes | yes (v0.13.3+) | yes |
| OpenRouter | yes | yes (beta) | yes |
| vLLM / LM Studio | yes | yes | no |
| Synthetic | yes | no | yes |
Where a server offers both OpenAI protocols, prefer openai-responses: it is what OpenAI recommends for new work and what the agent tooling ecosystem has moved to. Use openai-chat-completions for a server that does not serve Responses.
Note that several of these also expose a legacy /v1/completions endpoint. That is a third, different protocol: a bare prompt string in, choices[].text out, no tool calling. meka does not speak it. It cannot: the agent loop needs tool calls, which that protocol has no representation for.
anthropic-messages vs claude-subscription
Both talk to Claude’s /v1/messages endpoint, but the auth and request shape differ:
anthropic-messagesis the straightforward path: anx-api-keyheader and a plain system prompt, plusanthropic-beta: interleaved-thinking-2025-05-14whenever thinking is on (the default). Choose this when you have a Claude API key.claude-subscriptionreplicates the Claude Code CLI exactly: OAuth tokens, fingerprint-encoded version header, xxHash64 attestation over the request body, injected billing system block. Choose this when you want to use a Claude Code subscription. Any deviation from the expected shape causes requests to be rejected, so avoid proxies that rewrite headers or reformat the body.
Choosing between the OpenAI backends
Three backends, two protocols:
openai-chat-completionsposts to/chat/completionswith an API key. Choose it for a server that serves only this protocol.openai-responsesposts to/responseswith an API key, the same protocolchatgpt-subscriptionuses. Choose it for OpenAI, or for any server that serves Responses.chatgpt-subscriptionposts tochatgpt.com/backend-api/codex/responses, authenticating by OAuth againstauth.openai.comand mirroring the first-party Codex CLI. Choose it to bill a ChatGPT Plus / Pro / Team / Business subscription instead of a per-token API key.
The first two differ by protocol; the last two differ only by auth and endpoint.
Streaming vs Non-Streaming
By default, meka uses streaming mode: tokens appear in the terminal as they are generated. Use --no-stream to wait for the complete response before displaying it.
Streaming is recommended for interactive use. Non-streaming may be useful for scripting or when the provider does not support SSE.