Permissions
Permissions control what an agent can do within its session. Herdctl provides fine-grained control over tool access and permission approval modes using a flat configuration structure that maps directly to the Claude Agents SDK. This allows you to create agents with appropriate access levels—from read-only support bots to full-access development agents.
Quick Start
Section titled “Quick Start”permission_mode: acceptEdits
# Restrict available tools (whitelist)tools: - Read - Write - Edit - Bash - Glob - Grep
# Pre-approve permissions (skip prompts)allowed_tools: - Read - Write - Edit - "Bash(git *)" - "Bash(npm *)" - "Bash(pnpm *)"
# Block dangerous patternsdenied_tools: - WebSearch - "Bash(rm -rf *)" - "Bash(sudo *)"Permission Modes
Section titled “Permission Modes”The permission_mode field controls how Claude Code handles permission requests. This maps directly to the Claude Agents SDK’s permission modes.
permission_mode: acceptEdits # defaultAvailable Modes
Section titled “Available Modes”| Mode | Description | Use Case |
|---|---|---|
default | Requires approval for everything | Maximum control, manual oversight |
acceptEdits | Auto-approve file operations | Recommended for most agents |
bypassPermissions | Auto-approve everything | Trusted, isolated environments |
plan | Planning only, no execution | Research agents, dry runs |
Mode Details
Section titled “Mode Details”default
Section titled “default”The most restrictive mode. Every tool use requires explicit approval through herdctl’s permission callback system.
permission_mode: defaultWhen to use:
- Testing new agents
- Running untrusted prompts
- Environments requiring audit trails
acceptEdits
Section titled “acceptEdits”Auto-approves file operations (Read, Write, Edit, mkdir, rm, mv, cp) while still requiring approval for other tools like Bash execution. This is the default mode if not specified.
permission_mode: acceptEditsWhen to use:
- Standard development agents
- Content creation agents
- Most production use cases
bypassPermissions
Section titled “bypassPermissions”Auto-approves all tool requests without prompting. Use with caution.
permission_mode: bypassPermissionsWhen to use:
- Fully trusted agents in isolated environments
- Docker-isolated agents with resource limits
- Automated pipelines with pre-validated prompts
Enables planning mode where Claude analyzes and plans but doesn’t execute tools. Useful for understanding what an agent would do.
permission_mode: planWhen to use:
- Previewing agent behavior before execution
- Research and analysis agents
- Generating plans for human review
Tool Permissions
Section titled “Tool Permissions”Control which Claude Code tools an agent can use with tools, allowed_tools, and denied_tools arrays. These are top-level configuration fields.
Tools (Availability Whitelist)
Section titled “Tools (Availability Whitelist)”Use tools to restrict which tools are available to the agent. Only listed tools exist in the agent’s context:
tools: - Read - Write - Edit - Glob - GrepAllowed Tools (Permission Pre-approval)
Section titled “Allowed Tools (Permission Pre-approval)”Use allowed_tools to pre-approve permissions for specific tools. These tools won’t prompt for permission:
allowed_tools: - Read - Write - Edit - Glob - Grep - Task - WebFetch - "Bash(git *)" - "Bash(npm *)"allowed_tools only controls permission prompts, NOT tool availability. To restrict which tools exist, use tools instead.
Denied Tools
Section titled “Denied Tools”Explicitly block specific tools:
denied_tools: - WebSearch - WebFetch - "Bash(sudo *)" - "Bash(rm -rf /)"Available Claude Code Tools
Section titled “Available Claude Code Tools”| Tool | Description | Risk Level |
|---|---|---|
Read | Read files from filesystem | Low |
Write | Create new files | Medium |
Edit | Modify existing files | Medium |
Glob | Find files by pattern | Low |
Grep | Search file contents | Low |
Bash | Execute shell commands (use patterns) | High |
Task | Launch subagents | Medium |
WebFetch | Fetch web content | Medium |
WebSearch | Search the web | Medium |
TodoWrite | Manage task lists | Low |
AskUserQuestion | Request user input | Low |
NotebookEdit | Edit Jupyter notebooks | Medium |
Bash Command Permissions
Section titled “Bash Command Permissions”Bash commands are controlled using Bash() patterns in the allowed_tools and denied_tools arrays. The pattern inside the parentheses is matched against the command being executed.
Allow specific commands:
allowed_tools: - "Bash(git *)" # All git commands - "Bash(npm run *)" # npm run scripts - "Bash(pnpm *)" # All pnpm commands - "Bash(node scripts/*)" # Node scripts in scripts/ - "Bash(make build)" # Specific make targetDeny dangerous patterns:
denied_tools: - "Bash(rm -rf /)" - "Bash(rm -rf /*)" - "Bash(sudo *)" - "Bash(chmod 777 *)" - "Bash(curl * | bash)" - "Bash(curl * | sh)" - "Bash(wget * | bash)" - "Bash(wget * | sh)" - "Bash(dd if=*)" - "Bash(mkfs *)" - "Bash(> /dev/*)"Understanding the Three Tool Fields
Section titled “Understanding the Three Tool Fields”| Field | What it does | Example behavior |
|---|---|---|
tools | Whitelist — only these tools exist | tools: [Read, Write] → Agent can ONLY use Read and Write |
denied_tools | Blocklist — these tools are removed | denied_tools: [Bash] → Agent cannot use Bash |
allowed_tools | Permission pre-approval — skip prompts | allowed_tools: [Read] → Read won’t require permission |
MCP Tool Permissions
Section titled “MCP Tool Permissions”MCP (Model Context Protocol) server tools use the mcp__<server>__<tool> naming convention:
allowed_tools: - Read - Edit - mcp__github__* # All GitHub MCP tools - mcp__posthog__* # All PostHog MCP tools - mcp__filesystem__read_file # Specific tool onlyWildcard support:
mcp__github__*— Allow all tools from the GitHub MCP servermcp__*— Allow all MCP tools (not recommended)
Common Permission Patterns
Section titled “Common Permission Patterns”Development Agent (Standard)
Section titled “Development Agent (Standard)”Full development capabilities with sensible restrictions:
permission_mode: acceptEditsallowed_tools: - Read - Write - Edit - Glob - Grep - Task - TodoWrite - "Bash(git *)" - "Bash(npm *)" - "Bash(pnpm *)" - "Bash(node *)" - "Bash(npx *)" - "Bash(tsc *)" - "Bash(eslint *)" - "Bash(prettier *)" - "Bash(vitest *)" - "Bash(jest *)"denied_tools: - "Bash(rm -rf /)" - "Bash(rm -rf /*)" - "Bash(sudo *)" - "Bash(chmod 777 *)"Read-Only Support Agent
Section titled “Read-Only Support Agent”Can read and search but cannot modify:
permission_mode: default# Only these tools existtools: - Read - Glob - Grep - WebFetch# No need for denied_tools when using tools whitelistContent Writer
Section titled “Content Writer”Can read/write files, no shell access:
permission_mode: acceptEdits# Whitelist only content toolstools: - Read - Write - Edit - Glob - Grep - WebFetch - WebSearch - TodoWrite# Bash and Task don't exist for this agentIsolated Full-Access Agent
Section titled “Isolated Full-Access Agent”Maximum permissions in a Docker container:
permission_mode: bypassPermissions# No tools restriction - agent has all tools
docker: enabled: true base_image: node:20-slimRestricted Auto-Approve Agent
Section titled “Restricted Auto-Approve Agent”Auto-approve but limit available tools:
permission_mode: bypassPermissions# Only these tools are availabletools: - Read - Write - Edit - Bash# allowed_tools has no effect with bypassPermissionsResearch/Planning Agent
Section titled “Research/Planning Agent”Plan and research without execution:
permission_mode: planallowed_tools: - Read - Glob - Grep - WebFetch - WebSearchGit-Only Agent
Section titled “Git-Only Agent”Can only perform git operations:
permission_mode: acceptEditsallowed_tools: - Read - Glob - Grep - "Bash(git status)" - "Bash(git diff *)" - "Bash(git log *)" - "Bash(git add *)" - "Bash(git commit *)" - "Bash(git push *)" - "Bash(git pull *)" - "Bash(git checkout *)" - "Bash(git branch *)" - "Bash(git merge *)" - "Bash(gh pr *)" - "Bash(gh issue *)"denied_tools: - "Bash(git push --force *)" - "Bash(git push -f *)" - "Bash(git reset --hard *)"Security Recommendations
Section titled “Security Recommendations”1. Start Restrictive
Section titled “1. Start Restrictive”Begin with minimal permissions and expand as needed:
# Start herepermission_mode: defaultallowed_tools: - Read - Glob - Grep
# Add more as you verify behavior2. Use Mode Appropriately
Section titled “2. Use Mode Appropriately”| Environment | Recommended Mode |
|---|---|
| Development/Testing | default |
| Production (standard) | acceptEdits |
| Production (Docker isolated) | bypassPermissions |
| Research/Preview | plan |
3. Block Dangerous Bash Patterns
Section titled “3. Block Dangerous Bash Patterns”Always deny dangerous patterns in denied_tools:
denied_tools: # Destructive commands - "Bash(rm -rf /)" - "Bash(rm -rf /*)" - "Bash(rm -rf ~)" - "Bash(rm -rf ~/*)" - "Bash(rm -rf .)" - "Bash(rm -rf ./*)"
# Privilege escalation - "Bash(sudo *)" - "Bash(su *)" - "Bash(doas *)"
# Remote code execution - "Bash(curl * | bash)" - "Bash(curl * | sh)" - "Bash(wget * | bash)" - "Bash(wget * | sh)" - "Bash(eval *)"
# System damage - "Bash(dd if=*)" - "Bash(mkfs *)" - "Bash(fdisk *)" - "Bash(> /dev/*)" - "Bash(chmod -R 777 *)"
# Fork bomb - "Bash(:(){ :|:& };:)"4. Scope MCP Permissions
Section titled “4. Scope MCP Permissions”Only allow necessary MCP tools:
allowed_tools: # Specific MCP tools, not wildcards - mcp__github__create_issue - mcp__github__list_issues - mcp__github__create_pull_request # NOT: mcp__github__*5. Use Docker for Untrusted Workloads
Section titled “5. Use Docker for Untrusted Workloads”Combine Docker isolation with permissions:
permission_mode: bypassPermissions
docker: enabled: true base_image: node:20-slim6. Limit Blast Radius
Section titled “6. Limit Blast Radius”Restrict workspace access when possible:
workspace: root: ~/herdctl-workspace/project-a # Agent can only access this directory7. Audit Regularly
Section titled “7. Audit Regularly”Review agent permissions periodically:
# Show effective permissions for an agentherdctl config show --agent my-agent --section permissionsPermission Inheritance
Section titled “Permission Inheritance”Agent permissions inherit from fleet defaults and can be overridden:
# herdctl.yaml (fleet defaults)defaults: permission_mode: acceptEdits denied_tools: - WebSearch - "Bash(sudo *)"# Override modepermission_mode: bypassPermissions
# Add to allowed toolsallowed_tools: - WebSearch # Override fleet denial
# Inherits denied_tools from fleetInheritance rules:
- Agent settings override fleet defaults
denied_toolstakes precedence overallowed_tools- Denied bash patterns always apply (never removed by inheritance)
Validation
Section titled “Validation”Validate your permission configuration:
# Validate specific agentherdctl validate agents/my-agent.yaml
# Validate entire fleetherdctl validate
# Show merged permissionsherdctl config show --agent my-agent --section permissionsSchema Reference
Section titled “Schema Reference”Permission Fields
Section titled “Permission Fields”// Top-level permission fields (not nested)permission_mode?: "default" | "acceptEdits" | "bypassPermissions" | "plan"tools?: string[]allowed_tools?: string[]denied_tools?: string[]| Field | Type | Default | Description |
|---|---|---|---|
permission_mode | string | "acceptEdits" | Permission approval mode |
tools | string[] | — | Tool availability whitelist - only these tools exist |
allowed_tools | string[] | — | Tools that skip permission prompts (including Bash() patterns) |
denied_tools | string[] | — | Tools explicitly blocked (including Bash() patterns) |
Bash Pattern Syntax
Section titled “Bash Pattern Syntax”Bash commands are specified using Bash(<pattern>) syntax:
| Pattern | Description |
|---|---|
Bash(git *) | Allow any git command |
Bash(npm run build) | Allow specific npm script |
Bash(node scripts/*) | Allow node scripts in specific directory |
Bash(sudo *) | (Deny) Block all sudo commands |
Bash(rm -rf /) | (Deny) Block dangerous rm command |
Related Pages
Section titled “Related Pages”- Agent Configuration — Full agent config reference
- Fleet Configuration — Fleet-level defaults
- MCP Servers — Configure MCP tools
- Agents Concept — Understanding agents