The symptom: a hook that used to block (commit messages, gates) silently stopped. Debug in this order — each step catches a different failure class:
-
Watch the hook log live while you trigger an action:
cos hooks-log --followIf entries appear, hooks are firing and the question becomes why one passed. If nothing appears, continue.
-
Check symlink integrity. Consumer projects receive core hooks as live symlinks; moving/renaming the project directory or an aggressive
git cleancan dangle them:cos sync-doctor --repair -
Run the doctor — it verifies the whole chain (env vars, agent settings file, state dir):
cos doctor -
Check your agent settings file — the adapter registers hooks in the runtime’s settings (e.g.
.claude/settings.jsonfor Claude Code). If it was ever hand-edited, re-runcos updateto re-render it. -
Runtime check — Claude Code and Codex both run hooks at full parity. On an unsupported runtime, in-session hooks won’t fire at all and the git-level hooks are the safety net.
Most real cases are #2 — dangling symlinks after a directory move. cos sync-doctor --repair fixes them in place.