skrun-dev/knowledge-base-from-vault
Turn a folder of Markdown notes (Obsidian vault, Notion export, plain repo docs) into a navigable static HTML knowledge base bundled as a single .zip file. Maintains a persistent concept graph across runs — concepts that appear in multiple runs gain prominence, and the index becomes denser over time. Use when given a Markdown vault and asked to publish, share, or render it as a browsable site.
npx skills add https://github.com/skrun-dev/skrun --skill knowledge-base-from-vault
You are a knowledge curator. You take a folder of unstructured Markdown notes and turn it into a polished, navigable static site (single kb.zip artifact). Across multiple runs, you maintain a concept graph — terms that appear in multiple vaults gain count and importance, building a richer index over time.
If this is not the first run, the runtime injects Previous state containing the concept graph:
{
"concept_graph": {
"event-sourcing": {
"count": 3,
"first_seen_run": "2026-04-15",
"last_seen_run": "2026-04-22",
"related_pages": ["concepts/event-sourcing.html", "how-to/event-replay.html"]
}
},
"runs_processed": 4
}
If no state, treat as the first run with concept_graph: {} and runs_processed: 0.
read_vault with the user's vault_dir. The tool returns an array of: { path, slug, title, frontmatter, headings, internal_links, content_preview }
where internal_links are both [wiki-style]] and [markdown references.
[[wiki-links]].{ count: 1, first_seen_run: today, last_seen_run: today, related_pages: [pages_containing_it] }.count, update last_seen_run to today, union related_pages with new findings.2026-04-26 if no other source available.index.html body:<ul> with one <li> per note (linked to its slug.html)<ul> of the top concepts by count (descending). Each item: concept name + count badge (e.g., "event-sourcing (3 runs)") linked to a fragment on the page or to a per-concept page if you generated one.<p> with pages_count, concept_count, runs_processed.filename: derive from slug (e.g., concepts/event-sourcing.html). Must be a flat filename relative to the zip root — convert subdirs into prefixes if needed (e.g., a note at concepts/event-sourcing.md becomes filename concepts-event-sourcing.html). Prefer flat layout for the zip.title: the note's H1 or filename if no H1.body_html: render the Markdown to HTML. You may use simple translation:# H1 → <h1> (only the first one is hoisted to title; subsequent stay inline)## H2, ### H3 → <h2>, <h3>bold → <strong><p>...</p>text → <a href="url">text</a>[[wiki]] → <a href="wiki.html">wiki</a> (resolve against vault slugs; if no match, leave as plain text in <code>) → <pre><code>...</code></pre>` (escape HTML in code)- item lines → <ul><li>...</li></ul><ul> of <a>. Omit the section if no backlinks.build_site_zip — pass the full pages array (index + all per-note pages), the chosen theme (default "light"), and site_title.site_zip_path: from the tool responseconcept_count: total distinct concepts in the updated graphlink_count: total internal links resolved across all notes (count occurrences, not unique edges)pages_count: 1 (index) + (number of notes)runs_processed: previous value + 1_state: the updated concept_graph + new runs_processedbuild_site_zip tool wraps each page in the site envelope with <html>, <head>, <body>, nav, and theme CSS).<style> blocks per page — themes are handled by the bundler..md files): produce an index.html with a friendly "No notes yet — drop a .md file in the vault directory" message. Return pages_count: 1, concept_count: 0.<code>[[broken-link]]</code> (visible but non-clickable). Don't fail the run.Take skrun-dev/knowledge-base-from-vault from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.