Bootstrap a Rust project with Nix flake development environment
/plugin marketplace add jwilger/claude-code-plugins/plugin install bootstrap@jwilger-claude-pluginsInitialize a new Rust project with a Nix-based development environment including:
Use AskUserQuestion to ask:
Question: Where should the project be created?
If creating new directory:
mkdir -p <project-name>Use AskUserQuestion to ask:
Question: Include database tooling?
Run these commands to get the latest versions:
# Get latest cargo-nextest version
nix shell nixpkgs#cargo -c cargo search cargo-nextest 2>/dev/null | head -1 | sed 's/.*= "\([^"]*\)".*/\1/'
# Get latest cargo-audit version
nix shell nixpkgs#cargo -c cargo search cargo-audit 2>/dev/null | head -1 | sed 's/.*= "\([^"]*\)".*/\1/'
Store these versions for use in the flake.nix template.
Create flake.nix in the project directory with this template (substitute PROJECT_NAME, CARGO_NEXTEST_VERSION, CARGO_AUDIT_VERSION, and conditionally include DATABASE_PACKAGES):
{
description = "PROJECT_NAME development environment";
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
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs {
inherit system overlays;
};
rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
in
{
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
rustToolchain
git
git-spice
pre-commit
nodejs_22
glow
just
jq
# DATABASE_PACKAGES (sqlx-cli and postgresql - only if database tooling selected)
];
RUST_SRC_PATH = "${rustToolchain}/lib/rustlib/src/rust/library";
shellHook = ''
# Configure git for stacked PR workflow
git config --local rebase.updateRefs true 2>/dev/null || true
CARGO_AUDIT_VERSION="CARGO_AUDIT_VERSION"
CARGO_NEXTEST_VERSION="CARGO_NEXTEST_VERSION"
# Setup local cargo bin directory
export CARGO_INSTALL_ROOT="$PWD/.cargo-bin"
export PATH="$CARGO_INSTALL_ROOT/bin:$PATH"
# Create directory if it doesn't exist
mkdir -p "$CARGO_INSTALL_ROOT/bin"
# Check cargo-nextest version
if ! command -v cargo-nextest >/dev/null 2>&1 || [ "$(cargo-nextest --version 2>/dev/null | awk '{print $2}')" != "$CARGO_NEXTEST_VERSION" ]; then
echo "Installing cargo-nextest $CARGO_NEXTEST_VERSION to $CARGO_INSTALL_ROOT..."
cargo install cargo-nextest --version "$CARGO_NEXTEST_VERSION" --locked --root "$CARGO_INSTALL_ROOT"
fi
# Check cargo-audit version
if ! command -v cargo-audit >/dev/null 2>&1 || [ "$(cargo-audit --version 2>/dev/null | awk '{print $2}')" != "$CARGO_AUDIT_VERSION" ]; then
echo "Installing cargo-audit $CARGO_AUDIT_VERSION to $CARGO_INSTALL_ROOT..."
cargo install cargo-audit --version "$CARGO_AUDIT_VERSION" --root "$CARGO_INSTALL_ROOT"
fi
# Use project-local advisory database
alias cargo-audit='cargo audit --db "$PWD/.cargo-advisory-db"'
# git-spice workflow alias: sync, restack all branches, and submit
alias gs-sync='gs repo sync --restack && gs stack submit'
'';
};
}
);
}
When creating the file:
sqlx-cli and postgresql to buildInputsCreate rust-toolchain.toml:
[toolchain]
channel = "stable"
components = ["rustfmt", "clippy", "rust-src", "rust-analyzer"]
profile = "default"
Create .envrc:
use flake
Create .gitignore:
.direnv/
.envrc
.cargo-bin/
Create CLAUDE.md with project-specific guidance:
# CLAUDE.md
This project uses a Nix-based development environment.
## Development Environment
We use Nix flakes for reproducible development environments. The dev shell should already be loaded.
### Running utilities not in the dev shell
If you need a utility that isn't already in the dev shell, use `nix shell` to temporarily run it:
```bash
nix shell nixpkgs#<package> -c <command>
For example:
nix shell nixpkgs#ripgrep -c rg "pattern" .
We use commitizen-style commit messages. The format is:
<type>(<scope>): <subject>
<body>
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
IMPORTANT: Commit messages should explain the WHY, not just the what/how. The code diff shows what changed; the commit message should explain the reasoning and context behind the change.
feat(auth): add rate limiting to login endpoint
Prevent brute-force attacks by limiting login attempts to 5 per minute
per IP address. This addresses security audit finding SEC-2024-042.
feat(auth): add rate limiting
Added rate limiting code to the auth module.
### 9. Build the Nix Development Environment
Build the development shell to verify the flake is valid and generate `flake.lock`:
```bash
nix develop --command echo "Development shell built successfully"
Error Handling:
If the build fails:
The build MUST succeed before proceeding to the git commit step.
Run these commands in sequence:
git init
git add flake.nix flake.lock rust-toolchain.toml .gitignore CLAUDE.md
git commit -m "$(cat <<'EOF'
chore(bootstrap): initialize Nix-based Rust development environment
Establish reproducible development environment using Nix flakes with:
- Rust stable toolchain via rust-overlay (with clippy, rustfmt, rust-analyzer)
- cargo-nextest for faster test execution
- cargo-audit for security vulnerability scanning
- git-spice for stacked PR workflows
- direnv integration for automatic environment activation
This foundation ensures all contributors have identical tooling without
manual setup, eliminating "works on my machine" issues and enabling
immediate productivity on project onboarding.
EOF
)"
Show a summary:
Rust project initialized successfully!
Created files:
- flake.nix (Nix development environment)
- flake.lock (pinned dependency versions)
- rust-toolchain.toml (Rust stable with rustfmt, clippy, rust-src, rust-analyzer)
- .envrc (direnv integration)
- .gitignore
- CLAUDE.md (development guidelines)
Tool versions:
- cargo-nextest: X.Y.Z
- cargo-audit: X.Y.Z
**IMPORTANT: Exit Claude Code now and load the Nix development shell.**
If you have direnv configured, the shell will load automatically when you cd into the project directory.
Otherwise, run `nix develop` manually to enter the development shell.
Once the development shell is loaded, restart Claude Code in the project directory.