July 2026Level 3 · ContextSkills

skilltree — How It Works (Deep Dive)

The mechanics only: the tree format, coordinate addressing, the Read-breadcrumb descent, and the CLI loop that keeps a hundred skills coherent while loading one layer at a time.

The story of why this exists is in Blog 1: The narrative — why this exists. This post is the mechanics only — assembled from skilltree's own impl docs (the README.md, and the two papers papers/skilltree-paper.md and papers/flat-vs-tree.md). It states what the system IS, not what it might become.

The architecture

skilltree imposes a coordinate-addressed tree on the flat .claude/skills substrate using the only three levers the platform leaves open (source: README, "Turn a flat folder…" intro):

  1. placement — each node is a plain directory carrying its own one-skill .claude/; the path is the coordinate (0 -> 0.1 -> 0.1.1);
  2. the inert-nested-.claude boundary — only the top layer auto-loads, so deeper nodes stay out of context until entered;
  3. breadcrumbs — each node's SKILL.md ends with an index summary of its subtree and explicit instructions to Read its children.

The construction emulates the two things a graph would supply natively (source: papers/skilltree-paper.md §2, "coordinate as identity, breadcrumb as edge"):

- 0.1-A (cor): Read `…/domain/A/.claude/skills/0.1-A/SKILL.md`
    

The breadcrumb names the child's coordinate and the single operation that loads it. A coordinate stands in for node identity; a breadcrumb stands in for a directed edge.

Retrieval that survives flattening (source: papers/skilltree-paper.md §4) recovers what a flat list of leaves loses. Each non-leaf node's body carries an index summary composed from its subtree's own vocabulary, so a query about a descendant still retrieves the branch that leads to it. A retrieval index (SQLite FTS5 / BM25) ranks nodes by relevance, and because every node carries its coordinate, the same index can restrict a query to a coordinate subtree — the coordinate is simultaneously the address and the search scope. One engine, one --scope flag.

How it runs

The runtime cycle is descent by reading (source: README, "The load mechanism it exploits (verified against the runtime)"; corroborated by papers/skilltree-paper.md §6). Exactly one node — the root — auto-loads; every other node loads only when its breadcrumb is followed. Entering a node loads exactly its layer — its own content plus the breadcrumbs to its children — and nothing below it. You load one layer and walk; you never load the pile.

The three runtime facts this depends on, verified directly against the tested Claude Code runtime and observed as a state-change in the live skill manifest (not asserted) (source: papers/skilltree-paper.md §6, reproduced verbatim):

Observation Result
A .claude/skills nested below the directory in scope not auto-loaded
Reading a file in a directory with the Read tool injects that directory's layer, one level; ancestors load, descendants do not
A shell cat of the same file injects nothing

The third row is a correctness condition on the emulation: the breadcrumb must invoke the Read tool, not a byte read, or the edge silently fails to load and is therefore not an edge.

Because the platform will not maintain a structure it never shipped, skilltree maintains its own coherence with a four-operation loop (source: README, "Self-management (it keeps itself coherent)"; papers/skilltree-paper.md §5):

A scheduled check (skilltree watch <root>) writes its verdict into a single managed rule, so a decohered tree announces itself in every subsequent session.

Where things live

The file geometry, on disk and in source.

A tree on the filesystem looks like this (source: README, "How a tree looks on disk", reproduced verbatim):

domain/.claude/skills/0-domain/SKILL.md          # root menu — the only node that auto-loads
    domain/A/.claude/skills/0.1-A/SKILL.md            # child A   — loaded only when Read
    domain/A/A1/.claude/skills/0.1.1-A1/SKILL.md      # grandchild — one level deeper
    domain/B/.claude/skills/0.2-B/SKILL.md
    

The root menu's generated body carries the index summary and the descend block (source: papers/flat-vs-tree.md Appendix A.1, reproduced verbatim):

## Index summary
    [0] domain — a sc index node; opens to 2 branch(es): A (cor), B (ac). Reachable below: A, A1, A2, B.

    ## Descend — the next layer (2)
    Only this layer is loaded now. To descend, use the Read tool on a child below — that injects
    the child's layer. A shell `cat` reads the bytes but loads nothing; you must use the Read tool:

    - 0.1-A (cor): Read `…/domain/A/.claude/skills/0.1-A/SKILL.md`
    - 0.2-B (ac): Read `…/domain/B/.claude/skills/0.2-B/SKILL.md`
    

The implementing source, by path:line (source: papers/flat-vs-tree.md Appendix A and papers/skilltree-paper.md):

The one CLI exposes the whole toolkit — skilltree <command> … (source: README, "Subcommands", reproduced verbatim):

Command What it does
tree <root> show the coordinate tree on disk (every node by its <coord>-<name> address)
map <folder> [--write] render a flat folder into one coordinate-addressed CLAUDE.md (Folder Map + addressable Index + branch summaries) — progressive disclosure over a flat pile
search <folder> <query> [--scope <coord>] FTS5/BM25 over any folder; --scope restricts to a coordinate subtree when the folder carries skilltree coordinates (a plain folder = coordinate-free search)
fold <framework_dir> --into <node> --tree <root> bind a framework (its skill dir) into a volume node's ## Frameworks tome table — idempotent, one row per framework; the manifest is the source of truth and the node's SKILL.md is regenerated from it
project <root> <target> [--policy flat\|progressive] [--link absolute\|relative] [--node N] deploy a tree into a skills dir as symlinks: progressive surfaces root + first-layer branches; flat projects a volume's tome rows + holder so every held framework auto-discovers top-level
cohere <root> report drift between the on-disk tree and its coherent shape
emit <root> [--root-forest] re-cohere in place; --root-forest tree-ifies a bare forest (lossless, journaled)
unemit <root> reverse the last emit, byte-for-byte
discover · validate · build · notify · watch read a tree · gate breadcrumb-resolvability · materialize from a manifest · write the notification rule · run the decoherence cron

The invariants

The rules and gates the system holds itself to (source: papers/skilltree-paper.md §6 and README, "Self-management" + the v0.3.0 changelog):

Read the story first, then the mechanics: Blog 1 — the narrative.

Chapter links

Read the story, then install: https://pypi.org/project/agent-skilltree/

Next note: skilltree — the story →

See one actually run.

The fastest way to judge any of this is to watch the engine do it.

Watch a world run →