# Dependencies

> Declare Maven, npm and PyPI dependencies in elide.pkl and install Maven and npm packages with `elide install`: ecosystems, options and installed files.

Declare dependencies in `elide.pkl` and install them with `elide install`.

| Ecosystem | Enable with | Read from |
| --- | --- | --- |
| Maven | default | `elide.pkl`, or a `pom.xml` project selected with `-p` |
| npm | `--ecosystems=npm` | `elide.pkl` and `package.json` |
| PyPI | — | `dependencies.pypi` is accepted; `elide install` does not install it |

## Install dependencies

```bash
elide install                         # Maven
elide install --ecosystems=npm        # npm
elide install --ecosystems=maven,npm  # both
elide install --workspace             # every ecosystem the project declares
```

<img src="https://elide.help/assets/demos/install.gif" alt="Installing Maven and npm dependencies explicitly with Elide" width="1591" height="509" loading="lazy" decoding="async" class="rounded-lg border border-border my-6 w-full" />

A `package.json` does not turn on npm; name every ecosystem CI needs. An unknown or unavailable ecosystem is a usage
error.

## Declare dependencies

```pkl
amends "elide:project.pkl"

dependencies {
  maven {
    packages {
      "com.google.guava:guava:33.4.8-jre"
    }
  }
  npm {
    packages { "react@19.0.0" }
    devPackages { "typescript@5.6.2" }
  }
  pypi {
    packages { "requests>=2" }
    optionalPackages { ["dev"] { "pytest>=8" } }
  }
}
```

For a project with only a `pom.xml`, run `elide install -p .`; see [Maven Dependencies](https://elide.help/docs/toolchain/jvm/maven).

### Maven buckets

An entry is `group:artifact:version[:classifier]`, a `MavenPackageSpec`, a local JAR path, or a `project("name")`
reference. Workspace members can omit the version and take the root's
([Workspaces](https://elide.help/docs/elide-pkl-reference#workspaces)). Conflicts resolve nearest-first, as in Maven, unless overridden by `resolutions`.

| Bucket | Applies to |
| --- | --- |
| `packages` | Compile and runtime classpaths of production sets. |
| `devPackages` | Development time only. |
| `modules` | `--module-path` for compiles, runs, tests and native images. |
| `compileOnly` | Compile classpath only. |
| `runtimeOnly` | Runtime classpath only. |
| `processors` | Annotation-processor path; see [Maven Dependencies](https://elide.help/docs/toolchain/jvm/maven#annotation-processors). |
| `testPackages` | Test sets, in addition to their production set's dependencies. |
| `kotlinPlugins` | Kotlin compiler plugins; see [Kotlin Compiler](https://elide.help/docs/toolchain/jvm/kotlinc). |
| `exclusions` | Removed from resolution and every classpath. |
| `substitutions` | Local files replacing a coordinate on every classpath; see [reference](https://elide.help/docs/elide-pkl-reference#dependencies). |

### Maven version resolutions

Use `resolutions` to select an exact version wherever a module appears in the dependency graph:

```pkl
dependencies {
  maven {
    resolutions {
      ["org.example:library"] = "1.2.3"
    }
  }
}
```

Keys are `group:artifact`; the override applies to direct and transitive requests, including all
classifiers and packaging types, before their POMs are fetched. It does not add a dependency or
restore an excluded dependency. Version ranges, wildcards, `LATEST` and `RELEASE` are rejected.
Workspace members inherit root resolutions and can override them by key. Changing or removing a
resolution causes the dependency graph to be resolved again.

Spring Boot starters:

```pkl
dependencies {
  spring {
    version = "4.0.0"
    starter { "web"; "actuator" }
    testStarter { "test" }
  }
}
```

Each name becomes `org.springframework.boot:spring-boot-starter-<name>:<version>` in `packages` or `testPackages`.
Other Spring artifacts (`spring-boot-devtools`, `org.springframework:*`) go in `maven`; the two merge.
The [Spring Boot guide](https://elide.help/docs/toolchain/jvm/spring) shows a complete manifest for building, testing and packaging an application with Elide.

### Repositories

```pkl
dependencies {
  maven {
    repositories {
      ["company"] = "https://maven.example.com/releases"
      ["private"] {
        url = "https://packages.example.com/maven"
        credentials {
          username = read("env:MAVEN_USER")
          password = read("env:MAVEN_TOKEN")
        }
      }
    }
    localRepository = ".m2/repository"
  }
}
```

| Property | Meaning |
| --- | --- |
| `repositories[name].url` | Repository URL. |
| `repositories[name].credentials.username`, `.password` | Basic authentication. |
| `repositories[name].credentials.ntlmDomain`, `.ntlmWorkstation` | Either one selects NTLM. |
| `repositories[name].name`, `.description` | Display name and description. |
| `enableDefaultRepositories` | Include Maven Central (default `true`). |
| `localRepository` | Local Maven repository to resolve into. |

- Plain `http://` to anything but `127.0.0.0/8` fails with `Maven repository 'name' uses plain HTTP`.
  `elide build deps --allow-http-repositories` accepts it.
- `read("env:…")` needs `--allow-env`; see [Build Flags](https://elide.help/docs/toolchain/build-flags#environment-variables).
- With `enableDefaultRepositories`, Maven artifacts come from the `maven.pkg.st` proxy first, then Maven Central.
  `elide build deps --use-pkgst=false` (or `--no-use-pkgst`) uses Maven Central only; the global `--pkgst` and
  `--no-pkgst` flags do not change this.

## Maven options

| Option | Effect |
| --- | --- |
| `--slim` | Skip sources and Javadoc. |
| `--with=sources` | Also fetch sources; `javadoc` and `docs` work too. Unknown values exit 2. |
| `--direct` | Copy artifacts into the project instead of linking. |
| `--fresh` | Download every dependency again, refreshing the global cache. |

`elide build deps` runs the same resolution as a task and also takes `--offline`, `--allow-http-repositories` and
`--use-pkgst`.

## Installed files

| Path | Contents |
| --- | --- |
| `.dev/dependencies/npm/node_modules` | npm packages; `node_modules` at the project root links here. |
| `aube-lock.yaml` | npm lockfile. |
| `.dev/dependencies/m2` | Links into the standard Maven cache. |
| `.dev/dependencies/m2/{compile,runtime,test,processors}.classpath` | Resolved classpaths; see [`elide classpath`](https://elide.help/docs/toolchain/source-sets#dependencies-and-classpaths). |

In a workspace, links are in the root's `.dev/dependencies/`; classpath files stay per project. There is no
cross-ecosystem lockfile; see [Build state](https://elide.help/docs/toolchain/build-tasks#build-state).

## Query dependency code

The experimental [dependency code index](https://elide.help/docs/toolchain/jvm/code-index) records types, members, and references from
resolved Maven JARs. Build it with `elide index build --layers=l1,l2,l3`, then use `resolve` to find which artifact
defines a class, `get` to inspect a type or member, and `references` to follow its code references. `used-by` finds
matching compiled local sources.

[OpenRewrite](https://elide.help/docs/toolchain/jvm/rewrite) uses the same index for Java source transformations. Add recipe modules to
`devPackages`; they are development tools, separate from application dependencies.

## Implicit JVM libraries

- Java-only roots get no implicit Kotlin libraries, Metro runtime or Elide annotation API, even with a `kotlin` block.
- Kotlin roots get the libraries their `kotlin.features` enable.
- Kotlin roots also get the atomicfu runtime unless `kotlin.features.atomicfu = false`.
- Test sets get bundled JUnit unless `jvm.features.testing = false`; `elide test` then needs your own
  `junit-platform-console` for JVM tests.
- `dev.elide:elide-api` and `elide-insight` accept `latest` as a version and resolve to the bundled artifact.
- Bundled libraries link Elide's own JARs, but their sources and Javadoc come from your repositories like any other
  dependency's, so `--with=sources` attaches `kotlin-stdlib` sources too. `elide-api` and `elide-insight` have none.

The full list, with versions: [JVM APIs](https://elide.help/docs/api-jvm#projects). To use [Elide annotations](https://elide.help/docs/api-jvm-annotations) from
Java:

```pkl
dependencies {
  maven {
    compileOnly { "dev.elide:elide-api:1.0.0" }
  }
}
```

npm specifics: [NPM Installer](https://elide.help/docs/toolchain/web/npm).

Studio session defaults also apply to the embedded npm installer: `ELIDE_PKGST=1`
enables the package CDN unless explicitly overridden by CLI flags. Requests to
the HTTPS `npm.pkg.st` origin carry a valid `ELIDE_STUDIO_SESSION_ID` for internal
correlation. Other registries receive no Studio session header. The native
installer retains unchanged package content when dependency versions drift;
Elide's `.dev/dependencies/npm` layout does not require an exact whole-project
input match to reuse those packages.
