* Fix: Security allowlist not working in worktree mode
This fixes three related bugs that prevented .auto-claude-allowlist from working in isolated workspace (worktree) mode:
1. Security hook reads from wrong directory
- Hook used os.getcwd() which returns main project dir, not worktree
- Added AUTO_CLAUDE_PROJECT_DIR env var set by agent on startup
- Files: security/hooks.py, agents/coder.py, qa/loop.py
2. Security profile cache doesn't track allowlist changes
- Cache only tracked .auto-claude-security.json mtime
- Now also tracks .auto-claude-allowlist mtime
- File: security/profile.py
3. Allowlist not copied to worktree
- .env files were copied but not security config files
- Now copies both .auto-claude-allowlist and .auto-claude-security.json
- File: core/workspace/setup.py
Impact: Custom commands (cargo, dotnet, etc.) were always blocked in worktree mode even with proper allowlist configuration.
Tested on Windows with Rust project (cargo commands).
* Address Gemini Code Assist review comments
- hooks.py: Add input_data.get("cwd") back to priority chain (HIGH)
- coder.py: Move import os to top of file (MEDIUM)
- loop.py: Move import os to top of file (MEDIUM)
- profile.py: Remove redundant exists() check, catch FileNotFoundError (MEDIUM)
- setup.py: Refactor security files copying with loop (MEDIUM)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add clarifying comment for security file overwrite behavior
Addresses CodeRabbit review comment explaining why security files
always overwrite (unlike env files) - prevents security bypasses.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: Add security commands configuration guide
Explains the security system for command validation:
- How automatic stack detection works
- When and how to use .auto-claude-allowlist
- Troubleshooting common issues
- Worktree mode behavior
This helps users understand why commands may be blocked
and how to properly configure custom commands.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add error handling for security file copy
Addresses CodeRabbit review: wrap shutil.copy2 in try/except
to provide clear error messages instead of crashing on
permission or disk space issues.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: Fix markdown formatting nitpicks
- Add 'text' language specifier to ASCII diagram code block
- Add 'text' language specifier to allowlist example
- Add blank line before code fence in troubleshooting section
Addresses CodeRabbit trivial review comments.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: Use shared constants for security filenames and env var
Addresses Auto Claude PR Review findings:
MEDIUM:
- setup.py: Use ProjectAnalyzer.PROFILE_FILENAME and
StructureAnalyzer.CUSTOM_ALLOWLIST_FILENAME instead of magic strings
- profile.py: Use StructureAnalyzer.CUSTOM_ALLOWLIST_FILENAME
LOW:
- Create security/constants.py with PROJECT_DIR_ENV_VAR
- Use constant in hooks.py, coder.py, loop.py
- Expand worktree documentation to explain overwrite behavior
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: Centralize security filenames in constants.py
Move ALLOWLIST_FILENAME and PROFILE_FILENAME to security/constants.py
for better cohesion. All security-related constants are now in one place.
- setup.py: Import from security.constants
- profile.py: Import from .constants (same module)
Addresses CodeRabbit review suggestion.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* style: Simplify exception handling (FileNotFoundError is subclass of OSError)
* style: Fix import sorting order (ruff I001)
* style: fix ruff formatting issues
- Add blank line after import inside function (hooks.py)
- Split global statements onto separate lines (profile.py)
- Reformat long if condition with `and` at line start (profile.py)
- Break long print_status line (setup.py)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Arcker <Arcker@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>
5.4 KiB
Security Commands Configuration
Auto Claude uses a dynamic security system that controls which shell commands the AI agent can execute. This prevents potentially dangerous operations while allowing legitimate development commands.
How It Works
┌─────────────────────────────────────────────────────────────┐
│ Command Validation │
├─────────────────────────────────────────────────────────────┤
│ 1. Base Commands (always allowed) │
│ └── ls, cat, grep, git, echo, etc. │
│ │
│ 2. Auto-Detected Stack Commands │
│ └── Analyzer detects Cargo.toml → adds cargo, rustc │
│ └── Analyzer detects package.json → adds npm, node │
│ │
│ 3. Custom Allowlist (manual additions) │
│ └── .auto-claude-allowlist file │
└─────────────────────────────────────────────────────────────┘
Automatic Detection
When you start a task, Auto Claude analyzes your project and automatically allows commands based on detected technologies:
| Detected File | Commands Added |
|---|---|
Cargo.toml |
cargo, rustc, rustup, rustfmt, cargo-clippy, etc. |
package.json |
npm, node, npx |
yarn.lock |
yarn |
pnpm-lock.yaml |
pnpm |
pyproject.toml |
python, pip, poetry, uv |
go.mod |
go |
*.csproj / *.sln |
dotnet |
pubspec.yaml |
dart, flutter, pub |
Dockerfile |
docker |
docker-compose.yml |
docker-compose |
Makefile |
make |
The full detection logic is in apps/backend/project/stack_detector.py.
Generated Profile
The analyzer saves its results to .auto-claude-security.json in your project root:
{
"base_commands": ["ls", "cat", "grep", "..."],
"stack_commands": ["cargo", "rustc", "rustup"],
"detected_stack": {
"languages": ["rust"],
"package_managers": ["cargo"],
"frameworks": [],
"databases": []
},
"project_hash": "abc123...",
"created_at": "2024-01-15T10:30:00"
}
This file is auto-generated. Don't edit it manually - it will be overwritten.
Custom Allowlist
For commands that aren't auto-detected, create a .auto-claude-allowlist file in your project root:
# .auto-claude-allowlist
# One command per line, no comments on same line
# Custom build tools
bazel
buck
# Project-specific scripts
./scripts/deploy.sh
# Additional tools
ansible
terraform
When to Use the Allowlist
Use .auto-claude-allowlist when:
- Your project uses uncommon build tools (Bazel, Buck, Pants, etc.)
- You have custom scripts that need to be executable
- Auto-detection doesn't recognize your stack
- You're using bleeding-edge tools not yet in the detection system
Format
- One command per line
- Lines starting with
#are ignored - Empty lines are ignored
- Use the base command name only (e.g.,
cargo, notcargo build)
Troubleshooting
"Command X is not allowed"
-
Check if it should be auto-detected:
- Does your project have the expected config file? (e.g.,
Cargo.tomlfor Rust) - Run in project root, not a subdirectory
- Does your project have the expected config file? (e.g.,
-
Add to allowlist:
echo "your-command" >> .auto-claude-allowlist -
Force re-analysis (if detection seems wrong):
- Delete
.auto-claude-security.json - Restart the task
- Delete
Allowlist Changes Not Taking Effect
The security profile cache updates automatically when:
.auto-claude-allowlistis modified (mtime changes).auto-claude-security.jsonis modified
No restart required - changes apply on the next command.
Worktree Mode
When using isolated worktrees, security files are automatically copied from your main project on each worktree setup.
Important: Unlike environment files (which are only copied if missing), security files always overwrite existing files in the worktree. This ensures the worktree uses the same security rules as the main project, preventing security bypasses through stale configurations.
This means:
- Changes to allowlist in the main project are reflected in new worktrees
- You cannot have different security rules per worktree (by design)
- If you need to test with different commands, modify the main project's allowlist
Security Considerations
The allowlist system exists to prevent:
- Accidental
rm -rf /or similar destructive commands - Execution of unknown binaries
- Network operations with unrestricted tools
Only add commands you trust and understand.
Adding Support for New Technologies
If you're using a technology that should be auto-detected, consider contributing:
- Add detection logic to
apps/backend/project/stack_detector.py - Add commands to
apps/backend/project/command_registry/languages.py - Submit a PR!
See existing detectors for examples.