Skip to content

CLI — overview

punix is the single binary. Subcommands group by lifecycle:

punix help [TOPIC]               # quick overview + concept pages
punix check FILE                 # type-check (E1–E6 located)
punix build FILE                 # check + realise every package module
punix install MODULES... [--file FILE]  # build each MODULE + symlink its binaries onto $PATH
punix uninstall MODULE           # drop MODULE from the active profile
punix list                       # what's installed in the active profile
punix search REGEX [FILE]        # regex-search packages in a PCL tree
punix info MODULE [FILE]         # recipe metadata + predicted store path
punix upgrade --check-all [FILE] # report newer upstream versions (via gh)
punix profile list               # show profile generations; mark active
punix profile switch N           # atomic flip to gen-N
punix profile diff N M           # symmetric diff of installed_modules
punix why  FILE TARGET           # show resolved value + provenance chain
punix store path FILE MODULE     # predicted store path (no build)
punix store info                 # store root, artifact count, total size
punix store gc                   # GC the store; honours generation pins
punix service deploy STACK      # compose stack + realise + flip current
punix service rollback STACK    # flip current back one generation
punix fleet apply FLEET         # deploy many hosts (over SSH) in one command
punix fleet rollback FLEET      # roll back the fleet (reverse order)
punix migrate SRC OUT            # RCL → PCL bulk migrator (Stage 7)

Universal options

Most commands accept these:

  • --scenario NAME — evaluate under scenario NAME (see Modules).
  • --store-root PATH — store location (default ~/.punix/store, override with $PUNIX_STORE_DIR).
  • --deployments-root PATH — deployments location (default ~/.punix/deployments).
  • --bootstrap MODE — bootstrap trust policy on install / build. fast / seeded / source / bootstrappable. Default: $PUNIX_BOOTSTRAP_MODE or seeded. See the install page, or run punix help bootstrap.

Environment variables

Var Effect
PUNIX_PACKAGES Overrides the default packages-tree lookup
PUNIX_STORE_DIR Overrides the store-artifact location (~/.punix/store/ by default)
PUNIX_BOOTSTRAP_MODE Selects the default bootstrap mode for install / build (fast / seeded / source / bootstrappable). The --bootstrap flag overrides this for one call.

A typo in any of these is an actionable error. See punix help env for the full per-variable reference.

Default FILE discovery

The discovery commands (install, search, info, upgrade, check) accept FILE as an optional positional / --file flag. When omitted, Punix looks for the packages tree in this order:

  1. $PUNIX_PACKAGES — explicit operator intent. A missing target is an error.
  2. ./packages/official/ — the curated, known-to-work corpus. Default for daily use.
  3. ./packages/ — flat-tree fallback (useful for fresh / test projects without the official/experimental split).

So cd ~/projects/my-pcl-tree && punix install just works without any flags when a packages/official/ (or flat packages/) is present.

Package collections

A Punix repository typically holds multiple corpora, each its own tree:

packages/
  official/              # the daily-use, curated set; default discovery
  experimental/
    from-nix/            # imports from nixpkgs (auto-generated, scratch)
    from-slapos/         # imports from slapos
    from-homebrew/       # imports from Homebrew (regenerated via `make dogfood-translate`)

Each tree is composed independently — never together. The [E15] duplicate-pname rule makes this normative: composing two trees that share pnames is an error. Maintainers promote a package from an experimental tree to official/ by hand-editing + copying the recipe; the next translator run skips files whose pname is already in official/.

Exit codes

Per the exit-codes reference:

Code Class
0 OK
1 Located domain error ([E1][E15])
2 Usage error (bad flag, malformed arg, missing required)
3 Realise/deploy error (build failure, transport error, GC contamination)
>3 Internal (assertion, unhandled exception)

Reference: exit codes for the full table.

Common patterns

Inspect before acting

# Will the package build cleanly?
punix check stack.pcl

# What store path will the build produce?
punix store path stack.pcl Hello

# Where did this value come from?
punix why stack.pcl Hello.version

Dry-run any deploy

punix service deploy MyStack --file stack.pcl --dry-run

The --dry-run flag does the full deploy pipeline (compose, render config files, write the generation manifest, flip a scratch symlink) but against a sandbox directory instead of the real filesystem. The bytes that would land on /etc/ land under <deployments_root>/.dry-run/ for inspection.

First deploy walks through this.

Hermetic local testing

punix service deploy MyStack \
  --file stack.pcl \
  --transport-root /tmp/test-host \
  --store-root /tmp/test-store \
  --deployments-root /tmp/test-deploys

--transport-root rebases the entire filesystem surface under a tmp dir — so you can run a real (non-dry-run) deploy without root and without touching real /etc. Used heavily in the conformance suite.

Reading further

Per-command pages: