Find retired and broken status badges in Markdown that link checkers miss
Project description
badgevet
Find retired and broken status badges in Markdown that link checkers miss.
A retired shields.io badge returns HTTP 200 with a valid SVG whose title
reads retired badge, so ordinary link checkers (lychee, markdown-link-check)
mark it OK. badgevet fetches each badge and reads the rendered SVG title
instead, so it can tell a dead badge from a healthy one.
Install
cargo install badgevet
# or a prebuilt binary, no recompile:
cargo binstall badgevet
Usage
badgevet # scan README.md in the current directory
badgevet docs/ README.md # scan files and directories (dirs recurse for *.md)
badgevet ~/Projects/mine # one command scans every README under all your local repos
badgevet --only-broken . # report only permanently broken badges
badgevet | jq . # JSON when piped
Check every repo you own
Point badgevet at an owner and it checks the canonical published README of each of their repositories - no cloning needed. It reads the same README GitHub shows the world, so it catches badge rot even in repos you rarely touch.
badgevet --github rvben # all your public, non-fork, non-archived repos
badgevet --github rvben --only-broken
Set GITHUB_TOKEN (or GH_TOKEN) to lift GitHub's unauthenticated rate limit;
required for --include-private. Widen the default scope with
--include-forks, --include-archived, --include-private.
Example:
STATE PROVIDER LOCATION BADGE
broken shields.io README.md:3 Version
-> https://vsmarketplacebadges.dev/version/rvben.rumdl.svg
3 checked · 2 ok · 1 broken · 0 unconfirmed
How it classifies
Each badge lands in one of three states:
| State | Meaning | Fails CI? |
|---|---|---|
ok |
The badge renders a real value. | no |
broken |
A deterministic dead state (retired, deprecated). |
yes (exit 1) |
unconfirmed |
Could not be verified: an ambiguous invalid / inaccessible / empty title, or a transient network failure. Retried with backoff first. |
no (unless --strict) |
The distinction is the point. shields.io renders invalid both for a genuinely
bad badge and when its upstream API is merely rate-limiting, so unconfirmed
never fails your build by default. Only an explicit, permanent dead state does.
When a known-dead pattern has a modern replacement (e.g. shields.io's retired Visual Studio Marketplace routes), badgevet prints the suggested URL.
Fixing
scan never touches your files. The separate fix command applies those
suggestions in place:
badgevet fix # rewrite broken badges in README.md
badgevet fix docs/ # ...or across a directory of Markdown
It swaps only the badge image URL (leaving the surrounding link untouched),
changes only broken badges that have a known replacement, and is idempotent.
Broken badges with no known replacement are left alone and reported as
unfixable (exit 1). fix is local-only; it does not work with --github.
Since scan is read-only and fix mutates, they are separate commands with
honest mutating markers in the schema.
Options
| Flag | Default | Description |
|---|---|---|
--github <owner> |
- | Scan an owner's GitHub repos instead of local paths. |
--include-forks |
off | With --github: include forks. |
--include-archived |
off | With --github: include archived repos. |
--include-private |
off | With --github: include private repos (needs a token). |
--only-broken |
off | Report only permanently broken badges. |
--strict |
off | Also exit 1 on unconfirmed badges. |
--retries <n> |
2 |
Re-fetch an ambiguous badge before giving up. |
--timeout <secs> |
10 |
Per-request HTTP timeout. |
-o, --output <fmt> |
auto |
auto (text on a TTY, JSON when piped), json, text. |
Exit codes
| code | meaning |
|---|---|
0 |
no broken badges |
1 |
at least one badge is permanently broken (or, with --strict, unconfirmed) |
2 |
a path could not be read, or the HTTP client failed to build |
3 |
usage error |
Exit 1 is an outcome, not an error: stdout still carries
the full report and no error envelope is written. This makes badgevet a natural
CI or pre-commit gate.
For agents (clispec)
badgevet follows The CLI Spec: structured output on
stdout, structured error envelopes on the last line of stderr, and a schema
subcommand whose output validates against clispec.dev/schema/v0.2.json
(checked by the test suite).
badgevet schema
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file badgevet-0.1.0.tar.gz.
File metadata
- Download URL: badgevet-0.1.0.tar.gz
- Upload date:
- Size: 47.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
819646bf08d877ffccf9ee401599181a88dd8f779324206a8d0d526a03c957b1
|
|
| MD5 |
6cf6639bbddfcab673445e7101b4430b
|
|
| BLAKE2b-256 |
9995d39e669214264c410966bfdaf94347379230e0401836851cf227ebb7ec2a
|
File details
Details for the file badgevet-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: badgevet-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.9 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e18dd2277e40ac0620d55f3e5334f71e40ec15998f2150754dd7887c1b6367c
|
|
| MD5 |
ca0706307eafbfbbaa7d8a0adc9fd5fb
|
|
| BLAKE2b-256 |
2be4216e99e96df5b040a52014b9be87e3015326b92904fcac0be853e0a9b6ef
|
File details
Details for the file badgevet-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: badgevet-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.9 MB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bcfb60abb1d481c71a6f48d2ec23360043121eee5458a63c205dd828b776bdaf
|
|
| MD5 |
38091944c00f4fc85789f3876dd93c91
|
|
| BLAKE2b-256 |
d5377ceb5d4d1f0580e81b576285d3e32525f9b265652c3ee7366b673b89194a
|
File details
Details for the file badgevet-0.1.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: badgevet-0.1.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.7 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9b1492d68845635bd0b5c1e6f5c235d376f2698582f57d3f5c89282fddc13c3
|
|
| MD5 |
1e62dca9b6876a40b1de5f38a210145d
|
|
| BLAKE2b-256 |
f10e4a623ec4fcfa8991adae27cb852fda1b051d116edc8aadf18d0aa2ef1782
|
File details
Details for the file badgevet-0.1.0-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: badgevet-0.1.0-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.9 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c108a395308d4f6ec18587382fbe592cce9975d43dc53de6822d6f593dca54eb
|
|
| MD5 |
65c20d9adede0027e11b629663189428
|
|
| BLAKE2b-256 |
66b8d550de2bccd52ae72eb60608c435243447c635e735d3cd83b63d006141e4
|