Docs Engineering
hiroshiyui/GuilelessBopomofo
Writing/updating project documentation (README, PRIVACY-POLICY, NOTICES, changelogs) and maintaining F-Droid metadata.
Use EVERY time the user asks to update / bump the version catalogs, "сделать обновление", "обновить каталог(и)", "обнови версии", "оформи изменения", "update the catalog", or to record dependency…
$ npx skills add RedMadRobot/gradle-version-catalogs --skill update-version-catalog -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install RedMadRobot/gradle-version-catalogs update-version-catalog --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/RedMadRobot/gradle-version-catalogs.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/update-version-catalog .claude/skills/update-version-catalog && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "update-version-catalog" agent skill from https://github.com/RedMadRobot/gradle-version-catalogs/tree/main/.claude/skills/update-version-catalog into .claude/skills/update-version-catalog/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "update-version-catalog", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/RedMadRobot/gradle-version-catalogs/tree/main/.claude/skills/update-version-catalogType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add RedMadRobot/gradle-version-catalogs --skill update-version-catalog -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install RedMadRobot/gradle-version-catalogs update-version-catalog --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RedMadRobot/gradle-version-catalogs.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/update-version-catalog .agents/skills/update-version-catalog && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "update-version-catalog" agent skill from https://github.com/RedMadRobot/gradle-version-catalogs/tree/main/.claude/skills/update-version-catalog into .agents/skills/update-version-catalog/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "update-version-catalog", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add RedMadRobot/gradle-version-catalogs --skill update-version-catalog -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install RedMadRobot/gradle-version-catalogs update-version-catalog --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RedMadRobot/gradle-version-catalogs.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/update-version-catalog .cursor/skills/update-version-catalog && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "update-version-catalog" agent skill from https://github.com/RedMadRobot/gradle-version-catalogs/tree/main/.claude/skills/update-version-catalog into .cursor/skills/update-version-catalog/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "update-version-catalog", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/RedMadRobot/gradle-version-catalogs.git --path .claude/skills/update-version-catalog--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add RedMadRobot/gradle-version-catalogs --skill update-version-catalog -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install RedMadRobot/gradle-version-catalogs update-version-catalog --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RedMadRobot/gradle-version-catalogs.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/update-version-catalog .gemini/skills/update-version-catalog && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "update-version-catalog" agent skill from https://github.com/RedMadRobot/gradle-version-catalogs/tree/main/.claude/skills/update-version-catalog into .gemini/skills/update-version-catalog/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "update-version-catalog", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install RedMadRobot/gradle-version-catalogs update-version-catalogInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add RedMadRobot/gradle-version-catalogs --skill update-version-catalog -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/RedMadRobot/gradle-version-catalogs.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/update-version-catalog .github/skills/update-version-catalog && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "update-version-catalog" agent skill from https://github.com/RedMadRobot/gradle-version-catalogs/tree/main/.claude/skills/update-version-catalog into .github/skills/update-version-catalog/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "update-version-catalog", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add RedMadRobot/gradle-version-catalogs --skill update-version-catalog -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install RedMadRobot/gradle-version-catalogs update-version-catalog --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RedMadRobot/gradle-version-catalogs.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/update-version-catalog .opencode/skills/update-version-catalog && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "update-version-catalog" agent skill from https://github.com/RedMadRobot/gradle-version-catalogs/tree/main/.claude/skills/update-version-catalog into .opencode/skills/update-version-catalog/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "update-version-catalog", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
update-version-catalogUse EVERY time the user asks to update / bump the version catalogs, "сделать обновление", "обновить каталог(и)", "обнови версии", "оформи изменения", "update the catalog", or to record dependency…
Update Version Catalog is an agent skill from RedMadRobot/gradle-version-catalogs. Use EVERY time the user asks to update / bump the version catalogs, "сделать обновление", "обновить каталог(и)", "обнови версии", "оформи изменения", "update the catalog", or to record dependency version changes in the changelog. Renovate commits the version bumps into versions-/libs.versions.toml; this skill collects those changes, records them in CHANGELOG.md following the format rules below, and validates with ./gradlew validateCatalog. ALSO use it when the user asks to add a new dependency ("добавь…
Its SKILL.md is about 9.5k tokens, which your agent loads only when the skill is triggered. The skill folder holds 15 other files, including scripts (for example `scripts/bom-diff.sh`, `scripts/check-doc-links.sh` and `scripts/cherry-pick-renovate.sh`).
It sits in Development, covering Changelog and release notes. It works with Gradle and Android. The repository describes itself as: Version catalogs used in redmadrobot Android team. The licence is MIT.
10 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit c5bab82. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 14 files in scripts/ (Shell), which the agent can run.
Shell commands in SKILL.md call:
bashgitFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
plugins.gradle.orgdeveloper.android.comgithub.comFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
GITHUB_TOKENGH_TOKENFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Update Version Catalog loads about 9.5k tokens when it runs. Until then it costs about 180 tokens; SKILL.md has 4,619 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from RedMadRobot/gradle-version-catalogs at commit c5bab82, republished under its MIT licence (© RedMadRobot). 4,619 words, ~9,493 tokens.
.claude/skills/update-version-catalog/SKILL.md (or your agent's skills folder). This skill also uses 14 other files; get the full folder from GitHub.Renovate is the source of version updates: it keeps each dependency bump on its
own remote branch origin/renovate/<dep> (e.g. origin/renovate/dagger,
origin/renovate/compose-bom), with a commit topic like stack: dagger 2.60.
This skill does NOT invent versions — it collects Renovate's bumps onto a fresh
working branch, documents them in CHANGELOG.md, and validates the catalogs.
This document is self-contained: all CHANGELOG.md formatting rules are inlined
below. Everything that can be checked mechanically IS checked mechanically —
lint-changelog.sh, check-doc-links.sh and finish-check.sh are the source of
truth, not your own reading of the diff.
All output shown to the user — progress updates, questions, summaries, and the
final report — MUST be written strictly in Russian, regardless of the language
of the user's request. This applies only to the assistant's messages; code,
commit messages, CHANGELOG.md entries, and file contents follow their own
existing conventions and are unaffected.
All work happens on the single dev-update-YYYY-MM-DD branch created in step 1.
main. main may only be read (fetched /
pulled fast-forward in step 1) and used as the cherry-pick/reset base.git branch --show-current → must be dev-update-*). If it is not, STOP and
fix the branch before running the command.release/* or origin/renovate/* branches (renovate branches are
read-only sources for cherry-pick).git push anything unless I explicitly ask.If any step would require changing a branch other than the working one, STOP and ask me instead of proceeding.
Every command is one of three kinds:
| The user asks | Flow to follow | Commits produced |
|---|---|---|
| Update existing dependencies («обнови зависимости/каталоги», «сделай обновление», "update") | Workflow steps 1–10 | 1 update commit: all cherry-picked bumps + their CHANGELOG.md entries |
| Add new dependencies («добавь зависимость …», "add group:artifact") | "Adding a new dependency" section (its step 1 = workflow step 1) | 1 addition commit: catalog edits + their CHANGELOG.md entries |
| Both at once («обнови зависимости и добавь …») | TWO operations, both mandatory: workflow steps 1–9 in full first, then (step 10) the ENTIRE addition flow on top of the finished update commit | 2 commits: first the update commit, then the addition commit — never mixed |
All additions requested by one command share a single addition commit, no matter how many dependencies are added. A correction to an earlier result («исправь ссылку», «поправь changelog») is none of these — it is a continuation of the previous command (see workflow step 1) and creates no new commit.
Before doing ANYTHING else, classify the command against this table and tell
the user (in Russian) which kind it is. For a Both at once command,
explicitly announce the plan as two numbered operations — e.g. «Команда
двойная: 1) обновление каталогов, 2) добавление <deps>. Начинаю с
обновления.» — and track both as separate items in your task list so neither
can be dropped.
A command that both updates and adds (any phrasing that combines them: «обнови зависимости и добавь X», «сделай обновление и добавь X», "update the catalogs and add X", or an addition mentioned anywhere in an update request) is NOT one task. It is TWO complete, sequential operations:
Finishing operation 1 does NOT complete the command. Do NOT report results,
do NOT stop, do NOT wait for further input after the update — continue
straight into operation 2. The command is complete ONLY when
finish-check.sh --expect-commits 2 passes, i.e. git log origin/main..HEAD
shows BOTH commits (update + addition) and both passed validation. If you are
about to write the final summary and the user's request mentioned adding a
dependency but there is no addition commit — you are not done; go back and
perform operation 2.
<deps>") — the "Both at once" row of the command-types table — produce
two commits: first the update commit (all cherry-picked
bumps + their CHANGELOG.md entries), then the addition commit (catalog
edits + their CHANGELOG.md entries). Each commit follows the same rules —
changelog folded into its own commit, lint, link checks, validation. Never mix
bumps and additions in one commit.CHANGELOG.md or lint fixes into it). If the
dev-update-* branch already exists and carries commits from an earlier
command or session, record the current command's result as new commit(s) on
top — do not amend, reset, or squash into the old ones.start-update.sh records the command base and never moves it silently;
squash-commit.sh and commit-release.sh refuse to rewrite commits at or
below it; commit-release.sh also refuses to create a second message-commit
in the same command (a rephrased message would otherwise duplicate the
addition commit). If a script refuses, read its message — do not work around
it with hand-written git commands.Which catalog a dependency belongs to is decided by its Maven group alone — never by product name, ecosystem, or vendor. Apply the first matching rule:
| Maven group | Catalog |
|---|---|
androidx.* | versions-androidx |
com.redmadrobot.* | versions-redmadrobot |
| everything else | versions-stack |
Explicit consequences (do NOT ask about these — the rule already decides):
org.jetbrains.compose.* (Compose Multiplatform), org.jetbrains.androidx.*
(multiplatform ports of AndroidX libraries), org.jetbrains.kotlin*,
org.jetbrains.kotlinx.*, org.jetbrains.dokka.* → versions-stack.
"Compose" or "androidx" in the name does not move a JetBrains group into
versions-androidx.com.google.android.material (Material Components), com.google.*,
com.squareup.*, Firebase, Dagger, testing frameworks, Gradle plugins →
versions-stack.androidx.test.* group →
versions-androidx (group starts with androidx.).org.jetbrains.*, dev.*, com.* etc. → versions-stack unless the id
starts with androidx. or com.redmadrobot..If a dependency genuinely does not fit (e.g. a new red_mad_robot group that is
not com.redmadrobot.*), STOP and ask — do not guess a catalog.
All git operations use the ready-made scripts in
.claude/skills/update-version-catalog/scripts/ — do NOT hand-write git
commands, run these instead (via the Bash tool / Git Bash). Every mutating
script guards that HEAD is a dev-update-* branch, uses origin/main only as a
read-only base, and never opens an editor (so nothing can hang the session).
| Script | Purpose |
|---|---|
list-renovate-updates.sh | Fetch + list all renovate branches ahead of main, with bumps & diffs (read-only) |
start-update.sh [YYYY-MM-DD] [--new-command] [--force] | Start a command: fetch ALL remote branches, create/switch to (or stay on) the dev-update-* working branch, record the command base — run once at the start of every command |
cherry-pick-renovate.sh [names…] | Cherry-pick all (or named) renovate branches onto the working branch; safe to re-run |
squash-commit.sh ["msg"] | Squash the current command's picked commits into one |
show-version-diffs.sh | Catalog version diffs of the release commit + automatic version-format guard (read-only) |
bom-diff.sh <group:artifact> <old> <new> | Component version diff of two BOM releases, read from the BOMs' POMs (read-only) |
find-latest-version.sh <group:artifact>… | Latest stable version from Google Maven / Maven Central / Plugin Portal (read-only) |
resolve-doc-url.sh <group:artifact> <version> | Resolve a dependency's version-specific doc URL (known list → POM HomePage → GitHub tag) (read-only) |
known-doc-urls.tsv | Data file: dependencies whose docs have no per-version page (or are JS-rendered) + which link checks to skip for them |
commit-release.sh ["msg"] [--new-commit] | Create or amend the current command's commit (update or addition) with catalog + CHANGELOG.md changes |
lint-changelog.sh [--skip-renovate] | Cross-check [Unreleased] entries against the release diff, format rules, and renovate branches (read-only) |
check-doc-links.sh [--all] | Verify every added link: host policy, version-specific URL, reachability, version present on the page, #anchor exists (read-only) |
finish-check.sh [--skip-renovate] [--expect-commits N] [--with-gradle] | Final gate — git state, commit count, lint, links, :warning: candidates |
lib.sh | Shared helpers (sourced, never run): maps, version ordering, TOML parsing |
The scripts run on macOS and Windows/Git Bash alike: they stay within bash 3.2
(the version macOS ships) and POSIX/BSD tool behaviour. When editing them, keep to
the rules documented at the top of lib.sh — no associative arrays, no ${var,,},
no sort -V (use vsort/vge), no \t/\n in a sed replacement, no \s in a
regex, and no expansion of a possibly-empty "${array[@]}". *.sh is pinned to LF
in .gitattributes: a CRLF copy would fail on macOS with $'\r': command not found.
First check where you are: git branch --show-current.
On main or already on a dev-update-* branch → run:
bash .claude/skills/update-version-catalog/scripts/start-update.shThe script ALWAYS starts by fetching all remote branches with an explicit
refspec, so the fresh origin/main and every current origin/renovate/*
branch are available BEFORE the working branch is created. On main it then
creates dev-update-YYYY-MM-DD (today's date) off the freshly fetched
origin/main; local main is never modified. Pass an explicit YYYY-MM-DD
to override the date. Already on a dev-update-* branch it stays there — the
current command's results become new commit(s) on this branch.
It also refuses to start from any other branch and with a dirty working
tree (uncommitted changes would be swept into the release commit by
commit-release.sh). If it refuses, report the message and ask me — do not
pass --force on your own.
On any other branch (release/*, feature branch, …) → STOP and ask me
which branch to work on; do not guess.
Command base. The script records the current HEAD as the command base;
squash-commit.sh / commit-release.sh never rewrite anything at or below it.
Run it exactly once per command, at the start. If it is run again while a
command is in progress it now keeps the recorded base and prints a NOTE —
that is the safe behaviour, not an error. Only a genuinely NEW command on a
branch that already carries commits should move the base, with
start-update.sh --new-command.
What counts as a command. A command is a user request that starts a NEW
update or addition task («обнови каталоги», «добавь зависимость …»). A
follow-up request that corrects the result already produced in this session
(«исправь ссылку», «поправь changelog», fixing a lint/link problem you
reported) is a continuation of the previous command, NOT a new command: do
NOT re-run start-update.sh for it. Just edit the files and re-amend with
commit-release.sh.
First review what is available, then cherry-pick:
bash .claude/skills/update-version-catalog/scripts/list-renovate-updates.sh
bash .claude/skills/update-version-catalog/scripts/cherry-pick-renovate.sh # all
# or a subset: ... cherry-pick-renovate.sh dagger kotest hiltCherry-pick every renovate branch that has a new commit — not only the ones
touching versions-*/libs.versions.toml. Infrastructure updates such as the
Gradle wrapper (gradle/wrapper/*) and GitHub Actions (.github/workflows/*)
belong in the release commit too; they just do NOT get a CHANGELOG.md entry
(see "What NOT to record"). Skip a branch only if I explicitly say so — mention
what you skipped.
On a conflict the script stops and prints exactly what to do: resolve it in
versions-*/libs.versions.toml by keeping the newer version, git add the
file, run GIT_EDITOR=true git cherry-pick --continue, then simply re-run the
script — commits already on the branch are skipped by patch-id and by
subject, and a pick that turns out empty is skipped automatically.
All bumps collected by the current command must live in a single commit —
the CHANGELOG.md changes are added to that same commit later (step 8).
bash .claude/skills/update-version-catalog/scripts/squash-commit.shThe script builds the commit message itself (the subjects of the squashed
commits, oldest first, one per line — the same style as existing release
commits on main). Do NOT pass a message argument unless I explicitly asked
for a specific one.
After this, on a fresh branch git log origin/main..HEAD shows exactly one
commit. If the branch already carried commits from an earlier command, only the
current command's commits are squashed (the script says where it stopped).
bash .claude/skills/update-version-catalog/scripts/show-version-diffs.shFrom the output, collect per changed libs.versions.toml: library/plugin name,
old version (- lines), new version (+ lines). Classify each as added /
updated / removed / renamed (see symbols below).
Version-format change. The script's === version format guard === section
decides this for you: every FORMAT_CHANGE <alias> <old> → <new> (<reason>)
line is a bump whose version shape changed (pre-release suffix appeared or
disappeared, semver → calendar, plain → dash-compound, segment count changed
without shared leading segments). For each such line STOP and ask me to
confirm, showing the library with its old → new version; continue only
after I confirm. When the section prints OK — no version-format changes, do
not ask about version formats at all. (Gaining or losing a plain trailing patch
segment, 2.60 → 2.60.1, is not a format change and is never flagged.)
The catalog (and its changelog subsection) is determined by the catalog
distribution rule above — the subsection always matches the
libs.versions.toml the change lives in: versions-androidx/ → AndroidX,
versions-stack/ → Stack, versions-redmadrobot/ → red_mad_robot.
Every entry's library name is a link to release notes for that exact version. Where the URL comes from, in this order:
A previous release section of CHANGELOG.md already links this library →
reuse that URL with the new version substituted. This is the default for
:arrow_up: entries and almost always works.
Templates for the big families:
https://developer.android.com/jetpack/androidx/releases/{library}#{version}
(some libraries anchor as #{library}-{version} — the anchor check in
step 9 catches a wrong one);https://github.com/{org}/{repo}/releases/tag/{tag} —
the tag format varies per project (v1.2.3, dagger-2.60.1, r6.1.1,
plain 6.14.0), so do not assume the v prefix.Resolve it with the script — mandatory for :sparkle: entries and for
anything you are unsure about. Never construct a URL from a naming pattern:
bash .claude/skills/update-version-catalog/scripts/resolve-doc-url.sh <group:artifact> <version>It checks known-doc-urls.tsv first, then reads the artifact's HomePage
from its POM (Google Maven / Maven Central / Plugin Portal) and, when that is
GitHub, finds the tag matching the version via git ls-remote (no API
rate limit). Verdicts:
KNOWN <url> — from known-doc-urls.tsv; use as-is.RELEASE <url> / TAG <url> — the release/tag page for the version; use
it directly.HOMEPAGE <url> — only a project/repo home was found. This does NOT point
at the version, so it is not a valid CHANGELOG link: show me this URL
as the closest match and ask me for the correct version-specific URL.
Proceed only after I supply one (or confirm the shown one).NO_HOMEPAGE — the POM has no usable <url>/<scm> (common for Gradle
plugin markers). Use the Plugin Portal route in "Adding a new dependency"
step 5, or search GitHub for group:artifact.NOT_FOUND — the artifact POM is in no repository; STOP and ask me for the URL.GH_RATE_LIMITED <repo-url> — only from the API fallback; set
GITHUB_TOKEN/GH_TOKEN (or wait) and re-run. It is NOT "no release
exists" — do not downgrade to HOMEPAGE.A documentation link MUST point at the specific version (path, tag or
#anchor). A repository home, a docs landing page or a release-notes index
without a version anchor is invalid. A Maven artifact/repository page is
FORBIDDEN as an entry URL: never mvnrepository.com, search.maven.org,
central.sonatype.com, maven.google.com, repo1.maven.org or similar
listings. check-doc-links.sh enforces both rules in step 9.
Vendors without per-version pages. A few vendors (AppsFlyer, Firebase,
Google Play services, …) publish one release-notes page for everything, or
render the recent entries with JavaScript. They are listed in
known-doc-urls.tsv together with the checks to skip — resolve-doc-url.sh
returns their URL as KNOWN and check-doc-links.sh relaxes the version/anchor
checks for them. If step 9 fails for a NEW such vendor and you have verified in
a browser that the page really is the right release-notes page, propose adding a
row to known-doc-urls.tsv (and say so in the report) instead of silently
recording a version-less link.
[Unreleased]CHANGELOG.md, locate the ## [Unreleased] section.plugin: entries alphabetically.*No changes* when adding the first entry to a subsection; keep all
three subsections present even if some stay *No changes*.lint-changelog.sh matches by alias
name, not by version pair).CHANGELOG.md into the single commitThe CHANGELOG.md edit must go into the same commit as the version bumps —
do NOT create a separate commit for the changelog alone:
bash .claude/skills/update-version-catalog/scripts/commit-release.shThe script stages CHANGELOG.md plus any catalog edits and amends the squashed
commit from step 3 (or creates the release commit when none exists yet — see
"Adding a new dependency"). It prints git show HEAD --stat, which should list
both the versions-*/libs.versions.toml changes and CHANGELOG.md in one
commit, and warns about any modified file that was left out — read that
warning, it means something is not in the commit.
Run this BEFORE the checks in step 9: they read the commit, not the working
tree (lint-changelog.sh stops with an explicit message if you forget).
a. Lint the changelog against the release diff:
bash .claude/skills/update-version-catalog/scripts/lint-changelog.shCross-checks the [Unreleased] entries against the actual catalog diff and
the format rules: every catalog change (including added/removed/renamed modules
and plugin ids) is documented under its own alias, no phantom entries, exact
old → new versions — for nested BOM components too — correct subsection,
valid symbols/links/arrow, sorting, no duplicates, and that every renovate
branch's bump made it into the diff (a branch already superseded by a newer bump
is reported as INFO: … superseded, not as a problem).
The --skip-renovate flag is decided by the current command, not by the
commit being linted:
--skip-renovate, otherwise pending renovate branches would be falsely
reported as "not picked".Fix every reported problem in CHANGELOG.md, re-amend with commit-release.sh,
and re-run until it prints OK.
b. Verify every documentation link:
bash .claude/skills/update-version-catalog/scripts/check-doc-links.shFor each link added to CHANGELOG.md in HEAD it checks: forbidden Maven hosts,
that the URL itself carries the new version, reachability after redirects, that
the fetched page really mentions the version (dot/dash/underscore variants), and
that a #anchor exists in the HTML — a wrong anchor is invisible otherwise,
since fragments are client-side and the page still answers 200.
Do NOT check links by hand with WebFetch instead of this script. If it reports a
problem, fix the link (correct anchor/tag, or another release-notes source),
re-amend with commit-release.sh and re-run. Use WebFetch only to investigate
a reported problem, and known-doc-urls.tsv for a vendor that genuinely has no
per-version page (see step 6).
c. Validate the catalogs:
./gradlew validateCatalogConfirm the build passes. Report every result plainly — if a link is broken, a version is missing from its page, or validation fails, surface it rather than claiming success.
# update-only command
bash .claude/skills/update-version-catalog/scripts/finish-check.sh
# standalone addition
bash .claude/skills/update-version-catalog/scripts/finish-check.sh --skip-renovate
# combined update-and-add command
bash .claude/skills/update-version-catalog/scripts/finish-check.sh --expect-commits 2It re-checks the whole result in one place: working branch, no cherry-pick left
in progress, clean working tree, the expected number of commits ahead of
origin/main, every commit carrying its CHANGELOG entries, lint, links, and an
advisory list of :warning: candidates (major/minor bumps documented without
the mark — mention them to me, never add the mark yourself).
Combined command? Re-read the user's request: did it ALSO ask to add new
dependencies («…и добавь …», "…and add …")? If yes, the update you just finished
was only operation 1 of 2. Continue immediately with the "Adding a new
dependency" flow (steps 2–7 — do NOT re-run start-update.sh) and only report
the command as done when finish-check.sh --expect-commits 2 passes.
Report the result in Russian: the commits produced, what was documented, and any
ALL CHECKS PASSED / failures verbatim in substance. ./gradlew validateCatalog
is not part of the gate by default — either run it separately (step 9c) or pass
--with-gradle.
When I give Maven coordinates (group:artifact, e.g.
org.jetbrains.compose.foundation:foundation) and ask to add them, the flow
is: find the latest stable version → add to the right catalog → document →
one addition commit. This can happen inside a regular update session or
standalone.
When the same command also asked for an update, finish the update commit first (steps 1–9 of the workflow), then do the addition as a separate commit on top of it — never fold additions into the update commit (see "Commit rules"). All additions requested by one command share a single addition commit.
Working branch — same rule as workflow step 1: on main or a
dev-update-* branch run start-update.sh; any other branch → STOP and ask.
In a combined update-and-add command the update already ran it — do NOT run
it again for the addition.
Find the version in Maven:
bash .claude/skills/update-version-catalog/scripts/find-latest-version.sh org.jetbrains.compose.foundation:foundationfind-latest-version.sh only accepts group:artifact. Which coordinate to
pass depends on whether you are adding a library or a Gradle plugin —
tell them apart by how I gave it to you:
Library (goes in [libraries], given as Maven coordinates
group:artifact, contains a colon, e.g.
org.jetbrains.compose.foundation:foundation) → pass those coordinates
verbatim. Do not transform them.
Gradle plugin (goes in [plugins], given as a plugin id — a
dotted string with no colon, e.g. dev.drewhamilton.poko,
org.jetbrains.compose) → you MUST query the plugin's marker artifact,
whose coordinate is derived mechanically from the id:
<plugin.id>:<plugin.id>.gradle.plugini.e. the plugin id is used as BOTH the group and (with the
.gradle.plugin suffix) the artifact. Worked examples:
| Plugin id (given) | Coordinate to pass to the script |
|---|---|
dev.drewhamilton.poko | dev.drewhamilton.poko:dev.drewhamilton.poko.gradle.plugin |
org.jetbrains.compose | org.jetbrains.compose:org.jetbrains.compose.gradle.plugin |
com.google.devtools.ksp | com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin |
NEVER guess a group:artifact by splitting the id on the last dot (e.g.
dev.drewhamilton:poko is wrong and will return NOT_FOUND). Always
build the marker coordinate with the rule above. The marker artifact lives
in the Gradle Plugin Portal, which the script already queries.
Resolve the version to add by these rules, in order. Stable means a plain
release with no pre-release qualifier (no -alpha, -beta, -rc, -M,
-dev, -SNAPSHOT, etc.).
LATEST_STABLE <v>) → take it
and use it without asking.STABLE <v> NEWER_PRERELEASE <v>) → STOP and ask me which of the two
to use, showing both. Do NOT silently pick either.UNSTABLE candidates: …) → STOP and
ask me which of the shown versions to use. Do NOT silently pick a
pre-release.NOT_FOUND) → STOP and ask me both which
version to specify and which documentation URL to use. Do not guess.If repositories disagree on the latest version, show me both and ask.
Pick the catalog strictly by the Maven group per the
"Catalog distribution rule" section above: androidx.* →
versions-androidx; com.redmadrobot.* → versions-redmadrobot;
everything else (including org.jetbrains.compose.* and
org.jetbrains.androidx.*) → versions-stack. Do not ask which catalog —
the rule decides.
Edit that catalog's libs.versions.toml:
[versions]: add alias = "version". If the artifact shares a version
with already-present artifacts from the same project, reuse their existing
version alias instead of adding a new one.
[libraries]: add alias = { module = "group:artifact", version.ref = "alias" }
(for a Gradle plugin use [plugins] with id).
Follow the naming conventions: alias follows the Maven coordinates, drop module names that duplicate the group, version alias matches the library alias. Keep the file's existing grouping, comments, and alphabetical order within a group.
Gradle reserved words (the complete list) — never use extensions,
class, or convention as an alias segment, nor bundles, versions,
or plugins as the first segment. ./gradlew validateCatalog (step 9c)
is the final safety net for a bad alias.
Worked example — adding the libraries com.example.avocado:avocado and
com.example.avocado:avocado-core 1.2.0 plus the Gradle plugin
dev.drewhamilton.poko 0.19.3:
[versions]
avocado = "1.2.0" # one shared version alias for the whole project
poko = "0.19.3"
[libraries]
# artifact repeats the group's last word → alias keeps only "avocado"
avocado = { module = "com.example.avocado:avocado", version.ref = "avocado" }
avocado-core = { module = "com.example.avocado:avocado-core", version.ref = "avocado" }
[plugins]
poko = { id = "dev.drewhamilton.poko", version.ref = "poko" }CHANGELOG entry — a :sparkle: line in the matching subsection of
[Unreleased], with the version in backticks (see the format reference).
Entry name = the library alias; a plugin entry additionally carries the
plugin: prefix.
Resolve the link — never invent it, with resolve-doc-url.sh and the
verdicts listed in workflow step 6. For a library pass its Maven
coordinates verbatim. For a Gradle plugin the marker artifact's POM
usually has no HomePage (NO_HOMEPAGE) — then find the real repository via
the Plugin Portal page:
https://plugins.gradle.org/plugin/<plugin.id>e.g. https://plugins.gradle.org/plugin/dev.drewhamilton.poko →
github.com/drewhamilton/Poko → release/tag URL for the version. (Web search
for "<plugin.id> github" is a fine fallback.) A plugin id is NOT a GitHub
path — never turn dev.drewhamilton.poko into
github.com/dev.drewhamilton/poko.
The Maven artifact page and the Plugin Portal page are lookup aids only — never put them in the entry. If none of these steps yield a version-specific documentation URL, STOP and ask me for it before writing the entry.
Commit:
bash .claude/skills/update-version-catalog/scripts/commit-release.sh "stack: add <alias> <version>"Standalone add: the script creates the addition commit, and later re-runs (lint/link fixes) amend it — re-run it with the exact same message, a different message is refused so a rephrasing cannot produce a second commit. Combined update-and-add command: the update commit already exists, so this creates the addition commit on top of it.
Validate as in workflow step 9, then run the final gate (step 10). The
--skip-renovate rule applies: standalone add command (nothing
cherry-picked) → lint-changelog.sh --skip-renovate and
finish-check.sh --skip-renovate; combined update-and-add command → WITHOUT
the flag and with --expect-commits 2.
| Symbol | Meaning |
|---|---|
:sparkle: | Added dependency |
:arrow_up: | Updated dependency |
:x: | Removed dependency |
:memo: | Dependency or version name changed |
:warning: | Be careful on update. May contain breaking or behaviour changes. |
:warning: is NOT set by this skill — deciding whether an update is breaking
requires reading the dependency's release notes, which is out of scope here.
finish-check.sh lists major/minor bumps as candidates; report them to the
maintainer, who adds the mark. Preserve any existing :warning: marks when
editing entries.
## [Unreleased] — changes not yet released, with the three subsections
### red_mad_robot, ### AndroidX, ### Stack.## [YYYY.MM.DD], each with the same three subsections.# New dependency — link the library's release/tag page for the version;
# never a Maven artifact page (ask the user if none can be found)
- :sparkle: [library-name](release-or-tag-url) `version`
# Updated dependency
- :arrow_up: [library-name](release-notes-url) `old-version` → `new-version`
# Removed dependency
- :x: [library-name](release-notes-url)
# Renamed / changed
- :memo: [library-name](release-notes-url) description
# Plugin — prefix with `plugin:`
- :arrow_up: plugin: [Plugin Name](url) `old-version` → `new-version`Use the real arrow → (never ->). Wrap version numbers in backticks. Entry
name = the catalog alias. Sorting inside a subsection: libraries alphabetically,
then plugin: entries alphabetically; - *No changes* when there is nothing.
BOM updates — list individual component bumps nested under the BOM entry:
- :arrow_up: [compose-bom](url) `2026.06.00` → `2026.06.01`
- :arrow_up: [compose-animation](url) `1.11.3` → `1.11.4`
- :arrow_up: [compose-foundation](url) `1.11.3` → `1.11.4`Where the nested versions come from:
Components that have their own alias in the catalog (all compose-* ones
do — Renovate bumps them alongside the BOM) → take the versions from the
catalog diff (show-version-diffs.sh). This is the source of truth, and
lint-changelog.sh cross-checks nested entries against it.
Components without an alias of their own (e.g. individual Firebase
artifacts under firebase-bom) → get the list mechanically from the BOMs'
POMs:
bash .claude/skills/update-version-catalog/scripts/bom-diff.sh androidx.compose:compose-bom 2026.06.00 2026.06.01
bash .claude/skills/update-version-catalog/scripts/bom-diff.sh com.google.firebase:firebase-bom 34.16.0 34.17.0Do not read version numbers off the BOM-mapping web page; the POM diff is exact. Each nested component links to its own release notes.
Monorepo updates — each library from the same repo gets its own entry:
- :arrow_up: [okhttp](url) `5.2.1` → `5.3.2`
- :arrow_up: [okhttp-logging-interceptor](url) `5.2.1` → `5.3.2`Catalog name changes — use the memo symbol (a module/plugin-id change with
an unchanged version needs an entry too; lint-changelog.sh requires it):
- :memo: [library-name](url) Renamed from old-name to new-namelint-changelog.sh (step 9a) enforces symbols, link syntax, backticked
versions, the → arrow, plugin: prefixes, sorting, duplicates, the three
subsections, exact old → new versions and full coverage of the diff;
check-doc-links.sh (step 9b) enforces the link rules. Do not re-verify these
by hand — run the scripts and fix what they report. Two things they cannot
check, which stay on you:
:warning: marks are preserved (never add one yourself);Do not add to the changelog:
This skill records changes into [Unreleased]. Cutting an actual release
(moving [Unreleased] into a dated ## [YYYY.MM.DD] section, bumping
gradle.properties, updating footer compare links, tagging) is done by
./release.sh — do not do it here unless the user explicitly asks to release.
© RedMadRobot, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 14 other files (scripts) in .claude/skills/update-version-catalog of RedMadRobot/gradle-version-catalogs.
Open the folder on GitHubat commit c5bab82
Update Version Catalog next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Update Version Catalog this skillRedMadRobot/gradle-version-catalogs | 118 | — | ~9.5k | Automated safety check: Pass | MIT | |
| Docs Engineeringhiroshiyui/GuilelessBopomofo | 135 | — | ~806 | Automated safety check: Pass | GPL-3.0 | |
| Release Engineeringhiroshiyui/GuilelessBopomofo | 135 | — | ~1.6k | Automated safety check: Pass | GPL-3.0 | |
| Hz API Upgrademeta-quest/agentic-tools | 213 | — | ~1.8k | Automated safety check: Pass | Apache-2.0 | |
| AppsFlyer Unity Plugin Release CheckAppsFlyerSDK/appsflyer-unity-plugin | 178 | — | ~470 | Automated safety check: Pass | MIT | |
| AppsFlyer Unity SDK Version BumpAppsFlyerSDK/appsflyer-unity-plugin | 178 | — | ~789 | Automated safety check: Pass | MIT |
hiroshiyui/GuilelessBopomofo
Writing/updating project documentation (README, PRIVACY-POLICY, NOTICES, changelogs) and maintaining F-Droid metadata.
hiroshiyui/GuilelessBopomofo
Release engineering tasks including version bumping, building release APKs, creating git tags, writing changelogs, and preparing F-Droid releases.
meta-quest/agentic-tools
Upgrades Meta VR apps to newer Horizon OS SDK versions — migration guides, deprecated API replacements, changelog.
AppsFlyerSDK/appsflyer-unity-plugin
Reviews the AppsFlyer Unity plugin before a release: version consistency, changelog, Android and iOS parity, billing variants and .unitypackage freshness.
AppsFlyerSDK/appsflyer-unity-plugin
Guides a consistent bump of the Android or iOS SDK wrapped by the AppsFlyer Unity plugin, keeping both billing library variants and release files in step.
niki914/zafiro
A skill your agent uses when the user wants to release a new Zafiro version — drafting bilingual release notes, deciding the next version number, bumping app/build.gradle.kts, tagging, and…
Categories
Use EVERY time the user asks to update / bump the version catalogs, "сделать обновление", "обновить каталог(и)", "обнови версии", "оформи изменения", "update the catalog", or to record dependency…. Update Version Catalog is an agent skill from RedMadRobot/gradle-version-catalogs. Use EVERY time the user asks to update / bump the version catalogs, "сделать обновление", "обновить каталог(и)", "обнови версии", "оформи изменения", "update the catalog", or to record dependency version changes in the changelog.
Update Version Catalog fits situations like: the user asks to add a new dependency (добавь зависимость; add dependency) giving Maven coordinates like group:artifact — the skill finds the latest stable version; adds it to the right catalog; records it in the changelog.
Run `npx skills add RedMadRobot/gradle-version-catalogs --skill update-version-catalog -a claude-code`. Or copy the skill folder (.claude/skills/update-version-catalog in RedMadRobot/gradle-version-catalogs) into .claude/skills/update-version-catalog in your project. Claude Code loads it when a task matches its description.
Run `npx skills add RedMadRobot/gradle-version-catalogs --skill update-version-catalog -a codex`. Or copy the skill folder (.claude/skills/update-version-catalog in RedMadRobot/gradle-version-catalogs) into .agents/skills/update-version-catalog in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add RedMadRobot/gradle-version-catalogs --skill update-version-catalog -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/update-version-catalog, .gemini/skills/update-version-catalog, .github/skills/update-version-catalog and .opencode/skills/update-version-catalog in your project.
Going by SKILL.md and its folder, Update Version Catalog needs a shell for the scripts in its folder, the command-line tools its instructions call (bash and git) and credentials named GITHUB_TOKEN and GH_TOKEN. Our summary lists: A Bash shell.
SKILL.md names 3 domains. In commands or code: plugins.gradle.org, developer.android.com and github.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Update Version Catalog is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 9.5k tokens (SKILL.md is roughly 38k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Update Version Catalog: Docs Engineering (hiroshiyui/GuilelessBopomofo, 135 stars), Release Engineering (hiroshiyui/GuilelessBopomofo, 135 stars), Hz API Upgrade (meta-quest/agentic-tools, 213 stars) and AppsFlyer Unity Plugin Release Check (AppsFlyerSDK/appsflyer-unity-plugin, 178 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
RedMadRobot (a GitHub organization) maintains it in RedMadRobot/gradle-version-catalogs, which has 118 GitHub stars. The repository was last updated on October 3, 2026.
Source: RedMadRobot/gradle-version-catalogs on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.