diff --git a/.github/badges/release.json b/.github/badges/release.json
new file mode 100644
index 00000000..8c99b535
--- /dev/null
+++ b/.github/badges/release.json
@@ -0,0 +1,6 @@
+{
+ "schemaVersion": 1,
+ "label": "release",
+ "message": "v1.6.1",
+ "color": "brightgreen"
+}
diff --git a/.github/workflows/update-release-badge.yml b/.github/workflows/update-release-badge.yml
new file mode 100644
index 00000000..c0a1119a
--- /dev/null
+++ b/.github/workflows/update-release-badge.yml
@@ -0,0 +1,58 @@
+name: Update Release Badge
+
+# Keeps .github/badges/release.json in sync with the latest published release.
+# The README renders the release badge via shields.io's `endpoint` type, which
+# reads this committed JSON instead of calling the GitHub API live — avoiding
+# shields.io's intermittent "Unable to select next GitHub token from pool"
+# failures on the dynamic github/v/release badge.
+on:
+ release:
+ types: [published]
+ workflow_dispatch:
+
+permissions:
+ contents: write
+
+jobs:
+ update-badge:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: main
+
+ - name: Resolve latest release tag
+ id: tag
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ if [ "${{ github.event_name }}" = "release" ]; then
+ VERSION="${{ github.event.release.tag_name }}"
+ else
+ VERSION="$(gh release view --json tagName -q .tagName)"
+ fi
+ echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
+
+ - name: Write badge JSON
+ run: |
+ mkdir -p .github/badges
+ cat > .github/badges/release.json <