# Maven Dependency Updater

> Keep Maven POM files up to date by checking and upgrading all dependencies and plugins to their latest versions. Use this skill whenever the user mentions updating, bumping, upgrading, or checking Maven dependencies or plugins — even if they just say "update my POMs", "are my dependencies up to date?", "bump versions", or "check for newer versions". Trigger also when the user shares or references a pom.xml and asks about version currency. Handles multi-module Maven projects, asks before applying major version upgrades, and keeps a clear audit trail of every change made.

- Skill: `litsec/maven-dependency-updater` (Agent Skill)
- Install (CLI): `npx skillmds@latest add litsec/maven-dependency-updater`
- Raw SKILL.md: https://api.skillmd.com/api/skills/litsec/maven-dependency-updater/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: litsec (https://skillmd.com/u/litsec)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/litsec/maven-dependency-updater

---


# Maven Dependency Updater

Audit and update all `<dependency>` and `<plugin>` versions across one or more Maven POM
files. Check Maven Central for the latest releases, flag major-version bumps for user
confirmation, and apply approved updates directly to the POM files.

---

## Workflow

### 1. Discover POM files

```bash
find . -name "pom.xml" | sort
```

Start from the project root (or the path the user specified). In a multi-module project
the parent POM is typically `./pom.xml`; child modules will have their own `pom.xml` files.

### 2. Parse versions

Collect every artifact that has an explicit version. Versions may appear:

| Pattern | Where |
|---|---|
| Inline `<version>` in `<dependency>` | `<dependencies>` block |
| Inline `<version>` in `<plugin>` | `<build><plugins>` and `<pluginManagement>` |
| Property placeholder `${my.lib.version}` | Resolve from `<properties>` in the same POM or an ancestor |

Build a flat list of records:
```
groupId | artifactId | currentVersion | resolvedVersion | type (dep/plugin) | sourceFile
```

Skip artifacts with versions like `${revision}`, `${project.version}`, or other
project-internal properties that should not be bumped.

### 3. Query Maven Central for latest versions

Use the Maven Central REST search API — no authentication required:

```
https://search.maven.org/solrsearch/select?q=g:"<groupId>"+AND+a:"<artifactId>"&core=gav&rows=1&wt=json&sort=version+desc
```

Or the newer API endpoint:
```
https://search.maven.org/solrsearch/select?q=g:<groupId>+AND+a:<artifactId>&rows=20&wt=json
```

Parse `response.docs[*].v` to find the latest **stable** release (skip versions that
contain `-SNAPSHOT`, `-alpha`, `-beta`, `-rc`, `-M\d`, `-milestone`).

**Batch efficiently**: group lookups, respect a short delay between requests to avoid
rate-limiting (100 ms is usually enough).

**Fallback**: If Maven Central returns no result, try the Maven Plugin repository for
plugins: `https://repo1.maven.org/maven2/<group/path>/<artifactId>/maven-metadata.xml`
and parse `<release>` or the last `<version>` entry.

### 4. Classify changes

For each artifact compare `resolvedVersion` with `latestVersion`:

```
MAJOR bump  →  first numeric segment increases         e.g. 2.x → 3.y
MINOR bump  →  second segment increases                e.g. 2.3 → 2.4
PATCH bump  →  third segment increases                 e.g. 2.3.1 → 2.3.2
UP TO DATE  →  versions are equal
UNKNOWN     →  could not determine latest version
```

Use semantic versioning comparison. If a version is non-semver (e.g. `20240101`),
compare lexicographically and treat a leading-digit difference as "major".

### 5. Present a summary and ask about major bumps

Print a clear table **before making any changes**:

```
Dependency / Plugin Updates Found
══════════════════════════════════════════════════════════════════
 Type   │ Artifact                          │ Current  │ Latest  │ Change
────────┼───────────────────────────────────┼──────────┼─────────┼───────
 dep    │ org.springframework:spring-core   │ 5.3.39   │ 6.2.1   │ MAJOR ⚠️
 dep    │ com.fasterxml.jackson.core:...    │ 2.16.1   │ 2.18.2  │ minor
 plugin │ org.apache.maven.plugins:...      │ 3.2.5    │ 3.5.0   │ minor
 dep    │ org.slf4j:slf4j-api               │ 2.0.12   │ 2.0.16  │ patch
══════════════════════════════════════════════════════════════════
Up to date: 8 artifacts   Skipped (unknown): 1
```

For **every major version bump**, ask the user explicitly before updating:

> ⚠️ `org.springframework:spring-core` would jump from **5.3.39 → 6.2.1** (MAJOR).
> Spring 6 requires Java 17+ and has breaking API changes.
> Apply this update? [yes / no / yes-to-all-majors / skip-all-majors]

Collect answers before touching any files. Support short-circuit answers:
- `yes-to-all-majors` — approve all remaining major bumps
- `skip-all-majors` — reject all remaining major bumps

### 6. Apply approved updates

For each approved change, edit the POM file directly using precise string replacement:

**Inline version**:
```xml
<!-- before -->
<version>5.3.39</version>
<!-- after -->
<version>6.2.1</version>
```

**Property-based version** (preferred — update the property, not each usage):
```xml
<!-- before -->
<spring.version>5.3.39</spring.version>
<!-- after -->
<spring.version>6.2.1</spring.version>
```

Use targeted, minimal edits — do not reformat the file or alter surrounding whitespace.

### 7. Print a final change log

```
✅ Changes applied
──────────────────────────────────────────────────────────
  pom.xml                spring.version        5.3.39 → 6.2.1
  pom.xml                jackson.version        2.16.1 → 2.18.2
  modules/api/pom.xml    maven-compiler-plugin  3.12.0 → 3.13.0
──────────────────────────────────────────────────────────
Skipped (major, user declined): logback-classic 1.4.14 → 2.0.0
Not updated (already current): 8 artifacts
```

---

## Edge Cases and Rules

### Property resolution
- A version like `${jackson.version}` must be resolved to its value before comparison.
- If the property is defined in a parent POM not present locally, note it as `UNKNOWN` and
  do not update.
- When a property is shared by multiple artifacts (e.g. `${jackson.version}` used by
  5 Jackson modules), updating the property once updates all of them — say so explicitly.

### BOM / import-scoped dependencies
- `<scope>import</scope>` entries in `<dependencyManagement>` should be treated like
  regular dependencies for version-checking purposes.
- Flag them clearly as BOMs in the table (they cascade many versions).

### SNAPSHOT / local versions
- Never update a version that is a `SNAPSHOT` or that references `${project.version}` or
  `${revision}`.

### Already-managed versions
- If a `<dependency>` block has no `<version>` (inherited from `<dependencyManagement>`),
  skip it — version is managed centrally.

### Plugins without explicit versions
- Maven plugins without a `<version>` tag use Maven's default binding — skip these too
  unless the user explicitly asks to pin them.

### Pre-release versions
- Do **not** suggest alpha / beta / RC / milestone releases unless the user's current
  version is already a pre-release of the same major line.

---

## Tool Usage Notes

- **Read files** with `Read` or `cat` to inspect POM content.
- **Edit files** with `Edit` / `str_replace` for precise, minimal changes.
- **HTTP requests** to Maven Central via `curl` or `Bash` (the API is public and
  unauthenticated).
- **Maven wrapper / CLI**: If `mvn` or `./mvnw` is available, you may optionally run
  `mvn versions:display-dependency-updates` as a cross-check, but do not rely on it as
  the sole data source since it requires the full Maven build context.

---

## Example curl for Maven Central

```bash
curl -s "https://search.maven.org/solrsearch/select?q=g:org.springframework+AND+a:spring-core&rows=1&wt=json" \
  | jq -r '.response.docs[0].latestVersion'
```

For plugins, also try:
```bash
curl -s "https://repo1.maven.org/maven2/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml" \
  | grep -oP '(?<=<release>)[^<]+'
```

