Install¶
Three ways in, in increasing order of commitment: the install script, a wheel from PyPI, or a source checkout. uv is the supported package manager for working on Punix; everything below the source section assumes uv is on your PATH.
Prerequisites¶
- Python 3.13 or 3.14. The CI matrix tests both; earlier versions are not supported.
- uv ≥ 0.5, for the source path only. Install via
curl -LsSf https://astral.sh/uv/install.sh | shorbrew install uv. - POSIX shell + coreutils (
mkdir,cp,mv,ln,rm). Standard on Linux and macOS. - For SSH deploys:
ssh+rsync(any reasonably recent OpenSSH). - For multi-arch source builds:
curlorwget(the fetcher uses a curl-class User-Agent; browser UAs hit anti-AI gateways).
Install¶
The script¶
It prints what it will do and pauses before doing it.
From PyPI¶
The wheel depends on cyclopts and tabulate, and nothing else: no compiler, no git, no evaluator you don't invoke. (MIXINv2 is a development dependency, used only by the dual-engine differential harness; see architecture.)
From source¶
uv sync resolves the dependency graph (everything from PyPI, no git sources) and creates a .venv. After that, uv run punix --help works. This is the path to take if you intend to change Punix; see contributing.
Run without activating the venv
Prefix every command with uv run:
uv run punix check stack.pcl
uv run punix build stack.pcl
uv run punix service deploy MyStack --file stack.pcl
Or activate it once:
Verify¶
You should see the top-level command list:
Usage: punix COMMAND
Punix v2 — typed declarative build & service deployer.
Commands:
build Check + build-closure pre-pass, then realise every package module.
check Type-check FILE only.
help Show the help overview, or a focused help page for TOPIC.
info Show recipe metadata and the predicted store path for MODULE.
install Build MODULE (cache-hit if already built) and link binaries into the profile.
list List installed packages.
migrate Migrate a Homebrew formula tree to a mirrored tree of PCL files.
profile Inspect and switch the active user profile (list/switch/diff).
search Search packages whose pname or description matches REGEX.
service Deploy and roll back service stacks (atomic via single os.replace).
store Content-addressed store queries.
uninstall Remove module from the active profile.
upgrade Report newer upstream versions for packages with meta.upstream.
why Print TARGET's resolved value and its provenance chain.
Get the package collection¶
Installing the punix CLI doesn't ship the recipe corpus. Before your first
punix install, fetch the collection once:
This clones the recipe tree into ~/.punix/packages/ (pinned to a revision) so
punix install, search, info, and friends resolve against it from any
directory. Re-run it to update; check what you have with punix packages
status. Point it at a different collection or pin with [packages] in
~/.punix/config.toml or the --url / --rev flags; see punix help
collections.
If you're working inside a Punix source checkout, this step is optional: a
local packages/official/ tree is discovered automatically.
If you get command not found, your shell can't see uv's virtualenv; use uv run punix --help instead.
Run the test suite (optional)¶
Before relying on Punix, confirm the conformance suite passes on your box:
make test # uv run pytest
make check # ruff + ty + pyrefly + mypy
nox -s tests # the full matrix (3.13 + 3.14)
All tests should pass. The conformance suite (tests/c_e2e/test_conformance_stage*.py) is the executable spec; a failure there means a property this site claims does not hold on your box.
SSH-only: localhost sshd fixture¶
The SSH e2e tests spin up a real sshd on a free port. They auto-skip if sshd / ssh-keygen aren't on PATH. On macOS /usr/sbin/sshd ships with the OS; on Linux:
No daemon needs to be running: the fixture starts its own per-test.
Common install issues¶
uv sync fails resolving a dependency
Every dependency, including the mixinv2 dev dependency, resolves
from PyPI; there are no git sources and no [tool.uv.sources]
entries. A resolution failure signals a network or index problem.
There is no pin to adjust. (Earlier releases did pin MIXINv2 by git rev;
if you are following an old copy of these instructions, drop the
[tool.uv.sources] block.)
Python 3.12 or earlier
Not supported. Punix uses 3.13-specific typing features (PEP 695
type statement, TypeAliasType). Upgrade or use uv's --python
flag: uv sync --python 3.13.
macOS BSD vs GNU coreutils
Punix targets POSIX. macOS mv, ln, cp all work. One
historical snag was mv -T (GNU-only) for the
atomic symlink flip; now removed (see decisions).
Next¶
→ Your first build: a single-package PCL module, realised into the content-addressed store.