Deterministic & probabilistic, side by side
modesStatic analysis runs in milliseconds; LLM analysis runs in jobs. Same plugin model, same context, same graph.
Reclaim tokens (and money!), save time, and make your Markdowns deterministic. Detects collisions, orphans, semantic duplicates, and bloated skills.
All on the same graph, with static and semantic (LLM) analysis.
Static analysis runs in milliseconds; LLM analysis runs in jobs. Same plugin model, same context, same graph.
Per-node byte and token counts. Find the bloated skill that's eating your context window.
Every link between files: /slash invocations, @-mentions, imports, fetched URLs. The directory becomes a graph.
References pointing to triggers that don't exist. Caught at scan time, before the runtime drops the ball.
Two skills claiming the same invocation? Flagged before the runtime picks the wrong one.
Lists every URL and asset your workspace fetches. Audit your supply chain.
Six ways to extend this tool. Your plugin, your company's, the community's, all run against the same kernel.
Defines an agent (Claude, Codex, etc)
Declares the file kinds an agent exposes (skill / agent / command for Claude), where its content lives on disk, the frontmatter schema each kind follows, and how the UI renders it (label, color, icon). The Claude provider ships built-in; write one for Codex, Gemini, Copilot, or your own runner.
export const claude: IProvider = {
id: 'claude', kind: 'provider',
explorationDir: '~/.claude',
read: { extensions: ['.md'], parser: 'frontmatter-yaml' },
kinds: {
skill: { schema: './schemas/skill.schema.json', /* … */ },
agent: { schema: './schemas/agent.schema.json', /* … */ },
command: { schema: './schemas/command.schema.json', /* … */ },
},
classify: (path, fm) => /* skill | agent | command */,
};
Extracts data from a node
Each file is a node; an Extractor turns it into data. Links to other nodes, attributes that enrich the node, or signals you stash in your own KV store. Pure code, deterministic, runs in milliseconds inside `sm scan`, no LLM, no cost.
export const slash: IExtractor = {
id: 'slash', kind: 'extractor',
emitsLinkKinds: ['invokes'],
extract: (ctx) => {
for (const m of ctx.body.matchAll(SLASH_RE))
ctx.emitLink({ kind: 'invokes', target: m[1] });
},
};
Finds problems in the graph
Looks at the whole graph and spots problems: trigger collisions, orphans, dead dependencies, broken references. Write an analyzer, run it on any project, or publish it for others to use.
export const triggerCollisions: IAnalyzer = {
id: 'trigger-collisions', kind: 'analyzer',
evaluate: (graph) => byTrigger(graph)
.filter(([, ns]) => ns.length > 1)
.map(toCollisionIssue),
};
Improves your agents and skills automatically
Actions are the only plugin kind that touches disk. Deterministic mode: straight code (rename a trigger, tweak frontmatter). Probabilistic: a prompt run by the LLM (regenerate a summary, rewrite text).
export const renameTrigger: IAction = {
id: 'rename-trigger', kind: 'action', mode: 'deterministic',
run: async (node, { newTrigger }) => {
node.frontmatter.trigger = newTrigger;
await node.save();
},
};
Exports the graph to other formats
The graph lives in memory; a Formatter ships it out. ASCII for terminal, Mermaid for your README, DOT for Graphviz, JSON for your pipeline. Built-ins cover the common cases; write your own for the rest.
export const mermaid: IFormatter = {
id: 'mermaid', kind: 'formatter',
format: (graph) => 'graph LR\n' +
graph.edges.map(e => ` ${e.src} --> ${e.dst}`).join('\n'),
};
Notifies and integrates with other tools
When something happens in skill-map (scan finished, action executed, job failed), a Hook reacts. Send it to Slack, fire a webhook, gate a spawn before it starts. There are eight events you can subscribe to.
export const slackOnFailure: IHook = {
id: 'slack-on-failure', kind: 'hook',
triggers: ['job.failed'],
on: async (event) => slack.post('#alerts', event.error),
};
A plugin is ~30 lines of code.
sm plugins list
No config, no setup, nothing to read first. Run `sm` from any folder and it scans your skills, opens the explorer in your browser, and keeps watching for changes.
Trigger collisions, orphans, broken references, bloated skills, semantic duplicates. Static analysis runs locally in milliseconds; semantic checks (LLM) run when you want them.
Actions are the plugin kind that touches disk. Deterministic ones run as code (rename a trigger, edit frontmatter); probabilistic ones run a prompt on the LLM (regenerate a summary, rewrite copy).
No promises, no magic. Just a graph over the files you already have.
Skill, agent, or plain markdown: all your files live connected to the rest. skill-map shows duplicates, redundancies, and optimization opportunities before you publish.
Multiple projects, multiple agents, divergent copies of the same skill. One scan puts the whole hive in the same graph.
The agent picked the wrong invocation. What triggered it? skill-map follows the full path: from the trigger phrase to the skill that won the match. All in real time.
Every operation has a CLI verb, a JSON output, and a plugin hook. Wire skill-map into your CI, your dashboard, your LLM workflow, without forking the kernel.
“Found 14 trigger collisions across our internal agent fleet on the first run. We'd been debugging the resulting misfires for weeks.”
“The orphan check alone is worth it. We had 38 skills defined but never referenced. Dead code, just for agents.”
“I run sm in CI. If a PR introduces a collision or an external dep we don't allow-list, the build fails. End of debate.”