# How the Maven CLI Interacts with the Core Implementation in Apache Maven

> Discover how the Maven CLI interacts with Apache Maven's core. Learn how the CLI orchestrates and delegates build execution for efficient project management.

- Repository: [The Apache Software Foundation/maven](https://github.com/apache/maven)
- Tags: internals
- Published: 2026-07-07

---

**The Maven CLI is a thin orchestration layer that parses command-line arguments, bootstraps the Plexus container, populates a `MavenExecutionRequest`, and delegates all build execution to the core `DefaultMaven` component.**

The Apache Maven build tool maintains strict separation between user-facing command logic and build execution. While developers invoke the `mvn` command to compile projects, the actual lifecycle management resides in Maven's core implementation. Understanding how the Maven CLI interacts with the core implementation reveals the dependency injection patterns and request delegation that make Maven both embeddable and extensible.

## The Startup Sequence in MavenCli

### Entry Point and Phase Pipeline

The `main(String[] args)` method in [`compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java`](https://github.com/apache/maven/blob/main/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java) serves as the JVM entry point. It instantiates `MavenCli` and invokes `doMain(CliRequest)`, which executes a fixed pipeline: `initialize()` → `cli()` → `properties()` → `logging()` → `informativeCommands()` → `version()` → `container()` → `commands()` → `configure()` → `toolchains()` → `populateRequest()` → `encryption()` → `execute()`.

### Command-Line Parsing and Property Resolution

The `cli()` method utilizes **Apache Commons-CLI** to transform `String[] args` into a `CommandLine` object. The `properties()` phase expands system and user properties, interpolating values into the command line. These properties populate `CliRequest` and eventually become part of the `MavenExecutionRequest` that the core consumes.

## Bootstrapping the Plexus Container

### Container Initialization and Component Lookup

The `container()` method in [`MavenCli.java`](https://github.com/apache/maven/blob/main/MavenCli.java) creates a `DefaultPlexusContainer` instance, which acts as Maven's dependency injection framework. During initialization, the CLI looks up the `org.apache.maven.Maven` interface and stores the implementation—typically `DefaultMaven` defined in [`impl/maven-core/src/main/java/org/apache/maven/DefaultMaven.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/DefaultMaven.java)—in the `MavenCli.maven` field.

## Building the Execution Request

### Populating MavenExecutionRequest

The `populateRequest()` method constructs a `DefaultMavenExecutionRequest` instance, filling it with CLI options, resolved properties, toolchains, and class realms. This request object serves as the immutable contract passed to the core implementation, containing all necessary configuration for the build.

## Delegation to the Core Implementation

### The Execute Method Handoff

The `execute()` method retrieves the looked-up `Maven` instance and calls `maven.execute(request)`, delegating control to `DefaultMaven.execute()`. This method, located in [`impl/maven-core/src/main/java/org/apache/maven/DefaultMaven.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/DefaultMaven.java) (lines 195-258), initiates the full build lifecycle.

### Core Build Flow and Lifecycle Management

Inside `DefaultMaven.doExecute()`, the core validates the local repository, creates a `MavenSession`, fires lifecycle participants (including `afterSessionStart` and `afterProjectsRead` events), builds a `ProjectDependencyGraph` using `GraphBuilder`, and invokes `LifecycleStarter` to execute Maven phases and goals. The `LifecycleStarter` class in [`impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java) handles the actual goal execution.

### Result Processing and Exit Codes

After the core completes, execution returns to `MavenCli.execute()` (lines 1000-1012), which processes the `MavenExecutionResult` to determine the exit code. This phase handles error summaries, resumption hints, and cleanup without the CLI ever participating in the actual build logic.

## Code Examples: From Command Line to Core

### Standard Command Line Invocation

```bash
mvn clean install

```

This executes `MavenCli.main()`, triggering the complete orchestration sequence.

### Programmatic CLI Invocation

```java
import org.apache.maven.cli.MavenCli;

public class EmbeddedMaven {
    public static void main(String[] args) {
        String[] mavenArgs = { "-B", "clean", "package" };
        MavenCli cli = new MavenCli();
        int exitCode = cli.doMain(mavenArgs, null);
        System.out.println("Maven finished with exit code " + exitCode);
    }
}

```

### Direct Core Component Access

```java
import org.apache.maven.Maven;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.injector.plexus.PlexusContainer;
import org.apache.maven.injector.plexus.PlexusContainerUtils;

public class DirectCore {
    public static void main(String[] args) throws Exception {
        PlexusContainer container = PlexusContainerUtils.createContainer();
        Maven maven = container.lookup(Maven.class);
        
        DefaultMavenExecutionRequest request = new DefaultMavenExecutionRequest();
        request.setGoals(java.util.List.of("clean", "install"));
        request.setBaseDirectory(new java.io.File("."));
        
        MavenExecutionResult result = maven.execute(request);
        System.out.println("Build succeeded? " + result.isSuccessful());
    }
}

```

## Summary

- The Maven CLI in [`compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java`](https://github.com/apache/maven/blob/main/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java) functions exclusively as an orchestration layer with no build logic.
- The `container()` method bootstraps the Plexus DI framework and looks up the core `Maven` component.
- `populateRequest()` creates a `MavenExecutionRequest` containing all build configuration.
- `DefaultMaven.execute()` in [`impl/maven-core/src/main/java/org/apache/maven/DefaultMaven.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/DefaultMaven.java) receives the request and manages the complete build lifecycle.
- The CLI translates `MavenExecutionResult` into exit codes but contains no compilation or packaging logic.

## Frequently Asked Questions

### What is the difference between MavenCli and DefaultMaven?

`MavenCli` handles argument parsing, Plexus container setup, and result formatting, while `DefaultMaven` contains the actual build engine that manages sessions, project graphs, and lifecycle execution through `LifecycleStarter`.

### Can I use Maven's core implementation without the CLI?

Yes. By bootstrapping a `PlexusContainer` and looking up the `Maven` component, you can create a `MavenExecutionRequest` programmatically and call `execute()` directly, bypassing `MavenCli` entirely while using the same core implementation.

### Where does the MavenExecutionRequest get created?

The CLI creates it in the `populateRequest()` method within [`MavenCli.java`](https://github.com/apache/maven/blob/main/MavenCli.java), populating it with properties, goals, profiles, and toolchains before passing it to `DefaultMaven.execute()` in the core.

### How does Maven handle dependency injection between CLI and core?

The CLI creates a `DefaultPlexusContainer` during the `container()` phase, which autowires all core components. The `DefaultMaven` implementation is looked up from this container, ensuring loose coupling between the CLI interface and the core build engine.