omp keeps every provider credential — OAuth refresh tokens, OAuth access tokens, stored API keys — in a single local SQLite file. /login writes to it, /logout clears entries from it, and provider calls read from it. When you need the same logins on more than one host, swap the local file for a remote broker without touching any other config.
The credential store
Credentials live in ~/.omp/agent/agent.db (or the equivalent under PI_CONFIG_DIR). One row per credential, multiple credentials per provider allowed — round-robin selection picks between them at call time.
The store holds three things per row: the provider id (anthropic, openai-codex, google-gemini-cli, …), the credential type (OAuth or API key), and the secret payload. OAuth rows carry both the long-lived refresh token and the short-lived access token; refreshes happen in-process whenever the access token is within a minute of expiry. API-key rows hold the raw key.
Protect the file the way you would ~/.ssh/id_*: filesystem permissions are the only thing between an attacker with read access to your home directory and your tokens. If that worries you, move the credentials off the machine entirely with the auth broker — laptops then hold no refresh tokens at all.
Signing in and out
Inside omp:
-
/loginopens the provider picker. Pick a provider, complete the OAuth flow in your browser, and the resulting tokens are appended toagent.db. Pasting an API key when prompted does the same thing for non-OAuth providers. -
/logout <provider>deletes every credential row for that provider. Use it to revoke an account without touching others. -
To rotate,
/logoutthen/loginagain. There is no in-place rotation — the new tokens replace the old row.
OAuth flows bind a local callback port per provider so the browser can hand the code back to omp. The defaults: Anthropic 54545, OpenAI Codex 1455, Google Gemini CLI 8085, Google Antigravity 51121, GitLab Duo 8080. If one is busy, close whatever else is bound to it before re-running /login.
The picker is also the inspection surface: it shows every provider with at least one row in agent.db, so a glance at /login tells you what you are currently signed into. See Providers for the OAuth-capable provider matrix.
API keys vs stored credentials
When omp needs a credential for a provider, it walks this list and returns the first hit:
-
--api-keyon the omp command line. -
Stored API-key row in
agent.db. -
Stored OAuth row in
agent.db(refreshed if expiring). -
Provider env var (
ANTHROPIC_API_KEY,OPENAI_API_KEY,GEMINI_API_KEY, …).
Env vars are a fallback, not an override — a stored credential always wins over an env var for the same provider. To force the env var to take precedence, /logout <provider> first. The full env inventory lives in Environment variables.
One narrow override exists: a models.yml apiKey will beat a stored OAuth token without overriding a runtime --api-key. This is the escape hatch for “I want this one model config to use a specific key while leaving my OAuth login intact”.
Sharing credentials across machines
omp auth-broker serve turns one host into a credential vault that other machines query over HTTP. The broker is the only writer of refresh tokens; clients receive a snapshot in which refresh tokens are replaced by a sentinel, and they call back to the broker on access-token expiry.
# on the broker host
omp auth-broker serve --bind=0.0.0.0:8765
omp auth-broker login anthropic # OAuth flow runs here
omp auth-broker token --json # mint the bearer token for clientsPoint clients at it with OMP_AUTH_BROKER_URL and OMP_AUTH_BROKER_TOKEN (or the matching auth.broker.url / auth.broker.token keys in config.yml). When set, omp bypasses the local agent.db entirely and resolves every credential through the broker. /login and /logout proxy through too, so day-to-day usage is unchanged.
omp auth-broker login <provider> --via=user@host is the trick for laptops without a browser on the broker host: it opens an SSH tunnel so the OAuth callback hits your local browser while the credential lands in the broker’s agent.db. Other useful subcommands: omp auth-broker logout <provider> (interactive without an arg), omp auth-broker list to enumerate supported providers, omp auth-broker status, omp auth-broker token --regenerate to rotate the bearer.
Transport security between client and broker is your responsibility — terminate TLS at a reverse proxy, or put the broker behind Tailscale / WireGuard. The broker enforces a bearer token on every endpoint except /v1/healthz.
Routing provider calls through the gateway
The broker only resolves credentials; it does not proxy provider traffic. For clients that speak raw OpenAI Chat, Anthropic Messages, or OpenAI Responses wire formats — third-party CLIs, scripts, IDE plugins, containerised omp — pair the broker with omp auth-gateway serve. The gateway accepts those requests on 127.0.0.1:4000 (default), strips the inbound Authorization header, asks the broker to resolve the right credential for the requested model, and forwards the bytes upstream with the resolved access token injected.
The gateway is itself a broker client, so it inherits OMP_AUTH_BROKER_URL and OMP_AUTH_BROKER_TOKEN. Its own inbound bearer token lives at ~/.omp/auth-gateway.token (mode 0600); --no-auth disables that check for loopback-only use. Clients never see provider tokens, and credential rotation continues to flow from a single broker.
Related
-
Providers — OAuth-capable provider list and the full credential resolution order.
-
Environment variables — every
OMP_*and provider*_API_KEYvariable omp reads. -
MCP — MCP servers reuse the same
agent.dbfor their OAuth credentials.\n