LLM Wiki
lewislulu/llm-wiki-skill
Build and maintain a Karpathy-style LLM knowledge base — a self-compiling Obsidian markdown wiki where an Agent ingests raw sources, compiles cross-linked concept/entity/summary pages, answers…
Audit wiki health: broken links, orphans, contradictions, stale content, lifecycle and tag issues.
$ npx skills add Ar9av/obsidian-wiki --skill wiki-lint -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Ar9av/obsidian-wiki wiki-lint --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Ar9av/obsidian-wiki.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.skills/wiki-lint .claude/skills/wiki-lint && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "wiki-lint" agent skill from https://github.com/Ar9av/obsidian-wiki/tree/main/.skills/wiki-lint into .claude/skills/wiki-lint/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wiki-lint", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Ar9av/obsidian-wiki/tree/main/.skills/wiki-lintType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Ar9av/obsidian-wiki --skill wiki-lint -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Ar9av/obsidian-wiki wiki-lint --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Ar9av/obsidian-wiki.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.skills/wiki-lint .agents/skills/wiki-lint && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "wiki-lint" agent skill from https://github.com/Ar9av/obsidian-wiki/tree/main/.skills/wiki-lint into .agents/skills/wiki-lint/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wiki-lint", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Ar9av/obsidian-wiki --skill wiki-lint -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Ar9av/obsidian-wiki wiki-lint --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Ar9av/obsidian-wiki.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.skills/wiki-lint .cursor/skills/wiki-lint && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "wiki-lint" agent skill from https://github.com/Ar9av/obsidian-wiki/tree/main/.skills/wiki-lint into .cursor/skills/wiki-lint/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wiki-lint", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Ar9av/obsidian-wiki.git --path .skills/wiki-lint--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Ar9av/obsidian-wiki --skill wiki-lint -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Ar9av/obsidian-wiki wiki-lint --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Ar9av/obsidian-wiki.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.skills/wiki-lint .gemini/skills/wiki-lint && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "wiki-lint" agent skill from https://github.com/Ar9av/obsidian-wiki/tree/main/.skills/wiki-lint into .gemini/skills/wiki-lint/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wiki-lint", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Ar9av/obsidian-wiki wiki-lintInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Ar9av/obsidian-wiki --skill wiki-lint -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Ar9av/obsidian-wiki.git skills-src && mkdir -p .github/skills && cp -r skills-src/.skills/wiki-lint .github/skills/wiki-lint && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "wiki-lint" agent skill from https://github.com/Ar9av/obsidian-wiki/tree/main/.skills/wiki-lint into .github/skills/wiki-lint/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wiki-lint", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Ar9av/obsidian-wiki --skill wiki-lint -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Ar9av/obsidian-wiki wiki-lint --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Ar9av/obsidian-wiki.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.skills/wiki-lint .opencode/skills/wiki-lint && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "wiki-lint" agent skill from https://github.com/Ar9av/obsidian-wiki/tree/main/.skills/wiki-lint into .opencode/skills/wiki-lint/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wiki-lint", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
wiki-lintAudit wiki health: broken links, orphans, contradictions, stale content, lifecycle and tag issues.
Wiki Lint is an agent skill from Ar9av/obsidian-wiki. Audit wiki health: broken links, orphans, contradictions, stale content, lifecycle and tag issues. Use for maintenance or health checks. Default is report-only; use wiki-dedup for page-identity merges.
Its SKILL.md is about 9.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Knowledge Management, covering LLM wikis. It works with Obsidian. The repository describes itself as: Framework for AI agents to build and maintain a digital brain through Obsidian wiki | Memory System for Agents. The licence is MIT.
12 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 4a0630b. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
gitrgFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use git, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Wiki Lint loads about 9.1k tokens when it runs. Until then it costs about 53 tokens; SKILL.md has 3,952 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
line `@name` override → walk up CWD for `.env` → global config → prompt setup). This gives `OBSIDIAN_VAULT_PATH` plus anAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Ar9av/obsidian-wiki at commit 4a0630b, republished under its MIT licence (© Ar9av). 3,952 words, ~9,115 tokens.
.claude/skills/wiki-lint/SKILL.md (or your agent's skills folder).You are performing a health check on an Obsidian wiki. Your goal is to find and fix structural issues that degrade the wiki's value over time.
Before scanning anything: follow the Retrieval Primitives table in llm-wiki/SKILL.md. Prefer frontmatter-scoped greps and section-anchored reads over full-page reads. On a large vault, blindly reading every page to lint it is exactly what this framework is built to avoid.
Writing profile: Before drafting or rewriting natural-language Markdown, read and apply the Writing Profile Resolution section in llm-wiki/SKILL.md. Framework schema, provenance, safety, and operation-specific requirements take precedence.
Apply WRITING.md preferences only to generated consolidation reports; deterministic findings and fixes keep their existing formats.
llm-wiki/SKILL.md (inline @name override → walk up CWD for .env → global config → prompt setup). This gives OBSIDIAN_VAULT_PATH plus any OBSIDIAN_ALLOWED_LIFECYCLES, OBSIDIAN_ALLOWED_RELATIONSHIP_TYPES, OBSIDIAN_REQUIRED_TRUST_FIELDS, and OBSIDIAN_SCHEMA_SOURCE values.$OBSIDIAN_VAULT_PATH/AGENTS.md exists, read it before interpreting any schema. Owner rules override framework defaults.index.md for the full page inventorylog.md for recent activity contextPass the effective schema to deterministic checks explicitly. For example, add each owner extension with --allow-lifecycle / --allow-relationship-type, replace trust requiredness with repeatable --required-trust-field, and identify the authority with --schema-source "$OBSIDIAN_VAULT_PATH/AGENTS.md". The JSON report's schema block must match the schema you formed before findings are accepted.
Schema precedence is CLI flags > resolved environment/config values > framework defaults; lifecycle and relationship extensions remain additive. Strip every override before use. An explicitly configured empty or whitespace-only value—and any empty comma-separated list entry—fails closed; never treat it as a valid lifecycle, relationship type, required field, or authority locator. Remove the variable instead when defaults are intended.
When obsidian-wiki is on PATH, prefer obsidian-wiki lint "$OBSIDIAN_VAULT_PATH" --json (with the same schema override flags as above) and fold the JSON findings into the health report. If the CLI is unavailable, keep the grep-based checks below — do not require the binary.
If the JSON report includes findings.snapshot_mismatch, list those pages in the report. Missing or drifted snapshots: is not missing required frontmatter (section 3 still covers only title, category, tags, sources, created, updated). Do not rewrite sources: to fix snapshot drift. Run obsidian-wiki snapshots apply --from-json <lint.json> (dry-run), show the preview, and pass --apply only after explicit user confirmation. Apply writes quoted "[[_raw/_archived/stem|stem]]" list items (native Property links with display text). wiki-lint --consolidate still does not apply this finding.
Run these checks in order. Report findings as you go.
Scope: skip _archives/, _raw/, _readouts/, and .obsidian/ in every check. These hold frozen snapshots, unprocessed staging drafts, and derived readouts (saved by wiki-narrate) — they are not knowledge-graph pages, so orphan, frontmatter, and link checks don't apply to them.
Find pages with zero incoming wikilinks. These are knowledge islands that nothing connects to.
How to check:
.md files in the vault[[page-name]] referencesindex.md and log.md) are orphansHow to fix:
Find [[wikilinks]] that point to pages that don't exist.
How to check:
\[\[.*?\]\] across all pages| (alias) or # (heading/block anchor), and strip a trailing backslash left by an escaped \| inside a table cell.png, .jpg, .gif, .svg, .webp, .pdf, .canvas, .base, audio and video): it's an embed, not a page link, and has no entry in the .md inventory this check compares against[[Node.js]], [[Next.js]], and [[v1.2 release notes]] are page links whose names happen to contain a dot, and dropping them would both miss real broken links and make the target page look like an orphan.md suffix from what remains, then check if a corresponding .md file existsHow to fix:
Every page should have: title, category, tags, sources, created, updated.
How to check:
^--- at file heads) instead of reading every page in fullHow to fix:
Every page should have a summary: frontmatter field — 1–2 sentences, ≤200 chars. This is what cheap retrieval (e.g. wiki-query's index-only mode) reads to avoid opening page bodies.
How to check:
^summary: across the vaultHow to fix:
Pages whose updated timestamp is old relative to their sources.
How to check:
updated timestamps to source file modification timesClaims that conflict across pages.
How to check:
How to fix:
Verify index.md matches the actual page inventory.
How to check:
index.md to actual files on diskindex.md still match page contentCheck whether pages are being honest about how much of their content is inferred vs extracted. See the Provenance Markers section in llm-wiki for the convention.
How to check:
provenance: block or any ^[inferred]/^[ambiguous] markers, count sentences/bullets and how many end with each markerextracted, inferred, ambiguous)synthesis/sources: in frontmatter: flag as "unsourced synthesis" — the page is making connections but has nothing to citeprovenance: frontmatter block, flag it when any field is more than 0.20 off from the recomputed valueprovenance: frontmatter and no markers — treated as fully extracted by conventionHow to fix:
synthesis/ pagesources: to frontmatter or clearly label the page as synthesisprovenance: frontmatter to match the recomputed valuesChecks whether pages that share a tag are actually linked to each other. Tags imply a topic cluster; if those pages don't reference each other, the cluster is fragmented — knowledge islands that should be woven together.
How to check:
n = count of pages with this tagactual_links = count of wikilinks between any two pages in this tag group (check both directions)cohesion = actual_links / (n × (n−1) / 2)How to fix:
cross-linker skill targeted at the fragmented tag — it will surface and insert the missing linksChecks that visibility/ tags are applied correctly and aren't silently missing where they matter.
How to check:
password, api_key, secret, token, ssn, email:, phone: followed by an actual value (not a field description). If a page matches and lacks visibility/pii or visibility/internal, flag it as a likely mis-classification.visibility/pii without sources:: A page tagged visibility/pii should always have a sources: frontmatter field — if there's no provenance, there's no way to verify the classification. Flag any visibility/pii page missing sources:.visibility/ tags are system tags and must not appear in _meta/taxonomy.md. If found there, flag as misconfigured — they'd be counted toward the 5-tag limit on pages that include them.How to fix:
visibility/pii (or visibility/internal if it's team-context rather than personal data) to the page's frontmatter tagssources:: add provenance or escalate to the user — don't auto-fillvisibility/ entries from _meta/taxonomy.mdFind pages in misc/ that have accumulated enough project affinity to be promoted.
How to check:
$OBSIDIAN_VAULT_PATH/misc/*.mdaffinity frontmatter fieldHow to fix:
cross-linker skill first if affinity scores look stale (e.g., affinity: {} on a page with many wikilinks)projects/<project-name>/references/ (or another appropriate category), update its category frontmatter, remove promotion_status, and grep the vault for backlinks to update themEnforces the confidence + lifecycle frontmatter schema (see llm-wiki/SKILL.md, Confidence and Lifecycle section).
Two modes:
--check (default, read-only) — reports errors and warnings--consolidate — may apply separately approved structural maintenance, but never rewrites base_confidenceConfidence is a semantic judgment. A deterministic tool cannot infer independent evidence lineages or whole-page claim coverage from source strings alone. Confidence automation therefore validates an explicitly approved manual trust ledger; it never substitutes URL counting for review.
lifecycle enum validationHow to check: Grep frontmatter for ^lifecycle: across all pages. Flag any value outside the effective lifecycle set (framework default: {draft, reviewed, verified, disputed, archived}).
How to fix: n/a (only a human should set lifecycle state)
base_confidence rangeHow to check: Grep frontmatter for ^base_confidence: across all pages. Flag any present value outside [0.0, 1.0]; flag absence only when the effective owner schema requires the field.
How to fix: n/a (wrong value means the skill computed it wrong — surface for manual correction)
Staleness is never stored — it is computed at read time: is_stale = (today − updated) > 90 days.
How to check: For each page, read updated: from frontmatter and compute is_stale. If stale, also check lifecycle:. Report:
lifecycle: verified with a louder annotation (these are the most dangerous — high-trust pages that may be wrong)How to fix: --fix does not rewrite lifecycle. Staleness clears automatically when a re-ingest bumps updated.
The lifecycle enum is a state machine, not a free-form label. obsidian-wiki lint reports illegal_lifecycle_transitions by comparing each page's current lifecycle against the value recorded in _meta/trust-ledger.json at its last review.
Flagged: any state falling back to draft (only ingest sets draft), and any exit from archived (terminal — a restore is a deliberate human delete-and-recreate).
Not flagged: draft → verified. Ledger snapshots are sparse, so a legitimate intermediate reviewed may have happened between two reviews; flagging it would fire on valid history.
Warns by default; fails under --strict-trust. Pages whose ledger entry predates the lifecycle field have no baseline and are skipped silently.
How to fix: n/a — a page that moved along a forbidden edge means either a skill wrote lifecycle when it shouldn't have, or a human transition needs recording. Surface for human resolution.
How to check: For each page with superseded_by: "[[target]]":
archived (no circular or chained supersession)lifecycle != archived while superseded_by is set (inconsistent state)How to fix: n/a — flag for human resolution
How to check: Run the deterministic ledger validator first:
obsidian-wiki trust-check "$OBSIDIAN_VAULT_PATH" --strict --json --prettyUse --strict for CI and scheduled gates: stale, unreviewed, or missing-page
warnings then return nonzero. Without --strict, trust-check remains a
read-only reporting command and returns nonzero only for hard ledger errors or
score mismatches.
The approved ledger lives at _meta/trust-ledger.json. Each entry records the human-reviewed score plus a SHA-256 fingerprint of material page content and evidence metadata. The fingerprint excludes volatile bookkeeping (updated, base_confidence, and lifecycle transition fields), so timestamp-only edits do not reopen review.
Interpret results as follows:
reviewed — current material fingerprint and stored score both match the approved review; do not recompute from source strings.stale — body, summary, sources, provenance, tags, or relationships changed; perform a new manual lineage + claim-coverage review.unreviewed — page has no approved ledger entry; manual review is required.score_mismatches — material content still matches, but stored base_confidence differs from the approved value; fail the lint.errors — malformed/missing ledger data; fail the lint.For a separately approved full-vault review, record the accepted state explicitly:
obsidian-wiki trust-record "$OBSIDIAN_VAULT_PATH" \
--all --reviewed-at "<ISO-8601 timestamp>" --approved --json --prettyAfter a separately approved review of only specific stale/unreviewed pages, update only those entries:
obsidian-wiki trust-record "$OBSIDIAN_VAULT_PATH" \
--page "concepts/example.md" --page "skills/example.md" \
--reviewed-at "<ISO-8601 timestamp>" --approved --json --pretty--approved means a human approved every score being recorded. It is a workflow
assertion, not a cryptographic signature: keep _meta/trust-ledger.json under
version control and require human diff review before merging ledger changes.
--all is valid only after a full-vault review; use repeatable --page for
partial reviews so unrelated stale pages remain open. Never run trust-record
merely to silence warnings.
Manual recomputation protocol for stale/unreviewed pages:
llm-wiki buckets.raise, keep, lower, or repair first; require approval before changing base_confidence or refreshing the ledger.How to fix: There is no automatic confidence fix. Apply only an explicitly approved exact patch, verify its scope, then refresh only the reviewed ledger state. --consolidate must never rewrite base_confidence.
Under framework defaults, every non-reserved content page must contain a
finite base_confidence in [0.0, 1.0] and a documented lifecycle value.
An owner schema may relax either field; present values remain validated.
Missing or malformed trust fields, malformed ledger data, and a missing required
ledger are hard errors. New pages with valid trust fields but no approved ledger
entry are unreviewed; material changes to approved pages are stale.
Add to the Wiki Health Report:
### Confidence/Lifecycle Issues (N found)
- `concepts/foo.md` — missing `lifecycle` field (warning: Phase 1)
- `entities/bar.md` — `lifecycle: stalestate` is not a valid enum value
- `concepts/scaling.md` — `base_confidence: 1.4` is out of range [0.0, 1.0]
- `synthesis/old-analysis.md` — STALE (last updated 2025-10-01, 182 days ago) lifecycle=verified ⚠️ HIGH PRIORITY
- `concepts/outdated.md` — STALE (last updated 2025-11-15, 137 days ago) lifecycle=draft
- `entities/tool-v1.md` — `superseded_by: [[entities/tool-v2]]` but lifecycle=draft (expected archived)
- `concepts/drift-example.md` — confidence review stale: material fingerprint changed; manual lineage + coverage review required
- `entities/mismatch.md` — confidence mismatch: stored=0.80, approved=0.59Append to the LINT log entry:
- [TIMESTAMP] LINT ... lifecycle_issues=NValidate relationships: frontmatter blocks. Skip pages that have no relationships: block — the field is optional.
Framework-default types: extends, implements, contradicts, derived_from, uses, replaces, related_to. Validate against the effective set after applying owner extensions.
How to check:
^relationships: across all vault pagesrelationships: block, read its frontmatter (not the full page body)type: value not in the allowed set above[[ and ]] from the target: string, normalize (lowercase, spaces→hyphens, strip .md), and check whether a .md file at that path exists in the vault. Flag unresolved targets.
Before normalizing, drop everything from the first | (alias) or # (heading/block anchor): a pipe-aliased or heading-anchored target is not broken just because the literal bracket contents don't match a filename.How to fix:
related_to.Output additions:
### Typed Relationship Issues (N found)
- `concepts/foo.md` — relationships[1]: type "contradication" is not an allowed type (did you mean "contradicts"?)
- `concepts/bar.md` — relationships[0]: target "[[skills/nonexistent-skill]]" resolves to no page in vault
- `entities/baz.md` — relationships[2]: self-reference (target resolves to this page's own id)Append to the LINT log entry:
... relationship_issues=NValidate valid_from / valid_until / superseded_by frontmatter. All three are optional — skip pages that carry none of them.
created/updated are ingestion time; these three are event time, when the claim itself was true. A page whose valid_until has passed is historical, not wrong: it stays in the vault and in the graph, and only drops out of default retrieval.
How to check:
^valid_from:, ^valid_until:, ^superseded_by: across all vault pagesYYYY-MM-DD or a full ISO 8601 timestamp. Flag anything else.valid_until precedes valid_from[[/]] from superseded_by, drop everything from the first | or #, strip .md, normalize, and check the page exists. Flag unresolved targets and self-references.obsidian-wiki lint reports all three as temporal_errors (dates, windows) and superseded_dangling (successors). A bracketed dangling successor also shows up in broken_links.
Why the dates fail rather than warn: retrieval treats an unparseable window as current, so an unreported typo lets a stale claim answer as fact — the exact failure the fields exist to prevent.
How to fix:
YYYY-MM-DD; if the real date is unknown, remove the field rather than guessingOutput additions:
### Event-Time Issues (N found)
- `references/gateway-nginx.md` — valid_until (2026-04-01) precedes valid_from (2026-05-01)
- `references/old-limits.md` — valid_until "soon" is not a date
- `references/legacy-auth.md` — superseded_by "[[oauth-rollout]]" resolves to no page in vaultAppend to the LINT log entry:
... temporal_issues=NIdentify high-value synthesis opportunities the wiki is missing — concept pairs that co-occur across many pages but have no synthesis/ page connecting them.
How to check:
synthesis/ — collect the concept pairs each one already covers (from its [[wikilinks]] or title)concepts/ and entities/rg -l --glob '*.md' "\[\[ConceptA\]\]" "$OBSIDIAN_VAULT_PATH" > /tmp/a.txt
rg -l --glob '*.md' "\[\[ConceptB\]\]" "$OBSIDIAN_VAULT_PATH" > /tmp/b.txt
comm -12 <(sort /tmp/a.txt) <(sort /tmp/b.txt) | wc -lHow to fix:
/wiki-synthesize to automatically discover and fill the top gapsReport findings as a structured list:
## Wiki Health Report
### Orphaned Pages (N found)
- `concepts/foo.md` — no incoming links
### Broken Wikilinks (N found)
- `entities/bar.md:15` — links to [[nonexistent-page]]
### Missing Frontmatter (N found)
- `skills/baz.md` — missing: tags, sources
### Stale Content (N found)
- `references/paper-x.md` — source modified 2024-03-10, page last updated 2024-01-05
### Contradictions (N found)
- `concepts/scaling.md` claims "X" but `synthesis/efficiency.md` claims "not X"
### Index Issues (N found)
- `concepts/new-page.md` exists on disk but not in index.md
### Missing Summary (N found — soft)
- `concepts/foo.md` — no `summary:` field
- `entities/bar.md` — summary exceeds 200 chars
### Provenance Issues (N found)
- `concepts/scaling.md` — AMBIGUOUS > 15%: 22% of claims are ambiguous (re-source or move to synthesis/)
- `entities/some-tool.md` — drift: frontmatter says inferred=0.10, recomputed=0.45
- `concepts/transformers.md` — hub page (31 incoming links) with INFERRED=28%: errors here propagate widely
- `synthesis/speculation.md` — unsourced synthesis: no `sources:` field, 55% inferred
### Fragmented Tag Clusters (N found)
- **#systems** — 7 pages, cohesion=0.06 ⚠️ — run cross-linker on this tag
- **#databases** — 5 pages, cohesion=0.10 ⚠️
### Visibility Issues (N found)
- `entities/user-records.md` — contains `email:` value pattern but no `visibility/pii` tag
- `concepts/auth-flow.md` — tagged `visibility/pii` but missing `sources:` frontmatter
- `_meta/taxonomy.md` — contains `visibility/internal` entry (system tag must not be in taxonomy)
### Misc Promotion Candidates (N found)
Pages in misc/ that have ≥ 3 connections to a single project and are ready to be promoted:
| Page | Top Project | Affinity Score |
|---|---|---|
| `misc/web-martinfowler-articles-microservices.md` | `obsidian-wiki` | 4 |
### Typed Relationship Issues (N found)
- `concepts/foo.md` — relationships[1]: type "contradication" is not an allowed type
- `concepts/bar.md` — relationships[0]: target "[[skills/nonexistent]]" resolves to no page
### Synthesis Gaps (N found)
Concept pairs that co-occur frequently but have no synthesis page:
| Pair | Co-occurrence | Suggested Action |
|---|---|---|
| [[Caching]] × [[Consistency]] | 5 pages | Run `/wiki-synthesize` |
| [[Testing]] × [[Observability]] | 3 pages | Run `/wiki-synthesize` |Append to log.md:
- [TIMESTAMP] LINT issues_found=N orphans=X broken_links=Y stale=Z contradictions=W prov_issues=P missing_summary=S fragmented_clusters=F visibility_issues=V promotion_candidates=C synthesis_gaps=G relationship_issues=ROffer to fix issues automatically or let the user decide which to address.
--consolidate)Triggered by wiki-lint --consolidate. Switches from report-only to act-and-report — the "dream cycle" that runs periodically so the wiki self-heals.
Always run in dry-run first. Before writing anything:
"Apply these N changes? [yes / no / select]".wiki-dedup for that. Only link, promote, demote, and flag. Never apply snapshot_mismatch here; that stays on the snapshots CLI with its own confirmation (see Before You Start).Pre-write snapshot — before the first file write, check whether the vault itself is the root of a Git repository. Merely being a subdirectory of a larger repository does not qualify: running git add -A there could capture unrelated files. If the vault is not a standalone Git repository, skip this step silently — no nagging, no suggesting git init.
VAULT_REAL_PATH=$(cd "$OBSIDIAN_VAULT_PATH" && pwd -P)
VAULT_GIT_ROOT=$(git -C "$OBSIDIAN_VAULT_PATH" rev-parse --show-toplevel 2>/dev/null || true)
SNAPSHOT_SHA=""
if [ -n "$VAULT_GIT_ROOT" ] && [ "$VAULT_GIT_ROOT" = "$VAULT_REAL_PATH" ]; then
if git -C "$OBSIDIAN_VAULT_PATH" diff --quiet \
&& git -C "$OBSIDIAN_VAULT_PATH" diff --cached --quiet \
&& [ -z "$(git -C "$OBSIDIAN_VAULT_PATH" ls-files --others --exclude-standard)" ]; then
SNAPSHOT_SHA=$(git -C "$OBSIDIAN_VAULT_PATH" rev-parse HEAD)
else
if ! git -C "$OBSIDIAN_VAULT_PATH" add -A; then
echo "Pre-write snapshot failed; abort the skill without writing any vault files." >&2
exit 1
fi
if ! git -C "$OBSIDIAN_VAULT_PATH" commit -m "pre-wiki-lint snapshot" --quiet; then
echo "Pre-write snapshot failed; abort the skill without writing any vault files." >&2
exit 1
fi
SNAPSHOT_SHA=$(git -C "$OBSIDIAN_VAULT_PATH" rev-parse HEAD)
fi
fiThe clean-repository branch deliberately avoids calling git commit, so "nothing to commit" is not treated as an error. If git add or git commit fails, stop before editing the vault; never continue without the promised snapshot.
If SNAPSHOT_SHA is non-empty and the skill writes files, include the SHA in the final report. To discard the entire run, after confirming there are no later changes worth keeping, the user can run:
git -C "$OBSIDIAN_VAULT_PATH" reset --hard "$SNAPSHOT_SHA"
git -C "$OBSIDIAN_VAULT_PATH" clean -fdFor each broken [[Target]] found in Check 2:
Grep across index.md titles)[[Oringal]] → [[corrected-page]].~~[[Target]]~~ → Target) and add a comment <!-- broken link: no match found -->.For each orphan page found in Check 1 (zero incoming links):
[[wikilink]] replacing the plain-text mention.cross-linker which runs broadly).Apply these rules automatically (they don't require human judgment — they enforce the documented state machine):
draft → reviewed: pages where lifecycle: draft AND created > 30 days ago AND base_confidence > 0.7. Set lifecycle: reviewed, lifecycle_changed: <today>, lifecycle_reason: "auto-promoted by wiki-lint --consolidate: age>30d, confidence>0.7".verified → stale: NOT a state transition — stale is a computed overlay, not a lifecycle value. Instead: for verified pages where is_stale = (today − updated) > 180 days, add a callout at the top of the page body: > ⚠️ **Stale**: This page was last updated <date>. Verify before relying on it. Only add if the callout isn't already present.reviewed → verified or any other transition — those are human-only.For pages with tier: supporting (or unset) that have 0 incoming links AND haven't been updated in 90+ days:
tier: peripheral.tier: core pages automatically — those were manually set.Read _meta/taxonomy.md for the alias mapping (e.g., ml → machine-learning). For each page, replace known alias tags with their canonical form in the tags: frontmatter field. This is a subset of tag-taxonomy's work — only alias fixes, no full audit.
For each pair of pages marked as contradicting each other (via relationships: contradicts in frontmatter, or flagged in Check 5):
> ⚠️ Contradiction flagged with [[Other Page]] callout already exists near the relevant claim.After all actions, write a report to synthesis/consolidation-<YYYY-MM-DD>.md:
---
title: Consolidation Report <YYYY-MM-DD>
category: synthesis
tags: [maintenance, consolidation]
sources: []
summary: Auto-generated consolidation report from wiki-lint --consolidate run on <date>.
lifecycle: draft
lifecycle_changed: <date>
tier: peripheral
created: <ISO timestamp>
updated: <ISO timestamp>
---
# Consolidation Report — <YYYY-MM-DD>
## Summary
- Broken links fixed: N
- Cross-references added: M
- Lifecycle states updated: K
- Tier demotions: D
- Tags normalized: T
- Contradiction callouts added: C
## Broken Link Fixes
- `concepts/foo.md:12` — [[OldTarget]] → [[correct-target]]
- `entities/bar.md:8` — [[Missing]] → `Missing` (no match found)
## Cross-References Added (orphan rescue)
- `concepts/baz.md` — now linked from: [[concepts/alpha]], [[skills/beta]]
## Lifecycle Updates
- `concepts/old-draft.md` — draft → reviewed (age 45d, confidence 0.74)
- `synthesis/stale-verified.md` — stale callout added (last updated 2025-10-01)
## Tier Demotions
- `concepts/unused-concept.md` — supporting → peripheral (0 links, 120 days stale)
## Tag Normalizations
- `entities/some-tool.md` — `ml` → `machine-learning`
## Contradiction Callouts
- `concepts/scaling.md` — flagged contradiction with [[synthesis/efficiency]]wiki-lint --consolidate — Dry Run
Planned actions (N total):
[1] Fix broken link: concepts/foo.md:12 [[OldTarget]] → [[correct-target]]
[2] Add cross-ref: concepts/baz.md ← [[concepts/alpha]] (orphan rescue)
[3] Lifecycle: concepts/old-draft.md → reviewed (age 45d, confidence 0.74)
[4] Tier demotion: concepts/unused.md → peripheral (0 links, 112 days stale)
[5] Tag alias: entities/some-tool.md: ml → machine-learning
[6] Contradiction callout: concepts/scaling.md ↔ [[synthesis/efficiency]]
Apply these 6 changes? [yes / no / select by number]- [TIMESTAMP] LINT_CONSOLIDATE links_fixed=N orphans_rescued=M lifecycle_updates=K tier_demotions=D tag_fixes=T contradiction_callouts=C report=synthesis/consolidation-YYYY-MM-DD.mdQMD is a search index, not the source of truth. If $QMD_WIKI_COLLECTION is empty or unset, skip this step. Run it only after this skill has written or rewritten vault markdown. If QMD refresh fails, do not roll back the vault changes; report the QMD status separately.
Use $QMD_CLI if set; otherwise use qmd.
${QMD_CLI:-qmd} updateIf the output says vectors are needed or embeddings may be stale, run:
${QMD_CLI:-qmd} embedVerify the collection with either:
${QMD_CLI:-qmd} ls "$QMD_WIKI_COLLECTION"or, when a specific page path is known:
${QMD_CLI:-qmd} get "qmd://$QMD_WIKI_COLLECTION/<page>.md" -l 5Record one of:
QMD refreshed: update + embed + verifiedQMD refreshed: update only + verifiedQMD skipped: QMD_WIKI_COLLECTION unsetQMD skipped: qmd CLI unavailableQMD failed: <short error summary>© Ar9av, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .skills/wiki-lint of Ar9av/obsidian-wiki.
Open the folder on GitHubat commit 4a0630b
Wiki Lint next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Wiki Lint this skillAr9av/obsidian-wiki | 3.5k | — | ~9.1k | Automated safety check: Notes | MIT | |
| LLM Wikilewislulu/llm-wiki-skill | 655 | — | ~3.7k | Automated safety check: Pass | None | |
| LLM Wikizosmaai/pi-llm-wiki | 608 | — | ~4.4k | Automated safety check: Pass | MIT | |
| LLM Wikipraneybehl/llm-wiki-plugin | 118 | — | ~5.7k | Automated safety check: Pass | MIT | |
| Karpathy WikiSherwinQ/karpathy-wiki | 114 | — | ~967 | Automated safety check: Pass | MIT | |
| My LLM WikiMartinLwx/dotfiles | 140 | — | ~2.7k | Automated safety check: Pass | None |
lewislulu/llm-wiki-skill
Build and maintain a Karpathy-style LLM knowledge base — a self-compiling Obsidian markdown wiki where an Agent ingests raw sources, compiles cross-linked concept/entity/summary pages, answers…
zosmaai/pi-llm-wiki
Build and maintain a persistent, interlinked Obsidian-compatible markdown wiki using Karpathy's LLM Wiki pattern.
praneybehl/llm-wiki-plugin
Build and maintain an LLM-curated knowledge base from papers, articles, transcripts, notes and project findings.
SherwinQ/karpathy-wiki
A skill your agent uses when building or maintaining a personal knowledge base with LLM assistance.
MartinLwx/dotfiles
Provides access to the user's personal wiki, including notes, research, project documentation, decisions, and archived knowledge.
xoai/sage-wiki
Reference skill for sage-wiki — local-first knowledge graph with MCP server, REST API, compiled wiki, and Obsidian-compatible output.
Ar9av/obsidian-wiki
Ingest Codex CLI conversation/session history into Obsidian as distilled knowledge.
Ar9av/obsidian-wiki
Ingest GitHub Copilot CLI/session history into Obsidian as distilled knowledge.
Ar9av/obsidian-wiki
Ingest Hermes agent history into Obsidian as distilled knowledge.
Ar9av/obsidian-wiki
Adjust the user's Obsidian visual layout with CSS snippets. An agent skill from Ar9av/obsidian-wiki.
Ar9av/obsidian-wiki
Ingest OpenClaw session/history data into Obsidian as distilled knowledge.
Ar9av/obsidian-wiki
Turn the current conversation or finding into a structured permanent wiki note.
Works with
Categories
Audit wiki health: broken links, orphans, contradictions, stale content, lifecycle and tag issues. Wiki Lint is an agent skill from Ar9av/obsidian-wiki. Audit wiki health: broken links, orphans, contradictions, stale content, lifecycle and tag issues.
Wiki Lint fits situations like: tasks that involve LLM wikis.
Run `npx skills add Ar9av/obsidian-wiki --skill wiki-lint -a claude-code`. Or copy the skill folder (.skills/wiki-lint in Ar9av/obsidian-wiki) into .claude/skills/wiki-lint in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Ar9av/obsidian-wiki --skill wiki-lint -a codex`. Or copy the skill folder (.skills/wiki-lint in Ar9av/obsidian-wiki) into .agents/skills/wiki-lint in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Ar9av/obsidian-wiki --skill wiki-lint -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/wiki-lint, .gemini/skills/wiki-lint, .github/skills/wiki-lint and .opencode/skills/wiki-lint in your project.
Going by SKILL.md and its folder, Wiki Lint needs the command-line tools its instructions call (git and rg). Our summary lists: Node.js.
SKILL.md contains no URLs. Its commands use git, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Wiki Lint is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 9.1k tokens (SKILL.md is roughly 36k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Wiki Lint: LLM Wiki (lewislulu/llm-wiki-skill, 655 stars), LLM Wiki (zosmaai/pi-llm-wiki, 608 stars), LLM Wiki (praneybehl/llm-wiki-plugin, 118 stars) and Karpathy Wiki (SherwinQ/karpathy-wiki, 114 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Ar9av (a GitHub user) maintains it in Ar9av/obsidian-wiki, which has 3,538 GitHub stars. The repository holds 39 skills in this directory. The repository was last updated on October 8, 2026.
Source: Ar9av/obsidian-wiki on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.