skill-navigator
Turns skill directory into navigable decision tree with single root entry skill. Mirrors memory-palace hierarchy: Wing (domain) → Room (subdomain) → Zone (topic cluster) → Station (group of ~7 leaves) → leaf skill. Each internal node body is decision node: routing question + per-branch keyword hints + relative links to children.
When to use
- Skills directory has dozens to thousands of
SKILL.mdskills. - Flat description-routing unreliable; want guided drill-down.
- Want navigate subset by glob or name list.
Requirements
- Python with
sentence-transformers,scikit-learn,numpy. - Embedding model
all-MiniLM-L6-v2(auto-downloaded once; ~80MB).
Install as a plugin
Claude Code installs this repo as marketplace:
claude plugin marketplace add neXenio/skill-navigator
claude plugin install skill-navigator@skill-navigator
Codex installs same repo as Git marketplace:
codex plugin marketplace add neXenio/skill-navigator
codex plugin add skill-navigator@skill-navigator
Run the CLI with uvx
uvx --from git+https://github.com/neXenio/skill-navigator skillnav --help
Example use
Skills live in ~/agent-skills? Build navigator:
DIR=~/agent-skills
WORK=/tmp/skillnav-agent-skills
uvx --from git+https://github.com/neXenio/skill-navigator skillnav --skills-dir "$DIR" --work "$WORK" build --wings 3
uvx --from git+https://github.com/neXenio/skill-navigator skillnav --skills-dir "$DIR" --work "$WORK" emit
Label $WORK/labels_in/*.json into $WORK/labels_out/*.json, then render and verify:
uvx --from git+https://github.com/neXenio/skill-navigator skillnav --skills-dir "$DIR" --work "$WORK" render --root team-navigator --lang en --apply
uvx --from git+https://github.com/neXenio/skill-navigator skillnav --skills-dir "$DIR" --work "$WORK" stats --root team-navigator
uvx --from git+https://github.com/neXenio/skill-navigator skillnav --skills-dir "$DIR" --work "$WORK" find "database" --root team-navigator
Invoke team-navigator in agent. Agent follows linked child SKILL.md files until reach matching leaf skill.
Install from a clone
git clone https://github.com/neXenio/skill-navigator.git
cd skill-navigator
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
Apply to a skills directory
Point CLI at directory holding existing skill folders. Each leaf skill must be directory with SKILL.md file. Generated navigator nodes written into same skills directory.
Use scratch directory for build artifacts. Keep outside target skills directory.
Workflow (run from this plugin's scripts/)
Let PY = python with deps, DIR = target skills dir, WORK = scratch dir.
1. Build the tree (embed + cluster, caps by construction; no LLM):
$PY skillnav.py --skills-dir "$DIR" --work "$WORK" build \
--wings 9 --sizes 90,30,7 --branch 8,8,12 \
[--discover top|tree|flat] [--min-children 3] [--min-leaves 3] \
[--include "agb-*,ds-*"] [--exclude "_*,wing-*"] [--names-file subset.txt] \
[--stop "skill,nutzen,pruefen,dsgvo,bgb"]
Tune --wings for cleaner top domains; --sizes = target leaves per child at depth wing/room/zone (last value ≈ leaves per station). After clustering, build rebalances: collapses 1-child chains, dissolves leaf-holders below --min-leaves into nearest sibling, lifts nodes still below --min-children, so every node ends with ≥3 children and every holder ≥3 leaves. Check printed children/node and leaf/holder min/med/max.
--discover picks what counts as leaf when skills nested in trees:
top(default): top-level dirs directly holdingSKILL.md(flat skill dirs).tree: each top-level dir holdingSKILL.mdanywhere is one leaf, use for marketplaces whose plugins bundle many skills (<plugin>/skills/<skill>/SKILL.md).flat: everySKILL.mddir at any depth is leaf (id = its relpath), resorts whole tree into one fresh navigator.include/excludematch basename or relpath.
2. Emit label batches:
$PY skillnav.py --skills-dir "$DIR" --work "$WORK" emit --batch-size 40
Writes $WORK/labels_in/batch_NN.json.
3. Label every node with an LLM. For each labels_in/batch_NN.json, dispatch low-cost labeling job. Each job reads its batch, writes $WORK/labels_out/batch_NN.json as {node_id: "Label"}. Prompt template:
Read
$WORK/labels_in/batch_NN.jsonwith nodes{id, level, terms, samples, n}. For each, produce a concise label in : wing 1-2 words, room 2-3, zone 2-4, station 2-5 (more specific deeper). Derive fromterms+samples(folder-names encode the topic). Station labels may add identifiers/anchors. FORBIDDEN: generic catch-alls (Sonstiges/Allgemein/Misc/Other/cluster), bare numbers, quotes. Write ONLY{id:"Label",...}to$WORK/labels_out/batch_NN.json.
Node missing after labeling? Drop one fallback file $WORK/labels_out/batch_fix.json with {id:"Label"} from its terms.
4. Render (dry-run first to confirm missing=0, then --apply):
$PY skillnav.py --skills-dir "$DIR" --work "$WORK" render --root navigator [--layout flat|nested]
$PY skillnav.py --skills-dir "$DIR" --work "$WORK" render --root navigator --layout nested --apply
--layout flat (default) writes every node as top-level sibling dir (marketplace-safe, disable nesting here if marketplace updater expects flat skills). --layout nested mirrors tree on disk under root dir. Links relative either way (os.path.relpath), each non-root node gets "Up one level" backlink so agent backtracks when no branch fits. --apply deletes prior navigator nodes (marked navigator:true) and writes tree + root. Real skills and other routers untouched.
5. Inject cross-links (data-driven RELATES_TO, centroid cosine, cross-branch):
$PY skillnav.py --skills-dir "$DIR" --work "$WORK" relates --lang de
6. Verify:
$PY skillnav.py --skills-dir "$DIR" --work "$WORK" stats --root navigator
$PY skillnav.py --skills-dir "$DIR" --work "$WORK" find "<term>" --root navigator
$PY skillnav.py --skills-dir "$DIR" --work "$WORK" walk --root navigator | head
stats must show unreached=0. find prints full navigator → wing → … → leaf path.
Run as a user
After render --apply, target skills directory holds new root skill, named navigator in examples above. Invoke that skill in agent environment, answer routing question at each level. Agent follows linked child SKILL.md files until reach leaf skill matching request.
Re-running
Idempotent: re-run build→…→render --apply to rebuild from scratch (old navigator nodes replaced). Re-run relates after render (re-strips its own block). To re-tune, change --wings/--sizes and repeat.
Notes
- Leaf = skill dir with
SKILL.mdand no_manifest.json. Navigator nodes carry_manifest.jsonwith"navigator": trueandkind∈ {root,wing,room,zone,station}. - Root auto-discoverable (
user-invokable: true). All wing/room/zone/station nodes are references (user-invokable: false): agents reach them by reading../<name>/SKILL.mdduring traversal. Skill list shows one entry: the root. --lang de|enswitches node-body wording (defaulten).--layout flat|nested: flat = top-level sibling dirs (marketplace-safe, default); nested = nodes mirror tree on disk under root.- Rebalance guarantees ≥
--min-childrenper node and ≥--min-leavesper holder; capacity caps (--sizes/--branch) soft, large clusters may exceed. - Each non-root node has Up one level backlink for backtracking.
- Worked example over 25k-skill corpus in
examples/claude-fuer-deutsches-recht/.