@mrgoonie/openrouter-cli
v0.1.2
Published
OpenRouter CLI — agent + human friendly wrapper for the full OpenRouter API
Readme
openrouter
The all-in-one CLI for the OpenRouter API — agent-friendly by default.
Quickstart
# 1. Install
brew install openrouter/tap/openrouter
# 2. Authenticate
openrouter auth set-key sk-or-v1-...
# 3. Chat
openrouter chat send "What is the capital of France?" --model openai/gpt-4oFor agents — machine-readable JSON:
openrouter chat send "Summarize this" --model openai/gpt-4o --json --no-stream \
<<< "$(cat document.txt)"
# stdout: { "schema_version": "1", "success": true, "data": { ... } }Install
Homebrew (macOS / Linux)
brew install openrouter/tap/openrouterCurl script
curl -fsSL https://raw.githubusercontent.com/mrgoonie/openrouter-cli/main/install.sh | shnpm
npm install -g @mrgoonie/openrouter-cliFrom source (requires Bun ≥ 1.1.38)
git clone https://github.com/mrgoonie/openrouter-cli
cd openrouter-cli
bun install
bun run build # outputs bin/openrouter
./bin/openrouter --help
# Or run without building:
bun run dev -- --helpConfiguration
The CLI resolves every config value from 6 sources in priority order:
| Priority | Source | Example |
|----------|--------|---------|
| 1 (highest) | CLI flag | --api-key sk-or-v1-... |
| 2 | Environment variable | OPENROUTER_API_KEY=sk-or-v1-... |
| 3 | .env file (dotenv cascade) | .env in cwd or parents |
| 4 | TOML config file | ~/.config/openrouter/config.toml |
| 5 | OS keychain | openrouter auth login |
| 6 (lowest) | Built-in default | https://openrouter.ai/api/v1 |
Debug your config:
openrouter config doctor --jsonSet values:
openrouter config set defaults.model openai/gpt-4o
openrouter config get defaults.model
openrouter config path # print config file locationSee .env.example for all recognized environment variables.
Commands
| Command | Description |
|---------|-------------|
| analytics show | Usage analytics by endpoint |
| auth login | OAuth PKCE flow — stores key automatically |
| auth set-key <key> | Manually store an API key |
| auth status | Show resolved config + sources |
| auth whoami | Verify credentials with a live API call |
| chat send <msg> | Streaming chat completions |
| completion | Shell completion (bash/zsh/fish) |
| config doctor | Diagnose config resolution |
| config get/set/unset | Read and write TOML config values |
| credits show | Account credit balance |
| embeddings create | Text embeddings |
| generations get | Generation metadata by ID |
| guardrails list/create/… | Manage content guardrails |
| keys list/create/… | Manage API sub-keys |
| models list | Browse available models |
| org members | Organization member list |
| providers list | Provider status |
| rerank create | Rerank documents by relevance |
| responses create | Responses API (beta) |
| video create/status/wait/download | Async AI video generation |
Agent Mode
The CLI is designed to be called from scripts and AI agents.
JSON output
Every command supports --json for a stable envelope:
{
"schema_version": "1",
"success": true,
"data": { ... },
"error": null,
"meta": { "request_id": "gen-...", "elapsed_ms": 312 }
}Error envelope:
{
"schema_version": "1",
"success": false,
"data": null,
"error": { "code": "unauthorized", "message": "Invalid API key", "status": 401 },
"meta": {}
}NDJSON streaming
openrouter chat send "Write a haiku" --model openai/gpt-4o --output ndjson
# → one JSON object per line, tokens streamed as they arriveExit codes
| Code | Meaning | |------|---------| | 0 | Success | | 1 | Unexpected error | | 2 | Bad flags / missing args | | 64 | API key not set | | 65 | Unauthorized (HTTP 401) | | 66 | Forbidden (HTTP 403) | | 67 | Not found (HTTP 404) | | 68 | Insufficient credits (HTTP 402) | | 69 | Rate limited (HTTP 429) | | 70 | Server error (HTTP 5xx) | | 71 | Request timeout | | 72 | Unexpected API response shape | | 73 | Async video job failed / cancelled |
Check $? after every call. Exit codes are stable across patch versions.
Troubleshooting
No API key → exit 64
export OPENROUTER_API_KEY=sk-or-v1-...
# or:
openrouter auth set-key sk-or-v1-...Management key required → exit 64
Commands like credits show, keys list, guardrails list need a separate management key:
export OPENROUTER_MANAGEMENT_KEY=sk-or-v1-...
# or:
openrouter auth set-key sk-or-v1-... --managementRate limited → exit 69
The client retries automatically (up to 3 times with exponential backoff). If still hitting limits, reduce request frequency or add --timeout headroom.
SSE stream hangs
Add --no-stream to get a single blocking response instead:
openrouter chat send "hi" --model openai/gpt-4o --no-stream --jsonInspect full config resolution
openrouter config doctorClaude Code plugin
This repo ships a Claude Code plugin that teaches agents how to drive the CLI with JSON envelopes, stable exit codes, NDJSON streaming, and common workflows (chat, embeddings, rerank, video).
# Inside Claude Code:
/plugin marketplace add https://github.com/mrgoonie/openrouter-cli
/plugin install openrouter@openrouter-cliSource: plugins/openrouter · Marketplace manifest: .claude-plugin/marketplace.json.
Docs
- Project Overview & PDR — vision, target users, success metrics
- Design Guidelines — command structure, output formats, agent contracts, OAuth flow
- Tech Stack — Bun, Citty, libraries, build + release pipeline
- Codebase Summary — file-by-file purpose table
- Code Standards — TypeScript conventions, test patterns, exit codes
- System Architecture — request lifecycle, config cascade, video state machine
- Deployment Guide — install channels + contributor release flow
- Project Roadmap — v1 (shipped) → v2 → v3 milestones
Contributing
git clone+bun installbun run dev -- --help— verify CLI startsbun run test— unit tests (no network)bun run test:integration— real-API tests (requires.envwithOPENROUTER_API_KEYand/orOPENROUTER_MANAGEMENT_KEY; per-suite auto-skip if a key is missing)bun run lint && bun run typecheck— must be clean- Read Code Standards before submitting a PR
Integration tests
Integration tests spawn the compiled CLI and hit the real OpenRouter API. They use free / cheap models (meta-llama/llama-3.2-1b-instruct:free, google/gemini-2.0-flash-lite-001, openai/text-embedding-3-small) to keep cost negligible.
- Locally: put keys in
.env, thenbun run test:integration. - CI: configure
OPENROUTER_API_KEYandOPENROUTER_MANAGEMENT_KEYas repo secrets. TheIntegration Testsworkflow runs onpushtomainand viaworkflow_dispatch.
License
MIT © 2026
