Skip to content

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.

Set the mode with /permission during a session:

ModeAuto-allowedAsks approval for
read_onlyRead operations (read_file, list_dir, glob, grep)All writes and shell commands
reversibleRead + reversible writes (edit_file, write_file to new files)Destructive operations
yoloEverything except catastrophicrm -rf, force push, etc.

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.

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.

EventWhen it firesCan decide?
SessionStartSession beginsYes (fail-closed)
SessionEndSession endsNo
UserPromptSubmitUser sends a messageYes
PreToolUseBefore a tool executesYes
PostToolUseAfter a tool succeedsNo
PostToolUseFailureAfter a tool failsNo
SubagentStartSub-agent spawnedNo
SubagentStopSub-agent finishedNo
StopAgent turn endsNo

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.

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

Hooks on PreToolUse can modify tool arguments via the updatedInput field before execution.

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.

Use /hooks during a session to see all registered hooks and their configuration.