Guides
Security Best Practices
Autohand operates on your code with real file system access and command execution. This guide covers how to configure permissions, protect sensitive files, sandbox commands, and set up team-wide security policies.
Related Skills: Enhance your security posture with specialized skills from Skilled. Browse security scanning skills, security audit workflows, and compliance skills to protect your codebase.
Permission modes
Autohand has three permission modes that control how much freedom the agent has when interacting with your system. Choosing the right mode depends on the task and how much you trust the environment.
Interactive mode (default)
The agent asks for your approval before performing any potentially dangerous action. This is the safest mode for daily work. Every file write, command execution, and deletion prompts you with a yes/no confirmation.
# Default behavior, no flag needed
autohand "Refactor the auth module"
# The agent will prompt before each action:
# Allow writing to src/auth/middleware.ts? [y/n]
# Allow running: npm test? [y/n]
Use interactive mode when you are exploring a codebase for the first time, working on sensitive parts of your system, or running Autohand on a project you are not familiar with.
Unrestricted mode
The agent performs all actions without asking for permission. This is useful for trusted, well-scoped tasks where you have already reviewed the plan.
# Allow all actions without prompts
autohand --unrestricted "Add unit tests for every file in src/utils/"
Caution
Unrestricted mode gives the agent full access to read, write, and execute within your workspace. Only use it on isolated branches or when you can easily revert changes.
Restricted mode
The agent can only read files and search the codebase. It cannot write files, run commands, or make any modifications. This is the right choice for code review and analysis tasks.
# Read-only mode for safe analysis
autohand --restricted "Review the payment flow for security vulnerabilities"
# Also useful in CI where you don't want any side effects
git diff main...HEAD | autohand --headless --restricted \
--prompt "Review this diff for bugs"
Comparing the modes
| Capability | Interactive | Unrestricted | Restricted |
|---|---|---|---|
| Read files | Yes | Yes | Yes |
| Write files | With approval | Yes | No |
| Run commands | With approval | Yes | No |
| Delete files | With approval | Yes | No |
| Best for | Daily development | Trusted automation | Code review, CI |
Fine-grained permissions
Beyond the three main modes, you can define exactly which tools and commands the agent is allowed to use. Permission patterns let you whitelist safe operations and block dangerous ones.
Whitelist patterns
Allow specific commands while keeping everything else under interactive approval:
# Allow npm and node commands without prompts
autohand --allow "run_command:npm *" --allow "run_command:node *" \
"Fix all lint errors and run the tests"
Blacklist patterns
Block specific dangerous operations while allowing everything else:
# Block all deletion commands
autohand --deny "run_command:rm *" --deny "delete_path:*" \
"Clean up the unused modules in src/legacy/"
Pattern matching syntax
Permission patterns follow the format tool_name:argument_pattern. The * wildcard matches any string. You can combine multiple --allow and --deny flags in one command.
# Allow writing to src/ but block writes to config files
autohand --allow "write_file:src/*" --deny "write_file:*.config.*" \
"Refactor the service layer"
# Allow git commands but block force push
autohand --allow "run_command:git *" --deny "run_command:git push --force*" \
"Create a commit with the staged changes"
Permission patterns in configuration
Instead of passing flags every time, set default permissions in your project configuration file:
// .autohand/config.json
{
"permissions": {
"allow": [
"run_command:npm *",
"run_command:node *",
"run_command:git add *",
"run_command:git commit *",
"write_file:src/*",
"write_file:tests/*"
],
"deny": [
"run_command:rm -rf *",
"run_command:git push --force*",
"write_file:.env*",
"write_file:*.pem",
"delete_path:/"
]
}
}
The config file applies to everyone on the team, so it is a good place to encode your project's safety rules.
YOLO mode safety
YOLO mode (also called --yes or --unrestricted) lets the agent run without prompts. Used carelessly, it can overwrite files or run destructive commands. The key to using it safely is pairing it with deny patterns that act as guardrails.
Safe YOLO with deny patterns
Allow everything except the operations you never want to happen:
# YOLO mode with safety rails
autohand --unrestricted \
--deny "delete_path:*" \
--deny "run_command:rm *" \
--deny "run_command:git push *" \
--deny "write_file:.env*" \
"Add error handling to all API routes"
Scoped YOLO for testing
When generating tests, you usually want the agent to create files freely. Limit the scope so it only writes to the test directory:
# Free reign in tests, locked everywhere else
autohand --unrestricted \
--allow "write_file:tests/*" \
--allow "write_file:src/**/__tests__/*" \
--deny "write_file:src/**/*.ts" \
--deny "delete_path:*" \
"Generate comprehensive tests for the billing module"
YOLO in CI with safety nets
In CI environments, combine YOLO mode with restricted scope and dry-run checks:
# CI: auto-fix lint errors, but verify with dry-run first
autohand --headless --unrestricted --dry-run \
--prompt "Fix all ESLint errors in src/"
# If dry-run looks good, apply for real
autohand --headless --unrestricted \
--deny "delete_path:*" \
--deny "run_command:git push *" \
--prompt "Fix all ESLint errors in src/"
Tip: Always run --dry-run first to preview what YOLO mode will do. This lets you verify the scope of changes before they happen.
Workspace safety
Autohand automatically prevents the agent from operating on directories it should never touch. These built-in protections stop accidental damage to your system.
Protected directories
The agent will refuse to write or execute commands in these locations, regardless of permissions:
/(root directory)~(home directory, unless your project lives there)/etc,/usr,/bin,/sbin(system directories)/System,/Library(macOS system directories)C:\Windows,C:\Program Files(Windows system directories)
If you try to point Autohand at your home directory, it will ask you to narrow the scope:
# This will be rejected
autohand --add-dir ~ "Clean up old projects"
# Error: Cannot operate on home directory. Please specify a project subdirectory.
# This is fine
autohand --add-dir ~/projects/my-app "Clean up unused modules"
Scope limiting with --add-dir
By default, Autohand operates in the current working directory. You can expand its scope with --add-dir, but only to specific directories you trust:
# Work across two related projects
autohand --add-dir ../shared-lib "Update the shared library types to match the API changes in this project"
# Add a data directory for analysis
autohand --add-dir ./data --restricted "Analyze the CSV files in the data directory and suggest schema improvements"
Git worktree isolation
For risky operations, use a git worktree so that changes happen on a separate branch in an isolated directory:
# Create an isolated worktree for the refactoring
git worktree add ../refactoring-branch -b refactoring
cd ../refactoring-branch
autohand --unrestricted "Refactor the entire API layer to use the new router"
# Review changes, then merge if they look good
git diff main
cd ../main-project
git merge refactoring
Hook-based guardrails
Hooks let you run custom logic before or after the agent takes an action. You can use them to enforce policies, log activity, and block specific operations based on your own rules.
Block writes to production configs
Prevent the agent from modifying production configuration files:
// .autohand/hooks.json
{
"pre_write_file": [
{
"match": "config/production.*",
"action": "deny",
"message": "Cannot modify production config files. Make changes in config/development.* and promote through your deployment pipeline."
},
{
"match": "docker-compose.prod.yml",
"action": "deny",
"message": "Production Docker Compose file is managed by infrastructure team."
}
]
}
Require approval for database commands
Add an extra confirmation step before any database-related commands:
// .autohand/hooks.json
{
"pre_run_command": [
{
"match": "*migrate*",
"action": "confirm",
"message": "This command appears to run a database migration. Are you sure?"
},
{
"match": "*seed*",
"action": "confirm",
"message": "This command will seed the database. Confirm before proceeding."
},
{
"match": "psql*",
"action": "deny",
"message": "Direct database access is not allowed through the agent."
}
]
}
Log all file modifications
Keep an audit trail of every file the agent modifies:
// .autohand/hooks.json
{
"post_write_file": [
{
"match": "*",
"action": "run",
"command": "echo \"$(date -u +%Y-%m-%dT%H:%M:%SZ) WRITE ${AUTOHAND_FILE_PATH}\" >> .autohand/audit.log"
}
],
"post_run_command": [
{
"match": "*",
"action": "run",
"command": "echo \"$(date -u +%Y-%m-%dT%H:%M:%SZ) EXEC ${AUTOHAND_COMMAND}\" >> .autohand/audit.log"
}
]
}
Enforce code style on writes
Automatically format files after the agent writes them:
// .autohand/hooks.json
{
"post_write_file": [
{
"match": "*.ts",
"action": "run",
"command": "npx prettier --write ${AUTOHAND_FILE_PATH}"
},
{
"match": "*.py",
"action": "run",
"command": "black ${AUTOHAND_FILE_PATH}"
}
]
}
Sensitive file protection
Certain files should never be read or modified by the agent. Environment files, API keys, certificates, and credentials need explicit protection.
Default protected patterns
Autohand automatically avoids reading or writing these file patterns:
.env,.env.*- Environment variable files*.pem,*.key,*.cert- Certificates and keysid_rsa,id_ed25519- SSH keyscredentials.json,serviceAccountKey.json- Cloud credentials
If the agent tries to read a protected file, it will receive an empty result with a note that the file is protected.
Custom protection patterns
Add your own patterns to the deny list in the configuration:
// .autohand/config.json
{
"permissions": {
"deny": [
"read_file:.env*",
"read_file:*.secret",
"read_file:config/secrets/*",
"read_file:**/credentials*",
"write_file:.env*",
"write_file:*.pem",
"write_file:*.key",
"write_file:config/production.*"
]
}
}
Using .autohandignore
Create an .autohandignore file (similar to .gitignore) to exclude files from the agent's view entirely:
# .autohandignore
.env
.env.*
*.pem
*.key
*.cert
config/secrets/
credentials/
**/serviceAccountKey.json
**/*.secret.yaml
node_modules/
.git/
Files listed in .autohandignore will not appear in search results, will not be read by the agent, and will not be offered as context. This is the strongest form of protection because the agent does not even know these files exist.
Verifying protection
Test that your protections work by asking the agent to read a protected file:
# Verify sensitive files are protected
autohand --restricted "Can you read the contents of .env?"
# Expected: The agent reports that the file is protected or not accessible
Sandbox mode
Sandbox mode isolates command execution so that the agent's shell commands cannot affect your host system beyond the project directory. This adds an extra layer of defense on top of permission controls.
Enabling sandbox mode
# Run with sandboxed command execution
autohand --sandbox "Install the testing dependencies and run the full test suite"
What sandbox mode does
When sandbox mode is active:
- Commands can only access files within the project directory
- Network access follows your configured rules (default: allowed for package managers)
- No commands can modify files outside the project root
- Environment variables are filtered to remove sensitive values
- Process spawning is limited to the allowed command list
Sandbox configuration
Fine-tune sandbox behavior in your project configuration:
// .autohand/config.json
{
"sandbox": {
"enabled": true,
"network": {
"allow": ["registry.npmjs.org", "pypi.org", "crates.io"],
"deny": ["*"]
},
"env_filter": [
"AUTOHAND_API_KEY",
"AWS_*",
"DATABASE_URL",
"GITHUB_TOKEN"
],
"allowed_commands": [
"npm", "npx", "node", "bun",
"python", "pip", "pytest",
"cargo", "rustc",
"git", "make"
]
}
}
Sandbox in CI
Sandbox mode is especially valuable in CI where the agent runs unattended:
# GitHub Actions with sandboxed Autohand
- name: Autohand Fix
run: |
autohand --headless --sandbox --unrestricted \
--prompt "Fix the failing tests in src/api/"
Local model privacy
If your code must stay on your machine, you can run Autohand with a local model. No data leaves your network when you use a local backend. This is the right choice for classified projects, healthcare code, financial systems, or any codebase with strict data residency rules.
Using Ollama
Run a model locally with Ollama and point Autohand at it:
# Pull and start a model
ollama pull deepseek-coder:33b
# Point Autohand to the local model
AUTOHAND_PROVIDER=ollama \
AUTOHAND_MODEL=deepseek-coder:33b \
autohand "Refactor the authentication middleware"
Using llama.cpp
For maximum control over the inference stack:
# Start llama.cpp server
./llama-server -m models/codellama-34b.Q5_K_M.gguf --port 8080
# Connect Autohand
AUTOHAND_PROVIDER=openai-compatible \
AUTOHAND_API_BASE=http://localhost:8080/v1 \
AUTOHAND_MODEL=codellama-34b \
autohand "Add input validation to the user registration endpoint"
Using MLX on Apple Silicon
Take advantage of Apple's Metal framework for fast local inference on M-series Macs:
# Install MLX server
pip install mlx-lm
# Start the server
mlx_lm.server --model mlx-community/deepseek-coder-33b-4bit --port 8080
# Connect Autohand
AUTOHAND_PROVIDER=openai-compatible \
AUTOHAND_API_BASE=http://localhost:8080/v1 \
autohand "Write tests for the payment processing module"
Verifying no data leaves your machine
You can confirm that all traffic stays local by monitoring network connections:
# Monitor outbound connections while running Autohand
sudo lsof -i -n | grep autohand
# Or use a stricter approach: block all outbound traffic for the process
# On macOS, use Little Snitch or the built-in firewall
# On Linux, use iptables rules scoped to the user
Team security
When multiple developers use Autohand on the same project, you need consistent policies. Configuration files checked into the repository ensure that everyone operates under the same security rules.
Shared permission policies
Commit your security configuration to the repository so every team member inherits it:
// .autohand/config.json (committed to repo)
{
"permissions": {
"allow": [
"run_command:npm *",
"run_command:bun *",
"run_command:git add *",
"run_command:git commit *",
"write_file:src/*",
"write_file:tests/*"
],
"deny": [
"run_command:rm -rf *",
"run_command:git push --force*",
"run_command:git rebase*",
"write_file:.env*",
"write_file:*.pem",
"write_file:*.key",
"write_file:config/production.*",
"write_file:infrastructure/*",
"delete_path:*"
]
}
}
Protecting company secrets
Use a combination of .autohandignore and deny patterns to keep secrets out of the agent's reach:
# .autohandignore (committed to repo)
# Secrets and credentials
.env
.env.*
config/secrets/
*.pem
*.key
# Internal documentation
docs/internal/
docs/architecture/threat-model.md
# Infrastructure
terraform/*.tfvars
ansible/vault/
Audit logging with hooks
Set up hooks to log every action the agent takes, creating an audit trail for compliance:
// .autohand/hooks.json (committed to repo)
{
"post_write_file": [
{
"match": "*",
"action": "run",
"command": "echo '{\"timestamp\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"action\":\"write\",\"file\":\"'${AUTOHAND_FILE_PATH}'\",\"user\":\"'$(whoami)'\"}' >> .autohand/audit.jsonl"
}
],
"post_run_command": [
{
"match": "*",
"action": "run",
"command": "echo '{\"timestamp\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"action\":\"exec\",\"command\":\"'${AUTOHAND_COMMAND}'\",\"user\":\"'$(whoami)'\"}' >> .autohand/audit.jsonl"
}
]
}
The audit log records who ran the agent, what it did, and when. Add .autohand/audit.jsonl to your .gitignore but ship it to your central logging system for compliance teams.
Role-based permissions
For larger teams, use environment-specific config files that give different access levels to different roles:
# Developers: standard permissions
AUTOHAND_CONFIG=.autohand/config.dev.json autohand "Fix the failing tests"
# Senior engineers: expanded permissions
AUTOHAND_CONFIG=.autohand/config.senior.json autohand "Refactor the database layer"
# CI bot: restricted to read-only analysis
AUTOHAND_CONFIG=.autohand/config.ci.json autohand --headless --restricted \
--prompt "Review the latest changes"
Security checklist
Use this checklist when setting up Autohand for a new project or team. Each item takes a few minutes and significantly reduces risk.
Initial setup
- Create
.autohand/config.jsonwith deny patterns for dangerous operations - Create
.autohandignoreto exclude secrets, keys, and internal docs - Commit both files to the repository
- Store API keys in environment variables, never in config files
Daily usage
- Use interactive mode (the default) for most work
- Use
--restrictedfor code review and analysis - Use
--dry-runbefore running--unrestricted - Review the agent's plan before confirming batch operations
CI/CD pipelines
- Always use
--headlessin CI environments - Default to
--restrictedfor review and analysis jobs - Use
--sandboxwhen the agent needs write access in CI - Store
AUTOHAND_API_KEYas a CI secret, not in the workflow file - Set timeouts on all Autohand steps to prevent hanging jobs
Team rollout
- Document your team's Autohand security policy
- Set up audit logging with hooks
- Ship audit logs to your central logging platform
- Review and update deny patterns quarterly
- Test your protections by trying to access blocked resources
Enterprise environments
- Evaluate local model deployment for air-gapped or regulated environments
- Configure network-level controls for cloud API access
- Set up role-based permission configs for different team tiers
- Integrate audit logs with your SIEM or compliance platform
- Include Autohand configuration in your security review process
Next steps
- CI/CD Automation - Set up Autohand in your build pipelines
- Hooks Reference - Full documentation on hook configuration
- YOLO Mode - Detailed reference for unrestricted operation
- Configuration - All configuration options explained
- Enterprise Security - Advanced deployment and compliance