Skip to content
Agent Memory
Skill

/wiki-lint

Use when auditing a wiki for health issues — contradictions between pages, orphan pages, broken cross-references, stale claims, missing pages, or coverage gaps. Run after every 5-10 ingests.

BOOST
From plugin
wiki-skills
1897 skills
Install
$ npx -y skills add kfchou/wiki-skills --skill wiki-lint --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/wiki-lint

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when auditing a wiki for health issues — contradictions between pages, orphan pages, broken cross-references, stale claims, missing pages, or coverage gaps. Run after every 5-10 ingests.

SKILL.md

wiki-lint.SKILL.md
name: wiki-lint
description: Use when auditing a wiki for health issues — contradictions between pages, orphan pages, broken cross-references, stale claims, missing pages, or coverage gaps. Run after every 5-10 ingests.

Wiki Lint

Audit the wiki as a four-phase pipeline that keeps page bodies out of the main context: a deterministic script (Phase 1) and per-cluster subagents (Phase 2) do the heavy reading; the main thread only assembles findings. Produce a categorized report, offer concrete fixes, log the operation.

Pre-condition

Find `SCHEMA.md` (search from cwd upward, or `~/wikis/`). If not found, tell the user to run `wiki-init` first. Read it to get wiki root path and conventions.

**Link style.** Read `link_style:` from `SCHEMA.md`. If the field is missing or `<wiki-root>/config/link-style.md` does not exist, default to `obsidian` (`[[slug]]`). Otherwise, read `<wiki-root>/config/link-style.md`. All link scanning below uses the `## Parse` rule from that file (which may match more than one form). The lint report you write is itself a wiki page, so its cross-references use the `## Emit` rule.

Why the pipeline

The old whole-wiki pass loaded every page body into one context — it nuked the context window as the wiki grew. Instead:

  • **Phase 1** runs `bin/lint-mechanical.py`, which computes the deterministic checks (graph

and string properties) with **no LLM and no bodies in your context**, and emits the tag-cluster list for Phase 2.

  • **Phase 2** dispatches one subagent per tag cluster. Each reads only its cluster's pages

(bodies live in the *subagent's* context, discarded on return) and reports the cross-page and body-level findings. You aggregate compact findings, never bodies.

Phase 1 checks are whole-wiki exhaustive. Phase 2 checks are **cluster-scoped**: a page that shares no tag with any other page is not body-checked (approach A's accepted recall limit — see *Phase 2*). Run lint periodically (every 5–10 ingests) so the scoped passes accumulate coverage.

Process

Phase 0 — regenerate the index

`python bin/generate-index.py` so the index reflects current page frontmatter.

Phase 1 — deterministic checks (script, no LLM)

Run `python bin/lint-mechanical.py` and parse its JSON. It returns:

{ "findings": { "broken_links": [...], "missing_frontmatter": [...], "orphans": [...],
                "slug_collisions": [...], "stale_date": [...], "missing_concept": [...] },
  "clusters": [ {"pages": ["slug-a", "slug-b"], "split": false}, ... ] }

These map to report sections directly:

  • **🔴 Broken links** — `broken_links` (`{page, link}`).
  • **🔴 Missing frontmatter** — `missing_frontmatter` (`{page, missing:[...]}`). `overview.md`

lives in `wiki/`, not `wiki/pages/`, and is exempt.

  • **🟡 Orphan pages** — `orphans` (`{page}`): zero inbound `[[slug]]` links.
  • **🟡 Colliding slugs** — `slug_collisions` (`{token, pages:[...]}`): a bare slug clashing

with qualified ones (`mercury` vs `mercury-element`). Flag the pair; never auto-rename — renaming is a `wiki-merge` split.

  • **🟡 Stale claims** — `stale_date` (`{page}`): not updated in 90 days and the body still

says `current`/`latest`/`recent`/`state-of-the-art` or names a year ≥2 years old.

  • **🔵 Missing concept pages** — `missing_concept` (`{slug, count}`): a `[[slug]]` referenced

3+ times with no page.

Do **not** re-derive these by reading pages yourself — the script is the source of truth.

Phase 2 — cluster subagents (contradictions + body-level checks)

For each cluster in the Phase 1 `clusters` list, dispatch a subagent (parallel fan-out, batched to bound concurrency). Give it the cluster's page paths and this instruction:

> Read these pages. Report, **within these pages only**, as a compact list — each finding as > `{type, pages:[slug,...], detail}`, or `clean` if none: > - `contradiction` — two pages describe the same entity with conflicting dates, counts, > names, or relationships. > - `missing-xref` — two pages clearly discuss the same entity but don't `[[link]]` each > other. > - `merge-candidate` — two pages describe the *same concept under different slugs* > (near-duplicate titles / near-identical Description sections). > - `chronological-section` — a page body carries date-stamped journal headers (`## [Month]`, > `**[Month] N update`) that should be integrated in-place. > - `addable-line-range` — a footnote citing a *text-addressable* raw file (markdown / > plaintext / code / cached HTML) with no `L<start>-<end>` token. Exempt: PDFs, transcripts, > live URLs — never flag those. > Return findings only — no page bodies.

**Aggregate** all subagent findings in the main thread and **dedup** on `(type, sorted(pages), detail-entity)` — a page in K tags sits in K clusters, so the same finding can surface more than once.

**Coverage note:** because subagents only see their cluster, body-level findings are cluster-scoped. Pages sharing no tag with any other page are not body-checked. This is the accepted limit of tag-cluster scoping; Phase 1 (graph/string checks) still covers every page.

Phase 3 — coverage gaps, then assemble the report

First, the one body-level check that needs no page bodies: read `wiki/overview.md` and flag **🔵 Coverage gaps** — open questions that a web search or a new ingest could answer.

Then write `wiki/pages/lint-<today>.md` (do not ask permission — always write this), merging Phase 1 findings, the deduped Phase 2 findings, and the coverage gaps. The template below shows slug references in obsidian form for readability; in the actual report you write, every slug reference must follow the `## Emit` rule from `config/link-style.md`:

---
title: Lint Report <today>
category: Maintenance
summary: <N> errors, <N> warnings, <N> info
tags: [lint, maintenance]
sources: []
created: <today>
updated: <today>
---

# Lint Report — <today>

## Summary
- 🔴 Errors: N
- 🟡 Warnings: N
- 🔵 Info: N
<!-- note here if any cluste
Read more
Ships withwiki-skills

A Claude Code plugin implementing Karpathy's LLM Wiki pattern — a persistent, compounding knowledge base maintained by your LLM.

Get the whole plugin
Stats
189
Stars
29
Forks
Maintained
Maintenance
Python
Language
MIT
License
3mo ago
Last commit
6mo ago
Created
2d ago
Added

Repo: kfchou/wiki-skills

Other skills on wiki-skills.