Pantry package manager

This reference is reproduced from Pantry v0.10.48 at immutable commit f1cc9159b6a944d93fe401ed614cb61520ed6871. The copied contract and its executable evidence are checksummed in evidence/pantry/evidence.lock.json. Stacks relies on this boundary; it does not redefine Pantry behavior.

ProvenanceValue
Pantry release0.10.48 / v0.10.48
Pantry commitf1cc9159b6a944d93fe401ed614cb61520ed6871
Upstream contractdocs/package-manager.md
Contract digestsha256:2059dd6a524d48bbfe2d5999db848be96e8054b209b16314c4bb22b08ca651bb
Documentation checkbun run docs:contracts:check (54 source-linked markers)
Targeted HTTP/contract tests16 passed, 0 failed
Native test graph29 semver tests passed; zig build test completed 32/32 steps

The text below is the upstream implementation contract. Normative words apply to Pantry at the pinned revision, not to every historical Pantry version.

This document describes the package-manager behavior implemented by the native Zig CLI in packages/zig. It is a contract and operations reference, not a list of intended features. bun run docs:contracts:check links every critical claim below to its command registration or implementation source and fails CI when the documentation drifts.

Scope and source of truth

Pantry manages three related dependency classes:

ClassResolution sourceInstallation shapePrimary implementation
System tools and runtimesPantry's generated recipe catalog and binary metadata at registry.pantry.devVersioned native archives, binaries, shims, and environment linkspackages/zig/src/packages, packages/zig/src/install
JavaScript packagesnpm-compatible metadata, with the resolved URL and integrity claim retained in pantry.lockExtracted package tree under the configured modules directorypackages/zig/src/install/installer.zig, packages/zig/src/install/pipeline.zig
Workspace and local packagesWorkspace manifests, workspace: ranges, and Pantry's local-link registryLinked or copied workspace package with resolved external dependenciespackages/zig/src/cli/commands/install/workspace.zig, packages/zig/src/cli/commands/link.zig

The generated system catalog is local to the CLI, so normal search and package classification do not require an online third-party catalog. Live Pantry-registry search supplements the generated catalog for newly published packages. npm is a separate compatibility and JavaScript dependency source; it is not Pantry's system-package registry.

Manifest discovery and precedence

Pantry recognizes project manifests including pantry.json, package.json, and the YAML dependency files documented in the quick start. A workspace root owns a single pantry.lock; workspace package constraints are recorded separately from their resolved package entries. Explicit CLI package arguments narrow or extend the manifest operation depending on the command.

Configuration precedence is:

  1. explicit command options;
  2. project configuration (pantry.toml and supported dependency manifests);
  3. environment settings;
  4. compiled defaults.

--no-save prevents both manifest and lockfile writes. --force intentionally bypasses the normal lockfile/cache fast paths and resolves again. These options are not equivalent: forcing a refresh does not imply that state must be saved.

Install and resolution commands

CommandContract
pantry install [packages...]Resolve and install manifest dependencies or explicit package specs. Alias: pantry i.
pantry ciPerform a strict install with frozen-lockfile behavior; missing or divergent lock state is an error.
pantry add <packages...>Add constraints to the selected dependency section, install them, and update lock state unless saving is disabled.
pantry remove <packages...>Remove dependency declarations and corresponding project content. Supports preview and global selection.
pantry uninstall <packages...>Remove installed package content from Pantry-managed locations.
pantry update [packages...]Re-resolve selected or all dependencies subject to constraints; --latest may ignore the current constraint.
pantry outdated [patterns...]Compare installed/declared versions with the appropriate Pantry or npm registry source.
pantry list / pantry lsList installed packages with table, simple, or JSON output where registered.
pantry why <package>Explain the dependency path that caused a package to be installed.
pantry treeDisplay the dependency graph with depth, production, peer, and version controls.
pantry dedupeReduce duplicate compatible resolutions while preserving dependency constraints.
pantry link / pantry unlinkRegister or consume a local package without publishing it.
pantry search <query>Search the generated Pantry catalog, then supplement it from the live Pantry registry.
pantry info <package>Show catalog metadata, or query the live Pantry registry for a user-published package.
pantry auditQuery vulnerability data for JavaScript dependencies with severity, production, and ignore controls.

Install option semantics

OptionEffect and failure behavior
--globalInstall into the system/global prefix rather than a project environment.
--userInstall globally for the current user under Pantry's user data directory.
--forceFetch current metadata and reinstall; ignore the normal cache and lockfile preference.
--productionInstall production dependencies and omit development dependencies.
--devInstall only development dependencies.
--peerInclude peer dependencies when they are not enabled by project configuration.
--ignore-scriptsDo not execute package lifecycle scripts. This reduces behavior, not integrity verification.
--offlineMake no registry request; a missing resolution or tarball in local state is an error.
--filter <pattern>Restrict a workspace operation to matching packages.
--frozen-lockfileReject a missing lockfile or any install result that would change it.
--no-cacheIgnore the manifest cache; this is distinct from --force and deleting the content cache.
--dry-runCompute and report the plan without installing or persisting it.
--no-saveDo not change the dependency manifest or pantry.lock.
--quietSuppress progress output, but never suppress the reason for a failed install.
--verboseEmit resolution, cache, download, environment, and install diagnostics.

Resolution and install pipeline

The normal project operation follows this order:

  1. Discover the effective project/workspace root and dependency manifest.
  2. Read pantry.lock and determine whether recorded constraints still match.
  3. Use the lockfile fast path only when every package is resolvable, destination content exists, and every concrete catalog-declared program is a regular, non-empty executable; otherwise repair or resolve the package.
  4. Classify each spec as a Pantry system package, npm package, workspace package, local link, Git source, or another supported source.
  5. Resolve exact versions and tarball URLs, retaining integrity metadata when the upstream registry supplies it.
  6. Download in parallel unless offline or satisfied by cache.
  7. Verify any supplied integrity claim before extraction.
  8. Extract into managed content, validate declared programs, create executable shims/links, and run permitted lifecycle hooks.
  9. Update the lockfile only after successful results and only when writes are allowed.

Partial failures return a non-zero command result. Quiet mode may remove progress noise but cannot convert a failure into success or hide its final reason.

Version-constraint semantics

Exact versions remain exact. Caret ranges keep the first non-zero component stable (1.2.3 stays below 2.0.0, 0.15.1 stays below 0.16.0, and ^0.0.3 stays on 0.0.3). Tilde ranges keep the minor component when one is present. >=, <=, >, <, and = compare the complete ordered version. If no available version satisfies a declared range, installation fails instead of substituting latest.

Prerelease intent is explicit. A stable range does not select development builds. A range containing prerelease metadata, such as ziglang.org: ^0.17.0-dev, may select the newest matching development build. Pantry retains the complete prerelease/build identifier, consults live Pantry binary metadata for Zig, orders its numbered development builds numerically, and records the selected concrete version in pantry.lock. Registry-safe underscores and upstream + build separators are treated as equivalent version metadata for ordering, but the exact registry key is preserved for download.

Lockfile contract

pantry.lock is the reproducibility boundary. It records exact package versions, resolved locations, integrity when available, dependency relationships, and workspace constraint state. It supports lockfile-first restore, which avoids redundant registry resolution, and frozen validation, which compares the computed result to committed state and rejects a missing or changed lockfile.

The lockfile does not create integrity evidence when an upstream package supplies none. Such an entry is reproducible by version and URL but has weaker content authentication and must not be described as cryptographically verified.

Integrity, cache, and extraction

For npm-style tarballs, Pantry verifies a supplied raw SHA-256 digest or SRI sha256, sha512, or legacy sha1 value. A mismatch, malformed base64 value, missing algorithm separator, or unsupported algorithm fails closed. When no integrity claim exists, the installer can still validate archive structure and uses the content cache's SHA-256 bookkeeping, but that is not equivalent to an upstream-authenticated digest.

Downloaded content is cached by package, version, source, and checksum. A poisoned cache entry that fails verification or extraction is evicted and may be fetched again when networking is allowed. --offline never silently crosses the network; if verified content is unavailable locally, the install fails.

Native archives are validated for expected archive structure. When a valid sidecar checksum is available, it is checked before extraction. Absence of a sidecar is explicitly weaker than a verified sidecar and is not a signature.

Project materialization is transactional at the package-directory boundary. Pantry copies a verified global package into a sibling .partial directory, checks its package structure and every concrete catalog-declared program, then replaces the project copy. A zero-byte, non-regular, missing, or non-executable program never satisfies the lockfile fast path. When the global package is usable, rerunning pantry install repairs the project copy from it without a network request. A failed or canceled copy leaves .partial state that cannot count as installed and is removed on the next attempt.

Lifecycle scripts and trust

Lifecycle scripts execute dependency code and are therefore a separate trust decision from checksum validation. Pantry supports pantry trust, pantry untrusted, and pantry default-trusted for managing that decision. --ignore-scripts is the deterministic opt-out for CI or security-sensitive installs. An integrity match proves bytes match the declared digest; it does not prove that running those bytes is safe.

Workspaces and local development

Workspace installs use the workspace root for pantry.lock, resolve workspace: ranges before publication, deduplicate shared external packages where compatible, and retain per-workspace declared constraints. --filter limits the selected workspace set. Local links are recorded in Pantry's link registry and avoid a publish round trip; they are mutable development inputs and do not carry normal immutable-registry guarantees.

Publication channels

CommandDestination and contract
pantry publishPublish archives to the Pantry registry. The default is https://registry.pantry.dev; a bearer token is required.
pantry npm:publishPublish npm-compatible packages to npm or an explicitly selected compatible registry, with token or OIDC authentication.
pantry publish:checkValidate names and registry collisions without publishing; offline mode performs syntactic checks only.
pantry publish:commitPublish temporary, commit-addressed monorepo packages and return installable URLs. Existing names can be skipped unless forced.
pantry publish:binaryPublish a platform-specific native binary and metadata to Pantry object storage.
pantry publisher:add, publisher:list, publisher:removeManage npm-style trusted publisher configuration for OIDC flows.
pantry sign / pantry verifyCreate or verify package signatures with configured Ed25519 key material.

Pantry-registry publication and npm publication are intentionally different surfaces. The command and selected registry determine the protocol; Pantry does not transparently republish every npm dependency.

npm publication semantics

pantry npm:publish and pantry publish --npm enter the same npm publication pipeline. The package is staged according to npm's files and lifecycle rules, workspace and catalog ranges are rewritten to registry-installable versions, and the tarball summary is computed before authentication. --dry-run stops after that preparation boundary: it does not request OIDC credentials, read a token, or upload bytes.

The effective dist-tag and access level use explicit precedence:

  1. --tag and --access command options;
  2. publishConfig.tag and publishConfig.access in package.json;
  3. npm defaults: latest for the tag, restricted for scoped packages, and public for unscoped packages.

An empty tag or access other than public or restricted fails before authentication. Pantry serializes the resolved tag into dist-tags and the resolved access into the npm registry payload; printing those values without including them in the upload is not considered a successful implementation.

OIDC trusted publishing is attempted first by default. On success, provenance is attached unless --no-provenance is set. --no-oidc skips the exchange and uses token authentication directly. A missing trusted-publisher relationship may fall back to a token, while immutable-version conflicts and registry validation errors fail without retrying through another identity. --otp <code> adds npm's npm-otp header to token publication; Pantry never writes or prints the code.

Token discovery is deterministic:

  1. NPM_TOKEN, NODE_AUTH_TOKEN, or BUN_AUTH_TOKEN;
  2. project .npmrc;
  3. NPM_CONFIG_USERCONFIG, when set, otherwise ~/.npmrc;
  4. NPM_TOKEN or npm_token in ~/.pantry/credentials;
  5. an interactive prompt when the process is not running in CI.

npmrc parsing accepts _authToken, registry-scoped keys such as //registry.npmjs.org/:_authToken, matching single or double quotes, and a whole-value ${ENV_VAR} reference. Project configuration takes priority over user configuration. Missing referenced environment variables do not expose the placeholder or silently select a lower-precedence credential. Tokens and OTPs are excluded from diagnostics.

Package/version conflicts remain immutable. Rate-limit and transient server responses may be retried with bounded exponential backoff; authentication, validation, and version-conflict responses are returned as failures. Lifecycle scripts remain subject to the explicit script policy, and publication success is reported only after the registry accepts the package.

Environment and installation locations

Project installs live in Pantry-managed project environments. Global installs select the system prefix when writable, while --user selects the user-owned global data directory. Custom paths are explicit and should be treated as an operator choice because ownership, PATH behavior, and cleanup boundaries change.

Shell integration performs environment lookup on directory changes. The environment identity incorporates project location and dependency state so two projects, or two dependency revisions of one project, do not accidentally share an incompatible active toolchain. Leaving the project restores the previous environment instead of copying packages into the global shell.

Failure modes operators should preserve

  • Unknown package, impossible version, invalid manifest, or malformed lockfile: fail with the package/config cause.
  • Frozen lockfile missing or divergent: fail without modifying it.
  • Offline cache miss: fail without a network fallback.
  • Integrity mismatch or unsupported integrity algorithm: fail before extraction.
  • Missing, empty, non-regular, or non-executable declared program: repair from a verified global package or fail installation; never report the package as current.
  • Untrusted lifecycle script: require trust or an explicit script policy.
  • Registry authentication failure: fail without uploading.
  • Duplicate immutable version: registry returns conflict; do not overwrite it.
  • Partial workspace failure: return non-zero and do not claim complete success.

Test and evidence map

ContractEvidence
Integrity algorithms and tamper rejectionpackages/zig/src/install/pipeline.zig unit tests
Native program validation and zero-byte repair gatingpackages/zig/src/install/validator.zig and installer tests
Frozen, missing, and stale lockfile behaviorinstall/workspace/lockfile tests under packages/zig
Registry resolution and install integrationpackages/zig/test/registry_integration_test.zig and install tests
Workspace lock and publication behaviorworkspace and catalog tests under packages/zig/test
Ed25519 signing and wrong-content rejectionpackages/zig/src/auth/signing_test.zig
Documentation/source freshnessscripts/docs-contracts.test.ts and bun run docs:contracts:check

Run the focused checks with:

bun run docs:contracts:check
bun test scripts/docs-contracts.test.ts
cd packages/zig && zig build test