Safety and Guardrails (Hooks)
Relevant source files
The following files were used as context for generating this wiki page:
The ai-dev-atelier project implements a system of safety guardrails using PreToolUse hooks. These hooks intercept tool calls made by an AI agent before they are executed, allowing for validation, modification, or blocking of commands based on predefined rules. The primary purpose of this system is to enforce specific development workflows, prevent common errors, and guide the agent towards using more efficient, specialized skills instead of raw commands.
For example, hooks are used to block standard git commands in favor of gt (Graphite) commands and to prevent redundant API calls that can be handled by dedicated skills. This ensures agents adhere to the project's stacked PR workflow and use resources efficiently.
Sources: AGENTS.md:47-55
Architecture
The hook system is composed of three main parts: a central JSON configuration file, individual hook implementation scripts, and an installation script that deploys them into the agent's environment (e.g., OpenCode).
hooks.json: A manifest file that defines all available hooks, their trigger conditions, and the path to their implementation scripts.- Hook Scripts: Executable shell scripts (
.sh) that contain the logic for a specific hook. Each script determines whether to allow, block, or modify a tool command. install.sh: A setup script that copieshooks.jsonand the individual hook scripts into the agent's designated hook directory (~/.opencode/hook/).
Sources: AGENTS.md:20, install.sh:42-49, hooks.json
Execution Flow
When an AI agent attempts to execute a tool (e.g., a bash command), the PreToolUse hook mechanism intercepts the call. It consults hooks.json to find a matching hook and then executes the corresponding script to decide the outcome.
The following diagram illustrates the hook interception and execution flow.
Sources: AGENTS.md:47-49, hooks.json
Hook Configuration (hooks.json)
The hooks.json file is an array of objects, where each object defines a single hook.
Sources: hooks.json:1-20
[
{
"id": "graphite-block",
"matcher": "bash",
"script_path": "skills/use-graphite/scripts/graphite-block-hook.sh",
"description": "Blocks git push, git checkout -b, and gh pr create in Graphite-enabled repos"
},
{
"id": "pr-comments-block",
"matcher": "bash",
"script_path": "skills/resolve-pr-comments/scripts/pr-comments-block-hook.sh",
"description": "Blocks gh api calls fetching PR comments on current repo's open PRs"
}
]
Sources: hooks.json:2-19
Configuration Fields
| Field | Description | Example |
|---|---|---|
id | A unique identifier for the hook. | graphite-block |
matcher | The type of tool call to match against. Currently, bash is used for shell commands. | bash |
script_path | The relative path from the repository root to the hook's implementation script. | skills/use-graphite/scripts/graphite-block-hook.sh |
description | A brief explanation of the hook's purpose. | "Blocks git push, git checkout -b, and gh pr create..." |
Sources: hooks.json:3-18
Available Hooks
The repository currently defines two primary hooks to enforce workflow constraints.
graphite-block
This hook prevents the use of standard Git and GitHub CLI commands that conflict with the Graphite stacked pull request workflow. It guides the agent to use gt commands instead.
*Sources: hooks.json:3-7, skills/use-graphite/scripts/graphite-block-hook.sh *
Blocked Commands:
git pushgit checkout -bgh pr create
The hook's logic is activated only if the current repository is managed by Graphite (i.e., a .graphite/ directory exists).
The diagram below shows the decision logic of the graphite-block hook.
pr-comments-block
This hook blocks direct gh api calls that attempt to fetch pull request comments. Its purpose is to steer the agent towards using the more sophisticated resolve-pr-comments skill, which provides a structured and efficient way to handle PR feedback.
*Sources: hooks.json:11-15, skills/resolve-pr-comments/scripts/pr-comments-block-hook.sh *
Blocked Command Pattern:
gh api ... repos/.*/.*/pulls/.*/comments
This pattern matches API calls targeting the comments endpoint of any pull request in any repository.
The following diagram illustrates the hook's logic.
Installation
The hooks are not active by default. They must be installed into the AI agent's environment by running the install.sh script. This script copies the hooks.json file and all referenced hook scripts to the ~/.opencode/hook directory.
Sources: install.sh:42-49, AGENTS.md:53-55
The installation process is as follows:
# install.sh
# ...
HOOK_DIR="$OPENCODE_DIR/hook"
# ...
echo "Installing hooks to $HOOK_DIR..."
mkdir -p "$HOOK_DIR"
cp hooks.json "$HOOK_DIR/hooks.json"
# Copy hook scripts
cp skills/use-graphite/scripts/graphite-block-hook.sh "$HOOK_DIR/"
cp skills/resolve-pr-comments/scripts/pr-comments-block-hook.sh "$HOOK_DIR/"
# ...
Sources: install.sh:13, 43-49
The sequence diagram below visualizes the installation flow.
Sources: install.sh:42-49
Summary
The PreToolUse hook system is a critical guardrail feature in the ai-dev-atelier project. By intercepting and validating tool commands before execution, it enforces project-specific workflows, prevents common mistakes, and promotes the use of specialized, higher-level skills. This ensures that AI agents operate safely, efficiently, and in alignment with the repository's development practices, particularly regarding the Graphite workflow and PR comment resolution.
Sources: AGENTS.md:47-55