From zettelkasten
This skill should be used when the user asks to "check knowledge base", "zet lint", "vault health", "any broken links", "check frontmatter", "find orphan notes", "what's wrong with the vault", "knowledge base health", or wants a structural health check of their Zettelkasten.
How this skill is triggered — by the user, by Claude, or both
Slash command
/zettelkasten:zet-lintThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Scan the knowledge base for structural problems: orphan notes, broken links, incomplete frontmatter, MOC gaps.
Scan the knowledge base for structural problems: orphan notes, broken links, incomplete frontmatter, MOC gaps.
1_zettel/ recursively for all .md files (not just one subdirectory)2_maps/ dynamically with Glob — never hardcode MOC filenames.py file, then run it with Bash. Do NOT use Bash heredoc or inline Python — the != operator gets escaped to \!= in heredoc, causing SyntaxError.Any generated script that writes back to note files MUST follow these rules:
\u201c, \u201d → " and \u2018, \u2019 → ' in the raw frontmatter text before calling yaml.safe_load(). Smart/curly quotes are common in CJK content and break YAML parsing.yaml.safe_load() still fails after normalization, store the raw frontmatter string. When writing the file back, reconstruct ---\n{raw}\n---\n{body} — never drop the frontmatter block.--- fenced frontmatter block. If not, skip that file, log it as an error, and continue with the rest of the batch.re.MULTILINE for ^ anchored patterns. When searching multi-line strings with re.findall(r'^- \[\[', ...), always pass re.MULTILINE — without it, ^ only matches start of string.Run all checks below, collecting issues into three categories: errors, warnings, suggestions.
Scan all .md files in 1_zettel/ and 2_maps/ for wikilinks [[...]].
For each wikilink, verify the target note exists somewhere in 1_zettel/ or 2_maps/.
Report any links pointing to non-existent notes.
Category: Error
Find notes in 1_zettel/ that have:
## Links section, ORUse Grep to search for [[note-title]] across all files to detect inbound links. When counting "effective" inbound, exclude links from 2_maps/ files.
Check 2 only covers peer-to-peer links. MOC coverage issues belong to Check 4.
Category: Warning (zero outbound, or only-MOC inbound), Error (zero inbound — completely disconnected)
Read ${CLAUDE_PLUGIN_ROOT}/references/frontmatter-spec.md for required field lists.
For each file in 1_zettel/:
## Links section exists in the bodyFor each file in 2_maps/:
Category: Warning
Count how many notes in 1_zettel/ are referenced by at least one MOC in 2_maps/. Report notes not referenced by any MOC.
Category: Suggestion (if the note has tags that match an existing MOC but isn't listed)
Collect all tags from 1_zettel/ frontmatter. Normalize tags to lowercase kebab-case before counting (per frontmatter-spec.md Tag Normalization — AI and ai count as the same tag). For normalized tags with ≥3 notes:
Category: Suggestion
Find files in 1_zettel/ and 2_maps/ with no content (only frontmatter or completely empty).
Category: Error
For each MOC in 2_maps/, count the actual - [[ entries under ## Notes and compare to the note_count frontmatter field (per moc-rules.md — note_count must equal the count of - [[ lines, not inbound links from other files).
Report mismatches.
Category: Warning
Collect all tags from 1_zettel/ frontmatter. Group tags by their lowercase form. Report any tag that appears in multiple case variants (e.g. AI in 15 notes vs ai in 15 notes).
Also check for non-kebab-case tags: spaces, underscores, slashes, uppercase letters. Report any tag that violates the lowercase-kebab-case rule per frontmatter-spec.md Tag Normalization.
Category: Warning (case variants exist), Error (if variants merged would reach ≥3 notes but no MOC exists)
Scan all .md files in 1_zettel/ for image references matching:
![[filename.png]] (Obsidian wikilink, including ![[Pasted image ...]]) (standard markdown)For each referenced image, verify the file exists in 4_assets/. Report missing images.
Category: Error
Scan all notes in 1_zettel/. Flag potential duplicates by checking:
For each pair of suspected duplicates, report both file paths and their titles for user review.
Category: Suggestion
Generate 3_output/lint-report-YYYY-MM-DD.md:
# Zettelkasten Lint Report — YYYY-MM-DD
## Summary
- Total notes: N
- Total MOCs: N
- Errors: N
- Warnings: N
- Suggestions: N
## Errors
- [list each error with file path and description]
## Warnings
- [list each warning]
## Suggestions
- [list each suggestion]
## Relink Candidates
- Notes with 0 peer inbound links (N):
- note-a.md
- note-b.md
- Notes with only-MOC inbound links (N):
- note-c.md
- Estimated backlinks to add: N
After presenting the report, offer to auto-fix:
AI → ai in 15 notes").2_maps/ files to lowercase kebab-case (e.g. AI.md → ai.md). On macOS APFS (case-insensitive), use two-step rename: git mv AI.md tmp.md && git mv tmp.md ai.md. Do NOT modify wikilink text content — Obsidian wikilinks are case-insensitive.- [[ entries per moc-rules.md, also append missing note entries and update Related Maps cross-links## Links sections (with placeholder for user to fill)## Links section. Three-level candidate search:
[reciprocal] — outbound target A→B exists, add B→A (highest confidence, no search needed)[tag-match] — same tag, different note (deterministic)[slug-match] — 2-3 meaningful slug segments via Grep (only if levels 1-2 yield nothing, search terms ≤ 3)## Links total ≤ 10 entries (skip if exceeded)[[slug]] only, existing links are not duplicated1. sydney-tap-water-safety.md (0 inbound → 1)
+ Add to wolli-creek-rental-arrangement.md (current: 3 links) [reciprocal]:
"Sydney tap water safety is relevant to daily life in Wolli Creek"
Ask user for confirmation before applying fixes. If fixes are applied, commit:
git add 1_zettel/ 2_maps/
git commit -m "zet: lint auto-fix — N issues resolved"
npx claudepluginhub henrywen98/zettelkasten --plugin zettelkastenCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.