The FastTrackStudios fleet's shared devenv modules and pins. Every fleet Rust repo imports them, so each dev shell, each CI job and each release build compiles with one rustc store path, one gcc, mold and glibc, and kache shares their builds across repos.
Written for devenv 2.4.0.
| Module | What it gives a repo |
|---|---|
rust |
The fleet toolchain (lib/toolchain.nix: rust-overlay's rust-bin.stable."1.99.1" with rust-src, rust-analyzer, clippy, rustfmt and wasm32), mold as the linker, cargo-hakari, prek, cargo-rail, just, RUST_SRC_PATH, a fleet-doctor script, and prek's hooks in repos with a prek.toml |
dioxus |
The fleet's one dx (the Brahmastra-Labs fork plus pkgs/dx-no-rustc-wrapper.patch, DX_NO_RUSTC_WRAPPER=1), binaryen, wasm-bindgen-cli, tailwindcss and the wasm32 C toolchain |
telemetry |
devenv up runs a local Teley on :8787 (the room in ~/.teley/session.json, which Claude's Teley MCP subscribes to) and an OpenTelemetry Collector on :4318 that batches and forwards to it |
darwin |
iOS and macOS: xcrun linker wrappers, IPHONEOS_DEPLOYMENT_TARGET, DYLD_LIBRARY_PATH. Inert on Linux |
pins.json is the one source of truth for the revisions: nixpkgs,
rust-overlay, nixpkgs-dx, the dx fork, Teley, the rustc store path each
system should get, and the devenv that CI bootstraps.
On 2.4.0 a remote import's own devenv.yaml is not evaluated, so each
module is a devenv.nix only and the importing repo declares the inputs.
A repo's devenv.yaml:
require_version: ">=2.4.0"
strict_ports: true # with `telemetry`: 8787 and 4318 never move
inputs:
nixpkgs:
url: github:NixOS/nixpkgs/<pins.json nixpkgs.rev>
rust-overlay:
url: github:oxalica/rust-overlay/<pins.json rust-overlay.rev>
inputs:
nixpkgs:
follows: nixpkgs
overlays:
- default
nixpkgs-dx: # with `dioxus` only
url: github:NixOS/nixpkgs/<pins.json nixpkgs-dx.rev>
devenv-fleet:
url: github:FastTrackStudios/devenv-fleet/v0.1.1
flake: false
imports:
- devenv-fleet/rust
- devenv-fleet/dioxus # optional
- devenv-fleet/telemetry # optional
- devenv-fleet/darwin # optionalThen the repo's own devenv.nix adds its libraries, env and processes.
Don't write the revisions by hand. From a checkout of this repo at the tag you want:
scripts/fleet-pins --write /path/to/repo # rewrite devenv.yaml, then devenv update
scripts/fleet-pins /path/to/repo # check devenv.yaml, devenv.lock and flake.lock; exit 1 on driftA repo that keeps a packaging flake.nix takes the same pins from this
repo's flake.nix: inputs.devenv-fleet.url = "github:FastTrackStudios/devenv-fleet/<tag>",
nixpkgs.follows = "devenv-fleet/nixpkgs", rust-overlay.follows = "devenv-fleet/rust-overlay",
and devenv-fleet.lib.toolchainFor pkgs for the toolchain.
-
.envrcmust load devenv's direnvrc beforeuse devenv. A bareuse devenvfails withuse_devenv: command not found, and in an agent shell that error is silent, so the agent falls back to whatever rustc is on the host PATH:eval "$(devenv direnvrc)" use devenv
-
Never use devenv's dotenv (
dotenv.enable). It copies the whole.envfile, secrets included, into the Nix store. Load.envwith direnv's owndotenv_if_exists .env, afteruse devenv, and in a process withset -a; [ -f .env ] && . ./.env; set +a. -
Don't let devenv pick the linker. The
rustmodule setslanguages.rust.clangLinker.enable = false. devenv's Linux default passes--ld-path=ld.lld, which silently replaces the mold that.cargo/config.toml's-fuse-ld=moldasks for. Don't setlanguages.rust.rustflagsormold.enableeither:RUSTFLAGSreplaces the fleet's.cargo/config.tomlrustflags tables. -
kache is the host's. When
kacheis on PATH andRUSTC_WRAPPERis unset, therustmodule's shell exportsRUSTC_WRAPPERas kache's path. A host that setsRUSTC_WRAPPERitself (THEBATTLESHIP's runners) or kache as cargo'sbuild.rustc-wrapperkeeps its own. Never unsetRUSTC_WRAPPERin a shell. -
One cargo-hakari.
pins.jsonpins it (cargo-hakari.version); therustmodule fails to evaluate if the pinned nixpkgs carries another. CI installs that version (taiki-e/install-actionwithcargo-hakari@<version>). -
Extra Rust targets change the rustc path.
fleet.rust.extraTargetsbelongs in a profile (profiles.mobile.module), not the default shell. -
The OTLP env goes to processes only. Merge
config.fleet.telemetry.processEnvinto a process'senv; the shell gets none, so tests export nothing.
devenv shell -- fleet-doctor # rustc path (exit 1 if not pins.json's), kache wrapper, linkerOn a runner without devenv, take the pinned one (it is on cache.nixos.org):
nix build --no-link --print-out-paths "github:NixOS/nixpkgs/$(jq -r .devenv.nixpkgs pins.json)#devenv"then run steps as devenv shell -- bash -e {0}.
MIT OR Apache-2.0, at your option (LICENSE-MIT, LICENSE-APACHE).