Health-check the Obsidian wiki — the "static analysis" pass for a knowledge base.

MITAuto-check passedKnowledge Management

Install Lint

skills CLI
$ npx skills add HurricaHjz/second-yourself --skill lint -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install HurricaHjz/second-yourself lint --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/HurricaHjz/second-yourself.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/lint .claude/skills/lint && rm -rf skills-src

Use ~/.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/

Facts

Skill name
lint
GitHub stars
123
Token cost
~6.3k tokens
SKILL.md length
3,088 words
Files
18
Skills in repo
12
Repo updated
First seen
Licence
MIT

At a glance

Health-check the Obsidian wiki — the "static analysis" pass for a knowledge base.

  • Works in 4 steps: Index consistency (one scripted check) → Link health (one shared script — the… → Conflict audit → …
  • The user runs /lint
  • SKILL.md covers Goal, When to run (and when not), Triggers and Pipeline (read-only until the…, plus 3 more sections
  • Runs Python and Shell scripts from its folder; calls python3, bash and sh

What it does

Lint is an agent skill from HurricaHjz/second-yourself. Health-check the Obsidian wiki — the "static analysis" pass for a knowledge base. Use when the user runs /lint, /health, /scan, or asks to "check the wiki", "find broken links", "clean up the wiki", or "find gaps/orphans/conflicts". Read-only scan that reports dead links, dead media embeds, orphan pages, pages missing from index.md, unresolved knowledge conflicts, live links leaking into the attic, wikilinks from shipped skill or agent files into wiki pages that never ship, and the count of pending flagged…

Its SKILL.md is about 6.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 17 other files (for example `anomaly-lister.py`, `apply-palette.py` and `check-index.py`).

It sits in Knowledge Management, covering Linting and formatting, Knowledge bases and Theming and dark mode. It works with Obsidian. The repository describes itself as: Second yourself. One agent that remembers you, with many hands to act for you: a multi-agent harness (Claude Code, with Codex helpers), a self-maintaining local wiki as its… The licence is MIT.

When your agent uses it

  • The user runs /lint
  • Asks to check the wiki
  • Find broken links
  • Clean up the wiki

Example prompts

  • “static analysis”
  • “check the wiki”
  • “find broken links”
  • “/lint”

Requirements

  • Python 3
  • A Bash shell

Workflow steps

4 steps, taken from the step headings in SKILL.md.

  1. Index consistency (one scripted check)
  2. Link health (one shared script — the single source of truth for link rules)
  3. Conflict audit
  4. Gap scan (optional, suggestive)

What it can do on your machine

Read from SKILL.md and the folder at commit 17c03f2. It shows what the files ask for, not the result of running them.

  • Tool permissions

    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.

  • Runs code

    Ships script files (Python and Shell), which the agent can run.

    Shell commands in SKILL.md call:

    • python3
    • bash
    • sh

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Lint loads about 6.3k tokens when it runs. Until then it costs about 179 tokens; SKILL.md has 3,088 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~179
When it runs · the whole SKILL.md, loaded when a task matches
~6.3k

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.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated 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.

SKILL.md

The full file from HurricaHjz/second-yourself at commit 17c03f2, republished under its MIT licence (© HurricaHjz). 3,088 words, ~6,336 tokens.

Download SKILL.mdSave it as .claude/skills/lint/SKILL.md (or your agent's skills folder). This skill also uses 17 other files; get the full folder from GitHub.
name
lint
description
Health-check the Obsidian wiki — the "static analysis" pass for a knowledge base. Use when the user runs /lint, /health, /scan, or asks to "check the wiki", "find broken links", "clean up the wiki", or "find gaps/orphans/conflicts". Read-only scan that reports dead links, dead media embeds, orphan pages, pages missing from index.md, unresolved knowledge conflicts, live links leaking into the attic, wikilinks from shipped skill or agent files into wiki pages that never ship, and the count of pending `flagged:` freshness flags (≥5 suggests a deep-lint). Also restores the graph colour palette on request (on-demand only, never on a routine scan). Proposes fixes but only applies them after the user confirms.
user-invocable
true

lint — knowledge-graph health check

Goal

Find the rot that accumulates as a knowledge base grows: dead links, orphans, unindexed pages, unresolved conflicts.

When to run (and when not)

Don't lint routinely after a normal ingest — ingest/query leave the graph integrity-clean by construction (CLAUDE.md §6). Run lint for drift (manual edits/renames/deletes in Obsidian, external or OneDrive/git sync changes) and periodic discovery (emerging gap pages, cross-corpus contradictions, stale claims).

Scope boundary: confidence coverage, staleness scoring, and online-source freshness are not lint's job — they live in the heavier, ~monthly deep-lint. Routine /lint stays cheap and never reads pages for confidence or fetches anything.

Triggers

/lint · /health · /scan · "check my wiki" · "find broken links / orphans / gaps".

Pipeline (read-only until the user approves fixes)

1 — Index consistency (one scripted check)

Run python3 .claude/skills/lint/check-index.py --vault . (exit 0 = the probe ran, findings or none; 2 = broken premise). It compares wiki/index.md with the pages on disk and prints three lists with their counts: unindexed pages (on disk, registered by no - [[…]] entry), dangling index entries (registered, no page on disk) and duplicate entries (the same target registered twice). The rules are deep-lint audit-pools.py's, copied so a reader can check them against it: resolution on the basename with or without .md, index.md and log.md excluded as pages, and a page's frontmatter aliases: counting as a resolution on both sides (one deliberate departure from audit-pools, which aliases the dangling side only). It prints SCANNED: <pages> pages · <entries> index entries as its own positive control (§11): a root it cannot scan ends in PROBE FAILED and exit 2 before any list prints, so a clean result always carries non-zero counts. Copy the three figures into the report — never re-derive them by hand. Shared stems are printed as information, not a finding.

Run python3 .claude/skills/lint/check-links.py (exit 0 = clean, 1 = findings; deep-lint's structural pass uses the same script). It applies the codified rules so scans never re-derive them: code spans / fenced blocks / HTML comments are not links; frontmatter aliases resolve; vault-path and root-doc targets resolve; wiki/log.md is exempt as a source (append-only history); and media embeds ![[name.png|pdf|…]] are checked against assets/ — a missing target is a dead embed, reported separately (they are checked, not skipped). The script prints its scan totals as its own positive control (§11): zero findings with zero links scanned is a broken probe, not a clean vault.

  • The same script resolves each page's frontmatter sources: entries against disk and reports dangling sources separately from dead links: one line per page · path, with SOURCES SCANNED: as that arm's control. A URL, prose provenance (email: …, session: …) and an entry that declares its own deletion (path (deleted YYYY-MM-DD)) are counted, never flagged — provenance written as prose is legitimate. An entry the parser could not read prints as (empty or unparsed sources) inside the same block: read it, since it is the parser's own gap detector, not a dangler. A ~- or /-led entry is provenance outside the vault (a run store, a home directory): resolved with expanduser, it prints under OUT-OF-VAULT SOURCES: n present | m missing — a missing one is a finding in that bucket, never a dangling vault path (register entry 2026-09-08).
  • The same script reads the frontmatter converted_from: of every raw/**/*.md conversion and lists, under MISSING ORIGINALS:, a local original found neither beside the conversion, nor at its vault path, nor anywhere under raw/ by file name, with CONVERSIONS SCANNED: as that arm's control; a URL or prose value is counted and never resolved, and a stale value whose original survives elsewhere under raw/ is listed apart, never as a finding (register entry 2026-09-09).
  • Beside it, python3 .claude/skills/lint/check_flag_admissions.py --vault . (exit 0 = clean, 1 = findings, 2 = premise: not a vault root, or no wiki/sources/) lists every page under wiki/sources/ whose prose or frontmatter comment admits conversion damage — the vocabulary collapsed, lost inter-word spaces, inter-word, space-restored, run-together, run together, verbatim quotation is unavailable, lost every chart, lost every figure, lost every table, charts lost, figures lost — while the page carries no conversion flag: a flagged: line counts only when its own text carries conversion (source conversion suspect …), so a flag about something else never masks an admission. A damage admission belongs in the flag channel (ingest Step 0 scores every file carrying converted_by: and records a suspect one in scope pdf as flagged:), which is the only channel deep-lint reads; the fix for a hit is a flagged: line on the page, never a rewrite of the prose — and the flag's end is ingest 3c's terminal state: a repaired conversion scored clean in sources: plus the dated Provenance sentence, which the probe counts under its RESOLVED: line (an admission that also names a repaired conversion), never as a finding. It prints its own in-memory controls (a page that must fire; its conversion-flagged twin that must not; a twin flagged for something else that must; a resolved twin; a marked twin and a negated twin that must not) and the count scanned (register entry 2026-09-08, ingest Step 0 conversions, and the folds of the same day). A line carrying <!-- lint: not a conversion admission -->, or whose term directly follows a negation (must not be collapsed), is listed under SUPPRESSED: and never counted as a finding (register entry 2026-09-09).
  • Every script in this directory refuses, in vault mode, a root that is not a vault (no raw/ + wiki/): one PROBE FAILED: <root> is not a vault root (no raw/ or wiki/) line on stderr and exit 2, so a wrong root can never read as a clean vault scan (the 2026-08-26 standard; the register entry of 2026-09-06 that closed it here; the file-mode forms anomaly-lister --pages and tier-cap-check --verdicts keep their own checks). Every Python script and check-qmd-registry.sh take --vault ROOT; an unknown flag is refused with exit 2, never read as the root.
  • Orphans are scripted too: python3 .claude/skills/lint/check-orphans.py --vault . reports a page with no inbound links from any other page as an orphan, exempting index, log, and maps/ pages (Maps of Content are navigational entry points, not orphans). It applies this directory's link rules, prints its own inbound-link control (zero orphans with a zero control is a broken probe, §11), and additionally lists the pages index.md alone reaches — information, not a finding.
  • Two further helpers in this directory serve deep-lint and the routing design's verify leg, not routine lint: tier-cap-check.py (§4.6 type caps and boundaries; a documented override on the confidence: line is reported separately, never as a violation) and anomaly-lister.py (page-visible anomalies: open conflict blocks, flagged: lines, thin-page notes, unverified markers). Suite for all three: bash .claude/skills/lint/test_lint_phase2.sh.
  • Structure: python3 .claude/skills/lint/check-required-sections.py --vault . lists every page missing a level-2 section its table requires, with each page's depth: beside it; the table covers ## Related for concept, entity and tool, ## Appears in for model and benchmark, ## Summary, ## Key Takeaways and ## Related for source, and ## Sources Used for synthesis and development, exempts maps, and checks no other part of CLAUDE.md §4.3 (register entry 2026-09-03). A research-depth source page carrying the ingest template's ## Citation is judged on ## Related alone (CLAUDE.md §4.3, the research-depth clause of 2026-09-14): the check reads depth: before judging a page's sections, and such a page is a finding only without ## Related.
  • Restated rules: python3 .claude/skills/lint/check-tier-vocabulary.py --vault . extracts every caps at / defaults to plus a tier word from CLAUDE.md §4.6 and from each skill's SKILL.md, and lists under MISMATCHES: a skill statement to which §4.6 gives another tier for the same page type (register entry 2026-09-03).
  • Register: python3 .claude/skills/lint/check_register.py --vault . lists an entry under ## Open in wiki/developments/known-issues.md whose **Status**: begins closed, fixed or resolved, and two Open entries citing one file:line locator, and prints register-check: n/a when the vault has no register yet (register entry 2026-09-07).
  • Each of those three prints its own in-memory control and its scan totals and exits 0 clean, 1 findings, 2 broken premise; they share the suite above.
  • Routing (M0, 2026-09-02; residue closed 2026-09-07): every lint check is a script; the agent reads reports and never re-derives a scripted count (orphans became check-orphans.py, Phase 2 of the routing design; Step 1's index-consistency comparison became check-index.py, the last hand comparison in this pipeline).
2b — Pending freshness flags (count only — reconciling them is deep-lint's job)

grep -rl "^flagged:" wiki --include='*.md' | wc -l — with the engine control grep -rl "^confidence:" wiki --include='*.md' | wc -l (must be >0, proving the probe ran). Report the count; at ≥5 flagged pages, suggest running /deep-lint (set by judgement, unmeasured). Never read or resolve the flagged pages here — lint counts, deep-lint reconciles.

2c — Attic-leak check (filenames only — attic contents are never opened)

Live pages must never link into the attic (CLAUDE.md §2.1): Obsidian resolves wikilinks vault-wide, so a surviving [[link]] to an archived note silently reconnects retired material and can pull a query in. List basenames only — find attic -type f -name '*.md', skip MANIFEST.md (the check reads names, never contents; attic absent or empty → report "attic-leak: n/a"). For each basename b, grep live wiki (excluding wiki/log.md, append-only history) for the exact link forms "[[b]]" "[[b|" "[[b#" "/b]]" "/b|" — plain-text mentions ("b (archived)") are the §2.1 sweep style and are NOT findings. Any hit is a leak finding: report it; the fix (owner-confirmed) is re-sweeping to plain text per §2.1, or /attic restore if the page should live again. Control (§11): the same pipeline against one known live page name must return >0 before reporting "no leaks".

2d — qmd registry guard (one scripted check; skipped silently when qmd is dormant)

wiki/log.md must stay out of the semantic index (CLAUDE.md §10) — embeddings key on a file's whole-content hash, so every append re-embeds the whole timeline, and a hit invites an unbounded whole-file read via qmd get. The exclusion lives in ~/.config/qmd/index.yml, outside the vault and outside both git repos, so it can disappear silently. Run sh .claude/skills/lint/check-qmd-registry.sh . and copy its one line into the report verbatim. The script carries its own §11 control (index.md, deliberately kept, must be listed) and reports PROBE FAILED rather than "clean" when its own premise breaks. Exit 1 = finding; the fix is to restore ignore: ["**/log.md"] on the wiki collection and re-run qmd update.

Show full SKILL.md (1,410 more words)Show less
2e — Injection guard (names only — no skill or definition contents are read)

Third-party installers write into the roots the harness auto-loads, and anything landing there reaches every session (Agent Reach's documented SKILL.md auto-install; two register incidents prove the class: wiki/developments/known-issues.md 2026-08-21/22). Two roots, four arms, and a plugin arm (below). Skills are directories under .claude/skills/; agent definitions are files under .claude/agents/, and each is auto-loaded — a definition names a lane's model, tools and write scope, so an unsanctioned one is the same exposure as an unsanctioned skill. The asymmetry is real: ls yields names in one case and filenames in the other, so the comm inputs differ. Both diff against the same baseline, .claude/skills/lint/sanctioned-skills.txt (its -skills filename is kept for compatibility; it is the registry for both).

bash
b=".claude/skills/lint/sanctioned-skills.txt"    # ships: vault skill names + agent definition filenames
hs="$HOME/.claude/skills/.sanctioned.txt"        # machine-local baselines, never shipped
ha="$HOME/.claude/agents/.sanctioned.txt"
[ -s "$b" ] || echo "PROBE FAILED: vault baseline missing/empty"            # premise guard, never "clean"
# vault skills (directories)
comm -13 <(grep '^vault:' "$b" | cut -d: -f2 | sort) <(ls .claude/skills | sort)
# vault agent definitions (FILES — list everything, do not filter to *.md: a stray file here is the finding)
[ -d .claude/agents ] && comm -13 <(grep '^agent:' "$b" | cut -d: -f2 | sort) <(ls .claude/agents | sort) \
                      || echo "agents-guard: n/a (no .claude/agents in this vault)"
# user-level roots
[ -d ~/.claude/skills ] || echo "PROBE FAILED: ~/.claude/skills missing"    # premise guard, never "clean"
[ -s "$hs" ] && [ -d ~/.claude/skills ] && comm -13 <(sort "$hs") <(ls ~/.claude/skills | sort)
[ -s "$ha" ] && [ -d ~/.claude/agents ] && comm -13 <(sort "$ha") <(ls ~/.claude/agents | sort)

Any name printed = an unsanctioned entry (finding: report it; the fix — owner-confirmed — is removal, or a conscious baseline addition in the same pass that sanctions it). Premise failures never read as clean, each in its own way: a missing/empty vault baseline reports PROBE FAILED; an absent .claude/agents/ reports n/a (a vault may legitimately have none, so absence is not a finding and not a pass either); an absent user-level root reports PROBE FAILED; no machine-local baseline yet (fresh machine) → report that root's current listing as info and propose seeding it after the owner reviews, never a finding, never auto-seeded. Baseline entries missing on disk are info (drift), not findings. §11 control before trusting any empty result: re-run each arm's comm with a known-absent name injected into the disk side (printf 'zzz-ctrl\n') and confirm it prints — one arm's control does not vouch for another's. (Deep-lint inherits this via its structural pass.) Plugin arm (the fifth). python3 .claude/skills/lint/check-plugins.py --vault . lists every plugin that enabledPlugins turns on in ~/.claude/settings.json (under $CLAUDE_CONFIG_DIR when it is set) and in this vault's .claude/settings.json and .claude/settings.local.json, and prints each key that has no plugin:<name>@<marketplace> line in the machine-local ~/.claude/skills/.sanctioned.txt as an unsanctioned plugin (exit 1). A plugin can ship hooks/hooks.json, and its hooks reach every session just as its skills do, so the arm names each enabled plugin's hooks state beside its key. Its premises follow the rules above: a baseline with no plugin: line yet is a fresh machine (the enabled list is information and a seeding proposal, exit 0), an unparseable settings file is PROBE FAILED (exit 2), and a known-absent key injected into the enabled side prints on every run as the arm's own control.

  • Throttle check (delegate skill §2, 2026-09-02): python3 .claude/skills/delegate/throttle.py check — each DRIFT / MISSING / UNROUTED / DESCRIPTION-TIER line is a finding (the fix is throttle.py set <active> for drift, a definition or routing entry for the other two, the range wording for a description); PROBE FAILED (unreadable routing.json, unknown throttle name, absent .claude/agents/) never reads as clean. The script prints its own §11 control (a planted-drift comparator) on every run.

Register arm (2026-09-05; names only, both directions). wiki/developments/capability-register.md lists every user-level skill as one row (| \name` |) under ## User-level skills`; the directory and the register must agree:

bash
reg="wiki/developments/capability-register.md"
[ -s "$reg" ] || echo "register-arm: n/a (no register page yet — a fresh vault; /adopt seeds it)"
[ -s "$reg" ] && rows=$(awk '/^## User-level skills/{f=1} /^## Plugins/{f=0} f' "$reg" | grep -oE '^\| `[a-z0-9-]+`' | tr -d '|` ' | sort -u) \
  && { echo "installed, no row:"; comm -13 <(printf '%s\n' "$rows") <(ls ~/.claude/skills | sort); echo "row, not installed:"; comm -23 <(printf '%s\n' "$rows") <(ls ~/.claude/skills | sort); }

Either list non-empty = a finding (the fix, owner-confirmed, is a row or an install, never a silent delete). Control before trusting two empty lists: re-run with one real row name filtered out of rows and see it appear under "installed, no row".

2f — Customisation pairing (cheap greps — no preference content is judged)

The preference layer is two files: always-on CUSTOMISATION.md (core: contracts + default style/role blocks + customised) and on-demand CUSTOMISATION-definitions.md (the other definitions; read on switch). Core absent (fresh vault) → report customisation-pairing: n/a and skip. Checks:

  • The style and role values in core's ## Settings each have a matching ^### <value> heading in core (the block-move rule keeps the defaults there). §11 control: the same probe must find ### customised in core (it never moves) before any missing-heading finding — or an all-present result — is trusted.
  • No ### heading appears in both files: comm -12 <(grep '^### ' CUSTOMISATION.md | sort) <(grep '^### ' CUSTOMISATION-definitions.md | sort) must print nothing. A hit = a duplicated definition (finding: propose removing one copy; the owner says which — never auto-edit their preferences). Note ### lines inside HTML comments (e.g. the generalist example) can surface here; a hit inside a comment is reported as info, not a finding.
  • Definitions file missing while core exists → warning (switches beyond the defaults will run without their definitions): propose recreating it from the private backup or the template seed (the mk_custom_defs function in the shipped setup.sh). Never fatal, never auto-created.

Every .md under .claude/skills/ and .claude/agents/ ships with the public framework; a [[wikilink]] in one of them that resolves in this vault but not in the published copy is dead for every installer — the class the 2026-08-30 delegate-skill finding proved. Run python3 .claude/skills/lint/check-shipped-links.py . and copy its first line into the report verbatim. Scope is keyed on the export's auto-discovery contract (list_skills/list_agents), minus vault-shaped content bundled inside a skill (any wiki/ or raw/ segment, i.e. the shipped seed demo); names that ship are never findings (index, log, and the seed's own pages); links inside code spans, fenced blocks and HTML comments are not links; targets resolve as Obsidian does, frontmatter aliases included; root docs are out of scope (their [[…]] are naming examples by design — CLAUDE.md §12's ship-safe-citation rule governs citations there). A link dead in both copies is counted on the control line, never flagged: shipped skills use placeholders such as [[topic]]. The script carries its own §11 control (a synthetic surface linking a synthetic page must be caught) and tells legitimate absence from a broken premise: an empty wiki/ (a fresh install, the published copy itself) reports n/a; a missing wiki/, no surfaces, an unreadable surface or a silent self-control reports PROBE FAILED, never "clean". Exit 1 = findings: the fix (owner-confirmed) is rewriting the citation in ship-safe wording — the page name in code font, no link — never deleting the reference. The publish gate's test suite runs the same script (its leg 14), so an edit-time miss here is caught there; regression fixtures live beside the script (bash .claude/skills/lint/test_check_shipped_links.sh).

3 — Conflict audit

Find pages containing ## Conflicts / Open Questions. List each unresolved conflict (the two sides) as cognitive tech-debt to resolve.

4 — Gap scan (optional, suggestive)

Note entities/concepts mentioned often but lacking their own page, and stale claims newer sources supersede. Suggest sources or web searches to fill gaps.

Graph colour restore (on-demand — NOT part of a routine lint)

The graph's per-type colours live in .obsidian/graph.json → colorGroups. That file is volatile: Obsidian rewrites it from memory whenever a graph setting changes (or a sync clobbers it), and can wipe the palette so the graph turns all-grey. A wiped palette is immediately visible, so handle it only on a real signal — never scan for it on a routine lint.

Trigger — do this only when:

  1. the user reports a grey/colourless graph or asks to check/fix/restore graph colours, or
  2. it is a fresh vault at first-run — ingest's bootstrap calls this once (see that skill).

Otherwise do nothing: a routine /lint never reads graph.json or the palette.

Procedure (one shared script — the single source of truth for the palette):

  • Detect: python3 .claude/skills/lint/apply-palette.py --check → exit 0 = palette complete (stop); exit 1 = it prints the missing framework groups.
  • Confirm, then restore: on the user's OK, python3 .claude/skills/lint/apply-palette.py --apply — it merges the canonical palette (.claude/skills/lint/palette.json) into colorGroups, adding only the missing framework groups and preserving any custom groups. Idempotent.
  • Reload: tell the user to close the graph view and reload Obsidian (Cmd/Ctrl+R), so Obsidian does not overwrite the edit with stale in-memory state.

The palette data (palette.json) and logic (apply-palette.py) ship with this skill, so setup.sh, ingest's first-run, and this restore all use the same definition — read only on this path, never on a routine lint.

Report format

markdown
## 🩺 Wiki Health Report — YYYY-MM-DD

### ✅ Healthy
- ...

### ⚠️ Warnings
- **N orphan pages**: [[..]] — suggest linking or categorizing
- **N unindexed pages**: [[..]] — on disk but missing from index.md

### ❌ Errors
- **N dead links**: [[Source]] → [[Missing Target]] · **N dead embeds**: [[Source]] → ![[missing.png]]
- **N unresolved conflicts**: [[Page]]

### ⏳ Flags
- **N pages carry `flagged:`** (engine control OK) — ≥5 → consider `/deep-lint`
- `<the qmd-registry line, verbatim from the script>` · `attic-leak: none / n/a / N leaks` · `skill-guard: clean / N unsanctioned (control OK)` · `customisation-pairing: ok / n/a / N findings` · `throttle-check: clean (N of M diffed, control OK) / N findings / PROBE FAILED` · `shipped-links: clean / n/a / N dead / PROBE FAILED` · `plugins-guard: clean / not seeded (N enabled) / N unsanctioned / PROBE FAILED` · `missing-originals: 0 / N` · `required-sections: clean / N pages · T research-depth template pages (judged on ## Related alone)` · `tier-vocabulary: clean / N mismatches` · `register-check: clean / n/a / N findings`

### 🛠️ Proposed next steps
1. Auto-register unindexed pages? (y/n)
2. Re-derive / resolve the listed conflicts?

Hard constraints

  • Read-only scan. Do not modify, rename, or delete anything before the report.
  • No unverified "clean". A check that returns zero findings must be validated with a positive control (the same probe matching something known to exist) before the report may say "clean" (CLAUDE.md §11).
  • Wait for confirmation before applying any fix.
  • Graph colour restore is on-demand only (see its section) — never scanned or read on a routine lint.
  • After approved fixes, append to wiki/log.md: ## [YYYY-MM-DD] lint | fixed N issues (M dead links, K unindexed).
  • Refresh on write: if approved fixes touched wiki pages, the qmd-search refresh applies — run it inline only where no turn-end refresh hook is installed (that skill owns the rule); a no-op when qmd is dormant.
  • Report in British/UK English.

© HurricaHjz, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 17 other files in .claude/skills/lint of HurricaHjz/second-yourself.

  • SKILL.md
  • anomaly-lister.py
  • apply-palette.py
  • check-index.py
  • check-links.py
  • check-orphans.py
  • check-plugins.py
  • check-qmd-registry.sh
  • check-required-sections.py
  • check-shipped-links.py
  • check-tier-vocabulary.py
  • check_flag_admissions.py
  • check_register.py
  • palette.json
  • sanctioned-skills.txt
  • test_check_shipped_links.sh
  • test_lint_phase2.sh
  • tier-cap-check.py

Open the folder on GitHubat commit 17c03f2

Compare with similar skills

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.

Lint compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Lint this skillHurricaHjz/second-yourself123—~6.3kAutomated safety check: PassMIT
LLM Wikilewislulu/llm-wiki-skill655—~3.7kAutomated safety check: PassNone
Knowledge Base Health Lintjason-effi-lab/karpathy-llm-wiki-vault721—~336Automated safety check: PassNone
LLM Wikipraneybehl/llm-wiki-plugin118—~5.7kAutomated safety check: PassMIT
Obsidian Vault Ingest Pipelinejason-effi-lab/karpathy-llm-wiki-vault721—~669Automated safety check: PassNone
Kbcompozy/kb110—~4.2kAutomated safety check: PassMIT

Similar skills

  • 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…

    655 GitHub stars~3.7k tokensUpdated 5 mo ago
    Knowledge ManagementAuto-check passed
  • Knowledge Base Health Lint

    jason-effi-lab/karpathy-llm-wiki-vault

    Scans an Obsidian-style wiki for broken double-link references, orphan pages, files missing from the index and unresolved knowledge conflicts, then reports the findings.

    721 GitHub stars~336 tokensUpdated 6 mo ago
    Knowledge ManagementAuto-check passed
  • LLM Wiki

    praneybehl/llm-wiki-plugin

    Build and maintain an LLM-curated knowledge base from papers, articles, transcripts, notes and project findings.

    118 GitHub stars~5.7k tokensUpdated 28 days ago
    Knowledge ManagementAuto-check passed
  • Obsidian Vault Ingest Pipeline

    jason-effi-lab/karpathy-llm-wiki-vault

    Compiles raw articles, papers and transcripts sitting in an inbox folder into linked Obsidian source, entity and concept pages, then archives the originals.

    721 GitHub stars~669 tokensUpdated 6 mo ago
    Knowledge ManagementAuto-check passed
  • Kb

    compozy/kb

    Operate the kb CLI to build and maintain topic-based Karpathy-style knowledge bases: gated ingestion, decision-model classification, linking, retrieval and review, wiki compilation, lint-and-heal…

    110 GitHub stars~4.2k tokensUpdated 15 days ago
    Knowledge ManagementAuto-check passed
  • LLM Wiki

    CharlesHoskinson/sevenlayer

    Builds and maintains a persistent, interlinked Obsidian-compatible markdown knowledge wiki in a git repo via three operations — ingest a source into linked pages, answer a question from the…

    116 GitHub stars~1.5k tokensUpdated 1 mo ago
    Knowledge ManagementAuto-check passed

More from HurricaHjz/second-yourself

All 12 skills in this repo
  • Qmd Search

    HurricaHjz/second-yourself

    OPTIONAL, DORMANT semantic-search layer over the wiki, powered by qmd (local hybrid BM25 + vector + rerank).

    123 GitHub stars~1.9k tokensUpdated 9 days ago
    Auto-check passed
  • Query

    HurricaHjz/second-yourself

    Answer questions against the local Obsidian wiki — not from model memory.

    123 GitHub stars~2.2k tokensUpdated 9 days ago
    Auto-check passed
  • Export Template

    HurricaHjz/second-yourself

    Sync THIS LLM-Wiki framework with its public GitHub repo, ONE direction per run: --push (vault → repo) publishes your framework; --pull (repo → vault) updates your framework from a newer repo version.

    123 GitHub stars~4.8k tokensUpdated 9 days ago
    Auto-check: warnings
  • Compile Core

    HurricaHjz/second-yourself

    The compile lane's half of the ingest skill: choose a source's depth after reading it, write the source page from the depth's template, assign confidence, network the knowledge, and propose the…

    123 GitHub stars~4.4k tokensUpdated 9 days ago
    Auto-check passed
  • Lint Slice

    HurricaHjz/second-yourself

    The read-only half of the lint skill for a headless lane: index consistency, link and orphan health, the pending-flag count, the attic, qmd-registry, injection, customisation-pairing and…

    123 GitHub stars~3.5k tokensUpdated 9 days ago
    Auto-check passed
  • Output

    HurricaHjz/second-yourself

    Produce a user-facing DELIVERABLE (report, brief, literature review, slide deck, table, email, outline, …) into the output/ directory — grounded in the wiki and strictly following the user's…

    123 GitHub stars~2k tokensUpdated 9 days ago
    Auto-check passed

Works with

Questions about Lint

What does Lint do?

Health-check the Obsidian wiki — the "static analysis" pass for a knowledge base. Lint is an agent skill from HurricaHjz/second-yourself. Health-check the Obsidian wiki — the "static analysis" pass for a knowledge base.

When should I use Lint?

Lint fits situations like: the user runs /lint; asks to check the wiki; find broken links; clean up the wiki.

How do I install Lint in Claude Code?

Run `npx skills add HurricaHjz/second-yourself --skill lint -a claude-code`. Or copy the skill folder (.claude/skills/lint in HurricaHjz/second-yourself) into .claude/skills/lint in your project. Claude Code loads it when a task matches its description.

How do I install Lint in Codex?

Run `npx skills add HurricaHjz/second-yourself --skill lint -a codex`. Or copy the skill folder (.claude/skills/lint in HurricaHjz/second-yourself) into .agents/skills/lint in your project. Codex loads it when a task matches its description.

Can I use Lint in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add HurricaHjz/second-yourself --skill 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/lint, .gemini/skills/lint, .github/skills/lint and .opencode/skills/lint in your project.

What does Lint need to run?

Going by SKILL.md and its folder, Lint needs Python and a shell for the scripts in its folder and the command-line tools its instructions call (python3, bash and sh). Our summary lists: Python 3; A Bash shell.

Does Lint access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Lint safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Lint use?

Lint is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Lint use?

About 6.3k tokens (SKILL.md is roughly 25k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Lint?

Skills that share tags, products or a category with Lint: LLM Wiki (lewislulu/llm-wiki-skill, 655 stars), Knowledge Base Health Lint (jason-effi-lab/karpathy-llm-wiki-vault, 721 stars), LLM Wiki (praneybehl/llm-wiki-plugin, 118 stars) and Obsidian Vault Ingest Pipeline (jason-effi-lab/karpathy-llm-wiki-vault, 721 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Lint?

HurricaHjz (a GitHub user) maintains it in HurricaHjz/second-yourself, which has 123 GitHub stars. The repository holds 12 skills in this directory. The repository was last updated on October 1, 2026.

Source: HurricaHjz/second-yourself on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.