devenv
Initialize and manage Nix flake development environments with auto-detection and security tooling
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Initialize and manage Nix flake development environments with auto-detection and security tooling
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Review and clean up commits before pushing. Uses planner/executor split: reads commits inline, authors final messages in saved style, replays via `git rebase --exec` with GIT_EDITOR=true so no editor opens. Detects logical clusters of granular TDD commits and proposes collapsing them into one logical commit. Auto-amends drifted subjects on revalidation. Activates on: "review commits", "clean up commits", "prep for push", "squash these commits", "finalize commits", "merge branch to main", "clean up my commits before pushing", "review before push".
Validate commits before pushing. Runs six deterministic checks: clean worktree, tests pass, no AI co-author leaks (Claude, Anthropic, GPT, OpenAI, Copilot), no conflict markers, no squash/fixup residue, and subject lines conform to the configured style (classic or conventional). Activates on: "validate commits", "check commits before push", "any AI leaks", "check for co-author", "are my commits clean", "validate before pushing", "check commits".
Triggers when user wants to PERFORM a git commit action. Activates on phrases like "commit these changes", "commit this", "let's commit", "make a commit", "create a commit", "commit my work", "commit the changes", "time to commit", "ready to commit", "commit what I've done", "save my changes" (git context), "commit for me", "do the commit", "commit now", "go ahead and commit", "please commit", "can you commit", "would you commit"
Provides educational guidance on writing good git commit messages. Activates when users ASK QUESTIONS about commit message formats, styles, conventional commits, classic commits, atomic commit principles, or git best practices. Does NOT activate when users want to PERFORM a commit (use the commit-action skill instead).
Guardrail for efficient refactoring. IDEs use AST-based semantic refactoring (instant, atomic, accurate). AI uses text-based pattern matching (slower, sequential, error-prone for structural changes). This skill provides decision criteria for when to delegate to IDE vs proceed with AI. Consult before: renames across files, moving packages, changing signatures, extracting interfaces, or any multi-file coordinated structural change.
This skill should be used when the user wants to create a visual sketch, diagram, or mind map from captured content like articles, videos, or blips. Enables creating Excalidraw visualizations from jot captures.
| name | devenv |
| description | Initialize and manage Nix flake development environments with auto-detection and security tooling |
| argument-hint | [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:
nixos-unstable)box)shell_welcome: custom)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:
.claude/devenv.local.md for use_mcp_search setting (default: true)mcp__1mcp__nixos_1mcp_nixos_search(
query="<package>",
search_type="packages",
channel="unstable",
limit=10
)
b. Global/project level MCP (if user has mcp-nixos configured):
mcp__nixos__nix(
action="search",
query="<package>",
source="nixos",
type="packages",
channel="unstable",
limit=10
)
c. Plugin's bundled MCP:
mcp__plugin_devenv_nixos__nix(
action="search",
query="<package>",
source="nixos",
type="packages",
channel="unstable",
limit=10
)
use_mcp_search: false, use bash:
nix-shell -p nix --run "nix search nixpkgs <package> --json"nodejs@20), handle version resolution:
a. Try mcp__1mcp__nixos_1mcp_nixhub_find_version(package_name="nodejs", version="20")
b. If 1mcp unavailable, try mcp__plugin_devenv_nixos__nix_versions(package="nodejs", version="20")
c. Also search for nixpkgs variants like nodejs_20
d. Prefer the nixpkgs variant if it exists; offer pinned commit hash as alternative2d. Offer security tools:
Use AskUserQuestion with multiSelect:
Security tools (recommended):
[ ] pre-commit - Git hooks with SAST tools for your stack (using git-hooks.nix)
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; trim-trailing-whitespace.enable = true; |
Then ask about secret scanning:
Use AskUserQuestion:
Secret scanner preference:
○ trufflehog (Recommended) - Built-in hook, works out of the box
○ gitleaks - Popular choice, requires custom hook configuration
○ None - Skip secret scanning
If trufflehog selected:
trufflehog.enable = true; to the hooks configuration (built-in, no extra config needed)If gitleaks selected:
gitleaks = {
enable = true;
name = "gitleaks";
entry = "${pkgs.gitleaks}/bin/gitleaks git --pre-commit --redact --staged --verbose";
language = "system";
pass_filenames = false;
};
gitleaks to the packages listgitleaks to packages for manual use2e. Choose direnv mode:
Use AskUserQuestion:
direnv mode:
○ direnv-instant (Recommended) - Async loading, instant shell prompt
○ Standard direnv - Traditional sync direnv (shell waits for Nix)
○ None - Use nix develop manually
Based on selection:
direnv-instant as a flake input (it's NOT a nixpkgs package):
inputs.direnv-instant.url = "github:Mic92/direnv-instant";
Then reference the package in devShell:
direnv-instant.packages.${system}.default
direnv to packages list in flake.nix (from nixpkgs)Save the selection to .claude/devenv.local.md as direnv_mode: instant|standard|none
2f. Choose shell welcome style:
Use AskUserQuestion to let the user choose their shell welcome message style:
Shell welcome message style:
○ Box style (Default) - Unicode box with devenv branding
○ Minimal - Single line "▸ devenv ready"
○ Project name - Shows current project directory name
○ Tech style - Terminal-inspired "[devenv] :: environment initialized"
○ Custom - Enter your own message
○ None - No welcome message
If "Custom" is selected:
Save the selection to .claude/devenv.local.md as:
shell_welcome: box|minimal|project|tech|custom|noneshell_welcome_custom: "user's custom message" (only if custom selected)2g. 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";
# DIRENV_INSTANT_INPUT_HERE (if selected)
};
outputs = {
self,
nixpkgs,
flake-utils,
# DIRENV_INSTANT_PARAM_HERE (if selected)
}:
flake-utils.lib.eachDefaultSystem (
system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.default = pkgs.mkShell {
packages = with pkgs; [
# PACKAGES_HERE
]
# DIRENV_INSTANT_PACKAGE_HERE (if selected)
;
shellHook = ''
# SHELL_WELCOME_HERE
'';
};
}
);
}
To add direnv-instant to the template:
# DIRENV_INSTANT_INPUT_HERE with: direnv-instant.url = "github:Mic92/direnv-instant";# DIRENV_INSTANT_PARAM_HERE with: direnv-instant,# DIRENV_INSTANT_PACKAGE_HERE with: ++ [ direnv-instant.packages.${system}.default ]To add standard direnv: Simply add direnv to the packages list (it's a nixpkgs package).
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";
# DIRENV_INSTANT_INPUT_HERE (if selected)
};
outputs = {
self,
nixpkgs,
flake-utils,
git-hooks,
# DIRENV_INSTANT_PARAM_HERE (if selected)
}:
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;
settings.edit = true;
settings.noLambdaPatternNames = true; # Preserve 'self' in flake outputs
};
# General
check-yaml.enable = true;
trim-trailing-whitespace.enable = true;
# LANGUAGE_HOOKS_HERE
# SECRET_SCANNER_HERE
# For trufflehog (built-in): trufflehog.enable = true;
# For gitleaks (custom hook):
# gitleaks = {
# enable = true;
# name = "gitleaks";
# entry = "${pkgs.gitleaks}/bin/gitleaks git --pre-commit --redact --staged --verbose";
# language = "system";
# pass_filenames = false;
# };
};
};
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
# DIRENV_INSTANT_PACKAGE_HERE (if selected)
;
shellHook = ''
${pre-commit-check.shellHook}
# SHELL_WELCOME_HERE
'';
};
}
);
}
direnv-instant integration: Same as basic template - add input, parameter, and package reference.
Shell welcome replacement: Replace # SHELL_WELCOME_HERE based on user's shell_welcome preference:
| Style | Replacement Content |
|---|---|
box | echo "╔══════════════════════════════════════╗"echo "║ 🔧 devenv ║"echo "║ Development environment loaded ║"echo "╚══════════════════════════════════════╝" |
minimal | echo ""echo " ▸ devenv ready"echo "" |
project | echo ""echo " ╭───────────────────────────────────╮"echo " │ 📁 $(basename $PWD)"echo " │ Development environment loaded"echo " ╰───────────────────────────────────╯"echo "" |
tech | echo ""echo " [devenv] :: environment initialized"echo " └── packages loaded, hooks active"echo "" |
custom | Parse shell_welcome_custom from settings, split by \n, wrap each line in echo "..." |
none | # No welcome message (empty comment, no output) |
For custom messages:
Read shell_welcome_custom from .claude/devenv.local.md
Split by \n for multi-line support
Wrap each line in echo "..." statements
Escape special characters: $ becomes \$, " becomes \", \ becomes \\
If empty, fall back to box style
Handle .envrc (if direnv mode is not "none"):
IMPORTANT: Never read .envrc files - they may contain secrets.
.envrc exists: test -f .envrc.envrc does NOT exist:
use flake.envrc EXISTS:
.envrc already exists. Ensure it contains use flake for direnv integration."Update .gitignore to exclude generated/sensitive files:
.gitignore exists# Nix/direnv
.direnv/
.pre-commit-config.yaml
# Environment files (sensitive)
.env
.env.*
.envrc
# Claude local settings (user preferences)
.claude/*.local.md
nix flake lock to generate flake.lock2h. Validate the flake:
After generating files, ALWAYS validate the flake works correctly:
nix flake check --no-build 2>&1
If validation fails:
self parameter in outputs (required by flake system even if unused)flake.nixImportant: Never finish the task if validation fails. The user should have a working environment.
2i. Output instructions:
If direnv-instant was selected:
Development environment created!
To enter the environment:
nix develop
Or with direnv-instant (async, instant prompt):
direnv allow
direnv-instant shell setup (one-time):
# bash (~/.bashrc) or zsh (~/.zshrc):
eval "$(direnv-instant hook bash)" # or zsh
# fish (~/.config/fish/config.fish):
direnv-instant hook fish | source
Note: Remove any existing `eval "$(direnv hook ...)"` first.
Your environment includes:
- [list packages]
If standard direnv was selected:
Development environment created!
To enter the environment:
nix develop
Or with direnv:
direnv allow
Your environment includes:
- [list packages]
If direnv mode is "none":
Development environment created!
To enter the environment:
nix develop
Your environment includes:
- [list packages]
[If pre-commit was selected, append:]
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)
○ Switch direnv mode - Change between direnv-instant, standard direnv, or none
○ Change welcome style - Customize shell welcome message
Only show "Setup security tools" option if git-hooks input is NOT present in flake.nix.
Show "Switch direnv mode" and "Change welcome style" options always (user may want to change their preference).
2c. Handle selected action:
Add packages:
.claude/devenv.local.md for use_mcp_search setting (default: true)mcp__1mcp__nixos_1mcp_nixos_search(query="<pkg>", search_type="packages", channel="unstable", limit=10)
b. Global/project MCP: mcp__nixos__nix(action="search", query="<pkg>", ...)
c. Plugin's bundled MCP: mcp__plugin_devenv_nixos__nix(action="search", query="<pkg>", ...)use_mcp_search: false, use bash:
nix-shell -p nix --run "nix search nixpkgs <package> --json"nodejs@20):
a. Try mcp__1mcp__nixos_1mcp_nixhub_find_version(package_name="nodejs", version="20")
b. If 1mcp unavailable, try mcp__plugin_devenv_nixos__nix_versions(package="nodejs", version="20")
c. Also search for nixpkgs variants like nodejs_20flake.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 outputSwitch direnv mode:
direnv-instant in inputs (it's a flake input, NOT a nixpkgs package)direnv in packages list (this IS a nixpkgs package)direnv mode:
○ direnv-instant (Recommended) - Async loading, instant shell prompt
○ Standard direnv - Traditional sync direnv (shell waits for Nix)
○ None - Use nix develop manually
direnv-instant.url = "github:Mic92/direnv-instant"; to inputsdirenv-instant, to outputs parameters++ [ direnv-instant.packages.${system}.default ] to packagesdirenv from packages if presentdirenv-instant input, parameter, and package reference if presentdirenv to packages list (from nixpkgs)direnv-instant input, parameter, and package reference if presentdirenv from packages if present.claude/devenv.local.md with new direnv_mode settingeval "$(direnv-instant hook ...)" instructionseval "$(direnv hook ...)"nix develop manuallyChange welcome style:
shell_welcome setting from .claude/devenv.local.md (default: box)Shell welcome message style:
○ Box style (Default) - Unicode box with devenv branding
○ Minimal - Single line "▸ devenv ready"
○ Project name - Shows current project directory name
○ Tech style - Terminal-inspired "[devenv] :: environment initialized"
○ Custom - Enter your own message
○ None - No welcome message
.claude/devenv.local.md with new shell_welcome (and shell_welcome_custom if applicable)shellHook section in flake.nix:
${pre-commit-check.shellHook} if present at the start of shellHookAfter any modification, validate the flake:
nix flake check --no-build 2>&1
If validation fails, fix the issue before completing the task.
nix-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-unstablegit-hooks.nix auto-generates .pre-commit-config.yaml via shellHook - no manual YAML needed!self parameter in flake outputs is REQUIRED by the Nix flake system, even if not explicitly used in the function body. The plugin's deadnix hook is configured with --no-lambda-pattern-names to preserve itnix flake check --no-build before completing any flake creation/modification taskinputs.direnv-instant.url = "github:Mic92/direnv-instant" and referenced as direnv-instant.packages.${system}.default. Standard direnv IS in nixpkgs and can be added directly to the packages list.This plugin uses NixOS MCP tools for package search, providing access to 130K+ NixOS packages with accurate, up-to-date information.
The command tries MCP tools in this order:
mcp__1mcp__nixos_1mcp_nixos_search — already running via 1mcp proxy, no extra processmcp__nixos__nix — if user has mcp-nixos configured globally or in projectmcp__plugin_devenv_nixos__nix — plugin's own MCP server (fallback for non-1mcp environments)nix search commandThis ensures the fastest available tool is used first, with graceful degradation.
1mcp (separate tools per action):
mcp__1mcp__nixos_1mcp_nixos_search(
query="<search_term>",
search_type="packages",
channel="unstable",
limit=10
)
Global/Plugin MCP (combined action parameter):
mcp__nixos__nix( # or mcp__plugin_devenv_nixos__nix
action="search",
query="<search_term>",
source="nixos",
type="packages",
channel="unstable",
limit=10
)
For versioned package requests (e.g., nodejs@20):
1mcp — find specific version:
mcp__1mcp__nixos_1mcp_nixhub_find_version(
package_name="nodejs",
version="20"
)
1mcp — list all available versions:
mcp__1mcp__nixos_1mcp_nixhub_package_versions(
package_name="nodejs",
limit=20
)
Plugin bundled MCP — version lookup:
mcp__plugin_devenv_nixos__nix_versions(
package="nodejs",
version="20"
)
Version resolution workflow:
nixhub_find_version (or nix_versions) to find the exact versionnodejs_20| Tool | Parameter | Value | Description |
|---|---|---|---|
1mcp_nixos_search | query | string | Package name or search term |
1mcp_nixos_search | search_type | "packages" | Search packages (not options) |
1mcp_nixos_search | channel | "unstable" | Nixpkgs channel |
1mcp_nixos_search | limit | number | Max results to return |
1mcp_nixhub_find_version | package_name | string | Package to find version for |
1mcp_nixhub_find_version | version | string | Desired version (e.g., "20") |
1mcp_nixhub_package_versions | package_name | string | Package to list versions for |
1mcp_nixhub_package_versions | limit | number | Max versions to return |
nixos__nix / plugin_devenv_nixos__nix | action | "search" | Search for packages |
nixos__nix / plugin_devenv_nixos__nix | query | string | Package name or search term |
nixos__nix / plugin_devenv_nixos__nix | source | "nixos" | Use NixOS packages source |
nixos__nix / plugin_devenv_nixos__nix | type | "packages" | Search packages (not options) |
nixos__nix / plugin_devenv_nixos__nix | channel | "unstable" | Use nixos-unstable channel |
nixos__nix / plugin_devenv_nixos__nix | limit | number | Max results to return |
plugin_devenv_nixos__nix_versions | package | string | Package to find version for |
plugin_devenv_nixos__nix_versions | version | string | Desired version (optional) |
plugin_devenv_nixos__nix_versions | limit | number | Max versions to return (optional) |
If no MCP tool is available, the command falls back to:
nix-shell -p nix --run "nix search nixpkgs <package> --json"
Users can customize behavior via .claude/devenv.local.md:
---
nixpkgs_channel: nixos-unstable
use_mcp_search: true
direnv_mode: instant
shell_welcome: box
shell_welcome_custom: ""
---
| Setting | Default | Description |
|---|---|---|
nixpkgs_channel | nixos-unstable | Nixpkgs channel to use |
use_mcp_search | true | Use mcp-nixos for package search. Set to false to always use bash fallback |
direnv_mode | instant | direnv integration: instant (async, recommended), standard (sync), or none |
shell_welcome | box | Welcome message style: box, minimal, project, tech, custom, or none |
shell_welcome_custom | "" | Custom welcome message text (only used when shell_welcome: custom). Use \n for multi-line |
| 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 | trufflehog, ripsecrets (built-in); gitleaks requires custom config |
| General | trim-trailing-whitespace, check-added-large-files, check-merge-conflicts |
hooks = {
# Enable a built-in hook
eslint.enable = true;
# Built-in secret scanner
trufflehog.enable = true;
# Enable with custom settings
ruff = {
enable = true;
settings.args = ["--fix"];
};
# Custom hook example: gitleaks (not built-in)
gitleaks = {
enable = true;
name = "gitleaks";
entry = "${pkgs.gitleaks}/bin/gitleaks git --pre-commit --redact --staged --verbose";
language = "system";
pass_filenames = false;
};
};
For full list of available hooks, see: https://github.com/cachix/git-hooks.nix