Weekly vault structural maintenance inspired by Karpathy's LLM Wiki approach. Cleans broken links, adds missing MOC entries, sorts sections, repairs taxonomy drift (tag case, synonym merges, folder routing), and proposes Topic MOCs for oversized sections. Structure only — semantic work belongs to the metabolism pipeline. Schedule weekly for a self-maintaining knowledge base.
57
66%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./.github/skills/obsidian-vault-lint/SKILL.mdWeekly vault maintenance inspired by Karpathy's LLM Wiki approach (~16M views, April 2026). Instead of RAG (re-reading raw docs every call), the LLM maintains a compiled wiki — incrementally building and cleaning a structured knowledge base.
Scope: structure, not meaning. This skill keeps the vault's skeleton clean — links resolve, the MOC matches the filesystem, tags are canonical, notes sit in the right folder. It does no semantic analysis. Anything that requires reading a note for what it argues is owned by the metabolism pipeline:
| Semantic concern | Owner |
|---|---|
| Connections between notes (supports / contradicts / extends / bridges) | obsidian-connection-detector — runs on every note creation → connections.json |
| Thesis clustering, contradiction resolution | obsidian-thesis-tracker → theses.json |
| Emerging topics, rising tags, cross-domain bridges | obsidian-weekly-brain (trend momentum + bridges passes) |
| Corpus synthesis into a report | obsidian-vault-report |
Division of labor within this skill:
Run time: ~2-5 min for a 500-note vault. No API calls, no API key, no network — pure filesystem work.
Do not use this for: "what's connected to what", "what topics are emerging", "what does my vault think". Those are obsidian-connection-detector, obsidian-weekly-brain, and obsidian-vault-report respectively.
Collects vault health metrics:
| Fix | Logic | Safety |
|---|---|---|
| Prune stale Recently Added | Remove entries older than --stale-days | MOC section only |
| Add missing notes to MOC | Insert under correct folder section, alphabetically | Append-only within sections |
| Sort MOC sections | Re-order wikilinks alphabetically within each ## section | Preserves all links |
| Fix broken wikilinks | Replace [[broken-slug]] with plain text broken-slug | One file at a time, logged |
All changes logged to the Phase 5 report. Use --dry-run to preview without writing.
Canonical Tag Guidance section to build the authoritative tag listResearch/Library/ (excluding 00 MOC/):
rag sitting in folder 01 instead of 05)RAG → rag, AI-Agents → ai-agentsResearch/Logs/vault-lint-YYYY-MM-DD-taxonomy.md):
| Action | Autonomous | Approval-gated |
|---|---|---|
| Tag case normalization | ✓ | |
| Synonym merge (canonical exists) | ✓ | |
| Folder move proposals | ✓ | |
| Orphaned tag flagging | ✓ |
Pure string/frontmatter work — no LLM call. Emergent topic detection used to live here and does not any more; obsidian-weekly-brain does it better over the whole corpus.
Autonomous:
Approval-gated (writes proposals file):
Research/Logs/vault-lint-YYYY-MM-DD-moc-proposals.mdWrites Research/Logs/vault-lint-YYYY-MM-DD.md with health metrics, all changes, and links to approval-gated proposal files. Includes the taxonomy repair summary (tag fixes applied).
After the report is written (non-dry-run full runs only), the script automatically commits all vault changes to git with message vault-lint: automated maintenance {date}.
# Full run (all 5 phases)
python .github/skills/obsidian-vault-lint/scripts/lint.py
# Dry run — preview all changes, nothing written
python .github/skills/obsidian-vault-lint/scripts/lint.py --dry-run
# Run specific phase only
python .github/skills/obsidian-vault-lint/scripts/lint.py --phase 1
python .github/skills/obsidian-vault-lint/scripts/lint.py --phase 2
python .github/skills/obsidian-vault-lint/scripts/lint.py --phase 3
python .github/skills/obsidian-vault-lint/scripts/lint.py --phase 4
# Verbose output (per-item detail)
python .github/skills/obsidian-vault-lint/scripts/lint.py --verbose
# Custom stale threshold (default: 7 days)
python .github/skills/obsidian-vault-lint/scripts/lint.py --stale-days 14Create a scheduled task using an XML definition file for reliable Task Scheduler v1.3 configuration:
# Save this XML to a file, then register it
$taskXml = @'
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Description>Weekly obsidian-vault-lint maintenance run</Description>
<URI>\obsidian-vault-lint</URI>
</RegistrationInfo>
<Triggers>
<CalendarTrigger>
<StartBoundary>2026-04-20T06:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByWeek>
<DaysOfWeek>
<Sunday />
</DaysOfWeek>
<WeeksInterval>1</WeeksInterval>
</ScheduleByWeek>
</CalendarTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>S-1-5-21-1397207858-461175-3826805727-1001</UserId>
<LogonType>InteractiveToken</LogonType>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>false</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
<Priority>7</Priority>
<RestartOnFailure>
<Interval>PT5M</Interval>
<Count>2</Count>
</RestartOnFailure>
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
</Settings>
<Actions Context="Author">
<Exec>
<Command>python</Command>
<Arguments>.github/skills/obsidian-vault-lint/scripts/lint.py</Arguments>
<WorkingDirectory>Z:\Projects\Eric-Cartman</WorkingDirectory>
</Exec>
</Actions>
</Task>
'@
# Write XML and register the task
$taskXml | Out-File -FilePath "$env:TEMP\obsidian-vault-lint-task.xml" -Encoding Unicode
Register-ScheduledTask -TaskName "obsidian-vault-lint" -Xml (Get-Content "$env:TEMP\obsidian-vault-lint-task.xml" -Raw)Or register via the /schedule skill:
/schedule obsidian-vault-lint weekly Sunday 06:00None. No env vars, no API keys, no network access — every phase is local filesystem work against the vault.
These paths match the vault structure discovered during development. Update if your vault structure changes:
MASTER_MOC_PATH = "Research/Library/00 MOC/\U0001f5fa️ MOC - Research Library.md"
LIBRARY_FOLDER = "Research/Library"
MOC_FOLDER = "Research/Library/00 MOC"
LOG_FOLDER = "Research/Logs".github/skills/obsidian-vault-lint/
├── DESIGN.md — architecture decisions and rationale
├── SKILL.md — this file
└── scripts/
├── __init__.py — package marker
├── lint.py — main entry point (orchestrator)
├── inventory.py — Phase 1: read-only vault health scan
├── fixes.py — Phase 2: autonomous safe writes
├── taxonomy.py — Phase 3: tag normalization + folder routing
└── moc.py — Phase 4: MOC dead-entry cleanup + proposalsobsidian.py from .github/skills/obsidian/scripts/C:\Program Files\Git\cmd\git.exe) — for auto-commit after full runs| File | Phase | Written when |
|---|---|---|
Research/Logs/vault-lint-YYYY-MM-DD.md | 5 | Always (full run) |
Research/Logs/vault-lint-YYYY-MM-DD-taxonomy.md | 3 | When tag fixes, folder moves, or orphaned tags are found |
Research/Logs/vault-lint-YYYY-MM-DD-moc-proposals.md | 4 | When sections exceed 12 entries |
| Skill | Relationship |
|---|---|
obsidian-connection-detector | Owns semantic linking (was this skill's Phase 3 until v2.0.0) |
obsidian-thesis-tracker | Clusters those connections into theses |
obsidian-weekly-brain | Owns emergent topic / rising tag detection (was Phase 2.5 Mode B until v2.0.0) |
obsidian-vault-linker | Graph health audit — feeds the orphan counts this skill reports |
obsidian-vault-lint-cowork | Linux-sandbox fork; still carries the old phase layout |
If you hit unexpected errors mid-run:
- Complete the step with a workaround
- Immediately invoke
skill-reflectionwith the friction details- Apply P0/P1 fixes to this SKILL.md now
- Save an Agent Memory
- Continue with remaining phases
aa16c9e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.