Initialize and manage Nix flake development environments with auto-detection and security tooling
Manages Nix flake development environments with auto-detection and security tooling
/plugin marketplace add jskswamy/claude-plugins/plugin install devenv@jskswamy-plugins[add|upgrade|remove|security]Initialize and manage Nix flake development environments. Provides a devbox-like experience with auto-detection of project dependencies and security tooling using native Nix solutions.
First, determine if this is a new setup or managing an existing environment:
flake.nix exists in the current directorygit-hooks input is present (indicates pre-commit is configured).claude/devenv.local.md if it exists for channel preference (default: nixos-unstable)2a. Auto-detect project stack:
Scan for language indicator files and suggest packages:
| File | Stack | Suggested Packages |
|---|---|---|
package.json | Node.js | nodejs, check lockfile for pnpm/yarn/npm |
pnpm-lock.yaml | Node.js + pnpm | nodejs, pnpm |
yarn.lock | Node.js + yarn | nodejs, yarn |
package-lock.json | Node.js + npm | nodejs |
Cargo.toml | Rust | rustc, cargo, rust-analyzer |
go.mod | Go | go, gopls |
pyproject.toml | Python | python3, uv |
requirements.txt | Python | python3, pip |
Gemfile | Ruby | ruby, bundler |
pom.xml | Java | jdk, maven |
build.gradle | Java/Kotlin | jdk, gradle |
*.csproj | .NET | dotnet-sdk |
Makefile | C/C++ | gnumake, gcc |
CMakeLists.txt | C/C++ | cmake, gcc |
Dockerfile | Docker | docker |
Also read CLAUDE.md if it exists to understand the project context and tech stack.
2b. Present detected packages:
Use AskUserQuestion with multiSelect to show detected packages:
Based on your repository, I detected these packages:
[x] nodejs_22
[x] pnpm
[x] typescript
Let user confirm, deselect, or add more via "Other" option.
2c. Ask for additional packages:
Ask: "Any additional packages you need? (e.g., redis, postgresql, jq)"
For each package mentioned:
nix-shell -p nix --run "nix search nixpkgs <package> --json" to find exact package namesnodejs@20), search for versioned variants like nodejs_202d. Offer security tools:
Use AskUserQuestion with multiSelect:
Security tools (recommended):
[ ] pre-commit - Git hooks with SAST tools for your stack (using git-hooks.nix)
[ ] gitleaks - Prevent secrets from being committed
If pre-commit selected, determine which git-hooks.nix hooks to enable based on detected stack:
| Stack | Hooks to Enable |
|---|---|
| JavaScript/TypeScript | eslint.enable = true; prettier.enable = true; |
| Python | ruff.enable = true; ruff-format.enable = true; |
| Go | golangci-lint.enable = true; |
| Rust | clippy.enable = true; rustfmt.enable = true; |
| Nix (always) | nixfmt-rfc-style.enable = true; statix.enable = true; deadnix.enable = true; |
| Shell scripts | shellcheck.enable = true; |
| Docker | hadolint.enable = true; |
| General (always) | check-yaml.enable = true; trailing-whitespace.enable = true; end-of-file-fixer.enable = true; |
If gitleaks selected:
gitleaks.enable = true; to the hooks configurationgitleaks to packages for manual use2e. Generate files:
flake.nix using the appropriate template:Basic Template (without pre-commit):
{
description = "Development environment";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = {
self,
nixpkgs,
flake-utils,
}:
flake-utils.lib.eachDefaultSystem (
system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.default = pkgs.mkShell {
packages = with pkgs; [
# PACKAGES_HERE
];
shellHook = ''
echo "╔══════════════════════════════════════╗"
echo "║ 🔧 devenv ║"
echo "║ Development environment loaded ║"
echo "╚══════════════════════════════════════╝"
'';
};
}
);
}
Template with git-hooks.nix (pre-commit enabled):
{
description = "Development environment";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
git-hooks.url = "github:cachix/git-hooks.nix";
};
outputs = {
self,
nixpkgs,
flake-utils,
git-hooks,
}:
flake-utils.lib.eachDefaultSystem (
system: let
pkgs = nixpkgs.legacyPackages.${system};
# Pre-commit hooks configuration
pre-commit-check = git-hooks.lib.${system}.run {
src = ./.;
hooks = {
# Nix
nixfmt-rfc-style.enable = true;
statix.enable = true;
deadnix.enable = true;
# General
check-yaml.enable = true;
trailing-whitespace.enable = true;
end-of-file-fixer.enable = true;
# LANGUAGE_HOOKS_HERE
# GITLEAKS_HERE
};
};
in {
# Run hooks in CI with: nix flake check
checks.pre-commit-check = pre-commit-check;
devShells.default = pkgs.mkShell {
packages = with pkgs; [
# PACKAGES_HERE
] ++ pre-commit-check.enabledPackages;
shellHook = ''
${pre-commit-check.shellHook}
echo "╔══════════════════════════════════════╗"
echo "║ 🔧 devenv ║"
echo "║ Development environment loaded ║"
echo "╚══════════════════════════════════════╝"
'';
};
}
);
}
.envrc:use flake
nix flake lock to generate flake.lock2f. Output instructions:
Development environment created!
To enter the environment:
nix develop
Or with direnv (recommended):
direnv allow
Your environment includes:
- [list packages]
[If pre-commit was selected:]
Pre-commit hooks are configured via git-hooks.nix.
They will auto-install when you run `nix develop`.
Available hooks:
- [list enabled hooks]
To run hooks manually: pre-commit run --all-files
To validate in CI: nix flake check
2a. Parse current state:
flake.nix and extract current packages from packages = with pkgs; [ ... ]git-hooks input exists in flake.nix (indicates pre-commit is configured)2b. Ask what to do:
Use AskUserQuestion:
What would you like to do?
○ Add packages - Add new packages to your environment
○ Upgrade packages - Update flake.lock to get latest versions
○ Remove packages - Remove packages from your environment
○ Setup security tools - Add pre-commit and gitleaks (only if not configured)
Only show "Setup security tools" option if git-hooks input is NOT present in flake.nix.
2c. Handle selected action:
Add packages:
nix-shell -p nix --run "nix search nixpkgs <package> --json"flake.nix to add packages to the listnix flake lock --update-input nixpkgs to update lockUpgrade packages:
nix flake update to update all inputsRemove packages:
flake.nix to remove selected packagesSetup security tools:
git-hooks input to flake.nixpre-commit-check configurationpre-commit-check.enabledPackages and shellHookchecks.pre-commit-check outputnix-shell -p <tool> --run "<command>" for nix tools - do NOT assume they are installed system-wideflake.nix after any Write/Edit operations.claude/devenv.local.md if it exists, otherwise default to nixos-unstable--json flag for easier parsinggit-hooks.nix auto-generates .pre-commit-config.yaml via shellHook - no manual YAML needed!Users can customize behavior via .claude/devenv.local.md:
---
nixpkgs_channel: nixos-unstable
---
| Language | Hook Names |
|---|---|
| JavaScript/TypeScript | eslint, prettier |
| Python | ruff, ruff-format, black, mypy |
| Go | golangci-lint, gofmt |
| Rust | clippy, rustfmt, cargo-check |
| Nix | nixfmt-rfc-style, statix, deadnix |
| Shell | shellcheck, shfmt |
| Docker | hadolint |
| YAML | check-yaml, yamllint |
| Secrets | gitleaks, detect-secrets |
| General | trailing-whitespace, end-of-file-fixer, check-added-large-files |
hooks = {
# Enable a hook
eslint.enable = true;
# Enable with custom settings
ruff = {
enable = true;
settings.args = ["--fix"];
};
# Custom hook
my-hook = {
enable = true;
entry = "my-script.sh";
files = "\\.py$";
};
};
For full list of available hooks, see: https://github.com/cachix/git-hooks.nix