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

@mirage-cli/openrouter-cli

v0.3.0

Published

OpenRouter CLI for model and image discovery, quota inspection, chat completions, and image generation through a fetch-only, Mirage-compatible command surface.

Readme

@mirage-cli/openrouter-cli

Fetch-only OpenRouter CLI for model and image discovery, API-key quota inspection, generation cost metadata, chat completions, typed decisions, and image generation. It exposes a pure buildProgram() for in-process hosts and a standalone openrouter binary.

Install and authenticate

bun add @mirage-cli/openrouter-cli
export OPENROUTER_API_KEY='sk-or-v1-...'

Optional configuration:

  • OPENROUTER_API_BASE_URL defaults to https://openrouter.ai/api/v1.
  • OPENROUTER_HTTP_REFERER sets the optional HTTP-Referer attribution header.
  • OPENROUTER_APP_TITLE sets X-OpenRouter-Title.
  • OPENROUTER_APP_CATEGORIES sets X-OpenRouter-Categories.

All values also have equivalent global CLI flags. Secrets are never persisted or printed.

Commands

openrouter models list --supports tools --sort pricing-low-to-high -f table
openrouter models get openai/gpt-4o
openrouter models endpoints anthropic/claude-sonnet-4.6
openrouter providers list
openrouter key
openrouter generation gen-abc123
openrouter chat --model openai/gpt-4o --prompt 'Say hello' -f text
openrouter images models -f table
openrouter images endpoints openai/gpt-image-1-mini
openrouter images generate \
  --model openai/gpt-image-1-mini \
  --prompt 'A blue orchid in a glass greenhouse' \
  --output /sessions/example/orchid.png

chat is billable. It requires an explicit model or models field and adds a conservative max_completion_tokens: 2048 cap when the request omits one. Override it with --max-completion-tokens or in a request file.

For tools, structured output, multimodal messages, fallback models, plugins, or other OpenRouter fields, pass a complete JSON body:

openrouter chat --request ./request.json
cat request.json | openrouter chat --request -

The request path is fixed to /chat/completions; this package intentionally does not expose arbitrary HTTP methods or API-key management endpoints.

Decisions

decisions calls the OpenRouter Decisions API (POST /api/alpha/decisions) with a decision model such as typesafe/jev-1.14. It returns typed answers with probabilities instead of text: noul (probability a condition holds), choice (one of your options), score (position on an ordered scale) and, on jev-1.14, box (where a target is in an image). It is billable on input tokens; output tokens are free.

openrouter decisions --model typesafe/jev-1.14 \
  --state 'Help! My payouts have been failing for 3 days.' \
  --questions ./questions.json -f text
openrouter decisions --model typesafe/jev-1.14 --state-file ./ticket.json \
  --questions ./questions.json --image ./screenshot.png
openrouter decisions --request ./decision.json

--questions is a JSON object keyed by question name:

{
  "urgent": { "type": "noul", "instructions": "Is this urgent?",
              "criteria": { "true": "Time-sensitive", "false": "Can wait" } },
  "team": { "type": "choice", "instructions": "Which team should handle it?",
            "criteria": { "billing": "Payments", "technical": "Bugs and outages" } },
  "severity": { "type": "score", "instructions": "How severe is it?",
                "criteria": ["Low", "Medium", "High"] }
}

--state-file sends a JSON object or array as structured state and anything else as text. --image (repeatable) appends an image URL or a local/mounted file to the state. -f text prints one tab-separated line per answer; the default JSON output is the full response, including usage.cost.

Image generation

images models and images endpoints inspect the dedicated OpenRouter Images API without generating anything. images generate is billable and always requires both an explicit --model and --output path. No model is silently selected on the operator's behalf.

The command currently generates exactly one image per invocation. Common image options are available as flags, and advanced OpenRouter fields can be supplied in a complete JSON request with --request <file|->. --model remains required and overrides the request file. Reference images may be public URLs, base64 data URLs, or local/Mirage-mounted paths supplied with repeatable --reference flags.

Generated base64 is decoded before output. The image bytes are written directly to --output, while stdout contains only a compact receipt with the selected model, path, media type, byte count, timestamp, and usage/cost when returned. Mirage runtimes should use a writable mounted path such as /sessions/<session-id>/image.png; standalone users may use a normal local path. The command never prints b64_json to stdout.

For inexpensive drafts, start with openai/gpt-image-1-mini. For final-quality output, choose openai/gpt-image-2. Model capabilities and pricing change, so inspect images endpoints <model> before relying on a quality, resolution, background, reference-image, or provider-specific option.

Streaming

openrouter chat --stream parses OpenRouter SSE correctly:

  • comment heartbeats are ignored;
  • [DONE] terminates the stream;
  • the final usage-only chunk is preserved;
  • X-Generation-Id is captured;
  • an in-band error chunk exits nonzero even though its HTTP status is 200.

The standalone binary writes -f text deltas immediately. Mirage command runtimes may materialize stdout before returning it, so streaming there is correct but may not appear token by token.

Output

JSON is the default. jsonl, table, csv, and text are available through -f, --format. Chat JSON preserves the upstream OpenAI-compatible response, including usage.cost, finish reasons, tool calls, and provider metadata. Image generation prints a compact receipt instead of the upstream base64 body.

Retry behavior

Read-only GET requests retry once only when a 429 or 503 includes a numeric Retry-After of at most 15 seconds. Billable chat and image POST requests are not automatically retried because a network failure may be ambiguous and the API does not document an idempotency key for either operation.

Library use

import { buildProgram, OpenRouterClient } from "@mirage-cli/openrouter-cli";

const program = buildProgram();
const client = new OpenRouterClient({ apiKey: process.env.OPENROUTER_API_KEY! });

Requires Bun 1.1+ or Node 18+ with global fetch.