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

the-expert-router

v1.0.2

Published

Routes each Claude API call to the right-sized model, learns from your ratings, and proves what it saved. For developers who pay per token — not a chat app.

Readme

the-expert-router

Pick the right Claude model for each message — and prove what you saved.

Most apps built on Claude send every message to the same model. A "what's 2+2" costs the same as "redesign my architecture." The price gap between tiers is 5–25×, and most questions don't need the expensive one.

This library reads each prompt before you send it, picks the right-sized model and effort level, learns from your users' ratings, and keeps honest books on what routing saved you versus always using the top model.

Zero dependencies. Framework-free. Works in Node and the browser.

npm install the-expert-router

Who this is for

✅ You call the Claude API from your own code — a chatbot, an agent, a support tool, a pipeline — and every request currently hardcodes one model.

✅ Your token bill is growing and you suspect much of it is over-powered answers to under-powered questions, but you have no way to prove it.

✅ You want routing you can inspect and defend — not a black box that silently picks for you.

Who this is not for

❌ You just want to chat with Claude. Use claude.ai — it's better at that and it's included in a subscription. This library doesn't help you.

❌ You want a proxy or a hosted service. This is a local decision function. It makes no network calls, holds no keys, and never sees your traffic. You call Claude; it just tells you which Claude.

❌ You need routing across providers (OpenAI, Gemini, local models). This is Claude-specific by design — it knows Claude's tiers, prices and effort model. For cross-provider routing, look at OpenRouter or LiteLLM.


Why this and not something else

Honest positioning, because you'll ask anyway:

vs. hardcoding one model — the status quo in most codebases. You're paying Opus rates for "summarise this line." Routing is the only optimisation that cuts cost without cutting quality, because it only ever down-shifts on questions that don't need the power.

vs. writing your own if/else — you can, and for ten prompt types you probably should. This becomes worth it when you want the parts that are tedious to build: a learning loop that adapts to your users' ratings, experiments that justify their own cost before adopting a pricier model, honest savings accounting against a real baseline, and an explanation of every decision.

vs. OpenRouter / LiteLLM — those are gateways: they proxy your traffic and route across providers. Different job, different trust model. This is a local decision function — zero dependencies, no network, no proxy, your keys never leave your process. Use them together if you like: ask The Expert which Claude, then send it wherever you send it.

vs. "just use the cheap model" — fine until a hard question lands on it. The point isn't cheapness; it's fit.

The honest catch: routing is a heuristic. It reads keywords, length and scope — it does not understand your prompt semantically. It will misroute sometimes. That's precisely why ratings, experiments and manual overrides exist, and why every decision is explainable rather than asserted.


60-second start

import { Expert } from "the-expert-router";
import Anthropic from "@anthropic-ai/sdk";

const expert = new Expert();
const claude = new Anthropic();

// 1. Route the prompt
const r = expert.route("what is a closure in javascript");
// -> { tier: "sonnet", effort: "medium", model: "claude-sonnet-5", reason: "no strong signal", id: "t..." }

// 2. Call Claude with the chosen model
const res = await claude.messages.create({
  model: r.model,
  max_tokens: 2048,
  messages: [{ role: "user", content: prompt }],
});

// 3. Record what it actually cost
expert.record(r.id, res.usage.input_tokens, res.usage.output_tokens);

// 4. Teach it from your user's feedback (1–5)
expert.rate(r.id, 5, "perfect, keep using sonnet here");

// 5. Ask what routing saved you
expert.savings();
// for 1,200 input + 400 output tokens
// -> { saved: 0.0096, spent: 0.0064, baseline: 0.016, percent: 60, turns: 1 }

Why it's different

It never overspends on faith. If a kind of question keeps scoring mediocre, The Expert runs a controlled experiment: it tries the next model up for a few turns and keeps the upgrade only if ratings actually improve. If they don't, it reverts and remembers not to waste money there again.

It explains itself. Every decision can be unpacked into plain English — which trigger words fired, the confidence, what learning changed and why.

expert.explain("refactor the entire auth module and debug the race condition");
// [
//   { icon: "📏", text: "Message length: 58 characters" },
//   { icon: "🔬", text: "Complexity words found: “refactor”, “debug”, “race condition”" },
//   { icon: "🌐", text: "Broad-scope wording (“entire/whole/all…”) — suggests a bigger job" },
//   { icon: "⚖️", text: "Classifier's verdict: Opus 4.8 at high effort (confidence 85%)" },
//   ...
// ]

Its accounting is honest. Savings are measured against a real baseline — the same tokens priced at Opus rates — and labelled as estimates, because the top model might have produced a different number of tokens.


API

new Expert(opts?)

new Expert();                                   // fresh
new Expert({ profile, ledger });                // rehydrate from storage

route(prompt) → RouteResult

Returns { tier, effort, model, reason, src, conf, bucket, id }. model is the concrete Anthropic model id. Keep the id to record() and rate() the turn later.

src tells you why: heuristic · learned · experiment · directed.

record(id, tokensIn, tokensOut) → TurnRecord

Logs actual cost, the always-Opus baseline, and the saving.

rate(id, score, comment?) → string | null

score is 1–5 (3 is neutral). A comment naming a model or effort — "use opus high next time" — becomes a standing rule that outranks learned behaviour. Returns an experiment-conclusion note when one fires.

savings() → { saved, spent, baseline, percent, turns }

lessons() → string[]

explain(prompt) → ExplainLine[]

export() → string / import(json) → { ok, error?, summary? }

Portable profiles. Import is strict: it validates format and version and refuses foreign or corrupt files rather than silently overwriting learning.

Persistence

The library holds no storage opinion — persist expert.profile and expert.ledger wherever you like (localStorage, a database, a file):

localStorage.setItem("profile", JSON.stringify(expert.profile));
const expert = new Expert({ profile: JSON.parse(saved) });

Lower-level pieces

If you want the parts rather than the class:

import { heuristic, decide, savingsForTurn, explainDecision, MODELS } from "the-expert-router";

heuristic(prompt) — pure classification, no learning. decide(prompt, profile) — classification + learning. savingsForTurn({ tier, tokensIn, tokensOut }) — cost maths. MODELS — the model registry (ids, prices, versions). Update here when Anthropic ships or retires a model.


How routing works

  1. A fast local classifier reads the prompt: length, complexity keywords (English and Turkish), scope words, code blocks.
  2. Trivial → Haiku. Standard work → Sonnet. Architecture, debugging, deep reasoning → Opus. Fable is never auto-routed (it's 2× Opus) but can be chosen manually.
  3. Learning overrides the classifier once there's evidence: standing rules first, then your best-rated model for that kind of question, then experiments.

No network calls, no API key needed for routing itself — it's local logic.

License

MIT © Cem Sari · github.com/cemsari/the-expert