Skip to content

Packages

nem use writes two files: the version you asked for into nem.toml and the exact resolved closure into nem.lock. Every other package command, unuse, update, lock, and sync, is a different way of moving those two files and the installs they describe.

Declaring packages

nem use [<catalog>:]<pkg>[@<version>]...

nem use resolves each package, installs it, and records the result in two files: the version in nem.toml, the exact resolved closure — with SHA-256 digests — and transitive dependencies in nem.lock.

If @<version> is not specified, nem takes the first entry of the package's versions list, which catalogs keep newest first, and steps down the list only when another package requires an older or compat-constrained version. If <catalog>: is not specified, nem searches for the package in all catalogs, in order, until it finds a match.

nem unuse <pkg>... removes declarations from nem.toml and re-resolves nem.lock. Dropping a pin can move a shared dependency, so it then installs what the new lock needs and relinks the packages that stay. It never deletes installed packages — other projects on the same machine may still be using them.

Updating packages

nem update [<pkg>...]

nem update (alias up) re-resolves declared packages — all, or just the ones named — to their catalog's latest, exactly as if you re-ran nem use for each. -g targets the global manifest; --dry-run reports the plan without writing anything. A catalog that was never updated is updated first; one last updated more than a week ago earns a warning to run nem catalog update. Each package settles on the first entry its dependents allow; a pick below a declared version aborts the whole update, and conflicting declarations fail it with the clashing requirements.

Project and global scope

By default nem works at project scope, where declared packages and environment are scoped to the project directory tree. nem finds a project's manifest by walking up from the current directory to the nearest nem.toml.

nem also supports a global scope, where declared packages and environment are available everywhere. The global nem.toml lives at $NEM_HOME/nem.toml, and every command that touches a manifest addresses it by adding --global / -g flag.

nem use -g go@1.27.0   # declare a package globally, not just for this project

When both scopes declare the same package or environment variable, the project's declaration wins — see the full precedence order.

Hand-editing nem.toml

nem.toml is meant to be edited by hand too, not only through nem use. After editing it, run nem lock to regenerate nem.lock and install:

nem lock

Every package must be pinned to the exact version string as it appears in the catalog — there's no "latest" keyword and no version ranges in nem.toml; a version nem can't find in the catalog is a lock error. If a dependency needs a different version than a package you pinned directly, that's a pin-conflict error, not a silent override. nem never installs a version that contradicts what the manifest declares.

Sharing

Commit both nem.toml and nem.lock. Teammates and CI run:

nem sync              # install what nem.lock pins

nem sync installs exactly what the lockfile pins and warns if nem.toml has drifted from nem.lock, for example a declared package the lock doesn't cover yet. It reads package manifests from the local catalog store, updating a store that was never updated first; a stale store needs nem catalog update.

WARN nem.toml declares tree@2.3.2, which nem.lock does not cover — run `nem lock`

Inspecting

CommandShows
nem status (-g for the global scope)Declared packages and composed environment variables
nem which <command>...Where a command resolves in the composed environment
nem info [<catalog>:]<pkg>A package's details and available versions
nem search [query]Catalog packages matching a query, omit query to list every package

Related