Permissions & Hooks
Fermi provides two systems for controlling agent behavior: a permission system that gates tool execution, and a hook system that lets you run custom commands in response to runtime events.
Permission Modes
Section titled “Permission Modes”Set the mode with /permission during a session:
| Mode | Auto-allowed | Asks approval for |
|---|---|---|
read_only | Read operations (read_file, list_dir, glob, grep) | All writes and shell commands |
reversible | Read + reversible writes (edit_file, write_file to new files) | Destructive operations |
yolo | Everything except catastrophic | rm -rf, force push, etc. |
How Classification Works
Section titled “How Classification Works”The permission system uses tree-sitter to parse bash commands and classify them into risk tiers:
- read — ls, cat, grep, git status
- write_reversible — mkdir, cp, git add
- write_potent — rm (single file), mv, git commit
- write_danger — rm -rf, git push —force, operations on broad paths
- catastrophic — dd to device files, rm targeting / or $HOME (always requires approval even in yolo mode)
File tools are classified by their operation type: read_file is always read, edit_file is write_reversible, bash depends on the command content.
Permission Rules
Section titled “Permission Rules”You can save rules to avoid repeated approval prompts. When the system asks for approval, it offers to remember your choice. Rules exist at four scopes:
- session — in-memory, this session only
- workspace — user-authored,
<project>/.fermi/permissions.json - project — system-managed,
~/.fermi/projects/<slug>/permissions.json - global —
~/.fermi/permissions.json, applies across all projects
Hooks are shell commands that execute in response to runtime events. They allow custom automation, validation, and context injection.
Supported Events
Section titled “Supported Events”| Event | When it fires | Can decide? |
|---|---|---|
SessionStart | Session begins | Yes (fail-closed) |
SessionEnd | Session ends | No |
UserPromptSubmit | User sends a message | Yes |
PreToolUse | Before a tool executes | Yes |
PostToolUse | After a tool succeeds | No |
PostToolUseFailure | After a tool fails | No |
SubagentStart | Sub-agent spawned | No |
SubagentStop | Sub-agent finished | No |
Stop | Agent turn ends | No |
Decision Events
Section titled “Decision Events”Hooks on decision events (UserPromptSubmit, PreToolUse) can approve or deny the action by returning a JSON decision field. If a hook denies, the action is blocked.
Context Injection
Section titled “Context Injection”Hooks on SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, and PostToolUseFailure can inject additional context via the additionalContext field. This context is included in the agent’s next prompt. (The other events — SessionEnd, SubagentStart, SubagentStop, Stop — do not support context injection.)
Input Update
Section titled “Input Update”Hooks on PreToolUse can modify tool arguments via the updatedInput field before execution.
Configuration
Section titled “Configuration”Hooks live in subdirectories of ~/.fermi/hooks/ (global), <project>/.fermi/hooks/ (project-scoped), or ~/.fermi/projects/<slug>/.fermi/hooks/ (the system-managed per-project store). Each hook is a directory containing a hook.json manifest:
{ "name": "my-hook", "type": "command", "event": "PreToolUse", "command": "/path/to/script.sh", "failClosed": true}Optional fields: args (string array), env (key-value), matcher (filter by tool names or agent IDs), timeoutMs (default 10000), disabled.
When failClosed is true, hook failure (crash, timeout) is treated as denial. Supported on: SessionStart, UserPromptSubmit, PreToolUse.
Viewing Hooks
Section titled “Viewing Hooks”Use /hooks during a session to see all registered hooks and their configuration.