Skip to content

Permissions

Permissions control what an agent can do within its session. Herdctl provides fine-grained control over tool access, bash command execution, and permission approval modes. This allows you to create agents with appropriate access levels—from read-only support bots to full-access development agents.

agents/my-agent.yaml
permissions:
mode: acceptEdits
allowed_tools:
- Read
- Write
- Edit
- Bash
denied_tools:
- WebSearch
bash:
allowed_commands:
- "git *"
- "npm *"
denied_patterns:
- "rm -rf *"
- "sudo *"

The mode field controls how Claude Code handles permission requests. This maps directly to the Claude Agent SDK’s permission modes.

permissions:
mode: acceptEdits # default
ModeDescriptionUse Case
defaultRequires approval for everythingMaximum control, manual oversight
acceptEditsAuto-approve file operationsRecommended for most agents
bypassPermissionsAuto-approve everythingTrusted, isolated environments
planPlanning only, no executionResearch agents, dry runs

The most restrictive mode. Every tool use requires explicit approval through herdctl’s permission callback system.

permissions:
mode: default

When to use:

  • Testing new agents
  • Running untrusted prompts
  • Environments requiring audit trails

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.

permissions:
mode: acceptEdits

When to use:

  • Standard development agents
  • Content creation agents
  • Most production use cases

Auto-approves all tool requests without prompting. Use with caution.

permissions:
mode: bypassPermissions

When 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.

permissions:
mode: plan

When to use:

  • Previewing agent behavior before execution
  • Research and analysis agents
  • Generating plans for human review

Control which Claude Code tools an agent can use with allowed_tools and denied_tools arrays.

Explicitly list tools the agent can use:

permissions:
allowed_tools:
- Read
- Write
- Edit
- Bash
- Glob
- Grep
- Task
- WebFetch

Explicitly block specific tools:

permissions:
denied_tools:
- WebSearch
- WebFetch
ToolDescriptionRisk Level
ReadRead files from filesystemLow
WriteCreate new filesMedium
EditModify existing filesMedium
GlobFind files by patternLow
GrepSearch file contentsLow
BashExecute shell commandsHigh
TaskLaunch subagentsMedium
WebFetchFetch web contentMedium
WebSearchSearch the webMedium
TodoWriteManage task listsLow
AskUserQuestionRequest user inputLow
NotebookEditEdit Jupyter notebooksMedium

MCP (Model Context Protocol) server tools use the mcp__<server>__<tool> naming convention:

permissions:
allowed_tools:
- Read
- Edit
- mcp__github__* # All GitHub MCP tools
- mcp__posthog__* # All PostHog MCP tools
- mcp__filesystem__read_file # Specific tool only

Wildcard support:

  • mcp__github__* — Allow all tools from the GitHub MCP server
  • mcp__* — Allow all MCP tools (not recommended)

Fine-tune which shell commands agents can execute with the bash configuration.

permissions:
bash:
allowed_commands:
- "git *"
- "npm *"
- "pnpm *"
- "node *"
- "npx *"
denied_patterns:
- "rm -rf /"
- "rm -rf /*"
- "sudo *"
- "curl * | sh"
- "wget * | sh"

Glob patterns for commands the agent can run:

bash:
allowed_commands:
- "git *" # All git commands
- "npm run *" # npm run scripts
- "pnpm *" # All pnpm commands
- "node scripts/*" # Node scripts in scripts/
- "make build" # Specific make target

Patterns that are always blocked, even if they match an allowed command:

bash:
denied_patterns:
- "rm -rf /"
- "rm -rf /*"
- "sudo *"
- "chmod 777 *"
- "curl * | bash"
- "curl * | sh"
- "wget * | bash"
- "wget * | sh"
- "dd if=*"
- "mkfs *"
- "> /dev/*"
- ":(){ :|:& };:"

Full development capabilities with sensible restrictions:

permissions:
mode: acceptEdits
allowed_tools:
- Read
- Write
- Edit
- Bash
- Glob
- Grep
- Task
- TodoWrite
bash:
allowed_commands:
- "git *"
- "npm *"
- "pnpm *"
- "node *"
- "npx *"
- "tsc *"
- "eslint *"
- "prettier *"
- "vitest *"
- "jest *"
denied_patterns:
- "rm -rf /"
- "rm -rf /*"
- "sudo *"
- "chmod 777 *"

Can read and search but cannot modify:

permissions:
mode: default
allowed_tools:
- Read
- Glob
- Grep
- WebFetch
denied_tools:
- Write
- Edit
- Bash

Can read/write files, no shell access:

permissions:
mode: acceptEdits
allowed_tools:
- Read
- Write
- Edit
- Glob
- Grep
- WebFetch
- WebSearch
denied_tools:
- Bash
- Task

Maximum permissions in a Docker container:

permissions:
mode: bypassPermissions
allowed_tools: [] # Empty = all tools allowed
docker:
enabled: true
base_image: node:20-slim

Plan and research without execution:

permissions:
mode: plan
allowed_tools:
- Read
- Glob
- Grep
- WebFetch
- WebSearch

Can only perform git operations:

permissions:
mode: acceptEdits
allowed_tools:
- Read
- Glob
- Grep
- Bash
bash:
allowed_commands:
- "git status"
- "git diff *"
- "git log *"
- "git add *"
- "git commit *"
- "git push *"
- "git pull *"
- "git checkout *"
- "git branch *"
- "git merge *"
- "gh pr *"
- "gh issue *"
denied_patterns:
- "git push --force *"
- "git push -f *"
- "git reset --hard *"

Begin with minimal permissions and expand as needed:

# Start here
permissions:
mode: default
allowed_tools:
- Read
- Glob
- Grep
# Add more as you verify behavior
EnvironmentRecommended Mode
Development/Testingdefault
Production (standard)acceptEdits
Production (Docker isolated)bypassPermissions
Research/Previewplan

Always deny dangerous bash patterns:

bash:
denied_patterns:
# Destructive commands
- "rm -rf /"
- "rm -rf /*"
- "rm -rf ~"
- "rm -rf ~/*"
- "rm -rf ."
- "rm -rf ./*"
# Privilege escalation
- "sudo *"
- "su *"
- "doas *"
# Remote code execution
- "curl * | bash"
- "curl * | sh"
- "wget * | bash"
- "wget * | sh"
- "eval *"
# System damage
- "dd if=*"
- "mkfs *"
- "fdisk *"
- "> /dev/*"
- "chmod -R 777 *"
# Fork bomb
- ":(){ :|:& };:"

Only allow necessary MCP tools:

permissions:
allowed_tools:
# Specific MCP tools, not wildcards
- mcp__github__create_issue
- mcp__github__list_issues
- mcp__github__create_pull_request
# NOT: mcp__github__*

Combine Docker isolation with permissions:

permissions:
mode: bypassPermissions
docker:
enabled: true
base_image: node:20-slim

Restrict workspace access when possible:

workspace:
root: ~/herdctl-workspace/project-a
# Agent can only access this directory

Review agent permissions periodically:

Terminal window
# Show effective permissions for an agent
herdctl config show --agent my-agent --section permissions

Agent permissions inherit from fleet defaults and can be overridden:

# herdctl.yaml (fleet defaults)
defaults:
permissions:
mode: acceptEdits
denied_tools:
- WebSearch
bash:
denied_patterns:
- "sudo *"
agents/trusted-agent.yaml
permissions:
# Override mode
mode: bypassPermissions
# Add to allowed tools
allowed_tools:
- WebSearch # Override fleet denial
# Inherits bash.denied_patterns from fleet

Inheritance rules:

  1. Agent settings override fleet defaults
  2. denied_tools takes precedence over allowed_tools
  3. bash.denied_patterns always apply (never removed by inheritance)

Validate your permission configuration:

Terminal window
# Validate specific agent
herdctl validate agents/my-agent.yaml
# Validate entire fleet
herdctl validate
# Show merged permissions
herdctl config show --agent my-agent --section permissions

permissions:
mode?: "default" | "acceptEdits" | "bypassPermissions" | "plan"
allowed_tools?: string[]
denied_tools?: string[]
bash?:
allowed_commands?: string[]
denied_patterns?: string[]
FieldTypeDefaultDescription
modestring"acceptEdits"Permission approval mode
allowed_toolsstring[]Tools the agent can use
denied_toolsstring[]Tools explicitly blocked
bash.allowed_commandsstring[]Allowed bash command patterns
bash.denied_patternsstring[]Blocked bash command patterns