This project is inspired by Andrej Karpathy's llm-wiki.md idea file, which describes the pattern of using LLM agents to build and maintain a persistent markdown wiki from raw sources.
LLM Wiki is a portable, schema-driven skill for building a maintained markdown knowledge base with an LLM agent.
Instead of treating sources as a pile of files to search every time, LLM Wiki turns them into:
- structured source records and source relation records in
wiki_records/; - canonical per-source BibTeX records for paper sources;
- readable Obsidian-friendly pages in
wiki_pages/; - source-record citations;
- Obsidian-visible source-to-source links;
- generated LaTeX-ready bibliography exports;
- an index and log;
- deterministic validation reports.
The core design goal is portability. The workflow is stored as files that can be copied into different agent environments, while the wiki itself remains plain markdown and YAML.
Create a wiki:
python3 llm-wiki/core/scripts/init_llm_wiki.py path/to/wikiValidate it:
python3 llm-wiki/core/scripts/validate_wiki.py path/to/wikiRender source-to-source graph links after relation records change:
python3 llm-wiki/core/scripts/render_relations.py path/to/wiki
python3 llm-wiki/core/scripts/render_relations.py path/to/wiki --applyFetch and export BibTeX for paper sources when needed:
python3 llm-wiki/core/scripts/fetch_bibtex.py path/to/wiki SRC-0001
python3 llm-wiki/core/scripts/fetch_bibtex.py path/to/wiki SRC-0001 --apply
python3 llm-wiki/core/scripts/export_bibtex.py path/to/wiki --applyAsk your agent to read:
path/to/wiki/WIKI_SCHEMA.md
Then tell the agent what source to ingest or what question to answer.
The initializer creates this layout:
path/to/wiki/
WIKI_SCHEMA.md
WIKI_SCHEMA_PROPOSALS.md
AGENTS.md
CLAUDE.md
raw/
wiki_records/
sources/
relations/
bibtex/
wiki_pages/
index.md
log.md
questions.md
sources/
entities/
concepts/
synthesis/
WIKI_SCHEMA.md is the operating contract. AGENTS.md and CLAUDE.md are pointer files that tell Codex and Claude Code to read the schema.
Keep the bundle layout intact:
llm-wiki/
adapters/
codex/SKILL.md
claude/SKILL.md
core/
The adapter files use relative paths such as ../../core/README.md. If you copy an adapter without the core beside it, the skill will not have its shared instructions.
For Codex, use llm-wiki/adapters/codex/SKILL.md as the host entrypoint. For Claude Code, use llm-wiki/adapters/claude/SKILL.md.
Put local source artifacts under raw/, or use an external URL. Then create one source record:
record_id: SRC-0001
record_type: source
status: active
duplicate_of:
superseded_by:
source_storage: local
raw_path: raw/example.md
source_url:
page_path: wiki_pages/sources/example.md
source_type: article
source_format: markdown
title: Example Source
authors: []
added_date: 2026-05-11
processed_date: 2026-05-11
published_date:
content_fingerprint:
arxiv_id:
doi:
bibtex_key:Then create a readable source summary:
---
record_id: SRC-0001
page_type: source_summary
title: Example Source
aliases: []
tags:
- source
---
# Example Source
Durable claims cite source records.[^SRC-0001]
[^SRC-0001]: `SRC-0001` - [[sources/example]]Update wiki_pages/index.md and wiki_pages/log.md, then run the validator.
Create a relation record when one source should point to another. For example, a safe-sleep guidance source can mark a hospital discharge checklist as background:
record_id: REL-0001
record_type: relation
status: active
source_record_id: SRC-0001
target_record_id: SRC-0002
relation_type: background_for
direction: source_to_target
evidence: []
created_date: 2026-05-16
reviewed_date:
confidence: highThen render managed graph links and validate:
python3 llm-wiki/core/scripts/render_relations.py path/to/wiki
python3 llm-wiki/core/scripts/render_relations.py path/to/wiki --apply
python3 llm-wiki/core/scripts/validate_wiki.py path/to/wikiThe renderer is dry-run by default. With --apply, it rewrites only managed ## Related sources sections in source summaries. Ordinary prose and freeform Obsidian links are left alone.
Run bibliography commands on the wiki root, not on raw/. The fetcher reads source records from wiki_records/sources/*.yaml; it does not scan raw/ directly.
For active paper sources with arxiv_id, doi, an arXiv source_url, or an arXiv-looking raw_path, fetch canonical BibTeX artifacts:
python3 llm-wiki/core/scripts/fetch_bibtex.py path/to/wiki SRC-0001
python3 llm-wiki/core/scripts/fetch_bibtex.py path/to/wiki SRC-0001 --applyFor a whole wiki, preview and then fetch missing entries:
python3 llm-wiki/core/scripts/fetch_bibtex.py path/to/wiki --missing
python3 llm-wiki/core/scripts/fetch_bibtex.py path/to/wiki --missing --applyUse --retry-unresolved when you want unresolved sidecars tried again. Use --all when you intentionally want to revisit every eligible active paper source.
The fetcher tries INSPIRE first. It tries NASA/ADS second only when ADS_API_TOKEN is set; ADS lookup searches for a bibcode, then calls ADS BibTeX export.
export ADS_API_TOKEN="..."The ADS token is runtime configuration. Do not put it in git, wiki records, README files, or shell commands you plan to share. If a token is exposed, regenerate it in ADS.
Fetched entries live under wiki_records/bibtex/ as SRC-0001.bib plus SRC-0001.yaml. Preview and export a LaTeX-ready aggregate file with:
python3 llm-wiki/core/scripts/export_bibtex.py path/to/wiki
python3 llm-wiki/core/scripts/export_bibtex.py path/to/wiki --applyTo write directly into a LaTeX draft:
python3 llm-wiki/core/scripts/export_bibtex.py path/to/wiki --output /path/to/draft/references.bib --applyThe generated wiki_records/bibtex/references.bib is non-canonical. Per-source .bib files and sidecar .yaml records remain authoritative. Each active per-source .bib file must contain exactly one BibTeX entry at the canonical wiki_records/bibtex/SRC-XXXX.bib path, and validation rejects a stale aggregate when it no longer exactly matches the active export.
Validate after fetching or exporting:
python3 llm-wiki/core/scripts/validate_wiki.py path/to/wikiUse these recurring operations:
ingest: process one source into one record, one source summary, index updates, and log updates.query: answer fromwiki_pages/first, then consult records and sources when needed.file: save durable query results intowiki_pages/synthesis/only with human approval.lint: fix mechanical drift, but ask before semantic, schema, duplicate, archival, deletion, or synthesis changes.render-relations: mechanically update managed related-source links from active relation records.fetch-bibtex: fetch canonical BibTeX for active paper sources from INSPIRE, then ADS when configured.export-bibtex: generatewiki_records/bibtex/references.bibfrom active canonical entries.validate: runvalidate_wiki.pyafter edits.
The validator is structural. It checks file layout, schema headings, proposal blocks, source records, page frontmatter, mirrored titles, wiki links, and source-record citations. It does not judge whether every claim is sufficiently supported. It also checks relation records, managed related-source links, and BibTeX sidecars when present.
The schema is living, but its top-level sections are fixed in v1.
To change schema behavior:
- Add a generic proposal to
WIKI_SCHEMA_PROPOSALS.md. - Keep entry-specific exceptions out of the schema.
- Get human approval.
- Apply the approved change to
WIKI_SCHEMA.md. - Update references and validator tests when the change is machine-checkable.
- Log the schema change.
Records are schema-closed. If you add a source record field or BibTeX sidecar field, also update the validator constants and tests in llm-wiki/core/scripts/validate_wiki.py.
Run:
python3 llm-wiki/core/scripts/init_llm_wiki.py path/to/wikiExisting files are skipped. Use --force only when you intend to overwrite starter-managed files:
python3 llm-wiki/core/scripts/init_llm_wiki.py path/to/wiki --forceThe initializer rejects file/directory conflicts and symlinked starter-managed paths.
Update all relevant layers:
WIKI_SCHEMA.mdllm-wiki/core/references/page-contracts.mdPAGE_TYPESinvalidate_wiki.py- starter wiki directories if the page type needs one
- tests in
tests/test_validate_wiki.py
Update:
WIKI_SCHEMA.mdllm-wiki/core/references/record-contracts.mdALLOWED_SOURCE_FIELDSinvalidate_wiki.py- validation logic if the field has constraints
- tests and examples
For small and medium wikis, start with wiki_pages/index.md and normal file search. Add tooling only when the wiki outgrows that.
Useful low-level improvements:
- add scripts for repetitive record creation;
- add local search over
wiki_pages/; - add CI that runs
validate_wiki.py; - add lint commands for mechanical fixes;
- add optional MCP tooling only for workflows that benefit from a long-lived server.
Do not move semantic decisions into automation. Duplicate merges, source supersession, relation creation or semantic relation changes, schema changes, durable synthesis, and deletion require human approval.
docs/llm-wiki-application.md: how to apply the skill to a wiki.docs/llm-wiki-implementation.md: implementation reference.docs/llm-wiki-extension.md: extension guide.docs/llm-wiki-packaging.md: packaging decision and future path.
The original idea essay is in llm-wiki.md.
Run:
PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests -vThe tests cover starter assets, initialization, validation, and an end-to-end source-record workflow.