Hooks (deterministic enforcement)
shared/constitution.md lists hard rules: no force-push, no merge from a skill, no rm -rf $HOME, no --no-verify, etc. Without hooks, those are advisory — the agent COULD follow them, and usually does, but nothing stops a buggy run from breaking the rules.
Hooks make the constitution real.
Source: hooks/hooks.json + hooks/banner.sh.
Three events
1. PreToolUse:Bash (safety blocker)
Inspects every Bash invocation before it runs. Blocks (with a precise reason in the agent’s transcript):
git push --force/--force-with-leaseto main / master / develop / release/* / prod/* or any branch inoverrides.yaml.protected_branchesgit reset --hardon protected branchesgit clean -fdat a repo rootgit branch -D main/master/develop/release/*/prod/*rm -rftargeting$HOME,/, anything under$ADK_CONFIG_HOME/, or any repo rootgh pr mergeUNLESS the user explicitly asked to merge a PR in the current sessiongh pr closeUNLESS the user explicitly asked- Any command writing into
$ADK_DATA_HOME/improve/learning/archive/(only/adk-improvewrites there) --no-verifyflags ongit commitorgit push
Allows: normal git, gh, npm, jq, fd, rg, curl, python3, ./install.sh, claude operations, and writes to .temp/<task-slug>/ paths.
2. PostToolUse:Edit|Write (validator)
After any Edit or Write:
- If the edited file is a
*/skills/<skill>/SKILL.md: verifies YAML frontmatter hasname:anddescription:, and thatname:matches the folder basename. - If the edited file is under
.temp/<task-slug>/: touches.temp/<task-slug>/.last-modifiedso monitors can detect activity. - If the edited file is
$ADK_CONFIG_HOME/overrides.yaml: regex-checks for raw token-looking values (/^[A-Z_]+:\s*['"]?[a-zA-Z0-9_-]{20,}['"]?$/outside${VAR}patterns). Refuses if a likely secret is detected.
3. SessionStart (banner)
Prints a one-screen status at session open:
[adk v3] — 8 skills: /adk-implement /adk-review /adk-investigate /adk-document /adk-sync /adk-setup /adk-improve /adk-explain[adk v3] MCPs: 6 env-ok, 2 env-missing · env: 12 present, 4 missing[adk v3] 3 pending /adk-improve proposals — run /adk-improve to reviewUses scripts/adk_mcp_health.py --json for the health summary. Surfaces pending /adk-improve proposals when they exist.
How they’re installed
install.sh --target claude merges hooks/hooks.json into ~/.claude/settings.json with each entry tagged _adk_managed: true:
{ "hooks": { "PreToolUse": [ { "_adk_managed": true, "matcher": "Bash", "hooks": [{ "type": "prompt", "prompt": "..." }] } ], "PostToolUse": [...], "SessionStart": [...] }}The marker makes the merge idempotent (re-running install.sh replaces only adk-managed entries — user-authored hooks are left untouched) and removable (install.sh --uninstall --target claude strips them).
Why only Claude Code
Cursor, Codex CLI, and Junie don’t have an equivalent hook system. In those environments, the constitution is enforced by advisor prose only.
If you need the safety guarantees outside Claude Code, run agents-as-CLI (Claude Code in a subprocess) or wait for the agent ecosystem to land a hooks equivalent.
Customizing
To add a custom rule:
- Edit
hooks/hooks.json. Add your entry —_adk_managed: trueis set automatically byinstall.pyduring merge. - Re-run
./install.sh --target claude.
To remove all adk hooks:
./install.sh --uninstall --target claudeTo remove a SINGLE adk hook without uninstalling everything: edit ~/.claude/settings.json and remove the specific entry. Re-running install.sh will re-add it; if you want it permanently gone, also edit hooks/hooks.json in the repo to remove the source.