惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Blog of Author Tim Ferriss
WordPress大学
WordPress大学
博客园 - Franky
The Cloudflare Blog
T
Tailwind CSS Blog
宝玉的分享
宝玉的分享
小众软件
小众软件
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
B
Blog
Y
Y Combinator Blog
V
V2EX
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
博客园 - 司徒正美
IT之家
IT之家
G
Google Developers Blog
C
Check Point Blog
Engineering at Meta
Engineering at Meta
Microsoft Security Blog
Microsoft Security Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Your docs have dead links. I built a zero-dependency CLI ...
benjamin · 2026-06-17 · via DEV Community
Cover image for Your docs have dead links. I built a zero-dependency CLI that catches the local ones — no network

benjamin

You rename a file, restructure a folder, tweak a heading — and quietly leave a trail of dead links across your README and docs. Nobody notices until a reader clicks ./old-guide.md and gets a 404.

There are tools for this, but each asks for something:

  • markdown-link-check works, but it pulls in ~9 dependencies and its headline feature is hitting external URLs over HTTP — slow, rate-limited, and flaky in CI (your build shouldn't go red because someone's blog was down).
  • lychee is fast and great, but it's a Rust binary to install.
  • The old Python option, mlc, has been unmaintained since 2021.

I wanted the deterministic part — local links — to be instant and dependency-free. So I built linkbust:

npx linkbust

README.md:8      ✗  ./setup.md           (file not found)
docs/api.md:14   ✗  #usage               (no anchor in this file)
guide.md:3       ✗  ./api.md#missing     (no anchor in ./api.md)

✗ 3 broken · 142 local links checked · 38 external skipped (never fetched)

What it checks (and skips)

  • Relative file links and image sources resolve on disk.
  • Anchors — both [x](#section) in the same file and [x](other.md#section) across files — match a real heading (GitHub-style slug) or an explicit <a id="…">.
  • Reference links [text][ref] have a matching [ref]: … definition.
  • Links inside fenced/inline code blocks are ignored, so examples don't cause false alarms.

It deliberately never makes a network requesthttp(s), mailto:, and /absolute paths are classified and skipped. That's the whole design: because it's offline, it's instant and can't flake. Which makes it ideal as a pre-commit hook:

- repo: local
  hooks:
    - id: linkbust
      name: linkbust
      entry: npx linkbust
      language: system
      pass_filenames: false

Exit code is 1 if anything's broken, so CI fails cleanly.

Zero dependencies, both ecosystems

Pure standard library — a small Markdown parser (code masking, reference links, GitHub anchor slugs) plus filesystem checks. The Node and Python ports are behavior-identical, byte-for-byte (same output, same exit codes).

npx linkbust              # Node >= 18
pip install linkbust      # Python >= 3.8

Do you check links in CI, or only find out when someone reports a 404? And for external URLs — worth the flakiness to catch them, or do you treat those as out of scope too?