Hi all,

I'd like to propose adding three new goals to the Maven Dependency
Plugin: `dependency:add`, `dependency:remove`, and
`dependency:search`. I'm volunteering to do the implementation work
and would appreciate feedback on the approach before I begin.

Every major dependency management ecosystem provides a simple,
single-command way to add a dependency from the command line, except
Maven. Consider how Google's recently released Agent Development Kit
(ADK) documents its installation across languages:

* **Python:** `pip install google-adk`
* **TypeScript:** `npm install @google/adk`
* **Go:** `go get google.golang.org/adk`
* **Java (Maven):** "Open your `pom.xml` and add the following
dependency block..." followed by a multi-line XML snippet that the
developer must manually copy, paste, and position correctly.

This isn't unique to Google's ADK... it's the same experience for
every Java library distributed through Maven Central. While Cargo has
`cargo add`, NuGet has `dotnet add package`, Maven requires developers
to leave their terminal, open an XML file, find the right insertion
point, paste a `<dependency>` block, and ensure the formatting is
consistent. Even for AI coding agents, calling a CLI would be
significantly cheaper (in terms of token usage) than editing an XML
file. This friction is a real barrier, particularly for developers
coming from other ecosystems, and it makes Maven feel dated compared
to its peers.

# Proposed goals

## `dependency:add` - Adds a dependency to the project's `pom.xml`.

```
mvn dependency:add -DgroupId=com.google.adk -DartifactId=google-adk
-Dversion=1.0.0
mvn dependency:add -Dgav="com.google.adk:google-adk:1.0.0"
mvn dependency:add -DgroupId=com.google.adk -DartifactId=google-adk
-Dversion=1.0.0 -Dscope=test
```

The goal would parse the existing `pom.xml`, insert the dependency in
the `<dependencies>` section, preserve existing formatting and
comments, and write the file back. If the dependency already exists,
it would update the version (or warn, depending on a flag).

### `<dependencies>` vs `<dependencyManagement>`

By default, `dependency:add` would insert into the `<dependencies>`
section, since that's the most common use case and the closest analog
to what `npm install` or `cargo add` do. However, a
`-DdependencyManagement` flag (or shorter alias `-Dmanaged`) would
target the `<dependencyManagement>` section instead:

```
mvn dependency:add -Dgav="com.google.adk:google-adk:1.0.0" -Dmanaged
```

When adding to `<dependencyManagement>`, the version is always
required. When adding to `<dependencies>` in a child module where the
parent already manages that dependency's version via
`<dependencyManagement>`, the version parameter would be optional —
the goal would detect the managed version and omit `<version>` from
the inserted block, following Maven's established convention.

### Multi-module projects

In multi-module projects, the behavior depends on where the command is executed:

* **From a child module directory:** the dependency is added to that
module's `pom.xml`. This is the default and most intuitive behavior:
you `cd` into the module you want to modify and run the command, just
as you would run `npm install` from a specific package directory in a
monorepo.

* **From the root/parent directory with `-Dmanaged`:** the dependency
is added to the parent's `<dependencyManagement>` section, making the
version centrally governed. Child modules can then declare the
dependency without specifying a version.

* **From the root/parent directory without `-Dmanaged`:** the
dependency is added to the parent's `<dependencies>` section, meaning
it will be inherited by all child modules. This is a legitimate use
case (e.g., adding a logging facade or a common utility across all
modules), but since it has broad impact, the goal would print a
warning: _"Adding dependency to parent POM — this will be inherited by
all child modules. Use -Dmanaged to add to dependencyManagement
instead."_

This goal would also support a `-Dmodule=module-name` parameter to
target a specific child module from the root directory without having
to `cd` into it.

## `dependency:remove` - Removes a dependency from the project's `pom.xml`.

```
mvn dependency:remove -DgroupId=com.google.adk -DartifactId=google-adk
mvn dependency:remove -Dgav=com.google.adk:google-adk
```

By default, this removes from `<dependencies>`. The `-Dmanaged` flag
would target `<dependencyManagement>` instead. When removing a managed
dependency from a parent POM, the goal would warn if any child modules
still reference that dependency without an explicit version, since
those modules would break on the next build.

## `dependency:search` - Queries Maven Central for artifacts matching
a search term.

```
mvn dependency:search -Dquery=google-adk
```

This would return a concise list of matching `groupId:artifactId`
pairs with their latest versions, making it easy to discover
coordinates without leaving the terminal.

# What I'm not proposing

## Conflict resolution tooling

Automatic resolution of version conflicts is a complex problem with
many edge cases. The existing `dependency:tree` and
`dependency:analyze` goals are better starting points for
understanding conflicts, and automated resolution would require
careful design. This is better left for a separate discussion. Adding
or removing dependencies using the command line achieves the same
result as manually editing the XML files; neither prevents potential
conflicts or issues.

## Vulnerability auditing or license checking

Plugins like `org.owasp:dependency-check-maven` and
`org.codehaus.mojo:license-maven-plugin` already handle these concerns
well. Duplicating their functionality here would fragment the
ecosystem without adding clear value.

## SBOM generation

Both `org.cyclonedx:cyclonedx-maven-plugin` (CycloneDX format) and
`org.spdx:spdx-maven-plugin` (SPDX format) are actively maintained and
closely track their respective evolving specifications. A
general-purpose plugin would inevitably lag behind these dedicated
implementations.

## Migration assistance

Helping developers navigate breaking changes across major dependency
upgrades requires deep semantic understanding of API changes; the kind
of analysis that likely depends on AI/LLM tooling rather than a build
plugin. This is an interesting space but outside the scope of what the
dependency plugin should tackle in my opinion.

# Implementation notes

* `pom.xml` modification would use a formatting-preserving XML
approach (likely `MavenXpp3Reader`/`Writer` or similar) to avoid
reformatting the entire file.
* The search goal would use the Maven Central REST API (or Solr search
endpoint) by default, with support for custom repository search if the
repository exposes a compatible API.
* All goals would respect the standard Maven plugin parameter
conventions and work in both single-module and multi-module projects.
* For multi-module projects, the goals would resolve the effective POM
to determine whether a dependency version is already managed by a
parent, and adjust the inserted XML accordingly (omitting `<version>`
when already managed).

I'd welcome any feedback on the scope, naming conventions, or
implementation approach. I will start working on it as soon as we have
some general agreement that this would be a valuable addition.

Best regards
---
Bruno Borges

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to