npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aaronjmars/openroutercli

v0.4.0

Published

Command-line interface for the OpenRouter API. Built for humans and LLM agents.

Readme


What it does

  • One CLI for the entire OpenRouter API - every endpoint in the OpenAPI spec is reachable.
  • Login once with browser-based OAuth (PKCE), paste an existing key, or use env vars. Separate slot for management/provisioning keys.
  • Streams chat completions in a TTY; emits clean JSON when piped or with --json. Built so an agent can --json | jq reliably.
  • Knows the difference between user keys and management keys - picks the right one per command.

Quick start

The recommended path: install with npm + openrouter login. First request in under 60 seconds.

Prereqs - Node.js 20+ and an OpenRouter account.

Install:

  • npm - npm install -g @aaronjmars/openroutercli
  • npx (no install) - npx -p @aaronjmars/openroutercli openrouter --help
  • From source - git clone https://github.com/aaronjmars/openroutercli && cd openroutercli && npm link

Then:

openrouter login                                            # OAuth in the browser
openrouter chat "say hi" -m openai/gpt-4o-mini              # streaming chat
openrouter --json models --filter sonnet | jq '.data[].id'  # pipeable JSON
openrouter credits                                          # what's left in the tank

Other paths - drop in an existing key with openrouter login --key sk-or-..., pipe one in with --stdin, or set OPENROUTER_API_KEY for ephemeral use. Management keys (for keys / guardrails / workspaces / activity) come from the dashboard and are saved with openrouter login --management.

Two key types - user vs management

The CLI keeps a separate slot for each key type and auto-routes per command. --key sk-or-... always wins as an override; otherwise inference reaches for the user slot, account-management commands reach for the management slot, and either falls back to the other when one slot is empty. Management keys cannot be obtained via OAuth - mint one in the dashboard and run openrouter login --management.

Features

| Feature | What it does | |---|---| | OAuth PKCE login | openrouter login opens the browser, catches the callback locally, exchanges the code, and stores the key - 0600 perms in ~/.config/openrouter/. No paste-an-API-key dance. | | Two-slot key management | User key + management/provisioning key live in separate slots. keys, byok, guardrails, workspaces, observability, activity auto-pick the management key; everything else uses the user key. --key always wins. | | Streaming + JSON modes | Streams in a TTY, switches to JSON when piped or --json is set. No global flag plumbing - works on every command. | | Chat with everything | Tool calls (--tool @file.json --tool-choice required), server tools (--server-tool web_search), deferred tool loading, structured output (--schema schema.json), JSON mode, multimodal images (--image url\|path), image output (--modalities text,image), reasoning effort, automatic prompt caching (--cache --cache-ttl 1h), alignment rules (--rule), provider routing, fallback models, service tiers, sessions and traces, full sampling controls. | | Interactive REPL | openrouter chat -i - slash commands /model <id>, /reset, /exit. History preserved per session. | | Multi-format inference | chat (OpenAI), messages (Anthropic), responses (OpenAI Responses) - same auth, same flags, same JSON contract. | | Batches | batches {create,list,get,wait,results,delete} - send a JSONL file of chat / responses / messages / embeddings requests as one async job at about half price. | | Embeddings + rerank + speech + video | embed (text or images), rerank, speech (tone instructions, multi-speaker turns, voice references), transcribe (URL input, speaker labels, key terms, word timestamps), video {create,wait,download} (resolution, first/last frame, references, audio, extend) - async video jobs poll-until-done with video wait <jobId>. | | Model discovery with detail | models list (filter, sort by price/context), models show <id> (full pricing breakdown - prompt, completion, cache r/w, reasoning, image, web search), models endpoints <id> --sort throughput\|latency\|prompt\|completion\|uptime --best for choosing the right provider variant. | | Benchmarks + rankings | benchmarks, classifications, and datasets {apps,daily,session-cost} expose OpenRouter's current public benchmark and usage datasets. | | Management analytics | analytics meta discovers fields; analytics query runs metrics/dimensions/time-range queries with a management key. | | Structured decisions | decisions (alias systemone) calls System One for typed choice, score, and yes/no outputs, with optional image inputs. | | Server tools catalog | tools list / tools get <name> - every OpenRouter-run tool (web search, fetch, datetime, ...) with params, engines and pricing. | | Hosted shell files | containers {list,get,download,promote} retrieves and promotes files produced by OpenRouter's hosted shell tools. | | Spend + activity + generations | credits for balance, whoami for daily/weekly/monthly usage + rate limit, keys get <hash> for per-key spend, activity --api-key-hash <hash> for daily aggregates, generation <id> [--content] for full per-request metadata + input/output. | | Account + governance | keys, guardrails (allow/deny lists, USD limits, ZDR, data regions, content filters), workspaces (defaults, members, budgets, disabled tools), observability destinations (Langfuse, Datadog, ...), org members / org settings, auth-code to mint claim links. All require a management key. | | Raw escape hatch | openrouter request <METHOD> <path> --body @file.json --query k=v --header k:v - talk to any current or future endpoint without waiting for a CLI release. | | Agent-friendly errors | Stable exit codes (1 usage, 2 API, 3 no key, 4 job failed). API error messages surfaced verbatim. OPENROUTER_DEBUG=1 for stack traces. | | Zero npm dependencies | Pure Node 20+ - built-in fetch, parseArgs, crypto. Cold install in seconds. Easy to audit. |

Each command supports openrouter <command> --help for full per-command flags.

Use cases

  • Throwaway prompts from the shell - echo "summarize this" \| openrouter chat -m openai/gpt-4o-mini instead of opening a browser tab.
  • Agent / script integration - openrouter --json chat ... \| jq keeps stdout clean and machine-parseable; meaningful exit codes let scripts branch on errors.
  • Comparing models head-to-head - for m in claude-sonnet-4.5 gpt-4o gemini-2.5-pro; do openrouter chat "$prompt" -m anthropic/$m; done
  • Picking the cheapest / fastest provider variant - openrouter models endpoints <id> --sort throughput --best before locking in a model in production.
  • Cost monitoring - openrouter credits + openrouter whoami in cron / a status bar; openrouter keys get <hash> per-app.
  • Provisioning per-customer keys - wrap openrouter keys create in your onboarding flow; rotate / disable / delete via keys update --disabled and keys delete.
  • Auditing a specific request - paste a gen-... id into openrouter generation <id> --content to see exactly what was sent and returned, with cost.
  • CI smoke-tests for prompt changes - fixed seed, JSON-schema response, exit non-zero on regression.

Examples

# Browser OAuth login (recommended)
openrouter login

# Manual key entry (and management/provisioning key)
openrouter login --key sk-or-v1-...
openrouter login --management --key sk-or-v1-...

# Streaming chat
openrouter chat "Write a haiku about caching" -m anthropic/claude-sonnet-4.5

# Multimodal
openrouter chat "What's in this picture?" -m google/gemini-2.5-flash --image ./photo.jpg

# Strict JSON output
openrouter chat "List 3 fruits" -m openai/gpt-4o-mini \
  --schema '{"type":"object","properties":{"fruits":{"type":"array","items":{"type":"string"}}},"required":["fruits"]}'

# Tool calling
openrouter chat "What is 2+2?" -m openai/gpt-4o-mini \
  --tool @calc.json --tool-choice required --raw

# Server tools (run by OpenRouter)
openrouter tools list
openrouter chat "What's new today?" -m openai/gpt-4o-mini --server-tool web_search

# Batches at about half price
openrouter batches create --endpoint chat -m openai/gpt-4o-mini --file reqs.jsonl
openrouter batches wait <id> && openrouter batches results <id> -o out.jsonl

# Discovery
openrouter models --filter claude --sort prompt
openrouter models show anthropic/claude-sonnet-4.5
openrouter models endpoints anthropic/claude-sonnet-4.5 --sort throughput --best
openrouter providers

# Spend / runs
openrouter credits
openrouter whoami
openrouter generation gen-1234567890 --content
openrouter activity --date 2026-04-28 --api-key-hash <hash>

# Management (provisioning key required)
openrouter keys create "agent-key" --limit 25 --limit-reset monthly
openrouter guardrails create "no-paid-models" --allowed-providers "" --enforce-zdr
openrouter workspaces create "staging" --slug staging --default-text-model openai/gpt-4o-mini
openrouter workspaces budgets set staging monthly --limit 100
openrouter observability create "langfuse" --type langfuse --config @langfuse.json

# Raw escape hatch - call any endpoint
openrouter request POST /chat/completions --body @body.json
openrouter request GET /endpoints/zdr

Documentation

| | | |---|---| | openrouter --help | Top-level command index | | openrouter <command> --help | Per-command flags + examples | | SKILL.md | Drop-in skill description for LLM agents (Claude Code / Cursor / etc.) - what to use, when, how, with patterns and pitfalls | | OpenRouter API docs | Upstream API reference | | OpenRouter dashboard | Manage keys, billing, workspaces in the browser | | Provisioning keys | Where management keys are minted |

Endpoint coverage map:

| OpenRouter endpoint | Command | |---|---| | POST /auth/keys (PKCE exchange) | openrouter login | | POST /auth/keys/code | openrouter auth-code | | GET /key | openrouter whoami | | GET /credits | openrouter credits | | GET /activity | openrouter activity | | GET /analytics/meta / POST /analytics/query | openrouter analytics {meta,query} | | GET /benchmarks | openrouter benchmarks | | GET /classifications/task | openrouter classifications | | GET /datasets/app-rankings / GET /datasets/rankings-daily / GET /datasets/session-cost | openrouter datasets {apps,daily,session-cost} | | GET /models | openrouter models list | | GET /model/{author}/{slug} | openrouter models show | | GET /models/count | openrouter models count | | GET /models/user | openrouter models user | | GET /models/{author}/{slug}/endpoints | openrouter models endpoints | | GET /providers | openrouter providers | | GET /endpoints/zdr | openrouter zdr | | POST /chat/completions | openrouter chat, openrouter complete | | POST /messages | openrouter messages | | POST /responses | openrouter responses | | POST /embeddings / GET /embeddings/models | openrouter embed [models] | | POST /rerank | openrouter rerank | | POST /audio/speech | openrouter speech, openrouter tts | | POST /videos, GET /videos/{id}, GET /videos/{id}/content, GET /videos/models | openrouter video {create,get,wait,download,models} | | GET /generation, GET /generation/content, POST /generation/feedback | openrouter generation [--content], openrouter generation feedback | | GET/POST/DELETE /batches[/{id}] | openrouter batches {list,create,get,wait,results,delete} | | GET /tools, GET /tools/{name} | openrouter tools {list,get} | | POST /audio/transcriptions | openrouter transcribe, openrouter stt | | POST /images, GET /images/models | openrouter image [models] | | GET/POST/PATCH/DELETE /keys[/{hash}] | openrouter keys {list,get,create,update,delete} | | GET/POST/PATCH/DELETE /guardrails[/{id}] + assignments | openrouter guardrails ... | | GET/POST/PATCH/DELETE /workspaces[/{id}] + members + budgets | openrouter workspaces ... | | GET/POST/PATCH/DELETE /observability/destinations[/{id}] | openrouter observability ... | | GET/POST/PATCH/DELETE /byok[/{id}] | openrouter byok ... | | GET /presets[/{slug}] + versions, POST /presets/{slug}/{chat/completions,messages,responses} | openrouter presets {list,get,versions,create} | | POST /systemone (and POST /api/alpha/decisions with --alpha) | openrouter systemone / openrouter decisions | | GET /containers/{id}/files[/{file}] + content/promote | openrouter containers ... | | GET /organization/members | openrouter org members | | GET/PATCH /organization/settings | openrouter org settings | | anything else | openrouter request <METHOD> <path> |

Configuration

| flag | env | description | |---|---|---| | -k, --key <key> | OPENROUTER_API_KEY (user, alias OPENROUTER_KEY) / OPENROUTER_MANAGEMENT_KEY (mgmt) | API key to use; flag overrides env / config | | --base-url <url> | OPENROUTER_BASE_URL | API base (default https://openrouter.ai/api/v1) | | --referer <url> | OPENROUTER_REFERER | HTTP-Referer header (your app URL) | | --title <name> | OPENROUTER_TITLE | X-Title header (your app name; appears on openrouter.ai) | | --categories <csv> | OPENROUTER_CATEGORIES | X-OpenRouter-Categories attribution header | | --json | - | JSON output, no streaming, no color | | -q, --quiet | - | Suppress informational stderr | | -V, --version | - | Print the version | | - | NO_COLOR (alias OPENROUTER_NO_COLOR) | Disable ANSI colors | | - | OPENROUTER_DEBUG=1 | Stack traces on error |

Config file: ~/.config/openrouter/config.json (or $XDG_CONFIG_HOME/openrouter/), 0600 perms.

License & disclaimer

MIT. See LICENSE.

This is an unofficial community project. It is not affiliated with, endorsed by, or sponsored by OpenRouter. "OpenRouter" and the OpenRouter logo are trademarks of their respective owners; usage here is for identification only.


Built by Aaron Elijah Mars, founder of Aeon and MiroShark · @aaronjmars