OverviewTypeScriptKotlinPythonGoRustC++

Packages

zlow install reads the package.json you already have and fills node_modules. Compiling stays on the TypeScript page.

How it fits

zlow does two different jobs for TypeScript. The compiler turns .ts files into JavaScript: build, check, bundle, and declarations. The package manager downloads the libraries those files import and puts them on disk.

Installing zlow itself is npm install @zlow/cli. After that command exists, zlow install inside a project installs that project’s dependencies.

zlow install does not type-check. When you want types, run zlow check on its own.

Install dependencies

From the project folder:

Terminal
zlow install
zlow install --ignore-scripts

zlow looks upward from the current directory for package.json. If a parent folder lists this directory in workspaces, that parent is the project root.

The first successful install writes zlow.lock next to package.json. Commit that file. Later installs repeat it, so the same project gets the same versions.

Where the versions come from:

Downloads come from https://registry.npmjs.org. Pass --registry to use another registry for this one command. zlow does not rewrite .npmrc.

Every package is checked against its sha512 checksum before it is kept. The bytes live in a cache on your machine: ~/.cache/zlow/store, or $XDG_CACHE_HOME/zlow/store when that variable is set. node_modules links to those cached copies, in the layout Node already walks. Removing a dependency from the project drops the link. The cached copy stays, so the next install can reuse it.

If a download fails, package.json, zlow.lock, and node_modules stay as they were.

Add and remove

Terminal
zlow add left-pad@1.3.0
zlow add --dev typescript@5.9.2
zlow remove left-pad

add updates package.json, zlow.lock, and node_modules together. --dev records the package under devDependencies. remove drops that direct dependency. A package that another installed package still needs stays on disk.

If the download fails, the previous manifest, lock, and tree are left in place.

Install again

Terminal
zlow install
zlow install --offline
zlow install --production

A later zlow install repeats the lock. It does not go looking for newer versions on its own.

--offline uses the cache only. If a required package is missing from the cache, install stops with error[pm.offline_miss].

--production leaves devDependencies out of node_modules. The lock still lists them. zlow prints dependencies: production (dev omitted).

Edit a range in package.json so the locked version no longer fits, and install stops with error[pm.lock_stale]. It does not quietly pick a replacement. Change the lock with zlow add when you want a new version.

If zlow.lock and package-lock.json disagree about a package, install stops with error[pm.lock_disagreement] and names that package. Fix one of the files yourself. zlow will not choose a side.

Scripts

Terminal
zlow run test
zlow run test -- --watch
zlow install --ignore-scripts

zlow run runs a script named in package.json. Anything after -- is passed through to that script. A missing name is error[pm.script_missing].

During install, zlow also runs preinstall, install, and postinstall from your project and from the packages it just installed. Each script runs in its own folder, through sh, with node_modules/.bin on PATH. node has to be installed for those scripts. If it is not, install stops with error[pm.script_host_missing].

zlow does not run npm, npx, yarn, pnpm, or bun. --ignore-scripts skips lifecycle scripts and prints scripts: skipped (--ignore-scripts).

Workspaces

A root package.json can name the folders that belong to one install:

package.json
{
  "workspaces": ["packages/*"]
}

zlow install at that root links each member into node_modules. If @app/a depends on @app/b with workspace:*, that name points at packages/b in the repo, the sources you are editing. Members can depend on each other in a cycle.

One command

Terminal
zlow exec prettier

zlow exec runs a package’s command from the cache. package.json and zlow.lock are not modified. --offline uses the cache, and stops with error[pm.offline_miss] when the package is not there yet.

Publish

Terminal
zlow publish
zlow publish --workspace @app/a

zlow publish uploads the package to the registry. package.json needs a name and a version, and you need a token in NPM_TOKEN or in .npmrc. The token is never printed. If any of those is missing, nothing is sent, and zlow reports error[pm.publish_incomplete].

Publishing a version the registry already has stops with error[pm.version_exists].

--workspace @app/a uploads that one member. A workspace: dependency is rewritten to a normal version range in the upload. The package.json on disk still says workspace:.

Limits

These dependencies are refused before anything is downloaded:

The message looks like error[pm.git_dependency]. The name after pm. says which limit you hit. A package that is optional, or that does not support this operating system, is skipped and named in a skipped: line. A required package that does not support this machine stops the install.