Skip to content

Permissions and Hooks

Permission System

Defined in agent-core, consumed by agent-sessions. Provides deterministic 3-step policy evaluation for tool calls.

Evaluation Algorithm

  1. Deny list — If any deny pattern matches, return deny
  2. Allow list — If any allow pattern matches, return auto (no prompt)
  3. Mode policy — Look up the tool in the mode matrix

Permission Modes

ModeReadWriteBash
planautodenydeny
defaultautoapprove (prompt)approve (prompt)
acceptEditsautoautoapprove (prompt)
bypassPermissionsautoautoauto

Pattern Syntax

Bash(pnpm *)        # Bash with command starting "pnpm "
Read(/src/**)        # Read for files under /src/
Write(*)             # Write with any argument
ToolName             # Match any invocation (no arg constraint)

Configuration

json
{
  "permissions": {
    "allow": ["Read(*)", "Glob(*)", "Grep(*)", "Bash(pnpm *)"],
    "deny": ["Bash(rm -rf *)"]
  }
}

Hook System

Lifecycle hooks for extending session behavior. Defined in agent-core and agent-sdk, consumed by agent-sessions.

Events

EventTimingPurpose
PreToolUseBefore tool executionValidation, blocking
PostToolUseAfter tool executionLogging, auditing
PreCompactBefore context compactionValidation
PostCompactAfter context compactionNotification (includes summary)
SessionStartSession initializationSetup
StopSession terminationCleanup
UserPromptSubmitBefore user prompt sentPrompt preprocessing, injection
NotificationOn notification eventsExternal alerting, logging

Exit Code Protocol

CodeMeaning
0Allow / proceed
2Block / deny (stderr = reason)
otherProceed with warning

Hook Types

TypeLayerDescription
commandagent-coreShell command; receives JSON via stdin, uses exit codes
httpagent-coreHTTP POST to a URL; supports env var interpolation in headers
promptagent-sdkSingle-turn LLM evaluation; returns model response
agentagent-sdkMulti-turn subagent; runs a full agent loop

Hook Input

Hooks receive JSON via stdin:

json
{
  "session_id": "session_1234",
  "cwd": "/path/to/project",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": { "command": "pnpm test" },
  "prompt": "the user's current prompt text"
}

The prompt field is included for Claude Code compatibility and contains the user's current prompt text (present for UserPromptSubmit and SessionStart events).

Hook Stdout Injection

For SessionStart and UserPromptSubmit events, hook stdout is injected into the AI context as a <system-reminder> block. This allows hooks to dynamically provide instructions, context, or constraints to the model.

Configuration

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{ "type": "command", "command": "bash .hooks/validate-bash.sh" }]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "",
        "hooks": [{ "type": "command", "command": "bash .hooks/log-tool-use.sh" }]
      }
    ]
  }
}

Hooks have a 10-second timeout. Empty matcher matches all tools.

Plugin Hooks

Plugins can define their own hooks in hooks/hooks.json within the plugin directory. Plugin hooks are merged into the session lifecycle alongside project-defined hooks.

Environment Variables

Plugin hooks receive additional environment variables:

VariableDescription
CLAUDE_PLUGIN_ROOTRoot directory of the plugin
CLAUDE_PLUGIN_PATHFull path to the hook script
CLAUDE_PROJECT_DIRCurrent project working directory
CLAUDE_SESSION_IDActive session identifier

These environment variables use the CLAUDE_ prefix for compatibility with Claude Code plugin conventions.

Execution Loop Context Management

The session execution loop includes context budget checks to prevent exceeding the model's context window:

  • Pre-send check: Before each provider call, context usage is checked against 83.5% of the context window. If exceeded, auto-compaction is triggered.
  • Tool result budget: Individual tool results are checked against an 80% context budget. Results exceeding this limit are replaced with an error message indicating the output was too large.
  • Forced summary on turn exhaustion: When maxRounds is exhausted, the session injects a synthetic user message and makes a final provider call without tools to produce a summary response.

See agent-sessions SPEC.md for implementation details.

Subagent Hook Forwarding

When a subagent session is created (via createSubagentSession), it inherits the parent session's hooks configuration. All hook events (PreToolUse, PostToolUse, etc.) fire in the subagent context with the same handlers as the parent. This ensures consistent policy enforcement across the parent and all spawned subagents.

Released under the MIT License.