Skill router
Skill hussi9/skill-router
INVOKE BEFORE EVERY NON-TRIVIAL TASK — before writing code, before using any tool, before answering. Do not skip. Produces the required Skill + Agent + Model for the task. Routing engine for 2,700+ skills.From its SKILL.md
npx -y skills add hussi9/skill-routerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- 17 stars17 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 4 commands, including `python3 ~/.claude/skills/skill-router/scripts/router_override.py "<reason>"` and 3 more.
- fetches URLsInstructs the agent to fetch 1 URL, including https://raw.githubusercontent.com/hussi9/skill-router/main/SKILL.personal.md.
SKILL.md
13.6 KB, ~3.6k tokens by cl100k_base, as published. Nobody here has run it
Skill Router — Universal Router
Output always: Skill + Agent + Model
THE 3-QUESTION TRIAGE (run now, takes 5 seconds)
Q1: Is something BROKEN / WRONG / FAILING?
Error, crash, test fail, unexpected output, user correction
YES → BROKEN PATH
Q2: Is this CREATE / BUILD / ADD something new?
New feature, file, component, integration, page, script
YES → BUILD PATH
Q3: Everything else (improve, ship, configure, automate, research)
→ OPERATE PATH
AMBIGUOUS? → Default to HIGHER-COMPLEXITY path
BROKEN PATH
| Signal | Skill | Agent | Model | Thinking |
|---|---|---|---|---|
| Error / crash / exception | superpowers:systematic-debugging | general-purpose | sonnet | think |
| Test failing | test-runner → superpowers:systematic-debugging | test-runner | sonnet | none |
| TypeScript errors | typescript-expert | general-purpose | sonnet | none |
| Performance regression | perf → superpowers:systematic-debugging | optimizer | sonnet | think |
| Security issue found | security | security-auditor | sonnet | think-hard |
| Deploy / build failed | superpowers:systematic-debugging | general-purpose | sonnet | think |
| User says "no" / "wrong" | STOP → superpowers:systematic-debugging | general-purpose | sonnet | think |
| Production incident | superpowers:systematic-debugging | general-purpose | opus | ultrathink |
BUILD PATH
Multi-file / new feature: brainstorming → writing-plans → domain skill
Single file / trivial add: go directly to domain skill
| What | Skill | Agent | Model | Thinking |
|---|---|---|---|---|
| UI component / page | frontend-design:frontend-design | feature-dev:code-architect | sonnet | none |
| API endpoint | feature-dev:feature-dev | feature-dev:code-architect | sonnet | think |
| Database schema | db-expert | db-expert | sonnet | think |
| Auth / permissions | brainstorming → security | security-auditor | opus | ultrathink |
| AI feature / agent | superpowers:brainstorming | feature-dev:code-architect | sonnet | think-hard |
| 3rd-party integration | connect-apps | integration-specialist | sonnet | none |
| Mobile screen | frontend-design:frontend-design | feature-dev:code-architect | sonnet | none |
| CLI / automation script | superpowers:writing-plans | general-purpose | sonnet | think |
| Skill / Claude skill file | superpowers:writing-skills | general-purpose | sonnet | think |
OPERATE PATH
| Signal | Skill | Agent | Model | Thinking |
|---|---|---|---|---|
| Refactor / clean up | refactor | code-simplifier:code-simplifier | sonnet | none |
| Add tests / coverage | superpowers:test-driven-development | test-runner | sonnet | none |
| Performance optimize | perf | optimizer | sonnet | think |
| Write docs | docs | general-purpose | sonnet | none |
| Code review | superpowers:requesting-code-review | superpowers:code-reviewer | sonnet | think-hard |
| Got review feedback | superpowers:receiving-code-review | general-purpose | sonnet | think |
| Deploy | superpowers:verification-before-completion → vercel:deploy | general-purpose | sonnet | none |
| Merge / PR / push | superpowers:finishing-a-development-branch | general-purpose | sonnet | none |
| DB migration | db-expert | db-expert | sonnet | think |
| 2+ independent tasks | superpowers:dispatching-parallel-agents | general-purpose | sonnet | none |
| Resume previous work | superpowers:executing-plans | general-purpose | sonnet | none |
| Research / docs lookup | context7 → brainstorming | general-purpose | sonnet | none |
| Architecture / scope decision | superpowers:brainstorming → superpowers:writing-plans | general-purpose | opus | ultrathink |
WHEN NO SKILL IS NEEDED
Single-line fix · reading code · one factual question · one command · under 3 trivial steps
Router precision contract: when no triage signal matches (BROKEN/BUILD/OPERATE), the
router emits nothing — silence is the correct output. A missing [skill-router] line
means the prompt was conversational, exploratory, or trivial. Do not interpret silence as
"OPERATE → refactor" by default; the router only suggests when it is confident.
Explicit slash-commands stand down: if the prompt is itself a slash-command invocation
(/gstack, /ship prod, /feature-dev:feature-dev), the user has already chosen the skill.
The router emits nothing and writes no pending state — it must never reclassify an explicit
command into a different skill. (Filesystem paths like /Users/... are not commands and route
normally.)
Iron rule enforcement: when the router does announce a chain, the announcement
includes an IRON RULE block naming the next required Skill(skill="<X>") call. A
PreToolUse hook denies the source-mutating tools (Edit, Write, Task, NotebookEdit,
MultiEdit) until that skill is invoked, and a Stop hook blocks turn end if it never was.
Read/Glob/Grep/TodoWrite/Bash/Skill remain allowed so context-gathering, shell
work, and the override below still function.
Two escape hatches:
-
User opt-out — the USER includes
[no-router]in their next message. The router stays silent and clears pending on UserPromptSubmit, so all hooks pass through. Writing[no-router]in your own response text does NOT clear pending — only the user's prompt triggers the clear. -
Reasoned override (model-driven, the ask+learn loop) — if you judge the announced route wrong, don't fight the rule: run
python3 ~/.claude/skills/skill-router/scripts/router_override.py "<reason>". This clears the pending rule for the turn, appends your reason to~/.claude/skill_router_overrides.jsonlfor audit, and bumps a per-skill tally. AfterOVERRIDE_THRESHOLDreasoned overrides the router defers that skill (announce-free) on similar prompts; a successful invoke re-arms it. The router asks and learns from you instead of blocking you.
If the Stop hook is blocking you on a ghost skill, it self-clears on the next user message regardless (ghost-skill guard).
Calibration: tests/calibration.py runs ~100 curated prompts through the router and
reports precision/recall/F1 by triage path. Run with --min-accuracy N for a CI gate.
Current baseline: 100% path accuracy, 95.2% skill accuracy.
Learning loop: scripts/learn-from-history.py joins announcement events
(~/.claude/skill_router_log.jsonl) with actual Skill invocations (~/.claude/ skill_usage.log) and surfaces tuning suggestions — which announced skills are ignored
most often, and which Skill invocations the router missed. Run periodically to keep
patterns calibrated to real usage.
COMPLETION GATE
Before any "done" claim → superpowers:verification-before-completion
□ Code actually runs correctly
□ TypeScript passes (tsc --noEmit)
□ Tests pass
□ Original request fully met (re-read it)
COMPLEXITY RULE
1 domain → 1 skill → single-domain announcement
2+ domains → announce chain → multi-domain announcement
Operators in the chain:
→sequential (B depends on A)+parallel (steps don't share state)
Full chain syntax + standard shapes: see references/multi-domain-chaining.md.
ANNOUNCEMENT FORMAT — Output VERBATIM (substitute only <vars>)
The announcement is the testable contract. Users will grep '\[skill-router\]'
their transcript to verify what fired matches what was announced. Format is
non-negotiable. Output it BEFORE any other tool call (Read, Edit, Bash, Agent).
Single-domain (one skill, no chain):
[skill-router] This is a <BROKEN|BUILD|OPERATE> task → <skill> → <agent>.
[skill-router] Model: <model> · Thinking: <thinking>
[skill-router] Invoke now:
▶ <skill> (<model>, <in-session | via Agent>)
Multi-domain (computed chain):
[skill-router] This touches <N> domains: <d1>, <d2>, <d3>.
[skill-router] Chain: <s1> → <s2> + <s3> → <s4>
[skill-router] Models: <m1> · <m2>+<m3> · <m4> · Thinking: <max-thinking>
[skill-router] Invoke step 1/<N> now:
▶ <s1> (<m1>, <in-session | via Agent>)
▶ <s2> + <s3> (<m2>, parallel via Agent)
▶ <s4> (<m4>, <in-session | via Agent>)
Multi-domain (saved chain wins):
[skill-router] Using your saved chain `<name>`: <s1> → <s2> + <s3>
[skill-router] Models: <m1> · <m2>+<m3> · Thinking: <max-thinking>
[skill-router] Invoke step 1/<N> now:
▶ <s1> (<m1>, <in-session | via Agent>)
▶ <s2> + <s3> (<m2>, parallel via Agent)
Rules:
Models:line uses·between sequential steps and+inside one parallel step.Thinking:is the highest depth of any step (none/think/think-hard/ultrathink). Omit the field when every step isnone.- Each
▶line ends with one of:in-session,via Agent, orparallel via Agent— matching the dispatch protocol decision below. - After each step completes, output
[skill-router] Step <n>/<N> done.before dispatching the next. - On chain end, output
[skill-router] Chain done.
Two layers of testability — keep them aligned:
[skill-router]lines +▶markers are the human-readable proof in the transcript.grep '\[skill-router\]'shows what was announced; the▶line shows the dispatch decision the parent made.~/.claude/skill_router_log.jsonlevents (chain-start,chain-step,thinking-active,chain-end) are the machine-readable proof read byscripts/audit-dispatch.pyand the statusline. The▶line does NOT replace the JSONLchain-stepevent — write both. Seereferences/dispatch-protocol.md.
Skipping the announcement format = silently breaking the testability claim.
NAMED CHAIN LOOKUP — Run Before Computing Fresh
After triage, BEFORE computing fresh, check SKILL.personal.md for a
chains: block. If any when: substring matches the user's prompt
(case-insensitive, first match wins), use the saved chain instead.
When a saved chain wins, announce it with provenance:
Using your saved chain `<name>`: <step1> → <step2> + <step3>
Schema, match algorithm, per-step model resolution: references/named-chains.md.
CATALOG CHECK — Run After Routing-Table Lookup (Key Differentiator)
If the table returned a generic skill (e.g. integration-specialist),
search local + remote catalogs for a more specific match. If found, use
the specialist instead.
1. Local: ls ~/.agent/skills/, ~/.claude/skills/, ~/.composio-skills/ | grep -iE '<keyword>'
2. Remote: site:github.com "SKILL.md" claude <keyword> (4 curated repos in ref doc)
3. Generate: superpowers:writing-skills (last resort)
Skip when: routing-table answer is already specialist · single-line fix · keyword is too generic ("code", "file", "text").
Full validation gates + curated repos: references/catalog-check.md, references/known-skill-repos.md.
PERSONAL OVERRIDES
Add project-specific routing on top of this file:
curl -sL https://raw.githubusercontent.com/hussi9/skill-router/main/SKILL.personal.md \
> ~/.claude/skills/skill-router/SKILL.personal.md
Edit SKILL.personal.md with your project signals. Your rules win over the core (CSS cascade model).
THINKING DEPTH — Pre-pend the Right Keyword
Pre-pend the routing row's Thinking value as the literal first word of the
dispatch prompt:
| Value | Pre-pend |
|---|---|
none | (nothing) |
think | think. |
think-hard | think hard. |
ultrathink | ultrathink. |
Do not paraphrase. If a community ultrathink / think-hard skill is
installed, invoke that skill INSTEAD of the bare keyword.
Full rules + community alternatives: references/thinking-depth.md.
DISPATCH PROTOCOL — How Each Step Actually Runs
This is what makes the Model column enforced, not advisory.
For each step in the announced chain:
IF step.model == parent_model AND not parallel-fan-out:
→ Skill(<skill>) in-session (cheaper, same context)
ELSE:
→ Agent(subagent_type=<agent>, model=<model>,
prompt="<thinking-keyword>. Use Skill: <skill>. Task: <slice>. Context: <files>")
Sequential `→`: wait. Parallel `+`: one message, multiple Agent calls.
After dispatching, write log lines to ~/.claude/skill_router_log.jsonl
(chain-start, chain-step, thinking-active, chain-end) for the
statusline + the scripts/audit-dispatch.py compliance auditor.
Full event schema, common skip patterns, and verification: references/dispatch-protocol.md.
RED FLAGS — Signs You're About to Skip This
"This is simple" → Simple things take 5s to route. Skip routing = hours wasted.
"I know what to do" → Then routing confirms it. 5s cost, 0 downside.
"No match in table" → Run Catalog Check above before giving up.
"Ambiguous task" → Default to higher-complexity path (BUILD).
"I already know the skill" → Still run catalog check — a better one may exist.
"I'll just paraphrase" → No. Output the [skill-router] format VERBATIM. Greppability is the contract.
"I can skip the ▶ lines" → No. Per-step ▶ lines are the dispatch-mode proof. Without them the audit script can't score the chain.
What ships with it: 43 files
529.0 KB alongside SKILL.md, 20 of them executable
assets/
- proof/chain-code-review.png59.8 KB
- proof/chain-multi-domain.png79.4 KB
- skill-router-visual.png85.1 KB
docs/
- customizing.md3.0 KB
- how-it-works.md7.0 KB
- proof.md2.2 KB
- README.md1.1 KB
- self-improvement.md10.0 KB
references/
- catalog-check.md4.3 KB
- dispatch-protocol.md4.0 KB
- known-skill-repos.md2.4 KB
- multi-domain-chaining.md4.0 KB
- named-chains.md4.0 KB
- thinking-depth.md2.7 KB
scripts/
- audit-dispatch.pyruns4.4 KB
- dashboard.pyruns9.0 KB
- embedder_client.pyruns4.1 KB
- embedder_daemon.pyruns15.9 KB
- ensure-plugin-deps.shruns2.9 KB
- learn-chains.pyruns4.8 KB
- learn-from-history.pyruns9.2 KB
- online_catalog_fetcher.pyruns13.1 KB
- query_online_catalog.pyruns2.9 KB
- router_override.pyruns2.3 KB
- router.pyruns57.5 KB
- scan_codex_inventory.pyruns478 B
- weekly-analysis.shruns3.3 KB
setup/
- launchd-embedder.plist1.8 KB
- launchd-weekly.plist1.9 KB
templates/
- AGENTS.codex.template.md1.6 KB
tests/
- calibration.pyruns17.6 KB
- calibration_real.pyruns10.8 KB
- CHANGELOG.md9.1 KB
- CONTRIBUTING.md3.3 KB
- .gitignore272 B
- LICENSE1.0 KB
- README.md12.1 KB
- run_routing_test.shruns2.1 KB
- settings-hooks.json8.6 KB
- statusline.shruns12.6 KB
3 more files not listed here. See all 43 in the repository.