Skip to content

C-Sinclair/link_verifier

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

link_verifier

CLI tool to verify markdown-style local links such as [text](./path/to/file.md).

If a scanned file contains markdown-style links in docs or markdown-style comments, those paths must resolve to real files or link_verifier exits with an error.

Features

  • Resolves relative links from the source file's directory, not the working directory
  • Handles balanced parentheses in filenames, e.g. [sheet](Onboarding Sheet (1).xlsx)
  • Decodes percent-encoded URLs, e.g. Scope%20Doc.md resolves to Scope Doc.md
  • Recognises directory links like [assessment](assessment/)
  • Skips external links (http://, https://), mailto:, tel:, bare anchors (#heading), and query-only links (?tab=...)
  • Strips #fragment suffixes before checking file paths
  • Exclude files or directories with --except / -x regex patterns (repeatable)

Install

Download the latest release (native binary; no runtime dependency):

# Example: macOS arm64
gh release download --repo C-Sinclair/link_verifier --pattern 'link_verifier-macos-arm64' --output ~/.local/bin/link_verifier --clobber
chmod +x ~/.local/bin/link_verifier

Pick the asset matching your platform:

  • link_verifier-macos-arm64
  • link_verifier-linux-x86_64

Homebrew support is planned after 1.0; for now, GitHub release assets are the fastest path.

Build from source

make build

Usage

./link_verifier <target> [target ...]

Targets can be:

  • A file path (e.g. README.md)
  • A directory (recursively scans files under it)
  • A wildcard pattern (e.g. docs/*.md)
  • Multiple targets in one run

Options

./link_verifier --help
./link_verifier --version

Excluding files

Use -x / --except to skip files matching a regex pattern. The flag can be repeated:

./link_verifier docs/ -x vendor/ -x "test/fixtures"

Exit codes

  • 0: all links valid
  • 1: usage/target/read error
  • 2: broken links found

Benchmark

Run:

./scripts/benchmark.sh

The script builds the native binary via dune build and benchmarks the default _build/default/bin/main.exe unless BINARY is set.

Default dataset generated by the script:

  • depth: 3
  • files per level: 100
  • total markdown files: 300
  • randomized content with mixed valid/invalid markdown links (BROKEN_RATE=0.35)

Latest sample run:

single-file-mixed: min=2.59ms avg=3.39ms p95=3.73ms runs=15 exit=2
directory-recursive-mixed: min=8.82ms avg=9.58ms p95=10.32ms runs=15 exit=2
wildcard-pattern-mixed: min=5.25ms avg=5.84ms p95=7.21ms runs=15 exit=2

Environment used for this run (relevant to native binary execution):

  • OCaml 5.3.0
  • dune 3.21.1
  • macOS 15.7.1 (Darwin 24.6.0, arm64)

Hook integration

Claude Code hook example

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "./link_verifier docs/*.md"
          }
        ]
      }
    ]
  }
}

Git pre-commit example

#!/bin/sh
./link_verifier README.md docs/*.md
status=$?
if [ "$status" -ne 0 ]; then
  echo "link_verifier failed"
  exit "$status"
fi

When a bad link is found, output includes file + line number, for example:

docs/guide.md:42: broken link -> ./missing-file.md

About

Verify Markdown style links are valid

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors