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

@razroo/iso-route

v0.6.0

Published

Author one model policy; fan out to every harness that supports it. Translates role-based model selection into settings.json, config.toml, opencode.json, .pi/settings.json, and resolved notes/maps.

Readme

@razroo/iso-route

One model policy, every harness.

agentmd, isolint, and iso-harness get your prompts to every coding agent. @razroo/iso-route does the same thing for your model choices: you declare a default model plus named roles once, and iso-route compiles that policy into the config file each harness actually reads — .claude/settings.json, .codex/config.toml, opencode.json, and .pi/settings.json — plus notes for harnesses with advisory role binding.

Use it to swap Opus for Sonnet everywhere with a single edit, pin a cheaper model to a fast-edit role, or send a reviewer role to a different provider entirely.

v0.1 scope: emits config files for Claude Code, Codex, OpenCode, and Pi, and a resolved role map (iso-route.resolved.json) that iso-harness consumes when it stamps per-subagent frontmatter. Fallback chains are recorded in the resolved map but not encoded into any harness config — runtime routing lives in proxy layers (OpenRouter, LiteLLM), not iso-route.

Install

npm install -D @razroo/iso-route

Policy shape

# models.yaml
default:
  provider: anthropic
  model: claude-sonnet-4-6

roles:
  planner:
    provider: anthropic
    model: claude-opus-4-7
    reasoning: high

  fast-edit:
    provider: anthropic
    model: claude-haiku-4-5

  reviewer:
    provider: openai
    model: gpt-5
    fallback:
      - { provider: anthropic, model: claude-sonnet-4-6 }

Valid providers: anthropic, openai, google, xai, deepseek, mistral, groq, ollama, openrouter, opencode, local. Valid reasoning levels: low, medium, high.

Per-harness overrides

Any role (and the top-level default) can declare a targets.<harness> block to pick a different provider + model when iso-route emits for that harness. Use this to run, for example, Claude on Claude Code, gpt-5.4 on Codex, and an OpenCode proxy token on OpenCode — all from one role:

roles:
  planner:
    provider: anthropic
    model: claude-opus-4-7
    targets:
      codex:
        provider: openai
        model: gpt-5.4
      opencode:
        provider: opencode
        model: opencode-go/deepseek-v4-pro

When emitting for harness X, iso-route uses targets.X if present; otherwise falls through to the generic provider + model. Emitters always see a flattened policy so they don't need to know targets: exists.

Bundled presets (extends:)

Three curated presets ship with the package so you don't have to pin per-harness model picks by hand. Extend one with a single line; override only what you want to differ.

| preset | thesis | | ------------------ | --------------------------------------------------------------------- | | standard | Quality-first. Sonnet/Opus on Claude Code and Pi, gpt-5.4 on Codex, OpenCode Zen/Go picks per tier. | | budget | Cost-optimized. Haiku/Sonnet on Claude Code and Pi, gpt-5.4-mini/nano on Codex, free-tier and pay-once OpenCode picks. | | openrouter-free | Standard-like Claude/Codex/Pi picks, but OpenCode routes through explicit free OpenRouter model IDs. |

Scaffold a starter with the right boilerplate:

iso-route init                         # writes ./models.yaml extending "standard"
iso-route init --preset budget         # use the budget preset instead
iso-route init --preset openrouter-free
iso-route init --out custom/path.yaml  # different location
iso-route init --force                 # overwrite existing

Or write the extension by hand:

extends: standard   # or: budget / openrouter-free
# ...override only what you want:
roles:
  quality:
    targets:
      codex:
        provider: openai
        model: gpt-5.4

User fields win at every key. roles merge by name, targets merge per harness (each harness override is atomic — a user's targets.codex replaces the preset's targets.codex as a unit, not field-by-field). Setting an override to null removes the preset's value for that harness.

Fan-out mapping

| Field | Claude Code | Codex | OpenCode | Cursor | Pi | | ------------------------- | ------------------------------------ | ---------------------------------------------------- | -------------------------------------- | -------------------------------- | --------------------------------- | | default.model | .claude/settings.json model | .codex/config.toml model | opencode.json top-level model | README note only | .pi/settings.json defaultModel | | roles.<name>.model | resolved map (iso-harness stamps) | [profiles.<name>] in config.toml | agent.<name>.model in opencode.json| advisory row in README note | advisory row + enabledModels | | reasoning | closest model tier | model_reasoning_effort | provider-specific | advisory | defaultThinkingLevel for default | | fallback[] | resolved map only (runtime unsupported) | resolved map only | resolved map only | resolved map only | notes only | | provider auth | env var convention | [model_providers.<name>] block (not for reserved Codex built-ins openai / ollama) | provider block with npm package | — | Pi provider/auth settings |

Cursor has no programmatic way to bind a model to a rule or chat, so iso-route emits a README note at .cursor/iso-route.md and warns at build time. Pi gets .pi/settings.json for the default provider/model and model cycling, plus .pi/iso-route.md because Pi does not have native role-specific subagent binding.

CLI

iso-route init                               # scaffold ./models.yaml (extends "standard")
iso-route init --preset budget               # or start from the budget preset
iso-route init --preset openrouter-free      # OpenCode => free OpenRouter shortlist
iso-route build models.yaml --out .
iso-route build models.yaml --verify-models  # verify model IDs first, then emit
iso-route build models.yaml --targets claude,codex --dry-run
iso-route plan  models.yaml
iso-route verify models.yaml                 # verify model IDs without emitting files
iso-route catalog openrouter                 # live advisory shortlist for OpenCode
iso-route catalog openrouter --limit 20 --json

init scaffolds a starter models.yaml that extends a built-in preset. build writes per-harness files under --out (defaults to .). Add --dry-run to preview without touching disk. plan prints the resolved role table so you can eyeball what each harness will see.

Opt-in model verification

iso-route verify and iso-route build --verify-models check declared OpenRouter model IDs against the live Models API before you ship the config. This keeps typo checking opt-in instead of turning the default build path into a networked step.

Non-OpenRouter providers are still reported as unverifiable rather than guessed. That means a mixed policy can still pass:

iso-route verify models.yaml
iso-route verify models.yaml --fail-on-unverifiable
iso-route build models.yaml --out . --verify-models

--endpoint <url> is also available on both commands for custom gateways or tests that want to point at a fixture server instead of the default OpenRouter API endpoint.

Advisory OpenRouter catalog

iso-route catalog openrouter fetches the live OpenRouter models API and ranks an advisory shortlist for OpenCode. By default it filters to models that are both:

  • free (prompt == 0 and completion == 0)
  • tool-capable (supported_parameters includes tools)

This command is intentionally separate from the default build path: it helps you pick candidate model IDs, while verify / build --verify-models provide the opt-in validation step.

iso-route catalog openrouter
iso-route catalog openrouter --limit 8
iso-route catalog openrouter --allow-paid
iso-route catalog openrouter --allow-no-tools --json

Library API

import { build, loadPolicy, verifyModelFile } from "@razroo/iso-route";

const result = build({ source: "./models.yaml", out: "./.out", dryRun: true });
for (const w of result.warnings) console.warn(w);

const verify = await verifyModelFile("./models.yaml");
console.log(verify.passed ? "ok" : "fix model ids");

Individual emitters are exported too (emitClaude, emitCodex, emitOpenCode, emitCursor, emitPi) if you only need one target. Verification helpers are exported too (verifyModelFile, verifyPolicyModels, formatVerifyResult) for callers that want to keep the network check in their own pipeline code.

How this fits the rest of the pipeline

agent.md  →  agentmd lint  →  agentmd render  →  isolint lint  →  iso-harness build
                                                                         +
                                        models.yaml  →  iso-route build  ┘
                                                                         │
                                                                         ▼
                                                          project with CLAUDE.md, settings.json,
                                                          config.toml, opencode.json,
                                                          .pi/settings.json, …

iso-harness owns what the agent reads. iso-route owns which model reads it. They share one output directory and are designed to be run back-to-back — the @razroo/iso wrapper will compose them for you.

What iso-route is NOT

  • Not a request-level router. Picking a cheaper model per-request based on prompt complexity belongs in a proxy (OpenRouter, LiteLLM, Portkey, Not Diamond). iso-route is a build-time transpiler, not an inference-path component.
  • Not a build-time model validator. iso-route catalog openrouter is advisory only, and the default build path still validates provider names, not model IDs. verify / build --verify-models are opt-in checks. If you skip them and type a model name your provider doesn't recognize, you'll still find out at runtime.

License

MIT — see LICENSE.