Skip to content

punix migrate

Bulk-migrate an RCL (the predecessor language; see history) package tree to a mirrored PCL tree. Mirrors the source directory layout one-to-one — every input .rcl produces one output .pcl.

Two migrators

punix migrate is the RCL → PCL path. The Homebrew formula → PCL path lives at tools/migrate-brew.py (run via uv run python tools/migrate-brew.py); it's how the recipes in packages/official/ were produced. See Corpus status.

Synopsis

punix migrate SRC OUT
  • SRC — a directory of .rcl files (typically nixos/ or slapos/-style trees).
  • OUT — destination directory; mirrors SRC's tree structure, with one .pcl per .rcl.

What it does

For each .rcl under SRC:

  1. Evaluate via the rcl CLI to get its resolved record form.
  2. Emit one PCL module per package, preserving the file structure.
  3. Annotate defects as # TODO[migrate] comments. The output PCL type-checks (you can punix check it) but unbuildable packages surface their gap loudly.

Output

$ punix migrate ./nixos ./pkgs
wrote 219 files under ./pkgs/: 198 ok, 12 todos, 9 eval-fails
  eval-fail nixos/exotic.rcl: rcl crashed on unbound ref
  TODO pkgs/curl.pcl:18: from_url with no hash — fixed-output not yet wired
  TODO pkgs/openssl.pcl:24: per-arch source needs more than one entry

The migrator output is not trusted: it's a starting point for hand-review. Every defect is located so you can grep for # TODO[migrate] and walk them.

Conformance

The conformance property: the migrator on real samples yields type-checking PCL whose build closure matches intent; defects surface as [E#] pre-build, not as runtime surprises. See Conformance — the brew-formula path is exercised by 95 tests under tests/a_unit/migrate/test_migrate_brew.py.

The brew→PCL translator

tools/migrate-brew.py reads Homebrew formulae from sandbox/homebrew-core/Formula/ and writes PCL recipes. It handles every dominant brew install shape (cargo, go, npm, autotools, cmake, meson, swift, pip, git-tag source). The output is reviewed, not trusted — # TODO[brew-import] markers point to anything the translator couldn't auto-translate.

uv run python tools/migrate-brew.py \
  --brew-core sandbox/homebrew-core \
  --out packages/experimental/from-homebrew \
  --names-from sandbox/brew-installed-on-request.txt

A produced recipe is promoted to packages/official/ once it builds green under make dogfood. See Corpus status for the full list of working recipes and Corpus blockers for what doesn't translate cleanly yet.

Status

punix migrate (RCL→PCL): code at src/punix/migrate/migrate.py. Stable.

tools/migrate-brew.py (Homebrew→PCL): code at src/punix/migrate/brew.py. Stable — 365 recipes successfully produced through it.

  • Corpus status — what's been ported through the brew translator.
  • Status: what works — engine breakdown.
  • Roadmap — what's next for the translator (multi-source, head do, vendored submodules).