Repository Layout & Codebase Walkthrough
Aeroflare is a Go module split along one line that matters: pkg/ is the
importable engine, internal/ is everything that only makes sense inside the
CLI. The Go toolchain enforces the second half of that (no external module can
import internal/), and make check-api enforces the first half by failing if an
internal/ type leaks into a pkg/ signature.
If you intend to use Aeroflare as a library rather than modify it, read the Go API page instead — this one is about finding your way around the source.
cmd/ — binaries
| Path | What it is |
|---|---|
cmd/aeroflare/ | The interactive CLI. main.go only. |
cmd/aeroflare-ci/ | The non-interactive CI runner, which the GitHub Action wraps. |
cmd/gen_docs/ | Generates the CLI reference pages under docs/docs/reference/cli/ from the Cobra tree. |
pkg/ — the engines
The four library packages, in dependency order. None of them read a config file, an environment variable, or the keychain; none of them write to stdout. Registry, repository, and credential are always parameters.
pkg/prepare/— turning a store path into artifacts. Sub-packages:store(querying the Nix store),hash,compress(zstd/xz/gzip),narinfo(generating and serialising the metadata),signing,cache, andprepareitself.pkg/oci/— the registry layer, and the most load-bearing package in the project.network.gostreams.narblobs as OCI layers and maps.narinfofields onto manifest annotations (vnd.aeroflare.nar.*) usinggoogle/go-containerregistry.oci.goparses those annotations back.auth.gobuilds credentials — and only builds them: the token exchange, the retry policy, and re-authentication on expiry are all delegated to go-containerregistry's transport rather than reimplemented.config_manifest.goreads and writes thecache-configmanifest.pkg/push/— the push pipeline. Prepares each path, filters out what the registry or the upstream cache already has, uploads the rest in chunks, and flushes receipts after each chunk so an interrupted push keeps what it uploaded. A per-path failure is collected, not fatal. Progress goes through aReporterthe caller supplies.pkg/proxy/— the substituter.proxy_server.goanswers/nix-cache-info,/<hash>.narinfo,/nar/<…>, and/public-key, resolving each narinfo from manifest annotations and streaming each NAR straight from the registry blob without buffering to disk.bootstrap.gostarts it and resolves cache-wide config. Requests the registry cannot satisfy fall through to the configured upstreams.
Supporting packages: pkg/cmd/* holds the Cobra command constructors (one
sub-package per command, each thin: parse flags, resolve config, call an engine);
pkg/cmdutil is the Factory plus registry/credential resolution — the
worked example of how to feed the engines; pkg/iostreams abstracts
stdin/stdout/stderr for testability.
internal/ — CLI-only logic
internal/aerocmd/— assembles the command tree and the factory.internal/auth/— token resolution and validation. TheResolverwalks flags → environment (GITHUB_TOKEN,GH_TOKEN, …) → secrets manager, in that order, and validates that a PAT actually carrieswrite:packages.internal/secrets/— token storage, backed by the OS keychain viazalando/go-keyring.internal/backend/— theCacheBackendabstraction and itsNativeBackendimplementation, which publishes each completed push as its own OCI image.internal/run/— theaeroflare runwrapper: spawn an ephemeral proxy on a free port, inject--option extra-substituters, run the subprocess, push what it printed.internal/ci/— theaeroflare-cirunner: config parsing, cache specs, build filtering, signing-key resolution, reporting.internal/init/— the provisioning wizard (GitHub/GitLab repo creation, Cloudflare Worker deployment) and thehuhtheme.internal/ui/— terminal output primitives (boxes, tables). Deliberately unreachable from the engines.internal/build/—VersionandDate, injected at link time.
How data flows through a push
Tracing aeroflare push --store-path /nix/store/abc…-package:
- Entry.
pkg/cmd/pushparses the flags.pkg/cmdutilresolves the registry, the repository, and a credential, and builds anauthn.Authenticator. - Preflight.
pkg/pushdecides what actually needs uploading, dropping paths the registry or the upstream cache already serves. - Prepare.
pkg/prepareserialises the store path into a.nar, compresses it (zstd by default), hashes it, and builds the.narinfoin memory — signing it if a key was supplied. - Upload blob.
pkg/ocistreams the compressed NAR to the registry as a rawv1.Layer. - Map metadata.
pkg/ocibuilds an OCI manifest and writes every narinfo field (StorePath,FileHash,NarHash,Sig, …) intovnd.aeroflare.nar.*annotations on it. - Tag. The manifest is tagged with the 32-character Nix store hash (
abc…). That tag is the index: a later<hash>.narinforequest becomes a single manifest fetch, with no database to consult.