FAQ
llm-wiki-newsroom is a Claude Code plugin with 6 hand-picked skills for content work, indexed on Flowy. Install it with the command on its page. It includes consulting-writing, encyclopedia-writing, guideline-writing. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
$ npx -y skills add alfadur7/llm-wiki-newsroom --agent claude-code
Repo: alfadur7/llm-wiki-newsroom
A multi-agent AI knowledge base run by a five-role "newsroom" — open-source, local-first, no vendor lock-in. Drop articles, documents, and PDFs into the raw/ folder, type a single command, and the newsroom — powered by an agent like Claude Code — reads them, extracts entities, concepts, and relationships, and organizes everything into a fully cross-referenced wiki, a structured and persistent alternative to RAG. Unlike most takes on the idea, the agent that writes a page is never the one that reviews it, and the authoring guidelines evolve themselves over time. Every new document you add also enriches the existing pages. This repo ships with a small example corpus — the debate over what "open source" means for AI — under wiki/, but the framework is domain-agnostic.
Most knowledge tools leave the finding to you. This project makes the AI read and understand your collected documents first, then organizes them into a wiki — with cross-references between pages, automatic flagging of conflicting claims, and per-topic synthesis built in from the start, so later retrieval is fast.
See the output before installing — the example corpus shipped in this repo is published as a browsable GitHub Wiki (no clone needed). It's a rendered static snapshot of the
wiki/folder; the interactive graph below runs locally.

The interactive knowledge graph (graph/graph.html) — every page a node, every wikilink an edge, color-coded by auto-detected cluster, with a live physics layout and filter/search built in. Shown here on a larger private deployment (~2,300 nodes) to convey how it scales; this repo ships a deliberately small 15-node example corpus you can browse the exact same way. (Interface shown in the optional Korean WIKI_LANG=ko mode.)
This project is one question worked into a running system: how far can you trust knowledge an AI wrote? Two ideas organize everything below.
1. The product is an LLM Wiki — Andrej Karpathy's three-layer pattern. The original documents you collect (Layer 1, raw/), the cross-linked wiki the agent maintains (Layer 2, wiki/), and the operating rules the agent follows (Layer 3, CLAUDE.md + .claude/) are kept strictly separate, so humans and AI don't trespass into each other's territory. As the operator you do exactly two things — feed Layer 1 and tune Layer 3; only the agent writes Layer 2. And ingesting one document doesn't just add a page: it refreshes the ~10–15 existing pages that mention the same entities and concepts, which is what makes the wiki compound instead of just piling up.
2. The factory is a newsroom running four loops. The wiki is produced by five roles modeled on a newspaper staff — and the agent that writes a page is never the one that reviews it:
| Role | What it does |
|---|---|
| Reporter | gathers material and drafts source pages + entity/concept stubs |
| Columnist | writes the deep cross-source analyses |
| Copy Editor | rule-based Python checks — not an LLM at all |
| Desk | re-reads finished drafts with fresh eyes; the only independent qualitative judgment in the system |
| Editor-in-Chief | routes work and gates publication — orchestration, not evaluation |
Four loops turn that division of labor into trust. The first three nest inside one another; only the fourth sits outside, feeding published pages back in:
%%{init: {"flowchart": {"wrappingWidth": 700}}}%%
flowchart BT
subgraph meta["Meta loop — mistakes become new rules"]
subgraph outer["Outer loop — two gates before publication"]
inner["Inner loop — the writer self-checks while drafting"]
end
end
%% the padding keeps this box as wide as the Meta loop box above
reground[" Reground loop — pages that go stale or inconsistent come back as input "]
reground -.-> meta
style meta fill:transparent,stroke:#58a6ff,stroke-width:2px
style outer fill:transparent,stroke:#3fb950,stroke-width:2px
style inner fill:transparent,stroke:#d29922,stroke-width:2px
style reground fill:transparent,stroke:#bc8cff,stroke-width:2px,stroke-dasharray:4 4
| Loop | When it runs | What it does |
|---|---|---|
| Inner | while drafting | the writer self-checks against the same yardstick the review gates will use later, and hands off instead of grinding |
| Outer | at publication | two gates — deterministic lint (Copy Editor), then a six-lens qualitative review (Desk) — and both must pass |
| Meta | when mistakes recur | repeat failures become proposals to amend the authoring rules themselves, adopted only after blind measurement plus operator sign-off |
| Reground | after publication | published pages that have gone stale or inconsistent come back around as factory input |
The first three loops mirror the "software factory" playbook for AI-assisted coding; the fourth exists because knowledge, unlike code, keeps decaying after you ship it. The full argument for this design is in the companion article: The Knowledge Factory.
Everything else in this README — the commands, the tools, the feature list — hangs off this map.
There are plenty of takes on Karpathy's LLM Wiki idea now. After reading the popular implementations, three things here are genuinely rare — and they are the bet:
The rest — the knowledge graph, contradiction tracking, cascading updates, plain-markdown/Obsidian output — many LLM-wiki tools have in some form.
git clone https://github.com/alfadur7/llm-wiki-newsroom.git
cd llm-wiki-newsroom
Or click "Use this template" to create your own wiki repo from this scaffold. To start from a clean slate, delete the example pages under
wiki/(keep the folders andgraph/cluster_labels.json), then ingest your own sources with/wiki-ingest.
This project assumes an environment where the AI agent reads and edits files and invokes tools on its own. Support levels by agent:
| Agent | Config file | Support level |
|---|---|---|
| Claude Code (primary) | CLAUDE.md + .claude/commands/ | All 9 slash commands + advanced features (cascading updates, associative discovery, etc.) |
| Codex | AGENTS.md | Basic workflow only (drive it with natural language) |
| Gemini CLI | GEMINI.md | Basic workflow only (drive it with natural language) |
Claude Code-only features include cascading updates that refresh related existing pages whenever a new document is added, a backlink index across all pages, automatic contradiction tracking, and associative discovery that follows connected concepts. AGENTS.md and GEMINI.md carry only the basic workflow from the original SamurAIGPT project. The Python tools used to build the wiki run locally with no external API keys.
In Claude Code, typing a /-prefixed command like /wiki-ingest runs the matching workflow. The table below gives each command's role in one line; the Key Features section explains how they work. Argument notation follows <required>, [optional], and a | b | c (pick one); invoking a command with no required argument prints usage and stops.
| Command | Arguments | Description | Example |
|---|---|---|---|
/wiki-ingest | <file | folder | inbox> | Absorb one document into the wiki while also refreshing related existing pages. inbox processes the mobile share-sheet queue in a batch | /wiki-ingest raw/NewsScrap/article.md |
/wiki-query | <question> | Find pages related to the question via the graph and answer with supporting evidence | /wiki-query open source AI definition |
/wiki-lint | [--fix] | Health-check for broken links, missing pages, contradictions, etc. (--fix auto-repairs) | /wiki-lint --fix |
/wiki-graph | — | Compute the connections between pages and generate an interactive graph | /wiki-graph |
| Command | Arguments | Description | Example |
|---|---|---|---|
/wiki-news | [cluster|keyword] | Search the web for the latest news related to the wiki's topics and recommend only new articles | /wiki-news open-source-ai-definition |
/wiki-export | — | Merge the entire wiki into files for upload to a Claude.ai project | /wiki-export |
"Associative discovery" is inspired by the Memex proposed by Vannevar Bush in 1945 — an exploration style that follows connected concepts to surface unexpected relationships without a fixed search term.
| Command | Arguments | Description | Example |
|---|---|---|---|
/wiki-discover | <seed | --random | --surprising | --gaps [<slug>]> | Unexpected connections within 2 hops from a seed (or random seed), or auto-ranking of hubs that bridge clusters | /wiki-discover Meta |
/wiki-trail | <create|follow|list> [args] | Build and save a 5–10 step page path that follows a single topic | /wiki-trail create open source AI definition |
/wiki-timeline | <entity> [year] | A chronological storyline of a person's or company's events sorted by year | /wiki-timeline Meta 2024 |
You don't have to memorize the slash commands — you can request the same tasks in natural language, and Claude Code figures out the intent and maps it to the right command.
"Ingest this file: raw/NewsScrap/article.md"
"What's the relationship between open weights and the OSI definition?"
"Check the wiki for contradictions and auto-fix them"
"Start from Meta and find unexpected connections"
Grouped by where each feature sits in the concept above: first the product (the wiki itself and the ways to explore it), then the loops that make it trustworthy.
AI conversation sessions evaporate when they end, but this project accumulates the extracted knowledge as structured markdown files. They're plain text files, version-controlled with Git and viewable in ordinary tools like Obsidian or VS Code, so you're not locked into any vendor.
Ingesting one new document automatically updates the existing entity/concept pages it mentions. For example, ingesting an article about "Meta releases an open-weights model" extends the fact list in Meta.md and adds an item to the releases section of OpenWeights.md. This implements Karpathy's original idea that "ingesting 1 document changes 10–15 pages" — one of the framework's core characteristics.
To avoid re-ingesting the same article, it double-indexes by URL and file path (wiki/sources/_source_map.json). Even if a re-scrape via Obsidian Web Clipper changes the filename slightly, a matching URL is detected as a duplicate. Cases where a filename drifts due to Unicode quote differences (' vs ') are normalized and handled too.
Beyond text articles, PDF documents are absorbed through the same pipeline. Drop a .pdf file into the raw/PDF/ folder, and the next /wiki-ingest run auto-detects it; Claude Code's Read tool opens the PDF directly and interprets its body, tables, and figures. It's a mechanism for handling long documents not published as HTML, like industry reports, regulatory filings, and conference materials.
raw/_inbox.md) and run /wiki-ingest inbox to save it as a binary under raw/PDF/. Just the .pdf lands, with no separate meta file.source_url: frontmatter of wiki/sources/<slug>.md generated at ingest, so dedup works even if the same document is re-downloaded. Even if you manually drop just a PDF with no URL, duplicates are filtered by file path.When a new document conflicts with existing claims, it's auto-recorded at ingest time. Readers drill down three levels using wiki/index.md as the entry point.
wiki/contradiction.md — global aggregation of contradictions. The editor's tension-axis narrative + theme summaries.wiki/contradictions/<theme>.md — per-theme deep analysis (e.g., whether an "open source" model must release its training data). Which themes exist and which raw issues belong to which theme is defined by _contradictions_themes.json as the mapping SoT.wiki/contradictions/_contradictions.json — source DB of auto-detected individual issues.It's designed in macro summary → theme interpretation → raw evidence order, so wherever a reader stops, that layer reads as self-contained. wiki/overview.md covers only per-domain overviews and includes no contradiction references — the common entry point for both axes is wiki/index.md.
Instead of a human assigning every entity/concept page to a category by hand, it uses an algorithm that groups similar topics looking only at the connections between pages (Leiden community detection). The result is intuitive clusters — here, the example corpus splits cleanly into "open-source AI definition," "open weights," and "licensing · open-washing." Each source document is assigned by weighted vote to the cluster of the entities it referenced, so documents that overlap in topic are listed in multiple cluster catalogs at once.
Leiden is the successor to the better-known Louvain algorithm, solving Louvain's limitation (the modularity-local-maxima trap) where cluster boundaries swing wildly under small graph changes, via a refinement stage and connectivity guarantees. In the larger corpus this engine was built for, as the wiki grew to ~470 hubs Louvain hit an unstable regime where adding just 7 new sources would make the cluster count jump from 7 to 10; after adopting Leiden, the same change was measured to stay stable at 8→8. (The small example corpus shipped here has only 3 clusters, so the instability doesn't show up — but the algorithm choice still matters as a wiki grows.)
The algorithm only finds clusters; it can't name them. graph/cluster_labels.json is a small config file that attaches a human-understandable name ("cyber security," "cloud native," etc.) to each automatically found cluster. This file is nearly the only config in this project that the operator opens and edits directly; everything else is auto-generated.
When a new topic cluster is discovered and needs a label, /wiki-lint tells you. Just add one entry in the format below.
{
"slug": "licensing-open-washing",
"name": "Licensing & Open-Washing",
"anchor_members": [
"concepts/ModelLicensing.md",
"concepts/OpenWashing.md",
"entities/Meta.md"
],
"paired_with": ["open-source-ai-definition"]
}
slug — an English identifier. Used as the catalog filename (_catalog-<slug>.md) and as the /wiki-news <slug> command argument, so use only letters, digits, and hyphens.name — the human-readable display name. Surfaced in the catalog title and the index.anchor_members — 3–6 pages representing this cluster. The script matches a label by "are at least half of the designated representative pages grouped into one community," so too few risks a match failure and too many risks overlap with another community.paired_with (optional) — an array of paired-cluster slugs whose work naturally overlaps. E.g., here "licensing · open-washing" ↔ "open-source AI definition" (the two debates share figures and arguments). Writing it on one side applies it both ways, and even if a paired cluster's representative page appears in the per-domain overview body, /wiki-lint won't flag it as narrative drift. Do not list a split-off relationship where a domain broke away — there you do need to check whether the body is stuck in the old flow.After editing, re-run python tools/build.py and the new name is reflected in every catalog and the index.
Drawing every page as a node and every wikilink as an edge, it generates an interactive browser graph (graph/graph.html). Clicking a node highlights its connections, and each edge carries a "why it's connected" label readable on mouse hover. Edges are classified into 5 types (contradicts·defines·cites·references·inferred) and color-coded — the 4 explicit edge types stated in the body get different colors by relationship meaning, while inferred edges leading to pages that aren't directly linked but share 3+ common references are shown in lavender, surfacing implicit relatedness.
Serve the graph/ folder over a local web server (e.g. python -m http.server) and open graph.html — it fetches its data, so a file:// double-click is unsupported — and these interactions are available right in the browser:
Once the wiki exceeds 1,000 documents, a single list file becomes hard to navigate. This project lists only entities/concepts/analyses in the main index (wiki/index.md) and splits documents into per-cluster sub-catalogs. A document spanning multiple clusters is listed in all relevant catalogs. All lists — entities, concepts, analyses — are uniformly sorted A–Z (under WIKI_LANG=ko, Hangul-titled pages sort first in ga-na-da order, then A–Z).
tools/query.py)Having the LLM read every page in full to answer a question is costly, and an AI agent can only handle a limited amount of context at once. This tool is a CLI that helps the agent understand the structure first, or narrow candidates, before reading pages, with two subcommands, graph and qmd.
Graph traversal (python tools/query.py graph ...) — structural queries using link relationships:
graph path Meta OpenSourceInitiative — shows the shortest path connecting two pages and why each link was formed ([[X]] — connection reason explanation). You can trace the logical flow from "Meta" to "OpenSourceInitiative" without a single click.graph explain OpenWeights — summarizes which cluster a page belongs to, which pages reference it, and what it points to.graph neighbors Meta — groups directly connected pages by cluster to see "what's around" at a glance.Body search (python tools/query.py qmd ...) — local search that actually inspects page bodies to find the ones matching a topic (no external transmission):
qmd hybrid "open weights vs open source" — recommendation search combining keyword, meaning, and reranking.qmd search "OpenAI" — BM25 keyword matching (fastest).qmd vsearch "models that are open in name only" — vector-based semantic similarity (finds it by context even when the exact keyword isn't in the body — here, surfacing the open-washing pages).--budget N limits the number of output lines so the agent pulls exactly as much as it can digest. --json enables program-to-program integration.
/wiki-discover surfaces connections hidden in the wiki in two ways.
Seed exploration: starting from a specific page like /wiki-discover Meta, it follows backlinks and co-references 2 hops to present pages not directly linked to the seed but unexpectedly close (e.g., "model licensing terms → training-data disclosure"). Giving --random picks a random hub in the mid-range of backlink counts and runs the same exploration.
Bridge-hub ranking (--surprising): automatically selects the pages that most bridge different topic clusters. The score rises the more often it appears on shortest paths, the more its neighbors span multiple clusters, and the less it's so famous as to seem "obvious." The "unexpected centers" are output as a top N even with no seed input.
Vannevar Bush's Memex (1945) proposed knowledge exploration that follows trails between pieces of information. /wiki-trail builds and saves a path of 5–10 pages woven in order, with commentary at each step, for a given topic. Good for sharing with a team: "to understand this topic, read it in this order."
Specifying an entity and a year like /wiki-timeline Meta 2024 generates a storyline sorted chronologically of that person's or company's events. It groups by year, combining backlinks and each source's publish date.
/wiki-news builds keyword combinations from the entities/concepts accumulated in the wiki and selects only the latest articles from the web. For example, specifying the open-source-ai-definition cluster generates search terms combining that cluster's major hubs ("OpenSourceInitiative," "OSAID," "training data"). It dedups against existing source titles and recommends only new articles as ingest candidates. It fetches the body even on sites with strong bot blocking by behaving like a browser. When a particular topic is empty, it follows the links in related articles to find further candidates to fill that gap.
/wiki-export exports the wiki in two layers — a RAG layer (synthesis pages + directory) that builds the answers, and deep links into the graph browser that serve the detailed originals. A Claude.ai project loads attached knowledge wholesale into context rather than retrieving it, so entity/concept bodies (about 70% of the total) and source originals are not put into RAG — doing so would vastly exceed the context limit (~200K tokens). Instead, index.md is a directory holding every entity/concept with a one-line description + deep link, and the synthesis layer (domain overviews · contradiction analyses · analysis reports) fills in the substance of answers. README.md carries the upload budget guide (start from Core ~130K tokens) and the deep-link convention to paste into project instructions. Push these files to GitHub and connect them as Claude.ai Project Knowledge, and you can query the wiki even from a phone — answers built from the synthesis layer, details pointed to via graph links.
So that answers understand the wiki structure and attach links to the graph, paste the entire wiki-export/README.md that export also produces (an instruction document covering file structure, answer rules, and the deep-link convention) once into the custom instructions box of the Claude.ai project. Then, when citing a hub the answer links to that page, and when pinning a specific claim's source it links straight to the original.
The wiki body is not typed by humans. Two kinds of automation handle it in layers.
/wiki-lint's automated metrics — the inner loop at workThe human operator's role is tuning the guidelines and rubric and making the final acceptance call — focusing on directional oversight rather than sentence-level copyediting. When the guidelines and rubric are fully captured in CLAUDE.md, any other Claude session rewrites to the same quality.
The probabilistic automation above doesn't have one Claude do everything. The Claude that writes the body and the Claude that re-reads and reviews it are split into different instances, reducing self-bias. Just as a newspaper divides labor among reporters, columnists, and the desk, authoring and verification are placed in different hands.
The body quality of per-domain overviews (wiki/overviews/<cluster>.md, wiki/overview.md) and per-theme contradiction analyses (wiki/contradictions/<theme>.md, wiki/contradiction.md) is judged by an evaluation rubric grounded in external editorial forms. It's designed to reduce subjective judgment and let different people or different AI sessions reproduce the same standard. The two axes use different forms — a domain overview is writing that spreads information out like a landscape, while a contradiction analysis fairly juxtaposes opposing viewpoints, so the editorial traditions differ.
Forms it draws on:
python tools/lint.py overview and python tools/lint.py contradiction instantly judge auto-verifiable criteria (total links, density ratio, dedup minimization, section completeness, domain boundaries, etc.) and emit a ✅/⚠️ report. The feedback loop in which Claude self-verifies against this report after writing and rewrites until the required criteria are met serves as the quality bridge of dual automation.
As the wiki grows, problems accumulate: orphan pages (referenced from nowhere), broken wikilinks, missing person pages, naming-convention violations (in the optional Korean mode, say, a Korean company page created under an English filename). /wiki-lint checks all of these in one pass and shows a report, and the --fix option immediately repairs the auto-fixable items. When topic clusters form differently than expected, the diagnosis is provided alongside. At the end of the report, "page candidates referenced in multiple places but not yet created" are attached as suggestions, hinting at what to create next.
Hard-to-reverse operations like creating a new page or deleting an existing one first show which files are affected and then ask for confirmation — preventing unintended changes even without Git. If the data that synchronization is keyed on (cluster definitions, contradiction theme mapping) is stale, auto-fix pauses briefly and first tells you which command to refresh with.
When the same review failure recurs, the system doesn't stop at fixing individual cases; it collects those failures and drafts a proposal to fix the authoring guidelines themselves. So not only the wiki body but the rules that build the wiki learn from their own mistakes.
Once code ships it stays put until the spec changes; knowledge doesn't — it drifts away from reality as the world moves. So this system feeds published pages back in as factory input, on three triggers, each an old newsroom practice:
/wiki-lint staleness surfaces derived pages that lag the sources they were built from; a Columnist re-reads the sources and rewrites. (A follow-up story.)These triggers surface work as advisories rather than hard failures (one narrow exception does fail the build), and a deterministic check never closes an item by itself — a human or the Desk does. One honest gap: follow-up items don't yet have a close procedure, so a surfaced item re-fires on every run until an adjudication ledger is built.
The three layers from the concept live in raw/ (Layer 1), wiki/ (Layer 2), and CLAUDE.md + .claude/ (Layer 3). The Layer 2 wiki is further formalized into four sub-layers. Knowing which slash command produces or updates each sub-layer makes the workflow intuitive to follow.
| Sub-layer | Role | Producing/updating command | Output location |
|---|---|---|---|
| L2-1 Source reflection | Reflect one source into summary, claims, quotes, and connection sections | /wiki-ingest | wiki/sources/<slug>.md |
| L2-2 Abstraction | Extract and update the entities, concepts, and timelines mentioned in sources | /wiki-ingest's cascading update · /wiki-timeline | wiki/entities/, wiki/concepts/, wiki/timelines/ |
| L2-3 Per-domain analysis | Cluster overviews · issue (contradiction) analyses · query answers · discovery trails | Skeletons auto-generated (the full tools/build.py rebuild via /wiki-ingest · /wiki-lint overview --fix; /wiki-lint contradiction --fix for issue analyses) → Claude writes the body against an evaluation rubric. Plus: /wiki-query · /wiki-trail | wiki/overviews/<cluster>.md, wiki/contradictions/<theme>.md, wiki/syntheses/<slug>.md, wiki/trails/<slug>.md |
| L2-4 Global aggregation | Restate each per-domain overview and per-theme contradiction analysis one paragraph at a time + cross-domain narrative | Claude rewrites periodically | wiki/overview.md, wiki/contradiction.md |
For example, ingesting one article with /wiki-ingest creates L2-1 and L2-2 at the same time. When the next full rebuild recomputes clusters, the relevant per-domain overviews (L2-3) are automatically affected, and Claude rewrites them against the evaluation rubric as needed. The global overview (L2-4) is rewritten periodically once the per-domain overviews stabilize, keeping it current. Each sub-layer is responsible only for its own axis (per-domain overview or issue/contradiction), so editing one page leaves the other axis's files untouched.
raw/ # Layer 1: original sources (immutable)
NewsScrap/ # HTML article clippings (Obsidian Web Clipper-compatible md)
PDF/ # centrally managed PDF documents (drop *.pdf only)
AiChat/ # topic notes excerpted from AI conversations
_inbox.md # mobile share-sheet URL queue (auto-managed)
_archive.md # accumulated inbox processing results (auto-managed)
wiki/ # Layer 2: agent-managed wiki
index.md # full page catalog + drill-down entry point (auto-generated)
overview.md # per-domain overview global aggregation — landscape axis (human + LLM co-managed)
contradiction.md # per-theme contradiction analysis global aggregation — conflict axis (human + LLM co-managed)
_backlinks.json # backlink index (auto-generated)
sources/ # individual source pages + catalog
_source_map.json # ingest deduplication map (auto-generated)
_catalog.md # full source catalog (auto-generated)
_catalog-<slug>.md # per-cluster catalog (auto-generated)
entities/ # companies, institutions, people
concepts/ # technology, strategy, regulation concepts
timelines/ # per-entity chronological timelines
overviews/ # per-domain overviews (landscape per cluster)
contradictions/ # per-theme contradiction analyses (conflict per theme)
_contradictions.json # contradiction source DB — per claim (auto-generated)
_contradictions_themes.json # theme ↔ claim mapping SoT (Claude-generated)
<theme>.md # per-theme deep analysis (human + LLM co-managed)
syntheses/ # saved query answers (Q-A)
trails/ # associative trails (Memex)
wiki-export/ # merged files for Claude.ai Project Knowledge (auto-generated)
graph/ # knowledge graph + clusters
_graph.json # node/edge data (auto-generated)
_clusters.json # Leiden clusters + source assignment (auto-generated)
cluster_labels.json # ★ stable cluster labels — manually edited config file
graph.html # interactive graph visualization (open in browser)
CLAUDE.md # Layer 3: schema (evolved jointly by humans and the LLM)
log.md # chronological operations log (append-only)
lint-report.md # health-check results (auto-generated)
tools/ # Python tools (no API key required)
| Type | Prefix | Examples |
|---|---|---|
| Auto-generated data — scripts overwrite it every run, so do not edit directly | _ | _backlinks.json, _graph.json, _clusters.json, _catalog*.md, _contradictions.json |
| Human-edited — for manual editing or viewing | none | index.md, overview.md, contradiction.md, graph.html, graph/cluster_labels.json |
Naming rule: an underscore prefix means a script output (don't touch it); no prefix means a file humans edit or read.
The wiki/ root meta files (index, overview, contradiction) start directly with # Title, without frontmatter. Only pages in subdirectories (sources/, entities/, concepts/, overviews/, contradictions/, etc.) require frontmatter.
wiki/ root: wiki-wide meta fileswiki/sources/: source-only meta filesgraph/: graph data and visualizationwiki-export/: merged files for external distributiontools/: Python scripts and script-only configThe framework's documentation, prose, and wiki page schema tokens are all in English. The tools grep for these exact strings, so they are part of the data format rather than display text: section headers such as ## Summary, ## Connections, ## Overview, and ## Timeline, and inline evidence/relation tags such as [fact], [analysis], and [forecast]. Full internationalization of the page schema — making these tokens configurable per language — is a future direction.
/wiki-ingest <file | folder>raw/NewsScrap/article.md or raw/PDF/report.pdf (folder argument scans both .md and .pdf)
1) Dedup: check whether it was already ingested, by both URL and file path
2) Read the body: markdown as-is; for PDFs the Read tool interprets the binary directly
3) Write the source page: wiki/sources/<slug>.md with summary, claims, quotes, connection sections
· For PDFs, the original URL is recorded in this page's source_url field (for dedup)
4) Cascading update: append new facts to the entity/concept pages that appear in the source and refresh their reference lists
5) Link enrichment: propose [[wikilink]] candidates for existing page names that appear as plain text in the body
6) Full rebuild: graph/visualization → clusters/catalogs/per-domain overviews → contradiction source DB → index → dependency index,
updated in that order (a single tools/build.py run)
7) Auto-validation: check broken links, filename convention, missing tags
8) Cluster health diagnosis: surface new topic clusters that need a label (graph/cluster_labels.json)
9) Append one line to log.md
/wiki-query <question>1) Classify the question by type (entity description / relationship between two pages / topic survey / short-fact / wiki overview / contradiction comparison)
2) Narrow candidates by type (the agent checks the "map" before reading full bodies):
tools/query.py graph explain <page> → summarize a page's in/out links, cluster, and connection reasons
tools/query.py graph neighbors <page> → group adjacent pages by topic
tools/query.py graph path <A> <B> → shortest path between two pages and the reason for each hop
tools/query.py qmd hybrid "topic" → body search combining keyword, meaning, and reranking
tools/query.py qmd search "keyword" → BM25 keyword matching (fastest)
tools/query.py qmd vsearch "context sentence" → vector-based semantic similarity
3) Read in full only the ≤10 pages selected above
4) Produce a markdown answer with supporting [[wikilinks]]
5) (Optional) Save the answer to wiki/syntheses/<slug>.md to reuse as material for later queries
/wiki-lint [--fix]Checks are split into the groups below; invoking with no argument runs them all in sequence
(auxiliary groups like synthesis·trail·timeline also run, and staleness is shown for reference only):
graph — graph topology and reference consistency
· structure : broken wikilinks, orphan hubs, missing entity candidates (and, under WIKI_LANG=ko, Korean entities with English filenames)
· orphans : bidirectional source↔entity reference match (sources frontmatter ↔ source ## Connections)
· clusters : Leiden community health codes [A]–[G] + health-trend log (isolated hubs, unnamed groups, fragile bridges, etc.)
· internal-refs : whether published content links internal build/guide files (.claude/·tools/·CLAUDE.md) — blocks self-references leaking into RAG
· raw-files : source page `source_file:` ↔ raw/ filename integrity (smart-quote folding/stripping; --fix repairs unambiguous matches)
hub — L2-2 hub page (entity·concept·timeline) status
· speakers : people cited ≥3 times across ≥3 distinct sources (speakers/quoted voices)
who lack their own entity page — stub candidates
(under WIKI_LANG=ko; English corpora use cit.A2 + count_mentions.py)
· suggestions : common broken links + frequent body nouns that have no page
(informational, no pass/fail impact)
· schema : required frontmatter fields for entities/·concepts/·timelines/ files
(common title·type·tags·last_updated; entity·concept add sources,
entity adds kind) + type matches the folder name
meta — meta-document conventions (bundle: integrity + drift + language + flat-path guard)
· CLAUDE.md anchor link and file path validity
· craft-skill chain integrity: .claude/layers/_manifest.json ↔ skills criteria.json/checks.py referential closure
· English section-header convention
· python tools/lint.py <flat-subcmd> recurrence prevention
overview — landscape-axis overview files (L2-3 cluster overview + L2-4 overview.md)
· Rubric metrics (W1·W2·W3·X2 / L2-4 adds D1·D2·D3·F1) · sections·frontmatter · Freshness
· narrative drift detection: if another domain's representative page is embedded in the body, advisory notice
(a case where the domain boundary was realigned but the body kept the old flow). Cross-references
declared as paired domains are auto-excluded — see the paired_with field in
graph/cluster_labels.json
· pass a cluster slug or 'aggregate' as the second argument to check only that file
contradiction — conflict-axis per-theme analysis files (wiki/contradictions/<theme>.md)
· frontmatter · four H2 sections · 1:1 theme↔analysis MD mapping
· pass a theme slug as the second argument to check only that file
source — L2-1 source page authoring convention (wiki/sources/<slug>.md)
· diagnose source-schema compliance: claim atomization · quote typing · evidence grading, etc.
· pass a source slug as the second argument to check only that file
Semantic checks (agent): mutually contradicting claims, stale information, empty knowledge gaps
Final result: lint-report.md
--fix behavior by group (only what the group supports actually runs):
| Invocation | What --fix does |
|------|-------------------|
| /wiki-lint --fix (= all) | Run all groups' safe auto-fixes in a batch. EDITOR rewrites and SoT JSON regeneration are **excluded** (require explicit invocation) |
| /wiki-lint graph structure --fix | Auto-add entities mentioned in the body to the source's `## Connections` to reconnect orphan hubs |
| /wiki-lint graph orphans --fix | Auto-backfill source `## Connections` → hub `sources:` frontmatter |
| /wiki-lint graph clusters --fix | Recompute graph data (`_graph.json`·`_clusters.json`) to the current wiki state |
| /wiki-lint hub schema --fix | Auto-fill `type`·`last_updated` in entity·concept·timeline frontmatter |
| /wiki-lint overview --fix | Reconcile cluster ↔ per-domain overview MD (create missing overviews, delete orphan overviews, with a pre-run confirmation prompt) |
| /wiki-lint overview <target> --fix | The above + a Claude EDITOR rewrite instruction block for that domain |
| /wiki-lint contradiction --fix | Reconcile theme ↔ per-theme analysis MD (create missing analyses, delete orphan analyses, with a pre-run confirmation prompt) + insert placeholders for missing H2 |
| /wiki-lint contradiction theme --fix | A Claude instruction block to regenerate the theme ↔ issue mapping SoT (`_contradictions_themes.json`) |
| Other groups/subcommands --fix | Unsupported (warns, then diagnoses only) |
The confirmation prompt can be bypassed with the `--yes` flag — use it in automated environments after pre-review.
New cluster labels are added manually to graph/cluster_labels.json after operator review (no auto-editing).
After --fix completes, tools/build.py runs in full (the empty per-domain overview skeletons get filled at this step).
/wiki-graphtools/build.py graph (runs the graph stage only)
· Parse every page and compute two kinds of connections (edges)
· explicit edges: [[wikilinks]] in the body
· inferred edges: pairs sharing 3+ common referenced pages
· Generate graph/_graph.json
· graph.html itself is a committed static shell — when opened directly in a browser the physics
simulation runs live to decide node placement. graph.html fetches its data as
JSON directly (_graph.json·_clusters.json·_pages.json); the reading-panel
bundle (_pages.json) is generated in the clusters stage
A full wiki rebuild is run automatically by /wiki-ingest · /wiki-lint --fix.
To run it directly: `python tools/build.py` — a 5-stage sequential pipeline:
graph → _graph.json
clusters → _clusters.json + source catalogs + automatic per-domain overview refresh
+ graph/_pages.json (the reading-panel bundle graph.html fetches)
(Leiden community detection; each document is assigned to the cluster of the hubs
it links to, by weighted vote; labels live in graph/cluster_labels.json)
contradictions → _contradictions.json (source DB collecting contradicting claims from source documents)
index → index.md + backlink index + source map
dependencies → _dependencies.json (dependency index to judge which documents lag behind updates)
Each stage can also run individually: `python tools/build.py <stage>`.
/wiki-news [cluster|keyword]1) Read the current wiki's topic composition (index.md, cluster meta) to generate search terms
· With a cluster specified: a query combining 3–5 representative hubs of that topic (English by default; Korean only under WIKI_LANG=ko)
· No argument: auto-iterate the top 5 clusters by document count
2) Collect the latest articles via web search → dedup against existing source titles
3) Summarize only new articles into a report and present them as ingest candidates
4) (Optional) Add the URLs of articles to ingest to the inbox queue (raw/_inbox.md)
5) `/wiki-ingest inbox` to fetch + absorb (HTML saved under raw/NewsScrap/, PDF under raw/PDF/)
/wiki-exportMerge only the wiki's synthesis and directory layers under wiki-export/ (for RAG)
· Root meta (overview · contradiction · index) copied 1:1
· Subfolders merged (per-domain overviews · contradiction analyses · timelines · query answers · associative trails)
· Entity/concept bodies are not generated — the graph holds the full text; index.md is a one-line + deep-link directory
· Sources carry only a one-line index instead of full text (all-sources-index.md) — originals live in the graph browser
· README.md — a 2-layer guide + upload budget guide + the deep-link convention to paste into the project instructions box
Push to GitHub to connect as Claude.ai Project Knowledge. Claude.ai loads knowledge in full
(no retrieval), so upload Core (~130K tok) first per the README's budget guide
/wiki-discover <seed | --random | --surprising>Seed exploration (<seed> or --random)
Choose a starting point:
· With a seed → start from that entity/concept
· --random → randomly pick a "mid-tier hub" with roughly 5–30 backlinks
(neither too famous nor too minor)
Explore:
· Read the seed page + the top 5 documents that reference it
· Find other pages those documents commonly point to
· Present 3–5 "unexpected connections" not directly linked to the seed
Bridge-hub ranking (--surprising)
tools/discover.py surprising
Multiply three criteria to score pages that "bridge topic clusters":
· shortest-path frequency : is the connection hard to make without passing through this page
· neighbor cluster diversity : how many different topics the neighbors span
· over-degree penalty : lower the score for pages that are already too famous
→ auto-present the top N "centers of unexpected connection" with no seed input
/wiki-trail create|follow|list <topic>create : explore pages related to the topic, build a 5–10 page "reading order" with
per-step commentary, and save it to wiki/trails/<slug>.md
follow : read an existing path in order with per-step commentary
list : list the trails under wiki/trails/
/wiki-timeline <entity> [year]1) Collect all documents referencing the given person/company and sort by publish date
2) Compose a flow summary in three parts:
· whole trajectory in 1 line (stage1 → stage2 → stage3 ...)
· per-stage summary (year range · key turning points, 2–3 sentences)
· current state in 1–2 sentences
3) Append year-grouped event groups and (optionally) save to wiki/timelines/<entity>.md
If you're weighing this against retrieval rather than against other wiki tools: RAG (Retrieval-Augmented Generation) retrieves source chunks per query and injects them into the answer context. This project instead takes the direction of structuring and accumulating the wiki in advance.
| RAG | LLM Wiki Newsroom | |
|---|---|---|
| Knowledge state | re-extracted per query | organized once and continuously updated |
| Retrieval unit | source chunk | structured wiki page |
| Cross-reference | none | wikilinks + backlink index |
| Contradiction handling | may surface at query time | flagged at ingest time + DB tracked |
| Accumulation effect | none | new sources enrich existing pages |
| Exploration | keyword search | graph traversal + associative trails (Memex) |
The scripts that work behind the slash commands. They run locally with no external API keys, and you can call them directly to run just part of the functionality.
| Script | What it does |
|---|---|
build.py | Rebuild the entire wiki — a 5-stage sequential pipeline: graph/visualization → clusters/catalogs/per-domain overviews → contradiction source DB extraction → index → dependency index. To run a single stage: python tools/build.py <stage> (graph / clusters / contradictions / index / dependencies) |
lint.py | Group checks: graph (page structure · document↔entity references · cluster health) / hub (quoted speakers · new-page candidates · L2-2 hub frontmatter) / meta (CLAUDE.md internal links · header convention · craft-skill chain integrity) / overview (landscape-axis overview file Rubric · Freshness) / contradiction (conflict-axis per-theme analysis) / source (L2-1 source page schema) / plus auxiliary groups synthesis·trail·timeline·staleness. Also suggests "new page candidates worth creating" at the end of the report. python tools/lint.py graph orphans --fix auto-connects orphan documents; python tools/lint.py overview <target> --fix produces a single per-domain overview skeleton + rewrite instructions |
query.py | Search/traversal CLI — graph subcommand for graph traversal (path A B·explain N·neighbors N), qmd subcommand for body search (hybrid·search·vsearch). --budget to reduce response size and --json for machine parsing |
discover.py | Rank pages that bridge clusters (surprising) — combine shortest-path frequency · neighbor cluster diversity · over-degree penalty to auto-surface "centers of unexpected connection" |
A small knowledge base mapping the debate over what "open source" should mean for AI (the example corpus shipped in this repo — kept deliberately small so the whole thing is readable end-to-end):
| Item | Count |
|---|---|
| Source pages | 4 |
| Entity pages | 5 (companies · institutions) |
| Concept pages | 6 (technology · licensing · policy) |
| Per-domain overviews (Cluster Overview) | 3 (covering the whole open-source-AI debate) |
| Per-theme contradiction analyses | 2 |
| Knowledge graph | 15 nodes, 80 edges (many with relation labels) |
| Backlink index | 11 targets |
| Contradiction tracking | 1 item (classified into 2 themes) |
Main topics (3 domain clusters): the open-source AI definition, open weights, and licensing · open-washing — plus 2 contradiction themes cutting across them. (Associative trails and timelines ship empty here; one example synthesis is included — generate more with /wiki-query, /wiki-trail, and /wiki-timeline once you've added sources.)
| Type | Filename | Examples |
|---|---|---|
| Entity (company · institution · person) | English TitleCase | Meta.md, HuggingFace.md, Microsoft.md, OpenAI.md |
| English abbreviation is the industry standard | English | AWS.md, CNCF.md, MIT.md |
| Concept | English TitleCase | AgenticAI.md, RAG.md |
| Non-Latin-script entity (optional, capability retained) | Native script | 신한은행.md (Shinhan Bank — native-script filenames are supported when a name has no standard Latin form) |
The python tools/query.py qmd ... subcommand and semantic search in Obsidian and Claude Code are powered by a local search engine called QMD. The embedding and reranking models all run on-device; no data leaves to an external service. If you'll only use graph traversal (the graph subcommand), you can skip this.
1) Install QMD + initial indexing
npm install -g @tobilu/qmd
qmd collection add "$(pwd)/wiki" --name wiki # register the wiki folder as one collection
qmd embed # generate embeddings (auto-downloads the GGUF model)
The config file is created at ~/.config/qmd/index.yml. This project configures it to exclude from search the root meta files (overview.md, index.md, contradiction.md, etc.) and the auto-generated catalogs (sources/_catalog*.md) — focusing only on source/entity/concept pages with real content to reduce noise.
collections:
wiki:
path: /path/to/llm-wiki-newsroom/wiki
pattern: "**/*.md"
ignore:
- "*.md"
- "sources/_*.md"
2) Use in Claude Code
Place a .mcp.json at the project root registering QMD as an MCP server, and Claude Code automatically invokes semantic search when you run /wiki-query. This file contains local paths, so it's in .gitignore and managed per personal environment.
3) Use in Obsidian
In Obsidian, open this project's wiki/ folder as a vault — it must match the collection path above for search results to link to the correct pages.
It's not in the official community store, so install obsidian-qmd via BRAT (a beta-plugin installer). After installing, apply two customizations for a smoother local-search experience at once with python tools/patch_obsidian_qmd.py:
title: value instead of the chunk heading (## Summary, etc.)The patch script is idempotent — just re-run it once each time BRAT updates the plugin.
On Windows, after installing Node.js, running the patch script above prepares the Node runtime the plugin needs and also prints the path to put in the plugin settings' Executable Path field. Paste the printed path into that field and search will work.
raw/./wiki-ingest inbox (one-time setup: .claude/operations/mobile-inbox-setup.md)./wiki-discover periodically keeps surfacing connections hidden in the wiki./wiki-trail create <topic> to build a knowledge path for a topic of interest and share it with your team.wiki/syntheses/ accumulates them like ingested sources.wiki/contradiction.md and wiki/contradictions/<theme>.md) lets you track how the tension axes of the wiki's whole discourse evolve.MIT License — see LICENSE.
.claude/
agents/
columnist.md
copyeditor.md
desk.md
editor-in-chief.md
README.md
reporter.md
commands/
README.md
wiki-discover.md
wiki-export.md
wiki-graph.md
wiki-ingest.md
wiki-lint.md
wiki-news.md
wiki-query.md
wiki-timeline.md
wiki-trail.md
hooks/
check_bullet_depth.py
dispatch.py
dispatch.sh
lint_chain_guard.py
lint-chain-guard.sh
layers/
_manifest.json
contradiction.md
hub.md
overview.md
README.md
source.md
synthesis.md
timeline.md
trail.md
operations/
.gitkeep
bundle-reground-runbook.md
codebase-audit-runbook.md
gap-detection-rollout.md
graph-hosting-setup.md
mobile-inbox-setup.md
proposal-validation-runbook.md
staleness-reground-runbook.md
policies/
directory-layout.md
index-log-format.md
language.md
naming.md
platform.md
README.md
settings.json
skills/
consulting-writing/
checks.py
criteria.json
SKILL.md
encyclopedia-writing/
checks.py
criteria.json
SKILL.md
guideline-writing/
checks.py
criteria.json
SKILL.md
journalism-writing/
checks.py
criteria.json
SKILL.md
ponytail-coding/
SKILL.md
scholarly-citation/
checks.py
criteria.json
SKILL.md
.editorconfig
.gitattributes
.gitignore
AGENTS.md
CLAUDE.md
docs/
_config.yml
_data/
faq_ko.yml
faq.yml
_includes/
head-custom.html
_layouts/
default.html
assets/
css/
style.scss
faq.md
index.md
knowledge-factory.md
knowledge-graph.png
ko/
faq.md
index.md
knowledge-factory.md
llms.txt
GEMINI.md
graph/
_clusters.json
_dependencies.json
_graph.json
_overlays.json
.gitkeep
cluster_labels.json
graph.html
LICENSE
log.md
raw/
_archive.md
_inbox.md
.gitkeep
README.md
requirements.txt
tests/
conftest.py
test_agent_tool_permissions.py
test_briefing_mailer.py
test_claim_id_stability.py
test_crawl.py
test_defect_loop.py
test_fetch_inbox_dedup.py
test_guideline_craft_split.py
test_hook_launch_anchor.py
test_hooks_dispatch.py
test_lib.py
test_lint_regressions.py
test_mine_feedback.py
test_net.py
test_roster_completeness.py
test_source_orphans.py
test_staleness.py
test_suggest_links.py
tools/
_briefing/
__init__.py
mailer.py
render.py
_build/
__init__.py
clusters.py
contradictions.py
dependencies.py
graph.py
index.py
overlays.py
pages.py
_contradiction_rules.json
_defect-log.jsonl
_discover/
__init__.py
surprising.py
_export/
__init__.py
site.py
_ingest/
__init__.py
fetch_article.py
fetch_inbox.py
prefilter_ingest.py
suggest_links.py
suggest_tags.py
_lib.py
_lint/
__init__.py
_advisory_common.py
_editor_date.py
_hub_common.py
_manifest_counts.py
_schema_common.py
cited_speakers.py
cluster_drift.py
contradiction_theme.py
contradiction.py
graph_clusters.py
graph_gaps.py
hub_body.py
hub_demotion.py
hub_promotion.py
hub_schema.py
hub_timeline.py
hub_voice.py
internal_refs.py
link_candidates.py
meta_schema.py
overview.py
raw_file_refs.py
source_orphans.py
source.py
staleness.py
structure.py
suggestions.py
synthesis.py
text_candidates.py
timeline.py
trail.py
_net.py
_news/
__init__.py
crawl.py
domains.py
gap_queries.py
normalize.py
_query/
__init__.py
graph.py
qmd.py
_review.py
build.py
count_mentions.py
discover.py
export.py
lint.py
list_week_sources.py
log_defect.py
mine_failures.py
mine_feedback.py
patch_obsidian_qmd.py
query.py
regression_set.json
send_briefing.py
show_workflow.py
wiki/
_backlinks.json
concepts/
FineTuning.md
ModelLicensing.md
OpenSourceAI.md
OpenWashing.md
OpenWeights.md
TrainingData.md
contradiction.md
contradictions/
_contradictions_themes.json
_contradictions.json
open-training-data-requirement.md
other-fragmentary.md
entities/
DeepSeek.md
FreeSoftwareFoundation.md
Meta.md
Mozilla.md
OpenSourceInitiative.md
index.md
overview.md
overviews/
licensing-open-washing.md
open-source-ai-definition.md
open-weights.md
sources/
_catalog-licensing-open-washing.md
_catalog-open-source-ai-definition.md
_catalog-open-weights.md
_catalog.md
_source_map.json
case-against-osaid.md
mozilla-celebrates-osaid.md
open-source-ai-models-how-open.md
osi-open-source-ai-definition.md
syntheses/
.gitkeep
open-source-ai-every-camp-standard.md
timelines/
.gitkeep
trails/
.gitkeep© 2026 Flowy · Free and open source
Built for Claude Code · Not affiliated with Anthropic