Skip to content

The dawn package tool

Dawn is the package tool for Dusk, and like the compiler it is written in Dusk. Since 1.14.0 it drives a full package system: a package is a git repository with a package.dawn manifest at its root, a version is a git tag pinned to a commit, and dawn’s job is to turn the references you declare into exact commits on disk. Dawn installs alongside the dusk compiler; the AUR package builds and installs the two binaries together (see the dusk CLI). Dawn’s version tracks the toolchain version, so dawn version prints dawn 1.15.0 on this release.

For the narrative walkthrough, creating a project, writing the manifest, adding a dependency, and importing through it, see the packages guide. This page is the command reference.

Dawn owns the network and nothing else. It resolves each reference to a commit, writes the lock, and checks code out under dawn_modules/. The compiler owns the build and never opens a socket: it reads the manifest, the lock, and the checkouts, and compiles. So a machine that has fetched a project once builds it offline forever, and a machine that has not is told which dawn command to run.

git is the whole network layer. Dawn shells out to the system git (ls-remote to resolve a reference, clone --depth 1 --branch, then a detached checkout), so git has to be on your path to fetch. A file:// source clones from a local path, which is how the test suite runs entirely offline.

Dawn has eight commands. A bare dawn, or help, --help, or -h, prints the usage text.

Terminal window
dawn init [name] # write a starter package.dawn, gitignore dawn_modules/
dawn get # resolve every requirement and write dawn.lock
dawn add <alias> <source> <ref> # append a @require line to the manifest
dawn update [alias] # re-resolve the lock (one alias, or all)
dawn tree # print the dependency graph, offline
dawn build # build the project through the compiler
dawn run [args...] # build, then run, forwarding args
dawn version # print the toolchain version

init scaffolds a project. add writes a @require line for you rather than editing the manifest by hand. get is the workhorse: it resolves each requirement to a commit and writes one @lock line per requirement into dawn.lock, in declaration order. update re-resolves the lock when you want to move a pin, either for a single alias or for the whole graph. build and run hand the project to the compiler, run forwarding any trailing args to the program and exiting with its exit code.

Added in 1.14.1, dawn tree prints the dependency graph from package.dawn, dawn.lock, and each checkout’s .dawn stamp, and it touches nothing else, so it works offline. It shows the root as name and version, then each requirement as its alias, source, ref, and the first twelve characters of the locked commit, indented one level per depth. A requirement that has no lock line prints (not locked) and one that is locked but absent from dawn_modules/ prints (not fetched); either way the command reports the state and exits 0. It takes no arguments.

dawn.lock is generated and committed next to the manifest. It holds @lock lines and only those, one @lock <alias> <source> <ref> <commit> per requirement in declaration order. It is what makes a build repeatable: the compiler builds against the locked commit, never a moving reference. A requirement with no lock line stops the build with 'maybe' is not locked; run dawn get, so the remedy is always a named command.

Every dependency in the graph lands flat at dawn_modules/<alias>/, a detached checkout at its locked commit, beside a one-line stamp dawn_modules/<alias>/.dawn. A checkout is vouched for by its actual git state (rev-parse HEAD plus status --porcelain), not just the stamp, so a tree that has been edited, detached, or gutted is replaced on the next get. The per-checkout line reads cached, fetching, or refreshing accordingly.

Added in 1.14.1, dawn keeps a bare mirror of every source it has seen, under $DAWN_CACHE, or ~/.dawn/cache when that is unset, at <host>/<owner>/<repo>-<hash8>.git. Every fetch after the first clones its working tree out of the mirror rather than off the network, so the second project to require a package costs no network trip, and a machine that fetched a source once can fetch it again offline.

A get asks the mirror before the network. dawn update always fetches first, since moving a pin must not read a stale mirror. The cache is an optimization and never a gate: if it cannot be written, dawn steps around it and fetches from the remote, reporting dawn: cannot update the cache for '<alias>' at <url> without failing the command.