Dependencies

Elide ships a unified, polyglot package installer. A single elide install resolves and installs dependencies across three ecosystems at once:
EcosystemResolverSource manifests
npm (JavaScript/TypeScript)aube, embeddedelide.pkl, package.json
PyPI (Python)uv, embeddedelide.pkl, requirements.txt, pyproject.toml
Maven (Java/Kotlin/JVM)Elide's native Maven resolverelide.pkl
Both resolvers run in-process, inside the Elide binary — there is no npm, pip, uv, or mvn to install separately, and no extra process to fork. One command, one lockfile story, every ecosystem.
bash
 elide install

Elide detects which ecosystems are in play (from your elide.pkl and from any foreign manifests present), resolves them, and installs everything into your project's .dev/dependencies directory.

Why it's built this way

One toolchain, many ecosystems

Most projects are already polyglot — a TypeScript frontend, a Python data script, a JVM service — and each ecosystem normally drags in its own package manager, its own daemon, its own cache, and its own version skew. Elide collapses all of that into the runtime you already have. The npm and PyPI resolvers are compiled directly into the binary, so resolution is a function call, not a subprocess: no Node, no CPython, no pip bootstrap, no JVM spin-up just to download a jar.

Security-first defaults

npm and PyPI resolution route through pkg.st by default — Elide's hardened package proxy (npm.pkg.st, pypi.pkg.st). Installs are reproducible: aube writes aube-lock.yaml, the JVM resolver records artifacts in the project lockfile, and the npm store is content-addressed. You can opt out of the proxy at any time with the global --no-pkgst flag to hit upstream registries directly.

Compatibility by default

Python dependencies are resolved against Elide's own embedded interpreter, not whatever Python happens to be on your PATH. Because Elide runs GraalPy, uv selects wheels that are compatible with the GraalPy ABI — so packages you install are the packages that will actually import and run under elide. The same principle holds across ecosystems: what elide install resolves is exactly what elide run will load.

Declaring dependencies

Unified manifest (elide.pkl)

The native way to declare dependencies is the elide.pkl project manifest. A single dependencies { } block holds all three ecosystems:

pkl
amends "elide:project.pkl"

name = "my-app"

dependencies {
  npm {
    packages {
      "react@19.0.0"
      "@scope/widget@1.2.3"
    }
    devPackages {
      "typescript@5.6.2"
    }
  }

  pypi {
    packages {
      "six==1.17.0"
      "requests>=2"
    }
  }

  maven {
    packages {
      "com.google.guava:guava:33.4.8-jre"
    }
  }
}

npm and PyPI specifiers use their native syntax (name@version, name==version / name>=version). For the full set of Maven dependency buckets (modules, testPackages, compileOnly, repositories, …), see Elide Projects → Dependencies.

Foreign manifests

You don't have to convert an existing project. Elide reads the ecosystem manifests you already have, and treats any of them as a project-root marker:

  • npmpackage.json
  • PyPIrequirements.txt, pyproject.toml
bash
# A directory with just a package.json and a requirements.txt:
 elide install

Foreign manifests and elide.pkl can coexist. When both are present, Elide resolves the union. (Direct pom.xml resolution is not yet supported — declare Maven dependencies in elide.pkl for now.)

Where things land

Everything installs under .dev/dependencies/, with conventional layouts linked back into your project root so existing tools "just work":
EcosystemLayout
npm.dev/dependencies/npm/ holds package.json, aube-lock.yaml, and node_modules. A root node_modules symlink points at .dev/dependencies/npm/node_modules.
PyPI.dev/dependencies/pypi/site-packages holds installed packages; Elide adds it to PYTHONPATH automatically when you run .py files.
Maven$HOME/.m2 is populated for coherent Maven caching; .dev/dependencies/m2 contains symlinks to the cached artifacts so your project's JVM dependency tree is easy to inspect.
Protip

elide classpath can format a classpath from your installed JVM dependencies.

Install options

bash
$  elide install                 # resolve & install every detected ecosystem
$  elide install --slim          # JVM: skip sources/javadoc classifiers
$  elide install --with sources  # JVM: also fetch a specific classifier
$  elide install --fresh         # ignore caches and re-resolve from scratch
FlagDescription
—slimSlim installation — skip extra Maven classifiers (sources, javadoc).
—with Also fetch a Maven classifier, e.g. —with sources or —with javadoc.
—freshIgnore existing caches/lockfiles and re-resolve everything.
—directResolve direct dependencies only, without transitive expansion.

Using the tools directly

The embedded resolvers are also exposed as first-class subcommands. Anything after -- is passed straight through to the underlying tool, so you get the full aube / uv / Maven CLI through elide:

bash
# aube (npm) — Elide's embedded Node.js package manager
 elide aube -- install --ignore-scripts
 elide aube -- --help

# uv (PyPI) — Elide's embedded Python package manager
 elide uv -- pip install rich
 elide uv -- --help

# Maven — Elide's native-image Maven runner
 elide mvn -- dependency:tree

Global flags such as --no-pkgst go before the subcommand (elide --no-pkgst aube -- install); tool flags go after --.

Platform support

Note

npm and Maven installs work on all supported platforms. On Windows, npm install links node_modules with a directory symlink, which needs Developer Mode or administrator privileges; without them the link step fails. PyPI install is available on macOS and Linux; Windows support is in progress.

See also