Bundle from a file
Point --file at a package.json, a lockfile, or a list of approved packages.
--file reads the specs from a file instead of the command line. It accepts three
shapes, and works out which one it has from the content, not the extension — so
--file deps.json, --file specs.txt and --file approved-packages all do the obvious
thing.
A project's dependencies
packall --file package.jsonEverything the project depends on, dev tooling included. If you are pointing this at a
package.json you are almost certainly trying to make that project buildable behind the
firewall, and a project without its dev dependencies does not build.
--prod excludes them:
packall --file package.json --prodLockfiles
A range resolves to whatever is newest at the moment you run the command. That is right
for "make this project installable offline" and wrong for "bundle what CI actually
installed" — between the two runs, ^1.2.0 quietly became 1.9.0.
So a lockfile beside your package.json is used by default, and the run says which one:
$ packall --file package.json
pinned by ./pnpm-lock.yaml (pnpm, lockfileVersion 9.0)package-lock.json (v1–v3), npm-shrinkwrap.json, pnpm-lock.yaml (v5, v6, v9) and
bun.lock are all read.
--lockfile | Behaviour |
|---|---|
detect (default) | Nearest lockfile at or above the package.json. Says which, or that it found none. |
off | Never look. Resolve every range fresh. |
npm · pnpm · bun | Require that manager's lockfile; fail if it is not there. |
| a path | Use exactly that file. |
A pinned run is pinned all the way down: every transitive edge comes from the lockfile
too. Pinning only the top level and letting tslib@^2 resolve fresh underneath would
put a version in the bundle that nobody installed.
Gaps are reported, never guessed at. A dependency the lockfile does not pin, or a pinned version
the registry no longer serves, fails the run and names every affected package at once. Entries
that cannot come from a registry — workspace:, file:, git dependencies — are warnings, and
skipped.
In a monorepo
A workspace member usually has no lockfile of its own; the one that pins it sits at the repository root and pins every other member too. The search climbs the tree, and the parse then takes only that member's dependencies:
$ packall --file ./packages/core/package.json
pinned by ./pnpm-lock.yaml (pnpm, lockfileVersion 9.0, workspace packages/core)The nearest level wins, so a package with its own lockfile is never overruled by the root's.
A list of approved packages
The third shape is a plain list — one spec per line, using the syntax you would type as arguments:
# What we are cleared to import this quarter
ms@2.1.3
semver@^7.6.0 // pinned by security review
@babel/code-frame@^7
typescript@nextpackall --file approved-packages.txt --out ./bundles# and // comments are allowed, full-line or trailing, and blank lines are ignored.
A line that will not parse is reported with its line number.
For a restricted network this is often the better fit: the file is a reviewable record of what was approved, it lives in version control next to the change that introduced it, and re-running it reproduces the same bundle.
Unsupported inputs
bun.lockb — bun's pre-1.2 binary format — cannot be read; the error tells you to run
bun install --save-text-lockfile. yarn lockfiles are not supported yet, and are named
as such rather than failing as an unparseable spec list.