ADR-336: Before 0.1 Nikaia Is Installed With cargo install From the Repository; 0.1 Publishes to crates.io; GitHub Releases Begin at 0.2, With the Binary and a Container Image; a .deb Waits for 1.0

Status: Accepted Date: October 8, 2026 (#541) Answers: how a person gets the compiler without building it in a checkout they must keep, and from which version each channel is offered Related: ADR-002 D4 (a project reaches std through a sysroot, which by default is the source tree the compiler was built from); ADR-286 D23-D26 (a published Nikaia package x is the crate nikaia_x, the prefix is added and removed by the tools and never written, and a crate under it that is not a Nikaia package is refused by name); Part III 13.2b, 13.3 (a Nikaia package x is the crate nikaia_x on crates.io)

1. Question

Through which channel is the compiler offered at each stage of the language’s version, and what does a release hold?

Today the compiler is built with cargo build --release -p nikaia in a clone, and the clone has to stay where it is, because the sysroot is the source tree the binary was built from. Every channel added is one more thing each change can break and one more promise to a user: an archive promises a layout, a package promises upgrades, a registry promises that a version stays installable. The question is which of them the project takes on, and when.

2. How others do it

Language / tool Its answer Source
Rust rustup and per-target archives; distribution packages are made by the distributions from memory, not checked
Zig per-target archives on the website from early versions; no installer of its own from memory, not checked
Gleam, Roc archives on GitHub releases; Gleam adds container images from memory, not checked
Rust tools in general (ripgrep, just) cargo install from crates.io first, archives and packages later from memory, not checked

What transfers: a language whose compiler is a Rust crate can be installed by cargo install from the day it builds, with nothing to maintain. What does not transfer: Nikaia needs a Rust toolchain at run time anyway (it compiles through rustc), so the main gain of an archive elsewhere, needing no toolchain, is smaller here.

3. Options, weighed

Option A — archives on GitHub releases now (#541’s proposal)

A tagged release builds bin/nikaia and the sysroot into an archive per target, with its SHA-256. The binary has to find a sysroot relative to itself, and every version tag is a release someone may depend on.

Option B — channels by version: cargo install --git now, crates.io from 0.1, GitHub releases from 0.2, .deb from 1.0

cargo install --git https://github.com/Nikaia-Language/Nikaia --locked nikaia

Cargo keeps the checkout it built from, and the compiler’s default sysroot is that checkout, so this works with today’s 13.2b and no change to the compiler.

Weighed

  Who pays What the user writes What it costs the project If it is wrong
A the project, at every tag: a layout, a sysroot lookup, a workflow, before the language is stable download, unpack, PATH a release workflow and a sysroot rule to decide now archives already downloaded stay out there, at versions nobody supports
B the user, once: a build of a few minutes one cargo install line nothing before 0.1; each channel arrives with the version that needs it cheap: a channel not yet offered can be offered earlier

4. Decision

B. A channel is a promise to keep, so each one starts at the version where the language is stable enough to keep it.

D1 — Before 0.1 the compiler is installed with cargo install from the repository

cargo install --git https://github.com/Nikaia-Language/Nikaia --locked nikaia, pinned with --tag or --rev where a user wants one version. The sysroot is the checkout Cargo built from, as 13.2b’s default already says. Building from a clone stays the second way. Nothing else is offered: no archive, no image, no package.

D2 — From 0.1 the compiler is published on crates.io

cargo install nikaia. Every crate it needs is on crates.io, and the sysroot travels inside what is published.

The prefix of ADR-286 D23 has no exception. Everything this project publishes is named the way a user’s package is: the tools put nikaia_ in front of the name it has here, so nikaia-std is published as nikaia_nikaia_std and nikaia-logic as nikaia_nikaia_logic. crates.io does not tell - from _. The compiler itself is nikaia, which is not under the prefix.

D3 — From 0.2 a GitHub release is made for each version, with the binary and a container image

Each release holds, per target, the compiler built with the release profile, together with its sysroot, and the archive’s SHA-256.

With it comes one container image, made to be used: compiling or running a .nika file with nothing installed but a container runtime. It holds nikaia, the Rust toolchain it compiles with, and std already compiled into the cache, so that the first nikaia run in it compiles only the program. It is published in GitHub’s container registry and on Docker Hub.

D4 — A .deb from 1.0, and system packages after the editor extension

Distribution packages promise upgrades within a distribution’s own cycle, which a language before 1.0 cannot keep. A .deb comes with 1.0; an .rpm comes no earlier than the editor extension of D6.

D6 — The VS Code extension comes before the system packages

The extension under editors/vscode is published before an .rpm, and may be before the .deb: an editor is where a person trying the language spends their time, and the extension promises no upgrade path to a distribution.

D5 — The version of a release is the specification’s

0.1, 0.2 and 1.0 are versions of the specification’s **Version:** line. A release carries that number and no second one.

Option A lost on cost: it makes the project keep a layout and a sysroot rule stable from the first tag, while D1 gives the same result, a compiler that runs from anywhere, for nothing.

5. Consequences

6. What this does not decide

This site is open source. Improve this page.