Skill-Atlas
Health Pass
- License — License: Apache-2.0
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 10 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Skill-Atlas
Skill Atlas
🔎 Query your whole skill collection at ~85% fewer tokens
A third tier for Claude Code skills — dormant, zero tokens, still findable.
Search a graph of your collection instead of preloading it.
53 skills, 6 kept enabled: 2,544 → 338 tokens per session (−86.7%). The other
47 cost nothing until asked for.

⚡ Install
claude plugin marketplace add danielLublinsky/Skill-Atlas
claude plugin install skill-atlas@skill-atlas
Python 3 only — no dependencies, no network (d3 is vendored).
Update. New versions arrive on their own — Claude Code refreshes marketplaces
periodically and picks up the new version, applying it on the next restart. To
pull one immediately:
claude plugin marketplace update skill-atlas
claude plugin update skill-atlas@skill-atlas
Then restart Claude Code — the update is staged until you do.
From a local clone (for hacking on it)git clone https://github.com/danielLublinsky/Skill-Atlas.git
claude plugin marketplace add ./Skill-Atlas
claude plugin install skill-atlas@skill-atlas
▶️ Run
| Command | What it does |
|---|---|
/skill-atlas |
Build the graph, categorize what's new, render atlas.html. Run this once to set up. |
/skill-atlas:edit-searchable |
Move plugins in and out of the searchable tier, interactively. |
/skill-atlas:skill-search |
Find the right skill for a task across the whole library, dormant tier included. Usually you never type this — Claude calls it on its own before a nontrivial task. |
| (automatic) | A SessionStart hook keeps everything fresh after that. |
Then open ./.claude/skill-atlas/atlas.html in a browser, and just ask for a
task — the search runs itself, names the skill it picked in one line, and gets
on with the work.
make build # graph.json + catalog/ from your live manifests
make render # atlas.html
make check # CI gate: exit 1 on any broken reference or dangling mention
make test # unit suite against fixtures — never touches the real ~/.claude
make release # bump both manifests, validate, test — never commits or pushes
The plugin cache is keyed by version, so a push without a bump ships no code to
anyone already installed. make release (or BUMP=minor, VERSION=1.0.0) is
what makes a change land.
🎯 The problem
Claude Code injects every enabled skill's description into every session —
~48 tokens each. At 100+ skills that's thousands of tokens you pay for constantly,
and near-duplicates quietly compete for the model's attention.
Disabling fixes the cost and loses the skill. So Skill Atlas adds a tier in between:
| Tier | In context? | Findable? | Cost / session |
|---|---|---|---|
| 🟢 enabled | yes | natively | ~48 tokens each |
| 🟣 searchable | no | via skill-search |
0 |
| ⚫ disabled | no | no | 0 |
A searchable skill is dormant — its description never enters your context, but
it stays discoverable on demand. All that advertises the whole dormant tier is one
~50-token line at session start.
🔍 Search reads two files, not the catalog
flowchart LR
A(["🧭 a task arrives<br/><i>“resolve this merge conflict”</i>"])
subgraph R1["1️⃣ read the index · ~1.6k tok"]
I["<b>_index.md</b> — 14 lines<br/><i>name · count · what it covers · member tokens</i>"]
end
subgraph R2["2️⃣ read one shard · ~0.6k tok"]
S["<b>version-control.md</b><br/>using-git-worktrees<br/>resolving-merge-conflicts ← hit"]
end
X["the other 13 shards<br/><i>~10k tok · never opened</i>"]
A --> I
I -- "pick ONE category" --> S
I -. skipped .-> X
S --> E["🟢 <b>enabled</b><br/><i>invoke natively</i>"]
S --> F["🟣 <b>searchable</b><br/><i>read its path,<br/>follow as instructions</i>"]
classDef file stroke:#8a8578,stroke-width:1.5px
classDef ghost fill:transparent,stroke:#8a8578,stroke-width:1.5px
classDef hit fill:#1baf7a26,stroke:#1baf7a,stroke-width:2px
classDef dormant fill:#8a5cd626,stroke:#8a5cd6,stroke-width:2px
classDef muted fill:transparent,stroke:#8a8578,stroke-width:1px,stroke-dasharray:4 3
class I,S file
class A ghost
class E hit
class F dormant
class X muted
style R1 fill:#3987e514,stroke:#3987e5,stroke-width:1.5px
style R2 fill:#3987e514,stroke:#3987e5,stroke-width:1.5px
A search costs ~2.4k tokens — the index (1.6k), one shard (~0.6k) and the
search skill itself (0.4k) — and you pay it only when a search happens. The
alternative it replaces is every dormant description sitting in context from
session start, billed whether you search or not. The arbitrage is real when
searches are occasional; it is not free, and the numbers above are measured
rather than estimated.
One shard is the norm. A second is opened only when the entry you found lists a
category you haven't read — the catalog pointing, not the model guessing — and
never a third. Counts overlap on purpose, so the pick doesn't have to land on
the right bucket, only a right one. Tier-off skills are excluded when shards
are written, so a disabled plugin can never return through a side door. The
result is announced in one line before the work continues: search is a lookup
inside a task, not a deliverable.
The model categorizes once. The first run drafts 8–12 categories named for
user-intent task shapes, not products, then freezes the taxonomy. Later runs only
file new skills and re-confirm the ones whose description changed — each assignment
carries a hash of the description it was made against.
🕸️ The graph

Discovery is manifest-driven — installed_plugins.json → each plugin.json →
settings — so marketplace catalogues and stale cached versions never pollute the
picture. (The naive "every directory with a SKILL.md" count over-counts by ~60% on a
real machine: build_graph.py --naive-count.)
Skills are nodes. The edges are the interesting part:
| Edge | Caught | |
|---|---|---|
| 🔗 | references — a skill → its own bundled files | broken when the file isn't there |
| 💬 | mentions — a skill naming another skill | dangling when the target is disabled, unregistered or absent |
Mention matching is deliberately strict — only backticked, skills/<name>, or
unambiguous hyphenated names, code fences stripped first. Loose matching produced 91
edges on a 41-skill collection, almost all of them ordinary English words. You also
get duplicate names, orphans, and an exit code to gate CI on.
atlas.html is self-contained and opens from file:// with zero network requests:
scope (origin, state, breakage in red) and categories (hub-and-spoke — solid
edge to the home category, dashed to the rest; search cat:<name> to isolate).
🛠️ Building and debugging skills

- What's really registered — discovery is manifest-driven, so unregistered copies
and stale plugin caches surface as their own nodes instead of quietly counting. - Broken bundles — a
referencesedge whose file isn't on disk draws red, so a
typo'dreferences/foo.mdis visible without opening anything. - Why it didn't trigger — tier is the node's fill (enabled · searchable ·
disabled), and duplicate names are called out in the footer with both nodes drawn. - Read it in place — pin any skill or bundled file and hit open markdown to
read the source in a popup without leaving the graph.
📚 Docs
docs/ — component guide, numbered 1–9: start at
overview, then jump to the component you're touching
(discovery, graph build, categorization, catalog & search, rendering, hooks).
DESIGN.md — the historical record for both phases: what was
considered, what was chosen, what was dropped, and why
⚖️ License
Apache-2.0 — see LICENSE.
D3 is vendored in vendor/d3.v7.min.js and inlined into
every generated atlas.html. It is ISC-licensed, © 2010-2023 Mike Bostock —
see vendor/LICENSE-d3.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found