Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Dependabot-aware dependency updates with security audit, real-CI validation, and a unified PR. Framework-agnostic.
.claude/skills/joshukraine-update-deps/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 90% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 152% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 146% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 98% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 51% | 0% |
Update project dependencies safely: reconcile open Dependabot PRs into one unified change, run the project's security audit, validate boot-affecting changes against the real CI environment, and open a single PR — instead of stopping at local commits.
This skill is framework-agnostic. It detects the project's package manager, test/lint commands, audit suite, and CI workflow rather than assuming a stack.
--dry-run: Show what would be updated without making changes--major: Include major version updates (default: minor/patch only)--package <name>: Update specific package only--skip-tests: Skip running tests between updatestextDetect → Reconcile Dependabot → Update → Audit → Validate on real CI → Open PR → Verify auto-close
Each stage feeds the next. Don't skip the audit or the real-CI validation for boot-affecting changes — those are the two stages that catch what local tests can't.
Detect both the package manager and the project's real entry points. The runners below are common defaults, not assumptions — always confirm against what the repo actually uses.
package.json (npm/yarn/pnpm) — check the lockfile to disambiguateGemfile (bundler)requirements.txt / pyproject.toml (pip/poetry/uv)Cargo.toml (cargo)go.mod (go modules)bin/ci, bin/test, script/test, or a Makefile/Justfile target is the canonical gate — use it if present.tsc, mypy, etc..github/workflows/*.yml and identify the workflow that runs on the default branch and the jobs it contains.Before making any changes, find out what Dependabot already has in flight:
bashgh pr list --app dependabot --state open --json number,title,headRefName,body
Keep the safe, category-by-category loop:
--major. Isolate a risky major into its own commit — or its own PR — so it can be rolled back cleanly without reverting the safe bumps.--skip-tests: skip test execution.require:), a renamed config key. These are where "the tests pass but boot breaks" lives.This is the highest-value stage on a dependency PR — not an afterthought. After updates, run the project's detected audit suite and fold any newly surfaced fix into this PR (a fresh advisory is in-scope, not a separate task):
| Ecosystem | Audit tools (detect what's present) | | --------- | ----------------------------------- | | Ruby | bundler-audit; plus brakeman and importmap audit on Rails | | Node | npm audit, yarn npm audit, pnpm audit | | Python | pip-audit, safety | | Rust | cargo audit | | Go | govulncheck |
If the project's CI gate (e.g. bin/ci) already runs these, run that gate rather than invoking each tool separately.
A change that touches the manifest (the Gemfile, package.json, pyproject.toml — not just the lockfile) can alter what loads at boot. Local gates cannot catch a failure caused by a system library that happens to be installed on the dev machine but missing on one CI job. Validate those changes on the actual CI environment before recommending merge:
bashgh workflow run <ci-workflow> --ref <branch> gh run watch # or: gh run list --branch <branch>
Do this when:
require:/load behavior, version constraint change), and/orLockfile-only patch bumps with a green local gate generally don't need a dedicated CI run.
Stop-at-commits is not the finish line. Open one PR for the reconciled set, following the project's PR conventions — hand off to the /create-pr skill (it generates the description, links issues, and updates the ROADMAP). Summarize in the PR body: the bumps grouped by category, the Dependabot PRs this supersedes, any CVE fixed, and the result of the real-CI run.
After the PR merges, expect Dependabot to auto-close the superseded PRs on its own — verify it did rather than pre-emptively closing them:
bashgh pr list --app dependabot --state open
dependabot/dependabot-core#13606) — close it manually with a note. Don't duplicate Dependabot's behavior or race its rebase.The lessons this workflow encodes, worth keeping in mind when a situation doesn't fit the steps above:
bashnpm outdated # check npm update <pkg> # update
bashbundle outdated bundle update <gem>
bashpip list --outdated poetry show --outdated && poetry update <pkg>
bashcargo outdated cargo update <pkg>
bashgo list -u -m all go get -u <pkg>
1.2.3 → 1.2.4.1.2.3 → 1.3.0.--major) — breaking changes, e.g. 1.2.3 → 2.0.0. Isolate for clean rollback.Use Conventional Commits format from global CLAUDE.md:
textchore(deps): update dependencies Security updates: - erb: 6.0.1 → 6.0.3 (CVE-2026-41316) Patch updates: - rails: 7.1.3 → 7.1.5 Minor updates: - image_processing: 1.12 → 2.0 Breaking changes: - image_processing 2.0 requires ruby-vips; added with require: false so a missing libvips does not crash boot.
Follow dependency best practices from global CLAUDE.md:
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 11,448 | 4,122 | -64% | 1 | 1 | 0% | 1,917 | 2,666 | +39% | 0 | 0 | — |
case-02 | fail→fail | 12,126 | 9,570 | -21% | 1 | 1 | 0% | 2,015 | 2,454 | +22% | 0 | 0 | — |
case-03 | fail→fail | 16,296 | 11,892 | -27% | 1 | 1 | 0% | 2,848 | 2,556 | -10% | 0 | 0 | — |
case-04 | fail→pass | 10,556 | 8,823 | -16% | 1 | 1 | 0% | 1,935 | 3,677 | +90% | 0 | 0 | — |
case-09 | fail→pass | 6,204 | 2,116 | -66% | 1 | 1 | 0% | 1,007 | 2,540 | +152% | 0 | 0 | — |
case-05 | pass→pass | 9,658 | 5,250 | -46% | 1 | 1 | 0% | 1,490 | 3,116 | +109% | 0 | 0 | — |
case-06 | fail→pass | 8,711 | 5,959 | -32% | 1 | 1 | 0% | 1,308 | 3,223 | +146% | 0 | 0 | — |
case-07 | pass→pass | 12,462 | 6,791 | -46% | 1 | 1 | 0% | 2,032 | 3,361 | +65% | 0 | 0 | — |
case-08 | pass→pass | 14,552 | 5,026 | -65% | 1 | 1 | 0% | 2,226 | 3,045 | +37% | 0 | 0 | — |
case-10 | fail→pass | 8,878 | 3,679 | -59% | 1 | 1 | 0% | 1,414 | 2,796 | +98% | 0 | 0 | — |
case-11 | pass→pass | 10,883 | 7,667 | -30% | 1 | 1 | 0% | 1,749 | 3,582 | +105% | 0 | 0 | — |
case-12 | pass→pass | 6,528 | 4,873 | -25% | 1 | 1 | 0% | 1,126 | 3,118 | +177% | 0 | 0 | — |
case-13 | fail→pass | 15,035 | 7,652 | -49% | 1 | 1 | 0% | 2,334 | 3,528 | +51% | 0 | 0 | — |
case-14 | pass→pass | 5,788 | 2,685 | -54% | 1 | 1 | 0% | 855 | 2,647 | +210% | 0 | 0 | — |
case-15 | pass→pass | 13,103 | 7,158 | -45% | 1 | 1 | 0% | 2,234 | 3,399 | +52% | 0 | 0 | — |
case-16 | fail→pass | 12,602 | 4,742 | -62% | 1 | 1 | 0% | 1,896 | 2,977 | +57% | 0 | 0 | — |
case-17 | pass→pass | 14,242 | 7,171 | -50% | 1 | 1 | 0% | 2,512 | 3,333 | +33% | 0 | 0 | — |
case-18 | fail→pass | 14,178 | 2,788 | -80% | 1 | 1 | 0% | 2,215 | 2,621 | +18% | 0 | 0 | — |
case-19 | pass→pass | 11,184 | 5,863 | -48% | 1 | 1 | 0% | 1,852 | 3,213 | +73% | 0 | 0 | — |
case-20 | pass→pass | 11,049 | 5,302 | -52% | 1 | 1 | 0% | 1,745 | 3,079 | +76% | 0 | 0 | — |
case-21 | pass→pass | 4,161 | 4,025 | -3% | 1 | 1 | 0% | 830 | 3,010 | +263% | 0 | 0 | — |
case-22 | pass→pass | 4,876 | 7,754 | +59% | 1 | 1 | 0% | 799 | 3,558 | +345% | 0 | 0 | — |
case-23 | pass→pass | 6,902 | 6,532 | -5% | 1 | 1 | 0% | 1,292 | 3,377 | +161% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 21 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +30 percentage points is the difference between those two pass rates over the 21 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.