Deterministic & probabilistic, side by side
modesStatic analysis runs in milliseconds; LLM analysis runs in jobs. One graph, analyzed from two angles.
Reclaim tokens (and money!), save time, and make your Markdowns deterministic. Detects collisions, orphans, semantic duplicates, and bloated skills.
All on the same graph: deterministic and semantic (LLM) analysis for your agent harness.
Static analysis runs in milliseconds; LLM analysis runs in jobs. One graph, analyzed from two angles.
Per-node byte and token counts. Find the bloated skill that's eating your context window.
Every link between files: /slash invocations, @-mentions, imports, URLs. The directory becomes a graph.
References pointing to triggers that don't exist. You catch them at scan time, before the agent drops the ball.
Two skills claiming the same invocation? You catch it before the agent picks the wrong one.
Lists every URL and asset that appears in your workspace. 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.
Bloated skills eating your tokens, trigger collisions, orphans, broken references, 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 markdown: all your Markdown lives 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 across your harness. 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.”