NPM

Hex.pmCI

npm package management for Elixir — resolve, fetch, cache, and link npm packages from Mix without requiring Node.js for installation.

mix npm.install lodash
mix npm.exec eslint .

npm_ex reads package.json, resolves npm semver with PubGrub, writes npm.lock, and links packages into node_modules/.

Why npm_ex

Elixir projects increasingly need JavaScript packages for assets, formatters, linters, browser libraries, and runtime integrations. npm_ex keeps that workflow inside Mix:

Installation

def deps do
  [{:npm, "~> 0.7.0"}]
end
mix npm.init
mix npm.install lodash

Common workflows

# Install and maintain dependencies
mix npm.install
mix npm.install lodash@^4.0
mix npm.install eslint --save-dev
mix npm.update
mix npm.remove lodash

# CI / reproducibility
mix npm.install --frozen
mix npm.ci
mix npm.verify

# Inspect dependency state
mix npm.list
mix npm.tree
mix npm.why accepts
mix npm.outdated

# Run scripts and binaries
mix npm.run build
mix npm.exec eslint .

# Registry, cache, and config
mix npm.info express
mix npm.search react
mix npm.cache status
mix npm.config

How installs work

  1. Read package.json dependencies, dev dependencies, optional dependencies, and overrides.
  2. Resolve the full dependency tree using hex_solver and npm_semver.
  3. Fetch registry packuments and tarballs with integrity verification.
  4. Store package contents in the global cache.
  5. Link packages into node_modules/ and write npm.lock.

npm_ex uses its own npm.lock because it is not npm. package.json remains the shared manifest; npm.lock records npm_ex's resolved dependency graph and security policy.

Supply-chain safety

npm_ex is intentionally conservative around install-time code execution:

This blocks common install-time credential stealers that rely on postinstall hooks reading files like .env and exfiltrating secrets during dependency installation.

Auditing malicious packages

mix npm.audit supports npm vulnerability checks and OSV/OpenSSF malicious-package intelligence:

# npm registry vulnerability audit
mix npm.audit

# Strict online OSV malicious-package gate
mix npm.audit --osv

# Refresh the shared local malicious-package cache for the current lockfile
mix npm.audit --osv --write-cache --policy warn

# Deterministic offline gate using the shared cache or configured DB
mix npm.audit --compromised

--write-cache merges matching OSV advisories into ~/.npm_ex/security/compromised_packages.json by default. mix npm.audit --osv fails closed when OSV cannot be queried; mix npm.audit --compromised is offline and deterministic.

OpenSSF/OSV is the default-compatible open data source. Socket, Snyk, and Phylum provide valuable proprietary intelligence or install-time firewall workflows; they fit best as external scanners/proxies or future optional integrations rather than default npm_ex install dependencies.

Configuration

Most projects only need the defaults. Use mix npm.config to inspect effective settings.

Common environment variables:

Elixir application config is also supported:

config :npm,
  registry: "https://registry.npmjs.org",
  token: System.get_env("NPM_TOKEN"),
  cache_dir: Path.expand("~/.npm_ex"),
  block_exotic_subdeps: true,
  exotic_deps: [],
  allowed_registries: ["https://registry.npmjs.org"],
  allow_registry_redirects: false,
  package_age_warning_days: 7,
  version_age_warning_days: 3,
  compromised_db_path: Path.expand("~/.npm_ex/security/compromised_packages.json"),
  compromised_policy: :error

API organization

The main public API is NPM. Supporting modules are grouped by domain: NPM.Package.*, NPM.Dependency.*, NPM.Lockfile.*, NPM.Security.*, NPM.Registry.*, NPM.Config.*, NPM.Install.*, NPM.Node.*, NPM.NodeModules.*, and NPM.Diagnostics.*.

See CHANGELOG.md for the 0.7 migration map from older pre-namespace module names.

Documentation

Full guides and API documentation are available on HexDocs:

License

MIT © 2026 Danila Poyarkov