From 3859627013d2aaa275d1923e387d5fdb1b772169 Mon Sep 17 00:00:00 2001 From: clawdbot Date: Mon, 12 Oct 2026 22:11:09 +0000 Subject: [PATCH] build: add Nix flake dev shell and claw package (#3247) --- .envrc | 1 + .github/workflows/rust-ci.yml | 4 + .gitignore | 4 + docs/nix-development.md | 203 ++++++++++++++++++++++++++++++++++ flake.nix | 115 +++++++++++++++++++ 5 files changed, 327 insertions(+) create mode 100644 .envrc create mode 100644 docs/nix-development.md create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..3550a30f --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 963b1874..c6d4e2f8 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -25,6 +25,8 @@ on: - tests/test_roadmap_helpers.py - docs/** - rust/** + - flake.nix + - .envrc pull_request: branches: - main @@ -47,6 +49,8 @@ on: - tests/test_roadmap_helpers.py - docs/** - rust/** + - flake.nix + - .envrc workflow_dispatch: concurrency: diff --git a/.gitignore b/.gitignore index 9ebbde0d..5def5d5d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,7 @@ status-help.txt .port_sessions/ # Local agent session state .gjc/ +# Nix build outputs and direnv +.envrc.local +result +result-* diff --git a/docs/nix-development.md b/docs/nix-development.md new file mode 100644 index 00000000..c73c3ad3 --- /dev/null +++ b/docs/nix-development.md @@ -0,0 +1,203 @@ +# Nix flake development environment + +This repository includes a **`flake.nix`** for reproducible development environments on NixOS and systems with Nix installed. + +## Prerequisites + +- **Nix** (version 2.4 or later with flakes support enabled) +- **direnv** (optional, for automatic environment loading via `.envrc`) + +To verify Nix is installed and flakes are enabled: + +```bash +nix --version +nix flake --help +``` + +If flakes are not enabled, add this to your `~/.config/nix/nix.conf`: + +``` +experimental-features = nix-command flakes +``` + +## Quick start + +### Enter the development environment + +**Option 1: Using `nix flake`** (without direnv) + +```bash +nix flake update # Update inputs (optional, pins nixpkgs) +nix develop # Enter default dev shell +nix develop .#full # Enter full dev shell with extra tools +exit # Leave the shell +``` + +**Option 2: Using direnv** (automatic on directory entry) + +```bash +direnv allow # Trust the .envrc file (one-time setup) +cd . # Direnv reloads the flake automatically +``` + +When you leave the repository directory, the environment is automatically unloaded. + +## Development shells + +The flake provides two development shells: + +### `default` (minimal) + +```bash +nix develop +``` + +Includes: +- Rust (stable, latest) +- Rust source code (`rust-src`) +- `cargo-edit` (dependency management helpers) +- `cargo-expand` (macro expansion tool) +- `cargo-watch` (file watcher for incremental builds) +- Build tools: `pkg-config`, `openssl`, `git`, `ca-certificates` + +### `full` (with extra tooling) + +```bash +nix develop .#full +``` + +Includes everything from `default` plus: +- `clippy` (linter) +- `rustfmt` (code formatter) +- `mold` (fast linker) +- `lldb` (debugger) + +## Building the claw binary + +### With the dev environment + +```bash +nix develop +cd rust +cargo build -p rusty-claude-cli +``` + +### Directly with `nix build` + +```bash +nix build .#claw # Build the claw binary +nix build # Same as .#claw (default package) +``` + +The compiled binary is symlinked to `./result/bin/claw`. + +## Running common tasks + +Once in the dev shell: + +```bash +# Format code +cd rust +cargo fmt + +# Run clippy linter +cargo clippy --workspace --all-targets -- -D warnings + +# Run all tests +cargo test --workspace + +# Run tests for a specific crate +cargo test -p rusty-claude-cli + +# Build with optimizations +cargo build --release -p rusty-claude-cli +``` + +## Environment variables + +The flake automatically sets: + +- `RUSTUP_TOOLCHAIN=stable` — uses stable Rust from nixpkgs +- Standard Rust build flags are inherited from the environment + +For development, the minimal dev shell includes a helpful message on entry: + +``` +Claw Code development environment +Run 'cargo build -p rusty-claude-cli' to build the claw binary +Run 'cargo test --workspace' to run tests +Run 'scripts/fmt.sh' to format code +``` + +## Troubleshooting + +### `command not found: nix` + +Nix is not installed. Install it from [nixos.org/download.html](https://nixos.org/download.html). + +### `error: experimental Nix feature 'flakes' is disabled` + +Enable flakes in your Nix configuration (`~/.config/nix/nix.conf` or `/etc/nix/nix.conf`): + +``` +experimental-features = nix-command flakes +``` + +### `error: ... does not provide attribute 'claw'` + +The flake structure may have changed. Try updating: + +```bash +nix flake update +nix flake check +``` + +### Rebuilds are slow after updating dependencies + +Cargo will recompile dependencies if `Cargo.lock` changes. This is expected: + +```bash +nix build --rebuild +``` + +### `cache lock file needs to be updated` + +The Cargo.lock in `rust/` needs to be committed. Run: + +```bash +cd rust +cargo generate-lockfile +git add Cargo.lock +git commit -m "update: Cargo.lock" +``` + +## Integration with other tools + +### IDE integration (VS Code, IntelliJ, etc.) + +Many IDEs can detect and use Nix environments. Direnv integration is recommended: + +1. Install the direnv extension +2. Enable `direnv` shell integration in your IDE +3. Run `direnv allow` in the repository + +Your IDE will automatically use the correct Rust toolchain and dependencies from the flake. + +### CI/CD + +For GitHub Actions, consider using [cachix/install-nix-action](https://github.com/cachix/install-nix-action) to set up Nix on the runner: + +```yaml +- uses: cachix/install-nix-action@v18 + with: + nix_path: nixpkgs=channel:nixos-unstable + extra_nix_config: "experimental-features = nix-command flakes" + +- run: nix develop -c cargo test --workspace +``` + +## More information + +- [NixOS flakes documentation](https://nixos.wiki/wiki/Flakes) +- [Direnv documentation](https://direnv.net/) +- [Rust on Nix](https://github.com/oxalica/rust-overlay) diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..72bfd384 --- /dev/null +++ b/flake.nix @@ -0,0 +1,115 @@ +{ + description = "claw-code: Claude Code CLI agent harness in Rust"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { self, nixpkgs, flake-utils, rust-overlay }: + flake-utils.lib.eachDefaultSystem (system: + let + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { + inherit system overlays; + }; + + # Build inputs needed for Rust and the project + buildInputs = with pkgs; [ + pkg-config + openssl + ca-certificates + git + ]; + + # Runtime inputs for the dev environment + nativeBuildInputs = with pkgs; [ + (rust-bin.stable.latest.default.override { + extensions = [ "rust-src" ]; + targets = [ ]; + }) + cargo-edit + cargo-expand + cargo-watch + ]; + + # Derivation to build the claw binary + clawBinary = pkgs.rustPlatform.buildRustPackage { + pname = "claw"; + version = (builtins.fromTOML (builtins.readFile ./rust/Cargo.toml)).workspace.package.version; + + src = ./rust; + + # Hash of all the dependencies in Cargo.lock + # This needs to be updated when dependencies change + # Run: nix flake update + cargoLock = { + lockFile = ./rust/Cargo.lock; + }; + + cargoBuildFlags = [ "-p" "rusty-claude-cli" ]; + + buildInputs = buildInputs ++ (with pkgs; [ + openssl + ]); + + nativeBuildInputs = with pkgs; [ + pkg-config + ]; + + meta = with pkgs.lib; { + description = "Claude Code CLI: agent harness with Rust implementation"; + homepage = "https://github.com/ultraworkers/claw-code"; + license = licenses.mit; + platforms = platforms.unix; + }; + }; + + in + { + # Provide the claw binary as a package + packages.claw = clawBinary; + packages.default = clawBinary; + + # Development shell for contributors + devShells.default = pkgs.mkShell { + name = "claw-dev"; + inherit buildInputs nativeBuildInputs; + + shellHook = '' + echo "Claw Code development environment" + echo "Run 'cargo build -p rusty-claude-cli' to build the claw binary" + echo "Run 'cargo test --workspace' to run tests" + echo "Run 'scripts/fmt.sh' to format code" + ''; + + # Make sure we have the right Rust toolchain + RUSTUP_TOOLCHAIN = "stable"; + }; + + # Alternative shell with additional development tools + devShells.full = pkgs.mkShell { + name = "claw-dev-full"; + inherit buildInputs nativeBuildInputs; + + nativeBuildInputs = nativeBuildInputs ++ (with pkgs; [ + clippy + rustfmt + mold + lldb + ]); + + shellHook = '' + echo "Claw Code full development environment (with extra tools)" + echo "Available tools: clippy, rustfmt, mold (linker), lldb (debugger)" + ''; + + RUSTUP_TOOLCHAIN = "stable"; + }; + } + ); +}