Llm wiki
npx -y skills add taikt/llm-wiki --skill llm-wikiAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Manage a personal LLM-maintained wiki: ingest source documents, answer questions, create/update concept pages, lint the wiki, and configure projects. Use when the user says 'ingest', 'add source', asks a question about wiki content, says 'lint', 'audit', 'configure wiki', or mentions a filename to add. Supports configurable root folder so you can work with any project's wiki regardless of the currently open workspace.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
17.9 KB, as published. Nobody here has run it
LLM Wiki Skill (Copilot)
Purpose
Maintain and query a structured, interlinked knowledge base following Andrej Karpathy's LLM Wiki pattern. The wiki is self-contained inside a configurable root folder — this skill can serve any project's wiki even when a different workspace is open.
⚙️ Project Configuration
Project paths are defined in
config.yaml(same directory as this file). Editconfig.yamlto add/modify/remove wiki projects — do NOT edit this file.
Config file location: .github/skills/llm-wiki/config.yaml
Example:
venv: ~/code/venv
converter: markitdown
projects:
- name: default
root: /path/to/your/wiki-root
description: Your wiki root
- name: japan
root: ~/Documents/wikis/japan
description: Japan trip planning
Argument parsing (Step 1 — always do first)
⚡ EXECUTE immediately — do not describe this workflow to the user. Read config, resolve root, then act.
- Read
config.yamlto load both global settings and the project list.- Global settings (top-level keys, all optional):
venv— path to a Python virtual environment. Auto-expand~. Default: none (use system Python).converter— preferred converter tool:markitdown(default) ordocling.
- Projects — entries under the
projectskey (YAML array).- Each project has:
name,root,description.
- Each project has:
- Store resolved
<venv>and<converter>for use in all subsequent steps.
- Global settings (top-level keys, all optional):
| Argument | Meaning |
|---|---|
--project <name> | Look up <name> in config.yaml to resolve root path |
--root <absolute-path> | Use the given path directly, ignore config.yaml |
| (none) | Use the project with name: default |
- The remainder after arguments is the user's question or command.
- Auto-expand
~in paths. - If the root path has no
wiki/subfolder, warn the user and stop. - If
--project <name>is not found in config.yaml, list available projects and stop.
Folder structure (relative to resolved <root>)
<root>/
raw/ -- source documents (immutable — NEVER modify)
.llm-wiki/cached/ -- converted .md cache (auto-created, never touch manually)
wiki/ -- markdown pages maintained by Copilot (= Obsidian vault folder)
wiki/index.md -- table of contents for the entire wiki
wiki/log.md -- append-only record of all operations
Obsidian tip: Point your Obsidian vault to
<root>/wiki/(or the parent<root>/). The.llm-wiki/folder can be excluded from the vault via Obsidian's "Excluded files" setting.
Commands & workflows
A. Ingest a source document
Triggered by: "ingest", "add source", or a filename inside raw/.
Step A-pre — Smart file resolution (always do this first for ingest):
Before looking up the file, run a fuzzy-match against <root>/raw/:
- List all files in
<root>/raw/(uselsor list_dir tool — do NOT use file_search which only searches the open workspace). - Normalize: lowercase the user's input and each filename, strip spaces/punctuation for comparison.
- Pick the best match using these rules (in priority order):
- Exact match (case-insensitive) → use it directly.
- Substring match → the user's input is contained in a filename, or vice versa.
- Fuzzy match → longest common subsequence / common words score ≥ 0.6.
- If exactly one file matches → proceed silently with that file (no need to ask the user).
- If multiple files match → show the list and ask which one:
Found multiple matches: … - If no file matches → list all files in
<root>/raw/and ask the user to pick one.
Never fail immediately with "file not found" without first listing and fuzzy-matching.
Step A-0 — Convert if needed (PDF/DOCX/XLSX/PPTX/images) — two-step process:
If the file extension is NOT .txt, .md, .rst, .log, .csv, .json, .yaml, or plain code:
A-0a — Convert source → save as .md file:
- Resolve settings from config:
<converter>— value ofconverterkey in config.yaml (default:markitdown).<venv>— value ofvenvkey in config.yaml (empty string if not set).- Resolve
<python_bin>— the interpreter used to run convert.py itself:- If
<venv>is set, check for<venv>/bin/python(POSIX) or<venv>\Scripts\python.exe(Windows) and use that path directly as<python_bin>. - If
<venv>is empty, or set but the venv python doesn't exist at that path, auto-create a venv (do NOT silently fall back to systempython, since installing packages there commonly fails witherror: externally-managed-environment/ PEP 668 on modern distros):- Pick a default venv location:
~/.llm-wiki/venv(expand~). Create parent dirs as needed. - Run
python3 -m venv <default_venv_path>(orpython -m venv ...on Windows).- If this fails because the
venv/ensurepipmodule is missing (e.g. Debian/Ubuntu withoutpython3-venv), tell the user exactly what to run to fix it, e.g.sudo apt-get install python3-venv, then stop and wait — do not attempt other workarounds (no--break-system-packages, no sudo pip, no manual ensurepip hacks).
- If this fails because the
- On success, set
<venv>=<default_venv_path>and persist it back to config.yaml (update the globalvenv:key) so future runs reuse the same venv instead of recreating it. - Resolve
<python_bin>=<venv>/bin/python(POSIX) or<venv>\Scripts\python.exe(Windows).
- Pick a default venv location:
- Only fall back to plain
python/python3on PATH if venv creation is truly not possible AND the user explicitly says to proceed with system Python anyway.
- If
- ⚠️ Important:
--venvonly tells convert.py whichpipto use for--auto-install; it does not change which interpreter runs the script. If you invokepython convert.py ... --venv "<venv>"using the systempython, the tool installs into<venv>but the running process still can't import it, and conversion silently falls back to a "[Cannot convert ...]" placeholder even though the install "succeeded". Always launch the script with<python_bin>resolved above — do not pass--venvas a substitute for invoking the right interpreter.
- Determine the output path for the converted Markdown:
<md_path> = <root>/.llm-wiki/cached/<filename-stem>.md
e.g. report.pdf → <root>/.llm-wiki/cached/report.md
- Create
<root>/.llm-wiki/cached/if it doesn't exist (auto-create). - Never write converted files into
<root>/raw/— that folder is immutable.
- Run the converter script using
<python_bin>directly, passing--outputto save to disk:"<python_bin>" <skill_dir>/scripts/convert.py "<root>/raw/<filename>" \ --tool <converter> \ --auto-install \ --output "<md_path>"<skill_dir>is the directory containing this SKILL.md file (.github/skills/llm-wiki).--auto-installautomatically installsmarkitdown[all]ordocling(depending on<converter>) if the package is missing in the environment. No manual install is needed.- The script prints the resolved output path to stdout on success.
- To override the converter for a single file, append
--tool docling. - This same
"<python_bin>" ... --output "<md_path>"form is used on all platforms (POSIX and Windows) — there is no separate Windows-only path anymore. - If conversion fails, show the error output to the user and stop.
- Always verify the resulting
<md_path>contains real converted content — open it and confirm it does NOT start with[Cannot convert ...: install markitdown or docling]. If it does, the wrong interpreter was used; re-run with the correct<python_bin>before proceeding.
A-0b — Ingest from the saved .md file:
- The source for all subsequent steps (A-1 onward) is the generated
<md_path>file, not the original binary file.- Read
<md_path>directly (it is a plain Markdown file — no further conversion needed). - Treat
<md_path>as the document content in steps A-1+.
- Read
Step A-1 onward (all file types):
- Read the full source document (use converted
.mdfrom<root>/.llm-wiki/cached/if available, otherwise read from<root>/raw/). - Auto-create all wiki pages immediately — do NOT ask the user for confirmation, and do NOT ask the user which method/script to use. Proceed directly to writing. Decide automatically per the rule below — never present this as a choice.
- Decide the ingest strategy automatically based on document size/structure (do not ask the user):
- Count numbered top-level headings (lines matching
^\d+\.\s+[A-Z]) or Markdown#/##headings in the cached.md. - If the document is large/structured (roughly 20+ headings, or a formal spec/SRD/standard style document): treat it as a grouped ingest automatically — run the two helper scripts back-to-back, with no intermediate question to the user:
This creates concise top-level pages directly inpython <skill_dir>/scripts/ingest_grouped.py "<md_path>" "<root>" python <skill_dir>/scripts/ingest_cached.py "<md_path>" "<root>"<root>/wiki/(updatingindex.md), and fine-grained per-heading pages archived in<root>/wiki/_detailed/(updating_detailed_index.md). See "Grouped ingest" below for full details on what each script does. - Otherwise (short/simple document): create pages manually following steps 4–7 below.
- Count numbered top-level headings (lines matching
- Create a summary page in
<root>/wiki/named after the source (lowercase, hyphens) — always do this regardless of which strategy was used in step 3. - For the manual path only: create or update concept pages for each major idea or entity — a single source may touch 10–15 pages, that is normal.
- Add
[[wiki-links]]to connect related pages throughout all affected pages. - Update
<root>/wiki/index.mdwith new/updated pages and one-line descriptions (the grouped-ingest scripts already do this automatically for their own pages). - Append to
<root>/wiki/log.md:## <YYYY-MM-DD> — Ingested: <source-filename> - Created: page1.md, page2.md - Updated: page3.md, index.md
B. Answer a question
Triggered by: any question about the wiki content.
- Read
<root>/wiki/index.mdto identify relevant pages. - Read those pages and synthesize a concise answer.
- Cite pages inline:
([[page-name]]). - If the answer is not in the wiki, say so clearly — never hallucinate.
- If the answer is valuable, offer to save it as a new wiki page (good answers compound over time).
C. Create or update a wiki page
Triggered by: "add a page", "write about", "note that…".
- Check
<root>/wiki/index.mdto avoid duplicates. - Create or update the page following the Page format below.
- Add
[[wiki-links]]to/from related existing pages. - Update
<root>/wiki/index.md. - Append to
<root>/wiki/log.md.
D. Lint / audit the wiki
Triggered by: "lint", "audit", "check wiki".
Check and report as a numbered list with suggested fixes:
- Contradictions between pages
- Orphan pages (no inbound links from other pages)
- Concepts mentioned in pages that lack their own page
- Claims that may be outdated based on newer sources
- Pages not following the page format
- Missing entries in
index.md
E. Configure the wiki (update config.yaml via chat)
Triggered by: "configure", "add project", "set venv", "change converter", "list projects", or when the user mentions config settings.
- Read
config.yamland display the current settings in a readable format. - Ask the user what they want to change. Accept free-form answers:
- "add project
<name>at<path>" → append a new entry toprojectslist. - "set default project to
<name>" → rename the existingname: defaultentry or update the first entry. - "set venv to
<path>" → update globalvenvkey. - "set converter to markitdown/docling" → update global
converterkey. - "remove project
<name>" → delete that entry fromprojects.
- "add project
- Show a preview of the updated config YAML to the user.
- On confirmation (or if user says "yes" / "apply"), overwrite
config.yamlwith the new content. - Confirm:
✅ Config updated. Active project: <name> → <root>.
Never overwrite config.yaml without first showing the preview. This is the only command that writes to the skill's own directory.
F. Ingest from Apple Notes or OneNote (macOS)
Triggered by: "ingest from notes", "sync from Apple Notes", "from OneNote", or when the user mentions a note or folder in Notes.
Apple Notes — fully automated (no need to open the app or export manually):
Step 1: List available notes in Apple Notes:
python <skill_dir>/scripts/notes_export.py --list --folder "<folder>"
Step 2: Export note(s) into the wiki's raw/ directory:
# Export a single note
python <skill_dir>/scripts/notes_export.py \
--root <root> --folder "<folder>" --note "<note title>"
# Export an entire folder
python <skill_dir>/scripts/notes_export.py \
--root <root> --folder "<folder>"
Files are saved to <root>/raw/notes/<folder-slug>/<note-slug>.txt.
Step 3: Run Command A (Ingest) on each exported .txt file.
OneNote (macOS):
OneNote does not support AppleScript. The only option: export the page from OneNote → PDF → save to <root>/raw/ → Command A will automatically use convert.py to process it.
Note: Original notes in Apple Notes / OneNote are never modified. The wiki page becomes the searchable, interlinked version.
Grouped ingest (for very large source documents)
Triggered automatically by Step A-1's size check — never presented to the user as a choice. For long structured documents (engineering specs, SRDs, etc.) that would otherwise explode into 100+ tiny per-heading pages, run these two helper scripts back-to-back instead of manually creating pages:
scripts/ingest_grouped.py <cached_md> <wiki_root>— creates one page per top-level numbered section (e.g. "1. Introduction", "2. Description", "3. Requirements", ...) directly in<root>/wiki/, and regenerates<root>/wiki/index.mdto list only these top-level pages. Only headings whose title starts with an uppercase letter are treated as real section headings, to avoid false positives from embedded numbered lists (e.g. retry sequences like "3. attempt 10 sec") being mistaken for sections.scripts/ingest_cached.py <cached_md> <wiki_root>— creates one page per fine-grained heading/requirement (can be 100+), but writes them into<root>/wiki/_detailed/(not the mainwiki/folder) and regenerates<root>/wiki/_detailed_index.mdto reference them. It also detects the fallback "Markdown headings" split (^#{1,3} ...) only when there are 5+ genuine matches, to avoid a single stray#(e.g. a "#" table column header from a converted PDF table) collapsing the whole document into 1–2 giant sections. Noise headings — review-tool markers ("Comment00000029"), bare numbers ("1", "3"), and numbered example/retry list items whose prefix was already stripped ("attempt 10 sec", "attempt 65 sec") — are folded back into the preceding real section instead of becoming their own junk pages.
Always run both scripts, in this order, with no confirmation prompt in between: ingest_grouped.py first (concise top-level index), then ingest_cached.py (searchable per-requirement detail pages archived under _detailed/). Both scripts are idempotent and safe to re-run — ingest_grouped.py will relocate (never delete) any stale/misnamed top-level pages from a previous run into _detailed/ rather than losing content. After both complete, report a brief summary of what was created/updated — do not ask the user to pick between scripts or confirm before running them.
Any hand-authored page you create in <root>/wiki/ (e.g. via Command C, or the Step A-1 summary page) is left untouched by these scripts as long as its filename doesn't start with <number>-.
Page format
Every wiki page must follow this structure:
# Page Title
**Summary**: One to two sentences describing this page.
**Sources**: List of raw source files this page draws from.
**Last updated**: YYYY-MM-DD
---
Main content. Use clear headings and short paragraphs.
Link to related concepts using [[wiki-links]] throughout.
## Related pages
- [[related-concept-1]]
- [[related-concept-2]]
Citation rules
- Every factual claim must reference its source:
(source: filename.ext) - If two sources disagree, note the contradiction explicitly.
- If a claim has no source, mark it:
⚠️ needs source.
Constraints
- Never modify anything inside
<root>/raw/. - Never write converted files into
<root>/raw/— always use<root>/.llm-wiki/cached/instead. - Always update
wiki/index.mdandwiki/log.mdafter any change. - Page filenames: lowercase with hyphens (e.g.
machine-learning.md). - Write in clear, plain language.
- When uncertain how to categorize something, ask the user.
- All file operations must stay within
<root>/— never touch files outside.