diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 88b236b..06d5349 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ Cargo.lock.bak # Local git worktrees for in-flight branches (never tracked) worktrees/ + +# direnv / nix dev shell +/.direnv diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..71442e2 --- /dev/null +++ b/flake.lock @@ -0,0 +1,96 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1781577229, + "narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "567a49d1913ce81ac6e9582e3553dd90a955875f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1782184651, + "narHash": "sha256-4XHdXp3MRa++XiGkltJChCtdbCmSlNTwQRfWQOhqbRw=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "f59bc28dd0b89e9c0240d1b80195559fc79c2471", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..38d8d5f --- /dev/null +++ b/flake.nix @@ -0,0 +1,78 @@ +{ + description = "Maestro — unified terminal-session orchestrator: reproducible dev shell"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + rust-overlay.url = "github:oxalica/rust-overlay"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = + { + self, + nixpkgs, + rust-overlay, + flake-utils, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ rust-overlay.overlays.default ]; + }; + + # Honor the repo's own pin (`rust-toolchain.toml` → stable + rustfmt + + # clippy) so a contributor builds the project as declared, independent of + # whatever toolchain happens to be installed via rustup. + rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; + in + { + devShells.default = pkgs.mkShell { + packages = [ + rustToolchain + pkgs.rust-analyzer + + # Fast linker the project's cargo config expects (clang driver + + # `-fuse-ld=mold`). Shipped here so the shell is self-contained and + # does not depend on a personal ~/.cargo/config.toml. + pkgs.clang + pkgs.mold + + # Web frontend (web/ pins pnpm@9.15.4 via package.json#packageManager). + pkgs.nodejs_22 + pkgs.pnpm_9 + + # Integration tests drive real tmux + git (see CLAUDE.md). + pkgs.tmux + pkgs.git + + # Task runner for the Justfile (just web / web-dev / test / fmt). + pkgs.just + ]; + + # Make linking self-contained and hermetic. Cargo picks the FIRST + # matching rustflags source (env > target. > target. > + # build.rustflags) — it does NOT merge them. Setting the per-target + # rustflags here therefore *replaces* any `[build] rustflags` coming + # from a global ~/.cargo/config.toml — in particular the nightly-only + # `-Z threads=8` that would otherwise break this stable toolchain — + # while keeping the fast mold link. + CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER = "clang"; + CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS = "-C link-arg=-fuse-ld=mold"; + + shellHook = '' + # Use the pnpm pinned in web/package.json (corepack) if present; + # otherwise fall back to the nixpkgs pnpm_9 on PATH. + export RUST_BACKTRACE=1 + echo "maestro dev shell" + echo " rust $(rustc --version 2>/dev/null | cut -d' ' -f2)" + echo " node $(node --version 2>/dev/null)" + echo " pnpm $(pnpm --version 2>/dev/null)" + echo " tmux $(tmux -V 2>/dev/null | cut -d' ' -f2)" + echo "Run the web stack: just web-dev (Vite → /api proxied to a local registry/daemon)" + ''; + }; + } + ); +}