UP

update-major-deps

Safely performs major version updates by grouping related dependencies, testing them, and committing changes individually.

Install

mkdir -p .claude/skills/update-major-deps && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/12225" && unzip -o skill.zip -d .claude/skills/update-major-deps && rm skill.zip

Installs to .claude/skills/update-major-deps

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Perform major dependency updates one logical group at a time, assessing breakage risk, then build, test, and create a signed commit per group
141 charsno explicit “when” trigger
Advanced

Key capabilities

  • Confirm a clean working tree before starting
  • Detect and group major dependency updates
  • Assess breakage risk for each dependency group
  • Apply dependency bumps while preserving the lockfile
  • Build and test after applying each bump
  • Create a signed commit for each successful group update

How it works

The skill identifies major dependency updates, groups them by coupling, assesses breakage risk, applies the bump, builds and tests, then creates a signed commit for each group.

Inputs & outputs

You give it
Optional scope argument (all or package-name)
You get back
A summary table of processed dependency groups, their risk, build/test status, and commit SHA

When to use update-major-deps

  • Updating monorepo dependencies
  • Bisecting regression risks
  • Modernizing devDependencies

About this skill

You are performing major version updates of devDependencies in this monorepo, one logical group at a time. For each group you assess breakage risk, apply the bump, build, test, and — only when green — create a single signed commit. You never push; the user pushes themselves.

Input

  • No args, or all → process every available major update.
  • <package-name> → process only the group containing that package (e.g. @babel/core processes the whole @babel/* group).

Core principles

  • One logical group per commit. Isolating each change makes regressions trivial to bisect and revert.
  • Tests gate every commit. Never commit a group whose build or tests fail.
  • Commit-only. Never git push. Never use --no-verify or otherwise bypass hooks.
  • Risk-gated. Auto-proceed for none/low risk; pause and ask the user before committing a medium/high risk group.

Process

1. Preflight

  • Confirm the working tree is clean (git status --short). If not, stop and report — do not mix unrelated changes into dependency commits.
  • Confirm Node/npm are available (node -v, npm -v). This repo uses Node 22.12 via nvm; if npm is missing, the terminal likely hasn't loaded nvm (source ~/.zshrc).
  • Note the current branch.

2. Detect and group major updates

Run a dry check:

npx --yes npm-check-updates --dep dev

Identify entries whose major version increases. Then group coupled packages that must move together:

  • All @babel/* (@babel/cli, @babel/core, @babel/preset-env, presets/plugins) → one group.
  • All @commitlint/* (@commitlint/cli, @commitlint/config-conventional) → one group.
  • Any other related family sharing a major line → one group.
  • Everything else → its own single-package group.

Order the groups lowest risk first (see step 3) so cheap wins land before risky changes.

3. Assess breakage risk (per group)

Produce a risk level of none / low / medium / high with a short rationale, using these signals:

  • Role in the pipeline (biggest factor):

    • Editor-only (e.g. @types/* in a JS-only repo with no tsconfig/.ts source) → none.
    • Test-only, using only stable core APIs → none/low.
    • Tooling / git-hook gating (lint-staged, husky) → low/medium (can block commits, but not ship broken code).
    • Commit/CI gating (@commitlint/*) → medium (a stricter ruleset can reject commit messages).
    • Affects compile output (@babel/*, webpack, loaders) → high (regenerates docs/** and dist artifacts; broad blast radius).
  • Usage breadth: count real usage sites (grep -rl across packages/*/*/src, packages/*/*/test, and root config). Few sites + only core APIs → lower risk.

  • Direct vs transitive: deduped/transitive-only presence → lower risk than a directly exercised dependency.

  • Changelog red flags: dropped Node/engine support, removed or renamed APIs, stricter-by-default behavior, config-format changes.

  • Engine vs active runtime (check explicitly): compare the target version's engines.node against the running node -v. Mismatch raises risk — and is especially dangerous for tools invoked by git hooks (lint-staged, commitlint), since a hook failure blocks every commit, including the bump's own commit. Resolve by upgrading Node first (e.g. nvm install 22 --reinstall-packages-from=<current>), then re-evaluate (risk usually drops once the engine is satisfied).

    npm view <pkg>@<target> engines
    node -v
    

State the level and rationale before touching anything.

4. Gate on risk

  • none / low → proceed automatically.
  • medium / highstop and ask the user to confirm before applying. Summarize the risk and what could break.

5. Apply the bump (lock-preserving)

Install the whole group to its new major in one command, e.g.:

npm install --save-dev @babel/core@^8 @babel/cli@^8 @babel/preset-env@^8

Confirm package.json reflects the new ranges.

Preserve the lockfile — never clean-nuke. Do not "fix" install problems with rm -rf node_modules package-lock.json && npm install. A lockfile-free resolve re-floats unrelated deps to the latest in-range version, which can land on a release your registry/security proxy blocks (e.g. a 403 Forbidden on [email protected] while the committed lock safely pinned 3.8.4). Keeping the lockfile as the baseline means only the group you target changes.

Handling ERESOLVE on coupled toolchains. Upgrading a coupled family (e.g. @babel/* core+cli+preset-env) against an existing lock can ERESOLVE because npm anchors on the locked old version (Found: @babel/[email protected]) while installing the new one — an incremental-resolver deadlock, not a real incompatibility. Both targeted (npm install pkg@^8) and full (npm install) forms can hit it. The lock-preserving fix:

npm install --legacy-peer-deps

With the lockfile present, this keeps every other dep pinned (so prettier stays at its safe version) while letting the babel subtree move to v8. After it completes, verify the resulting tree is self-consistent before trusting it:

npm ls @babel/core @babel/cli @babel/preset-env
npm ls babel-plugin-polyfill-corejs3   # must be a major that supports core 8 (1.x)
npm ls prettier                        # must be unchanged / safe version

6. Build and test

npm run build
npm test
  • Green → continue to commit.
  • Red → stop. Report the failure, leave the changes in the working tree for inspection, and do not commit. Suggest next steps (read changelog/migration guide, adjust config). Do not attempt unrelated fixes.

7. Commit (signed, commit-only)

Stage exactly the files this group changed (package.json, package-lock.json, and any legitimately regenerated build artifacts). For compile-affecting groups like @babel/* this includes the regenerated docs/**/*.min.js(.map) bundles and packages/**/dist/cjs/index.js outputs — stage them explicitly (git add package.json package-lock.json docs packages). Review with git status --short first. Never git add -A and never sweep in unrelated working-tree changes (e.g. skill files under .claude/ or CLAUDE.md).

Use a Conventional Commits message (the repo enforces commitlint + a husky commit-msg hook). Examples:

build(deps-dev): bump @types/node from 25 to 26
build(deps-dev): bump @babel/core, @babel/cli and @babel/preset-env from 7 to 8

Commits are GPG-signed automatically (commit.gpgsign=true). Verify with:

git log -1 --format='%h %G? %an <%ae>'

%G? should print G (good signature). Do not push.

8. Repeat and report

Move to the next group. When done (or stopped), output a summary table — one row per group, ordered as processed:

GroupRiskBuild/TestCommit
<pkg> <old><new>none/low/medium/highpass/fail<short-sha>

List any groups that were skipped (risk not confirmed) or failed (left uncommitted for follow-up).


Safety reminders

  • Never git push.
  • Never bypass hooks (--no-verify) or force anything.
  • Never bundle multiple groups into one commit.
  • Never clean-nuke the lockfile to resolve an install error — it can float unrelated deps to forbidden/newer versions. Prefer lock-preserving installs (--legacy-peer-deps with the lock present for coupled-toolchain ERESOLVE).
  • If the working tree starts dirty or a build/test fails, stop rather than working around it.

When not to use it

  • When the user wants to bypass hooks or force changes
  • When the user wants to bundle multiple groups into one commit

Prerequisites

Node 22.12npm

Limitations

  • Never `git push`
  • Never bypass hooks (`--no-verify`) or force anything
  • Never bundle multiple groups into one commit

How it compares

This skill updates major dependencies one logical group at a time with risk assessment and lockfile preservation, which is more controlled and less prone to regressions than a bulk update.

Compared to similar skills

update-major-deps side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
update-major-deps (this skill)01moNo flagsAdvanced
upgrade-deps02moNo flagsAdvanced
pr-workflow03moReviewIntermediate
ai-pr027dNo flagsAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry