Skip to content
Projects

hussi9/skill-router has 32 GitHub stars and 1 forks. GitHot measured +1 in 7 days. Last checked 2026-11-11 04:24 UTC. Last push 2026-11-02.

How these counts are measured

Skill + Agent + Model + Thinking depth — auto-routed before any tool fires. One SKILL.md for Claude Code. 90% routing accuracy, per-step model enforcement, 30%+ savings on multi-step chains.

Measured star growth

in 24h
Update delayed
in 7 days
+1
in 15 days
Collecting history
in 1 month
Collecting history

Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.

README.md

Original

skill-router

GitHub stars License CI

Your skill first, the process skill second, gates and memory on the card — before any tool fires.

A hook-driven router for Claude Code. It indexes every skill you have installed by when it applies, ranks them against each prompt in ~80 ms, asks a small model only when the ranking is unsure, and injects a route card before Claude's first action. Enforcement is tiered: hard where a wrong skill is expensive, soft everywhere else. The route follows every sub-agent you dispatch.

> my macbook restarted again last night, can you check why
[skill-router] This is a BROKEN task — 2-step chain.
[skill-router] Chain: mac-doctor → superpowers:systematic-debugging
[skill-router] Invoke step 1/2 now:
▶ mac-doctor  (inherit, in-session)
▶ superpowers:systematic-debugging  (inherit, in-session)
[skill-router] Memory: mac_crash_root_cause  (read from ~/.claude/projects/.../memory/)
[skill-router] IRON RULE: call Skill(skill="mac-doctor") before any Edit/Write/Task.

Every line is [skill-router]-prefixed, so grep '\[skill-router\]' on a transcript shows exactly what was routed.

Why (v4, September 2026)

An audit of this machine after five months of use:

Finding Number
Skills installed / ever invoked / invoked last month 291 / 80 / 32
Tokens the skill listing cost every session start ~22,600
Skills the v3 routing table could name ~20 (all process skills)
Real prompts the v3 router answered with silence 4 of 10
writing-plans announced / followed 6 / 1
Months routing was dead without anyone noticing 2

The routing table could never enumerate the domain skills — they change weekly — and hard-blocking edits on a process skill the model does not value produced workarounds, not compliance. v4 replaces the table with an index, and replaces uniform enforcement with tiers. Full evidence and design: docs/v4-design.md.

How it decides

prompt ──► project route (SKILL.personal.md)          deterministic, wins outright
       ──► Jev over the whole index (jev_choose.py)    ~0.4 s, two Choice questions, no pre-filter;
                                                      ≥ 0.8 route · below: silent (0.5–0.8 suggestion line is opt-in)
       ──► on Jev failure / 1.2 s timeout:
             enriched index rank (skill_index.json)     ~80 ms, name · use_when · keywords · project aliases
             small-model tie-break (Gemini Flash-Lite)  only below 35 % margin, ~1 s, cached
       ──► path (BROKEN / BUILD / OPERATE) + process leg from the table
       ──► route card: domain skill · process skill · gates · memory · tier
  • Index. build_index.py reads every invokable SKILL.md, extracts "use when" triggers and keywords, and a one-time small-model pass adds more — cached per file hash, so the bill grows only when a skill changes. Third-party skill files are never edited.
  • Routing descriptions. references/routing-descriptions.json supplies concise, source-hash-pinned summaries and reviewed kind corrections after index enrichment. Upstream skill files stay intact. Rebuilds skip stale rules with warnings; all skills remain available. The JEV confidence threshold remains 0.8.
  • Projects. A projects: block maps names to skills, memory files and completion gates. "push deenunlock to testflight" no longer lands on the scrollbook deploy skill because both ship to TestFlight.
  • Precision. A winner needs real evidence: a project hit, or a distinctive non-generic token in its name, triggers or keywords. "flow" alone never picks ux-flow.
  • Tiers. Hard (edit block until the skill loads) on the BROKEN path and on project routes with gates. Soft elsewhere: the Stop hook asks once, and the answer teaches the router.
  • Sub-agents. A PreToolUse hook on Task appends the parent's route to every dispatched prompt; SubagentStart briefs the agent with its paired skills.

Pipeline detail: docs/how-it-works.md.

Jev: the one model on the hot path

Jev (jev-1.13.0, TypeSafe System One) is a chooser: it picks from options you give it and returns a confidence. It cannot write text, and its answers are opaque keys mapped back to skills the router already knows.

  • Chooses the skill over your whole index in one ~0.4 s call. Routes only at confidence ≥ 0.8 (32 of 34 right in the author's set); below that the router is silent.
  • Chooses the model for sub-agents. light work dispatches on Haiku, standard on Sonnet, heavy and unsure inherit your session model. An explicit model= always wins. The main session is never switched.
  • Optional and fail-safe. No TYPESAFE_API_KEY, SKILL_ROUTER_JEV=0, a 1.2 s timeout or any error falls back to local ranking. A slow API never blocks a prompt.
  • Disclosed. With a key set, each uncached prompt (plus skill summaries) goes to api.typesafe.ai, ~$0.0005. Nothing is sent without a key.

Full detail, data flow and knobs: docs/jev.md.

Suggestions from skills.sh

When nothing installed fits, the router can point at a popular, audit-screened skill from skills.sh, with install count and audit status on the line. Opt-in cache (python3 scripts/skills_sh_catalog.py), public pages only, no prompt data sent, never installs. Top skills per category: docs/skills-sh-top.md. Detail: docs/skills-sh.md.

Install

git clone https://github.com/hussi9/skill-router ~/devpro/skill-router
ln -s ~/devpro/skill-router ~/.claude/skills/skill-router
python3 ~/.claude/skills/skill-router/scripts/install_hooks.py     # wires 6 hook events into ~/.claude/settings.json
python3 ~/.claude/skills/skill-router/scripts/build_catalog.py
python3 ~/.claude/skills/skill-router/scripts/build_index.py --enrich

Optional, for Jev: export TYPESAFE_API_KEY=.... For the fallback small-model stage: put GEMINI_API_KEY (or ANTHROPIC_API_KEY) in the environment, or in Doppler (shared/prd) and let scripts/refresh_env.py cache it. Without a key the router is lexical-only and still routes.

Restart Claude Code. The catalog, index and learner rebuild in the background at every session start.

Verify

python3 ~/.claude/skills/skill-router/scripts/doctor.py

Twelve checks: hooks wired, scripts present, no route names an uninstalled skill, catalog and index fresh, model stage status, sub-agent hand-off hook, no expired demotions, agents follow the session model, learned overlay fresh, smoke prompts routed. Then type any non-trivial task in a new session and look for [skill-router] before the first tool call.

A route looked wrong? See the ranking and why:

python3 ~/.claude/skills/skill-router/scripts/index_match.py --all "the prompt"

Measured

tests/calibration.py, 109 curated prompts, lexical stage only (Jev and the small model are off for determinism; cases whose expected skill is not installed on your machine are skipped and counted):

v3 (2026-09-07 morning) v4
Path accuracy 95.4 % 99.1 %
Skill accuracy (when path correct) 64.2 % 100 %
Silent on 10 real prompts from one week 4 0
Lexical stage, end to end — 80 ms
SKILL.md loaded per invocation 2,388 words 483 words

The calibration set is curated and encodes the author's expectations; read 99.1 % as "the regressions are gone", not as a field rate. The field number is the follow rate the learner computes over live sessions, baseline 17 % on writing-plans under v3.

Customize

  • Project routes and projects — SKILL.personal.md: routes: (name → skill, tier, gates) and projects: (aliases, skills, memory files, gates). Prove a route fires: python3 scripts/router.py <<< "your prompt".
  • Agent pairings — agent_skills.json, validated against the index at brief time.
  • Synonyms and phrases — scripts/index_match.py (SYNONYMS, PHRASES, GENERIC).
  • Escape hatches — the user writes [no-router]; the model runs scripts/router_override.py "<reason>" --session-id "<current session id>".

docs/customizing.md has the long form.

It learns

scripts/learn.py regenerates ~/.claude/skill_router_learned.json every session start — never the repo, never your personal file:

Learned Surfaces as
Follow rates (announced vs invoked, joined by prompt id) skills you routinely ignore stop leading routes
Keyword → skill triggers Learned from your history: prompts with testflight usually use scrollbook-deploy
Handovers and chains After writing-plans you usually run test-driven-development
Soft-skips per skill (v4) demotion signal for soft routes
Skills unused for 90 days (v4) the next archive pass

Prompt keywords are logged, never prompt text. SKILL_ROUTER_NO_LEARN=1 logs nothing. Details: docs/self-improvement.md.

Common questions

Will this slow Claude Code down? The lexical stage is ~80 ms. The model stage fires on low-confidence prompts only, ~1 s, cached by prompt hash. Hook timeout is 12 s so a slow network degrades to lexical rather than to a blocked prompt.

Why Gemini inside a Claude tool? claude -p inside a hook re-enters every hook and MCP server on the machine — measured at 3.5 minutes. The classification is ~60 tokens. Provider order is Anthropic Haiku → Gemini Flash-Lite; whichever key works first answers.

Can I turn it off? For one message, write [no-router]. For good, python3 scripts/install_hooks.py --remove.

What about my custom skills? They are exactly what v4 is for. Anything under ~/.claude/skills/, ~/.claude/commands/, project .claude/skills/, and every installed plugin is indexed. Non-invokable catalogs (~/.agent/skills, ~/.composio-skills) are install candidates only.

Where does it log? ~/.claude/skill_usage.log (every Skill call) and ~/.claude/skill_router_log.jsonl (announcements, prompts as keywords, invocations, soft-skips). Both feed the learner; both are hook-mode only, so tests and probes never teach the router.

Integrated manual external discovery: search skills.sh, inspect pinned sources, and optionally rank with JEV. It returns candidates for review and does not install or invoke them. Supplied-candidate ranking remains available. Fresh conversation-context results show no specialist-routing gain at the unchanged 0.8 threshold.

Documentation

Doc What you'll learn
docs/skills-sh.md The skills.sh cache: sources, screening, categories, limits
docs/jev.md What Jev decides, the 0.8 gate, model-per-tier, what leaves your machine
docs/v4-design.md The audit that motivated v4, the design, the deliverables
docs/how-it-works.md The pipeline, ranking rules, tiers, sub-agent hand-off
docs/customizing.md Personal routes, projects, named chains
docs/self-improvement.md What the learner computes and how it surfaces
references/routing-tables.md The process tables, announcement format, dispatch protocol
docs/proof.md Real-session screenshots

Works with

Source Skills How the router uses it
superpowers process discipline the process leg of every route
Claude Code plugins (~/.claude/plugins) frontend-design, supabase, vercel, … indexed, invokable
your ~/.claude/skills/ whatever you build indexed, invokable, project-aware
Antigravity, Composio 2,300+ install candidates only

Project

  • CHANGELOG.md — version history
  • CONTRIBUTING.md — how to propose changes
  • LICENSE — MIT
  • bash scripts/check.sh — syntax · unit tests · calibration gate (≥ 95 %) · doctor

Explore related projects