{"_id":"@0dust/claude-router","name":"@0dust/claude-router","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@0dust/claude-router","version":"1.0.0","description":"Intelligent model routing for Claude Code","main":"./dist/sdk/index.js","types":"./dist/sdk/index.d.ts","bin":{"claude-router":"dist/cli/index.js"},"scripts":{"build":"tsc && cp src/classifier/prompt.md dist/classifier/","test":"vitest run","dev":"tsc --watch","prepublishOnly":"npm run build && npm test"},"dependencies":{"@anthropic-ai/sdk":"^0.39.0"},"devDependencies":{"typescript":"^5.4.0","vitest":"^1.6.0","@types/node":"^20.0.0"},"keywords":["claude","claude-code","model-routing","ai","anthropic","llm"],"engines":{"node":">=18.0.0"},"repository":{"type":"git","url":"git+https://github.com/0dust/ClaudeRouter.git"},"homepage":"https://github.com/0dust/ClaudeRouter#readme","license":"MIT","gitHead":"9a4ba9cf02bfcc0ef56bd778c672f9224f926333","_id":"@0dust/claude-router@1.0.0","bugs":{"url":"https://github.com/0dust/ClaudeRouter/issues"},"_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-4zhQHDIyZu8hyAXrabOY6T6egzgQvcBs1sFnIPuLaVb3HoKC0o4drUx8Uzoe0bXa4n8juvSR/j6sBkVMe9sQHA==","shasum":"9b0c337b51a29cd40e7ad03d87769502cda48ba3","tarball":"https://registry.npmjs.org/@0dust/claude-router/-/claude-router-1.0.0.tgz","fileCount":61,"unpackedSize":106475,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDATqHmHIBhz9MBk/qehCgbaKyOqr78jv+h9GurQyd8DwIhAM+vhQMOMxtW5EIEDDLVKtXUnlEFzstRNkkJR3aBl5Al"}]},"_npmUser":{"name":"0dust","email":"himanshutripathi366@gmail.com"},"directories":{},"maintainers":[{"name":"0dust","email":"himanshutripathi366@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/claude-router_1.0.0_1775386131756_0.12776779346598177"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-05T10:48:51.685Z","1.0.0":"2026-04-05T10:48:51.944Z","modified":"2026-04-05T10:48:52.184Z"},"maintainers":[{"name":"0dust","email":"himanshutripathi366@gmail.com"}],"description":"Intelligent model routing for Claude Code","homepage":"https://github.com/0dust/ClaudeRouter#readme","keywords":["claude","claude-code","model-routing","ai","anthropic","llm"],"repository":{"type":"git","url":"git+https://github.com/0dust/ClaudeRouter.git"},"bugs":{"url":"https://github.com/0dust/ClaudeRouter/issues"},"license":"MIT","readme":"# ClaudeRouter\n\n[![npm version](https://img.shields.io/npm/v/@0dust/claude-router.svg)](https://www.npmjs.com/package/@0dust/claude-router)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n**Stop burning Opus tokens on grep.** ClaudeRouter classifies every prompt before it hits the model — routing simple tasks to Haiku, feature work to Sonnet, and architecture to Opus. Ships as a Claude Code plugin. Zero config.\n\n\n## Prerequisites\n\n- **Node.js 18+**\n- **Claude Code** installed ([install guide](https://docs.anthropic.com/en/docs/claude-code))\n- **Claude Pro or Max subscription** (required for subagent delegation)\n- **jq** — the hook script depends on it (`brew install jq` / `apt install jq`)\n\n## Installation\n\n```bash\nnpm install -g @0dust/claude-router\nclaude-router init\n```\n\n### From source\n\n```bash\ngit clone https://github.com/0dust/ClaudeRouter.git\ncd ClaudeRouter\nnpm install\nnpm run build\nnpm install -g .\nclaude-router init\n```\n\nThis will:\n- Verify dependencies (`jq`)\n- Register the `UserPromptSubmit` hook in `~/.claude/settings.json`\n- Append the routing directive to your project's `CLAUDE.md` (with markers for clean removal)\n\nYou can also target a specific project directory:\n\n```bash\nclaude-router init /path/to/your/project\n```\n\n## Verify It's Working\n\nRun the diagnostic check:\n\n```bash\nclaude-router doctor\n```\n\nAfter a few prompts, check your routing stats:\n\n```bash\nclaude-router stats\n```\n\nIf counts are incrementing, routing is active. You can also check the hook is registered:\n\n```bash\ncat ~/.claude/settings.json | jq '.hooks.UserPromptSubmit'\n```\n\n## How It Works\n\nClaudeRouter intercepts every `UserPromptSubmit` hook, classifies the prompt's complexity, and injects a routing directive into Claude's context. Claude then delegates to the appropriate subagent model.\n\n| Tier | Model | Example Prompts | Savings vs Opus |\n|------|-------|----------------|-----------------|\n| **LOW** | Haiku | \"what does this function do?\", \"yes do it\", file reads, grep | ~95% |\n| **MEDIUM** | Sonnet | \"add an endpoint for X\", \"fix this bug\", \"write tests for Y\" | ~60% |\n| **HIGH** | Opus | \"redesign the auth layer\", \"review this architecture\" | 0% (correct spend) |\n\n### Classification Pipeline\n\n1. **Pre-Haiku heuristics** (synchronous, zero cost) — catches ~30% of LOW prompts via token count, keyword matching, and confirmation detection. No API call needed.\n2. **Haiku classification** (async, <$0.001) — sends the prompt to Haiku with a structured classification prompt. Returns LOW, MEDIUM, or HIGH.\n3. **Context injection** — the routing directive is injected as context. Claude reads it and delegates to the appropriate subagent.\n\n### Routing Directives\n\n- **LOW** → Claude spawns a Haiku subagent via the Agent tool\n- **MEDIUM** → Claude spawns a Sonnet subagent via the Agent tool\n- **HIGH** → Claude handles the task directly with full reasoning\n- **Override** → User prefixed with `//opus`, Claude handles directly\n\n## Stats\n\nTrack your routing efficiency:\n\n```bash\nclaude-router stats\n```\n\n```\nClaudeRouter — last 7 days\n─────────────────────────────────────────\nPrompts routed:        847\nLOW  → Haiku:          312   (36.8%)\nMED  → Sonnet:         431   (50.9%)\nHIGH → Opus:           104   (12.3%)\nEstimated Opus saved:   148.6K tokens\nFollow-up rate (LOW):   4.1%    ← routing accuracy\nManual overrides:       7\n─────────────────────────────────────────\n```\n\nUse `--days N` to change the window: `claude-router stats --days 30`\n\n## Failure Behavior\n\nClaudeRouter is designed to never block Claude Code:\n\n- **Classifier fails**: Falls back to MEDIUM (Sonnet) — the safe middle ground\n- **API timeout**: Haiku classification has a 3-second timeout; on timeout, falls back to MEDIUM\n- **No internet**: Pre-Haiku heuristics still work (catches ~30% of prompts); the rest fall back to MEDIUM\n- **Missing dependencies**: Hook exits silently with no directive; Claude handles the prompt normally on whatever model the session is using\n- **Any unexpected error**: The hook always exits 0 and never blocks the user's prompt\n\n## Configuration\n\nClaudeRouter works with zero configuration. To customize, create `.claude-router.json` in your project root or `~/.claude-router.json` globally:\n\n```json\n{\n  \"tiers\": {\n    \"LOW\": \"claude-haiku-4-5-20251001\",\n    \"MEDIUM\": \"claude-sonnet-4-6\",\n    \"HIGH\": \"claude-opus-4-6\"\n  },\n  \"fallback\": \"claude-sonnet-4-6\",\n  \"conservative\": false,\n  \"override_keyword\": \"//opus\"\n}\n```\n\n| Field | Default | Description |\n|-------|---------|-------------|\n| `tiers.LOW` | `claude-haiku-4-5-20251001` | Model for trivial tasks |\n| `tiers.MEDIUM` | `claude-sonnet-4-6` | Model for standard engineering work |\n| `tiers.HIGH` | `claude-opus-4-6` | Model for deep reasoning tasks |\n| `fallback` | `claude-sonnet-4-6` | Model used when classification fails |\n| `conservative` | `false` | Shift all routes one tier up (LOW→Sonnet, MEDIUM→Opus) |\n| `override_keyword` | `//opus` | Prefix to force Opus on any turn |\n\nConfig is merged in order: hardcoded defaults → `~/.claude-router.json` → CWD `.claude-router.json`. Later values override earlier ones.\n\n### Team Configuration\n\nTo share routing config across a team, commit `.claude-router.json` to your\nrepo (you may need to remove it from `.gitignore`). Individual developers can\nstill override with `~/.claude-router.json` for personal preferences.\n\n## Troubleshooting\n\n**Stats show zero events after using Claude Code**\nThe hook may not be registered. Check:\n```bash\ncat ~/.claude/settings.json | jq '.hooks.UserPromptSubmit'\n```\nIf empty, re-run `claude-router init`.\n\n**Hook not firing**\n1. Verify `jq` is installed: `command -v jq`\n2. Verify the hook script exists at the path shown in settings.json\n3. Verify the hook is executable: `ls -la $(which claude-router)`\n\n**jq not installed**\nThe hook exits silently without jq. Install it:\n- macOS: `brew install jq`\n- Ubuntu/Debian: `sudo apt install jq`\n- Arch: `sudo pacman -S jq`\n\n**claude-router command not found after install**\nIf installed via `npm install -g .`, ensure your npm global bin directory\nis in your PATH: `npm bin -g`\n\n**I see [ROUTER] lines in my Claude Code transcript**\nThis is normal. The routing directive is visible in the transcript as hook\noutput, but Claude follows it silently and does not mention it in responses.\n\n**All prompts routing to Sonnet (MEDIUM)**\nThis is the fallback behavior when Haiku classification fails. Verify that\nClaude Code can reach the Anthropic API (this requires an active Claude\nPro or Max subscription).\n\n## Override Keyword\n\nPrefix any prompt with `//opus` to bypass classification and force Opus:\n\n```\n//opus explain the tradeoffs between these two architectures\n```\n\nThis routes directly to Opus regardless of what the classifier would have chosen. The keyword is stripped from the prompt before processing.\n\n## SDK Usage\n\nThe routing logic is available as a standalone SDK for any Claude-based agent stack:\n\n```typescript\nimport { classify, route, createRouter } from 'claude-router';\n\n// Single classification call\nconst result = await classify('fix the typo on line 42');\n// { tier: 'LOW', source: 'signal', latency_ms: 0, prompt_tokens: 7 }\n\n// Full routing decision\nconst config = loadConfig();\nconst decision = await route('add user authentication', config);\n// { model: 'claude-sonnet-4-6', tier: 'MEDIUM', source: 'haiku', ... }\n\n// Stateful router with telemetry\nconst router = createRouter({ telemetry: true });\nconst d = await router.route('redesign the auth layer');\nconsole.log(router.stats());\n// { total: 1, low: 0, medium: 0, high: 1, overrides: 0, avg_latency_ms: 12 }\n```\n\n### API\n\n- **`classify(prompt)`** — Returns `ClassificationResult` with tier, source, latency, and token count\n- **`quickClassify(prompt)`** — Synchronous heuristic-only classification. Returns tier or `null`\n- **`route(prompt, config)`** — Full routing decision with model, directive, and metadata\n- **`loadConfig()`** — Load merged config from defaults + global + local files\n- **`createRouter(options?)`** — Stateful router instance with `.route()` and `.stats()` methods\n\n## How the Plugin Works\n\nClaudeRouter uses Claude Code's `UserPromptSubmit` hook to inject routing directives as context. The `CLAUDE.md` file in your project root instructs Claude to follow these directives transparently — delegating to Haiku or Sonnet subagents for lower-complexity tasks.\n\nThis approach:\n- **Requires no model mutation** — works within the existing hook API\n- **Is minimally visible** — routing directives appear in the transcript but Claude does not mention or acknowledge them to the user\n- **Includes an infinite loop guard** — subagents don't re-trigger the classification hook\n\n## Uninstallation\n\n```bash\nclaude-router remove\nnpm uninstall -g claude-router\n```\n\nThis removes:\n- The `UserPromptSubmit` hook from `~/.claude/settings.json`\n- The `<!-- claude-router:start -->` ... `<!-- claude-router:end -->` block from your project's `CLAUDE.md`\n\nTelemetry data in `~/.claude-router/` is preserved. Delete it manually if desired.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-5df290666d601285635ca1c56b269657"}