What Issues Does the Claude-Obsidian Lint Workflow Detect?

The lint workflow in claude-obsidian performs deterministic, read-only analysis of Obsidian vaults to detect 11 distinct categories of structural defects—including dead links, ambiguous targets, orphan pages, and missing frontmatter—outputting detailed JSON or Markdown reports.

The claude-obsidian repository (AgriciDaniel/claude-obsidian) provides a comprehensive validation engine for knowledge-base maintenance. Implemented primarily in claude_obsidian/lint_engine.py, the lint workflow systematically identifies link resolution failures, metadata inconsistencies, and configuration problems that compromise vault navigability and integrity.

The workflow validates all internal wiki-links against the vault's actual file structure and naming conventions.

Dead links represent references pointing to non-existent files, headings, or block identifiers. During the resolution phase in claude_obsidian/lint_engine.py, when the resolver finds zero candidate targets for a link and the reference is not present in the allow-list, the issue is recorded in the dead_links category at lines [777‑789]. These entries include the source file, line number, target path, and specific failure reason.

Ambiguous Targets

Ambiguous targets occur when a single wiki-link resolves to multiple possible destinations, such as files sharing identical basenames or aliases. The detection logic populates this category when resolver.resolve(link) returns more than one candidate, as implemented at lines [664‑672]. This prevents editors from accidentally linking to incorrect documents when naming collisions exist.

Duplicate Basenames

The linter identifies duplicate basenames—markdown files sharing the same filename stem outside the intentional _index.md pattern—which can confuse automated link resolution. This check iterates through the basename_groups mapping at lines [290‑308] to flag naming collisions that might cause ambiguous target errors.

Links explicitly exempted from dead-link reporting via an allow-list file are tracked separately as allow-listed dangling links. The _is_allowlisted(link, patterns) function evaluates exemption status at lines [779‑789] and [1004‑1009], recording these entries in the allowlisted category for audit purposes rather than treating them as errors.

Content Structure Quality Checks

Beyond link validation, the workflow inspects document metadata and structural completeness.

Orphan Pages

Orphan pages are documents within the wiki/ folder that receive no inbound links from other vault pages, effectively isolating them from the knowledge graph. The linter filters these into the orphans category when a page is absent from the incoming link map, as seen at lines [511‑516].

Missing Frontmatter

The engine enforces standardized metadata by detecting missing frontmatter fields. It compares each page’s frontmatter.fields against REQUIRED_FRONTMATTER_FIELDS—including title, type, status, created, updated, and tags—at lines [560‑566]. Any required field absent from a markdown file generates a report entry specifying the missing keys.

Empty Sections

Empty sections refer to headings that contain no visible content, text, or non-comment code blocks. The _empty_sections(page) function walks heading ranges and validates stripped content at lines [970‑986], flagging structural placeholders that lack substantive information.

Index and Navigation Maintenance

The workflow includes specialized checks for navigation hub integrity.

Stale Index Entries

Index pages (index.md or _index.md) containing dead links or ambiguous targets are flagged as stale index entries, indicating outdated navigation hubs that misdirect users. This detection triggers at lines [674‑678] and [998‑1002] when resolution failures occur specifically on index-designated paths.

System and Configuration Health

The linter validates external dependencies and file accessibility.

Read Errors

Read errors capture I/O failures, permission denials, or Unicode decoding errors encountered while scanning vault files. The workflow collects these filesystem-level exceptions in read_errors during markdown file opening operations at lines [531‑537], ensuring visibility into access problems without crashing the analysis.

Configuration Errors

When the lint allow-list fails to load due to invalid JSON syntax, unreadable file permissions, or directory misconfiguration, the workflow generates configuration errors. The _load_allowlist function produces these diagnostics at lines [607‑629], distinguishing between file-not-found scenarios and parse failures.

Provenance Errors

The linter validates vault provenance ledgers—tracking content sources and claims—for structural integrity. Provenance errors encompass missing source ledgers, malformed entries, and validation failures against the schema defined in claude_obsidian/ledgers.py. These are gathered via _provenance_errors at lines [823‑848], utilizing strict JSON loading utilities from claude_obsidian/json_utils.py and low-level file reading from claude_obsidian/transaction.py.

Running the Lint Workflow

Execute the linter from the command line to analyze a vault directory:


# Generate a JSON report for programmatic processing

python -m claude_obsidian.lint_engine /path/to/vault --format json > report.json

# Generate a human-readable Markdown report

python -m claude_obsidian.lint_engine /path/to/vault --format markdown > report.md

For programmatic integration, import the core functions directly:

from claude_obsidian.lint_engine import lint_vault, render_markdown

# Analyze vault structure

report = lint_vault("path/to/vault")

# Access specific issue categories programmatically

dead_links = report["dead_links"]
for entry in dead_links:
    print(f"{entry['source']}:{entry['line']} → {entry['target']} ({entry['reason']})")

# Render formatted output

print(render_markdown(report))

All findings are accumulated into a deterministic categories dictionary at lines [1086‑1098] of the engine, then rendered by render_markdown at lines [1137‑1245].

Summary

  • The lint workflow claude-obsidian detects 11 distinct issue categories spanning link integrity, content structure, and system configuration.
  • Core link validation—including dead links, ambiguous targets, and duplicate basenames—resolves in claude_obsidian/lint_engine.py within the 290‑789 line range.
  • Content quality checks for orphans, frontmatter, and empty sections operate between lines 511‑986.
  • System health monitoring for configuration and provenance errors utilizes auxiliary modules json_utils.py, ledgers.py, and transaction.py.
  • Results aggregate into a structured categories object and render via render_markdown for both JSON and Markdown output formats.

Frequently Asked Questions

What file contains the core lint workflow implementation?

The primary implementation resides in claude_obsidian/lint_engine.py, which orchestrates vault parsing, link resolution, issue detection, and report generation. Supporting utilities for strict JSON parsing and ledger validation live in claude_obsidian/json_utils.py and claude_obsidian/ledgers.py, respectively, while claude_obsidian/transaction.py provides low-level file reading capabilities.

Before recording a dead link, the workflow invokes _is_allowlisted(link, patterns) at lines [779‑789] to check the exemption configuration. If the link matches an allow-list pattern, it is routed to the allowlisted category at lines [1004‑1009] rather than being reported as a resolution error, enabling intentional dangling references for external or future content.

What output formats does the Claude-Obsidian lint workflow support?

The workflow generates deterministic reports in both JSON and Markdown formats. The render_markdown function (lines [1137‑1245]) produces human-readable output with categorized sections, while the raw categories dictionary (lines [1086‑1098]) provides structured JSON suitable for CI/CD pipelines and programmatic processing.

Which pages are classified as orphans by the lint workflow?

Pages located within the wiki/ folder that have zero inbound links from other vault documents are classified as orphans. The detection logic checks the incoming link map at lines [511‑516]; if a page does not appear as a target in any other document's links, it is flagged as isolated content.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →