v1.20.60see what's new →

Hooks

Hooks are shell scripts that run automatically at moments you choose — before the agent edits a file, after it runs a command, when a session starts.

A quick example

Inject today's date into every prompt automatically, without adding it to every message yourself:

# ~/.agents/hooks/inject-date.sh
echo '{"context": "Today is '$(date +%Y-%m-%d)'"}'
# ~/.agents/agents.yaml
hooks:
  inject-date:
    script: inject-date.sh
    events:
      - UserPromptSubmit
  1. You type a prompt
    free-form input
  2. UserPromptSubmit hook fires
    injects “today is 2026-06-07” into context
  3. Model picks a tool
    e.g. Edit a file
  4. PreToolUse hook gates the call
    approve · block · log
  5. Result returns to you

Events you can hook into

The manifest

Declare hooks in ~/.agents/agents.yaml. The user layer wins over the system layer on key collision.

# ~/.agents/agents.yaml
hooks:
  post-edit:
    script: post-edit.sh           # filename in ~/.agents/hooks/
    events:
      - PostToolUse
    timeout: 30                    # seconds; default 600
    matches:
      tool_name: "Edit"            # only fire on Edit tool calls
      cwd_includes: /projects/myapp

  session-start:
    script: session-start.sh
    events:
      - SessionStart
    timeout: 10

  prompt-guard:
    script: prompt-guard.sh
    events:
      - UserPromptSubmit
    matches:
      prompt_contains: "deploy"

The script field is a filename resolved from ~/.agents/hooks/ then ~/.agents-system/hooks/. The agent passes event context as JSON on stdin when the script fires.

Predicate matchers

All predicates in a matches: block AND together — every declared predicate must pass, or the script is skipped. An empty matches: block always passes.

# Fire only on Edit or Write, in a specific repo, when git is dirty
matches:
  tool_name: ["Edit", "Write"]
  project_has: "go.mod"
  git_dirty: true

Disable a system hook

To turn off a hook shipped by the system without deleting or forking it, add an entry with enabled: false in your user layer:

# ~/.agents/agents.yaml
hooks:
  03-linear-inject-tasks-context:
    script: 03-linear-inject-tasks-context.sh
    events:
      - UserPromptSubmit
    enabled: false

An enabled: false entry is stripped before it reaches the agent — the hook will not fire for any agent.

Managing hooks

agents hooks list                    # show all registered hooks
agents hooks list claude             # filter to claude
agents hooks list --scope user       # only user-layer hooks
agents hooks add gh:team/hooks --agents claude,codex
agents hooks add --names post-edit --agents claude
agents hooks view post-edit          # print the script source
agents hooks remove post-edit        # remove from agent version homes

Related