DGC v0.47.2 is out
Navigate
Install DGC
DGC v0.47.2Edit on GitHub ↗
Features/Lifecycle hooks

run observable commands at agent boundaries

Lifecycle hooks

#

Configure hook commands under hooks in ~/.dgc/config.json. Native local/API turns can call six lifecycle events: SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, PreCompact, and Stop. Delegated subscription turns call SessionStart and Stop; their vendor-owned prompt and internal tool loop is not visible to DGC's prompt/tool hook events.

  • /hooks — show every supported event, its bounded configured count, redacted exact tool matchers, and invalid configuration state. Shell commands and environment values are never shown.
  • PreToolUse and UserPromptSubmit can block an action with a non-zero exit. PostToolUse output is returned to the model as bounded feedback.
  • Hook batches share the workspace mutation lease, own a process group, have one bounded deadline, drain a bounded redacted head/tail, and honor /sandbox.
  • Headless controllers use {"type":"list_hooks","request_id":"hooks-1"} and receive hook_catalog. Natural execution emits hook_activity with started and exactly one terminal status; there is deliberately no command that executes a hook outside its lifecycle boundary.
  • ACP represents configured hook runs as ordinary command-free tool-call lifecycle updates.

Configuring one

#

Each event takes a list of entries. command is required; matcher is optional and narrows a tool event to one tool:

{
  "hooks": {
    "PreToolUse":       [{"matcher": "bash", "command": "./scripts/guard.sh"}],
    "PostToolUse":      [{"command": "./scripts/format.sh"}],
    "UserPromptSubmit": [{"command": "./scripts/log-prompt.sh"}]
  }
}

The event payload arrives on stdin as JSON, so a hook reads it rather than taking arguments:

#!/usr/bin/env bash
# ./scripts/guard.sh — refuse a bash command that touches the release directory
payload=$(cat)
case "$payload" in
  *dist/release*) echo "release artifacts are off limits to the agent"; exit 1 ;;
esac

Exit status is the control surface:

  • a PreToolUse or UserPromptSubmit hook that exits non-zero blocks the action, and its output becomes the reason the agent is shown;
  • a PostToolUse hook's output is appended to the tool result as feedback, so the agent reads it and can react;
  • every other event ignores the exit status.

Use /hooks to confirm what DGC actually loaded — it reports the configured count and redacted matchers per event without echoing your commands.

Documentation