# Upgrade dependencies with AI without breaking the build

URL: https://agentvera.dev/en/blog/upgrade-dependencies-with-ai/ · Published: 2026-10-27

Upgrade dependencies with AI agents safely: triage npm outdated, one major per branch, read the migration guide, run codemods, verify with tests and fix Dependabot PRs.

**In short:**

- Start with an inventory: npm outdated, pnpm outdated or pip list --outdated, plus npm audit, then have the agent sort every update into patch, minor and major with a risk note.
- Batch patch and minor updates into one branch, but give each major upgrade its own branch or worktree, with the migration guide read first and the official codemod run before the agent edits.
- The test suite, type check and build are the proof. Forbid editing tests to make them pass, keep the lockfile committed and review its diff.
- Dependabot and Renovate open the PRs; an agent can read the failing CI log on that branch, fix the code and push, which is where most of the saved time is.

**To upgrade dependencies with AI, let the agent do the reading and the repetitive edits, and keep the safety rules for yourself: one major upgrade per branch, the migration guide read before any code changes, and the test suite as the only proof that it worked.** Coding agents such as Claude Code, Codex and Gemini CLI are good at the tedious part of upgrades: renaming an API in eighty files, adapting test setup to a new runner, explaining a cryptic peer dependency error. They are bad at one thing that matters a lot here: they remember the old version of the library.

This guide walks through a workflow that works for a small app and a large monorepo alike: inventory, triage, batching the easy updates, isolating the hard ones, codemods, lockfiles, verification, bot PRs and security advisories. Examples use npm and pnpm, with Python equivalents where they differ.

## Why dependency upgrades go wrong with agents

Upgrades look simple, which is why they go wrong. The usual failure modes:

- **Stale knowledge.** A model’s training data stops at some point. Ask it to move to a version released after that and it will confidently write code for the version it knows.
- **Scope creep.** “Upgrade React” turns into React, the router, the test library, ESLint and three plugins, all in one diff.
- **Moving the goalposts.** A test fails after the upgrade, so the agent updates the snapshot, loosens the assertion or skips the test.
- **Silencing the installer.** A peer dependency conflict gets “fixed” with `--force` or `--legacy-peer-deps` instead of finding versions that actually fit together.
- **Lockfile chaos.** The agent deletes the lockfile to make an install error go away, and hundreds of transitive packages change at once.

Every step below is there to block one of these.

## Step 1: take an inventory

Start with facts, not a prompt like “update everything”. Each ecosystem has a built-in command that lists what is behind:

```bash
npm outdated            # Current, Wanted (highest in your range) and Latest
pnpm outdated           # add -r in a workspace
pip list --outdated     # for the active Python environment
```

Add the security view:

```bash
npm audit
pip-audit               # PyPA tool: pip install pip-audit
```

Then hand the output to the agent and ask for a triage, not changes:

```text
Here is the output of npm outdated and npm audit. Don't change anything yet.
Make a table with: package, current, wanted, latest, update type
(patch/minor/major), whether it's a direct or dev dependency, and a link to
its changelog or releases page. Flag anything with a security advisory.
Then propose an order: what can be batched, what needs its own branch.
```

This is a read-only job, so it’s safe to run in a planning mode or with a read-only permission setting. The table becomes your plan, and it shows you early which upgrades are actually big.

## Step 2: batch the easy updates

Patch and minor versions are supposed to be backwards compatible. In practice they usually are, and the test suite catches the rest. Do them together, on one branch:

```bash
git switch -c deps/minor-patch
npm update              # stays inside the ranges in package.json
```

With pnpm, `pnpm update` does the same, `pnpm update --interactive` lets you pick, and `pnpm update --latest` crosses major versions, so keep that one for Step 3. Then:

```text
Run the full test suite, the type check and the build. If something fails,
find which package caused it and fix the code, not the tests. If a fix
needs more than a few lines, revert that one package to its previous
version and list it for a separate upgrade.
```

That last sentence matters. It keeps the batch small and boring, and moves anything surprising into its own branch.

## Step 3: one major upgrade per branch

A major version means breaking changes by definition. Give each one its own branch, and if you want to run several at the same time, its own folder with a [git worktree](/en/glossary/git-worktree/ "What is a git worktree"):

```bash
git worktree add ../app-vite -b deps/vite-major
git worktree add ../app-eslint -b deps/eslint-major
```

Now one agent upgrades the build tool, another the linter, and your main folder stays untouched. If one upgrade turns into a swamp, you delete that worktree and branch and lose nothing else. [Git worktrees for parallel agents](/en/blog/git-worktree-parallel-agents/ "Git worktrees for parallel agents") covers the setup in more detail.

Two rules for majors:

- **One major step at a time.** Going from version 3 to 6 in one jump stacks three sets of breaking changes in one diff. Go 3 → 4, get green, commit, then 4 → 5.
- **Upgrade related packages together, and nothing else.** A framework and its official plugins often have to move in lockstep. That’s fine. Unrelated packages wait.

## Step 4: read the migration guide before touching code

This is the step that fixes the stale-knowledge problem. Before the agent edits anything, it should read the real documentation for the exact version you’re moving to:

```text
We're upgrading eslint from 8 to 9. Before editing any file:
1. Read the official migration guide and the changelog for 9.0.0.
2. List each breaking change that applies to this repo, with the files
   it affects (search the code to confirm).
3. Say what you will do for each one.
Use the installed package's docs and type definitions as the source of
truth, not what you remember about older versions. Wait for my OK.
```

If your agent can browse, it fetches the guide itself; if not, paste the relevant parts or point it at the release notes in `node_modules/<package>/CHANGELOG.md` when the package ships one. An MCP documentation server helps here too; see [the best MCP servers for coding](/en/blog/best-mcp-servers-for-coding/ "Best MCP servers for coding").

The list it produces is also your review checklist later: every item should map to a change in the diff.

## Step 5: let the codemod go first

Many frameworks ship codemods: scripts that rewrite code mechanically for a new version. A codemod is deterministic and the agent is not, so let the codemod do everything it can and give the agent what’s left.

Two well-known examples:

```bash
# Next.js: upgrades Next.js, React and React DOM and runs the codemods
npx @next/codemod upgrade major

# Angular: updates packages and runs their migrations
ng update @angular/core @angular/cli
```

As of October 2026, the Next.js docs note that `@next/codemod upgrade` runs non-interactively and accepts every default when stdin isn’t a terminal, which is the case when an agent runs it. If you want to choose which codemods apply, run it yourself first and hand the result to the agent.

After the codemod, commit, then ask the agent to handle the remaining items from Step 4: the cases the codemod marked or skipped, custom wrappers around the old API, test setup, and config files. Keeping the codemod output and the agent’s edits in separate commits makes review much easier. The same idea applies to bigger migrations; [refactor legacy code with AI](/en/blog/refactor-legacy-code-with-ai/ "Refactor legacy code with AI") and [migrate JavaScript to TypeScript with AI](/en/blog/migrate-javascript-to-typescript-with-ai/ "Migrate JavaScript to TypeScript with AI") go deeper into step-by-step migrations.

## Step 6: treat the lockfile as part of the change

The lockfile is what makes “works on my machine” mean anything. A few rules worth putting in `AGENTS.md` or `CLAUDE.md`:

```markdown
## Dependencies
- Never delete package-lock.json / pnpm-lock.yaml to fix an install error.
- Don't use --force or --legacy-peer-deps without asking.
- Install with npm ci in CI; commit the lockfile with the package.json change.
- Don't add new dependencies during an upgrade task.
```

When an install fails on peer dependencies, ask the agent to explain the conflict instead of forcing it. `npm explain <package>` (alias `npm why`) shows why a package is in the tree and who requires which version; `npm ls <package>` shows every copy. Often the real fix is upgrading the plugin that pins the old peer, which belongs in the same branch.

When you review, look at the lockfile diff too. A minor bump of one direct dependency that changes three hundred transitive entries deserves a question.

## Step 7: verify with your own checks

“It installs” is not done. Define done in the prompt, in terms the agent can check:

```text
Done means: npm ci succeeds, npm test passes, tsc --noEmit passes,
npm run build passes, and no existing test file was changed except
where the migration guide requires it (explain each one).
```

If your test suite is thin around the library you’re upgrading, add a few tests first, on the old version, and keep them green through the upgrade. For UI libraries, a quick check in a real browser catches what unit tests miss: an agent with a browser can open the main pages and report console errors. For build tools, compare the build output size before and after; a doubled bundle is a bug even if every test passes.

Review the diff with three questions: did any test change, did any public behaviour change, and does every edit map to an item on the breaking-change list?

## Bot PRs: Dependabot and Renovate plus an agent

Dependabot and Renovate are good at opening upgrade PRs on a schedule. What they can’t do is fix the code when the upgrade breaks something. That’s the part an agent can take.

A minimal Dependabot config that groups the easy updates into one PR:

```yaml
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    groups:
      minor-and-patch:
        update-types:
          - "minor"
          - "patch"
```

The Renovate equivalent starts from its recommended preset:

```json
{
  "extends": ["config:recommended"],
  "packageRules": [
    { "matchUpdateTypes": ["minor", "patch"], "groupName": "minor and patch" }
  ]
}
```

When a bot PR goes red, the loop looks like this:

```bash
gh pr checkout 123
gh pr checks 123              # find the failing run
gh run view <run-id> --log-failed   # the log of its failed jobs
```

```text
This is a Dependabot PR that bumps zod to the next major. CI fails with the
log below. Find the root cause, read the release notes for the new version,
and fix our code so it works with the new version. Don't pin the old version
and don't change tests to hide the failure. Run the tests locally, then
summarize the change before you push.
```

One detail: once you push your own commits to a Dependabot branch, Dependabot stops rebasing that PR automatically, and `@dependabot recreate` would throw your fix away. Merge it soon or rebase it yourself. For the general version of this loop, see [auto-fix CI failures with AI](/en/blog/auto-fix-ci-failures-with-ai/ "Auto-fix CI failures with AI").

## Security advisories

`npm audit` lists known vulnerabilities in your tree. A few things that keep it useful:

- **Focus on what ships.** `npm audit --omit=dev` leaves out dev dependencies, and `--audit-level=high` makes the command fail only at high or critical severity, which is a sensible CI gate.
- **`npm audit fix` vs `--force`.** Plain `audit fix` stays inside your declared ranges. With `--force` it may install semver-major versions; treat that as a Step 3 upgrade, not a quick fix.
- **Transitive packages.** When the vulnerable package is deep in the tree and its parent hasn’t released a fix, npm’s `overrides` field in `package.json` (or pnpm’s `pnpm.overrides`) can force a patched version. Ask the agent to add a comment or an issue explaining why, so the override is removed later.
- **Ask whether it’s reachable.** Have the agent check if your code actually uses the vulnerable function. That doesn’t mean you skip the fix, but it tells you whether it’s urgent today or can go in the weekly batch.

For Python, `pip-audit` reports the same kind of findings for an environment or a `requirements.txt`, and `pip-audit --fix` tries to upgrade the affected packages. The wider topic of what agents themselves should be allowed to install is covered in [AI coding agent security](/en/blog/ai-coding-agent-security/ "AI coding agent security").

## Common mistakes

- **“Update all dependencies to latest” in one prompt.** You get one giant diff and no way to bisect it.
- **Skipping the migration guide.** The agent writes code for the version it remembers.
- **Letting tests change silently.** An updated snapshot is fine when the guide explains the change; otherwise it’s hiding a regression.
- **Forcing the installer.** `--force` today is a broken install for the next person.
- **Merging parallel upgrade branches without testing them together.** Two green branches can be red once combined; a [merge queue](/en/blog/merge-queue-for-ai-agents/ "Merge queue for AI agents") tests each one on top of the latest main.

## Doing it in AgentVera

AgentVera is a desktop app that runs coding-agent CLIs like Claude Code, Codex and Gemini CLI side by side, with git built in. A few of its features map directly onto this workflow:

- **A worktree per major upgrade.** Create a worktree from the [Git panel](/en/features/git-and-github/ "Git and GitHub") and start an agent in it with one click; run the Vite upgrade in one pane and the ESLint upgrade in another.
- **A weekly dependency rule.** [Automations](/en/features/automations/ "Automations") (Pro) can start an agent on a cron schedule in its own worktree. One of the built-in playbooks is “update dependencies (minor and patch only)”, and the result can land as a PR or go into the merge queue.
- **Red CI to an agent.** The [CI/CD center](/en/features/ci-cd-center/ "CI/CD center") lists GitHub Actions, GitLab CI and Jenkins runs; on a failed run, “Fix with an agent” opens a Claude agent with the run details and the log tail of up to three failed jobs. An automation can also start an agent when CI goes red on branches you choose.
- **Verify against your definition of done.** Write “tests, type check and build pass; no test file changed” in your message. [Verify](/en/features/verify/ "Verify") turns it into criteria and, when the turn ends, a separate verifier that can’t edit files checks each one with evidence.
- **Review and merge queue.** [Code review](/en/features/code-review/ "Code review") reads what the agent changed with a second model, and the [merge queue](/en/features/merge-queue/ "Merge queue") lands upgrade branches one at a time on top of the latest target, with your check command run on the merged result.

## Wrapping up

Upgrading dependencies with AI works when you keep the shape of the work small: inventory first, easy updates in one batch, each major on its own branch, the migration guide read before the first edit, the codemod before the agent, and the tests as the judge. The agent saves you the reading and the hundred small edits; the process keeps those edits honest. When the upgrade is done and you want to make the app faster as well, read [how to optimize code performance with AI](/en/blog/optimize-code-performance-with-ai/ "Optimize code performance with AI").

To try it on your own repo, [download AgentVera](/en/download/ "Download AgentVera").

## Frequently asked questions

**Can an AI agent upgrade my dependencies on its own?** For patch and minor updates with a good test suite, mostly yes: it runs the update, the tests and the build, and fixes small breakages. For major versions it should work from the official migration guide, one package per branch, and you should review the diff before merging.

**Why does the agent use old APIs when it upgrades a library?** Its training data is older than the release you are moving to, so it remembers the previous API. Have it read the changelog and migration guide for the exact target version first, and tell it to trust the installed type definitions and docs over its memory.

**Should I upgrade everything at once?** No. Group patch and minor updates together, but give each major upgrade its own branch. When five majors land in one diff and the tests fail, nobody can tell which package caused it.

**Is npm audit fix --force safe to run?** Not blindly. npm documents that --force lets audit fix install versions outside your declared ranges, including semver-major changes. Treat it like any other major upgrade: on its own branch, with the tests run and the diff reviewed.

**How do I let an agent fix a failing Dependabot pull request?** Check out the PR branch, give the agent the failing CI log (for example from gh run view --log-failed), ask for the root cause and a fix that keeps the new version, run the tests locally, then push. After you push your own commits, Dependabot stops rebasing that PR automatically.

---

**About AgentVera.** AgentVera is a desktop app for macOS, Windows and Linux, built by Solviera Teknoloji. It runs 18 AI coding agents (Claude Code, Codex, Gemini CLI, Copilot, Cursor, Antigravity, opencode, Hermes, Qwen Code, Kimi Code, Kiro, Amp, Droid, Goose, Vibe, Crush, Aider, Cline) side by side, per project, in real terminals with the user's own CLI installs and logins. The free plan has unlimited agents. Download: https://agentvera.dev/en/download/ · Pricing: https://agentvera.dev/en/pricing/
