Tool Permissions¶
CLIver provides a permission system that controls tool execution during LLM interactions. You can configure which tools are allowed, denied, or require user confirmation — with rules scoped to specific resources like file paths, URLs, or shell commands.
Permission Modes¶
Three modes control the baseline behavior:
| Mode | Behavior |
|---|---|
default | Safe tools auto-allow; all others ask for confirmation |
auto-edit | Safe + read + write auto-allow; execute/fetch ask |
yolo | All tools auto-allow (no confirmations) |
Safe tools (always auto-allowed): skill, todo_read, todo_write, memory_read, memory_write, identity_update, ask_user_question
Settings File¶
Permissions are configured in cliver-settings.yaml at two levels:
- Global:
~/.config/cliver/cliver-settings.yaml— user-wide defaults - Local:
.cliver/cliver-settings.yaml— project-specific overrides
Local settings take precedence over global.
Example¶
permission_mode: auto-edit
permissions:
# Allow reading files
- tool: "read_file"
action: allow
# Allow specific shell commands
- tool: "run_shell_command"
resource: "git *"
action: allow
- tool: "run_shell_command"
resource: "uv *"
action: allow
# Allow all tools from a specific MCP server
- tool: "github#.*"
action: allow
# Deny dangerous commands
- tool: "run_shell_command"
resource: "rm -rf *"
action: deny
Rule Format¶
Each rule has three fields:
| Field | Format | Description |
|---|---|---|
tool | Regex | Matched against tool identity via re.fullmatch |
resource | fnmatch glob | Optional — matched against the tool's resource (path, URL, or command) |
action | allow/deny | What to do when the rule matches |
Tool Identity¶
- Builtin tools:
read_file,write_file,run_shell_command, etc. - MCP tools:
<server>#<tool>, e.g.github#create_issue,ocp#get_pods
Common Patterns¶
# All tools from an MCP server
- tool: "github#.*"
action: allow
# Specific MCP tools
- tool: "ocp#(get_pods|get_nodes|describe_.*)"
action: allow
# Grant all (project-level yolo)
- tool: ".*"
action: allow
Constrained Allow¶
When a tool has resource-specific rules, non-matching resources are implicitly denied. This prevents a broad wildcard from overriding tool-specific constraints:
permissions:
- tool: "read_file"
resource: "/data/reports/**"
action: allow
- tool: ".*"
action: allow
With this config, read_file("/data/reports/q1.csv") is allowed, but read_file("/etc/passwd") still requires confirmation — even though ".*" would otherwise allow it.
Managing Permissions via CLI¶
Persistent Rules (/permissions)¶
# Show all rules
Cliver> /permissions rules
# Interactive rule builder
Cliver> /permissions add
# Remove a rule by index
Cliver> /permissions remove 2
# Show or set permission mode (saved to file)
Cliver> /permissions mode
Cliver> /permissions mode auto-edit
Session Grants (/session permission)¶
Session grants are in-memory and cleared when the session ends:
# Show session grants
Cliver> /session permission
# Override mode for this session only
Cliver> /session permission mode yolo
# Allow/deny specific tools this session
Cliver> /session permission grant web_fetch
Cliver> /session permission deny docker_run
# Clear all session grants
Cliver> /session permission clear
Interactive Prompt¶
When a tool requires permission, CLIver prompts:
⚠ Permission required: run_shell_command
Resource: docker ps
[y]es / [n]o / [a]lways allow / [d]eny always >
y— allow this one timen— deny this one timea— allow this tool for the rest of the sessiond— deny this tool for the rest of the session
Workflow Permissions¶
Workflows, LLM steps, and tasks can declare permissions in their YAML definition. This is important for automated or scheduled tasks where no user is present to approve tools:
name: daily-report
permissions:
mode: auto-edit
rules:
- tool: "read_file"
resource: "/data/reports/**"
action: allow
- tool: "web_fetch"
resource: "https://api.internal.com/**"
action: allow
steps:
- id: analyze
name: Analyze data
type: llm
prompt: "Summarize the latest report"
model: qwen
Workflow permissions are scoped — they are active only during execution and automatically cleaned up when the workflow completes.
API-Level Usage¶
The permission system works independently of the CLI. When using CLIver as a Python library, you can configure PermissionManager and pass it to TaskExecutor:
from cliver.permissions import PermissionManager, PermissionMode
from cliver.llm import TaskExecutor
# Create permission manager with custom settings
pm = PermissionManager(
global_config_dir=Path("~/.config/cliver").expanduser(),
local_dir=Path(".cliver"),
)
pm.set_mode(PermissionMode.AUTO_EDIT)
# Pass to TaskExecutor
executor = TaskExecutor(
llm_models=models,
mcp_servers=servers,
permission_manager=pm,
on_permission_prompt=my_custom_prompt_handler,
)
The on_permission_prompt callback lets you implement your own approval UI — a web form, a Slack message, or an auto-approver for testing.