Appearance
Grok agent hooks
Project lifecycle hooks for Grok coding sessions. They keep agent turns formatted and checked, format files as they are edited, and require human approval before deploys or other high-side-effect scripts.
Hooks live under .grok/hooks/ and are version-controlled with the repo.
Enable once per machine
Project hooks only run after the folder is trusted:
text
/hooks-trustOr launch with --trust. Trust is stored in Grok’s folder-trust store (same gate as repo-local MCP).
| Command / UI | Purpose |
|---|---|
/hooks | Extensions modal → Hooks tab |
r (in Hooks tab) | Reload hooks from disk after edits |
Space | Enable / disable a single hook |
/hooks-list | List hooks loaded this session |
If hooks never fire: check trust, reload with r, and confirm the files under .grok/hooks/ are present.
Layout
.grok/hooks/
post-agent-quality.json # Stop
format-on-edit.json # PostToolUse
pre-tool-safety.json # PreToolUse
bin/
post-agent-quality.sh
format-on-edit.sh
pre-tool-safety.shJSON registers the event; scripts do the work. Paths in command are relative to the JSON file (so bin/… resolves correctly).
Stop — post-agent quality gate
When: the agent finishes a turn (reason: end_turn). Session-end observe fires are ignored.
Runs a project script chain, typically:
pnpm run post-agent— Prettier write → ESLint →tsc --noEmit→ unit tests- A changed-files dead-code / complexity audit vs merge-base
On failure: the stop is blocked and truncated log output is fed back to the model so it can fix issues and continue (Grok caps stop-hook continuations per turn).
Timeout: 600 seconds (format + lint + types + tests can take a while on a cold cache).
Manual equivalent: run the same scripts locally.
PostToolUse — format on edit
When: a file edit tool completes (search_replace, Write, Edit, …).
Runs: prettier --write on that file only (via pnpm exec prettier).
Skips:
- Missing paths
- Non-source extensions
- Vendor / build / generated paths (
node_modules/,.next/,dist/, lockfiles, typegen dumps)
Timeout: 30 seconds. Failures are silent (do not block the agent).
PreToolUse — shell safety and deploy approval
When: a shell tool is about to run (run_terminal_command / Bash).
Hard deny (no dialog)
These patterns are always blocked:
rm -rf /orrm -rf ~(and similar)git push --force/-fgit reset --hardgit clean -f/-fdmkfs,dd if=, classic fork-bomb
The hook returns decision: deny and the command does not run.
User approval (macOS dialog)
These require an Allow / Deny dialog (default Deny, 120s timeout):
| Kind | Example commands |
|---|---|
| Production deploy (Vercel) | pnpm run deploy, vercel --prod, vercel deploy … |
| Nested app deploy | Package-specific deploy scripts |
| Data seed / write scripts | pnpm run *:seed-*, node scripts/seed-… |
On Allow, the command proceeds. On Deny or timeout, the agent is told the user refused.
Non-GUI environments (no osascript) fail closed — side-effect commands are denied with instructions.
One-off override
Skip the dialog only when you intentionally want that:
bash
ALLOW_DEPLOY=1 pnpm run deploy
GROK_HOOK_ALLOW_SIDE_EFFECTS=1 pnpm run some-side-effectThe hook recognises those assignments:
- On the hook process environment, or
- In the command string (so
ALLOW_DEPLOY=1 pnpm run deployworks even though the prefix env is not visible to the hook process)
Prefer clicking Allow for normal deploys.
What is not hooked
| Script / action | Why |
|---|---|
dev, nested servers, docs, watch | Long-running servers |
e2e suite, full production build | Slow / heavy for every agent turn |
| Silent auto-fix on Stop | Prefer explicit fixes |
| Interactive codegen / e2e UI | Human-driven |
Day-to-day flow
Troubleshooting
| Symptom | Check |
|---|---|
| Hooks never run | /hooks-trust; Hooks tab shows Project hooks; reload r |
| Stop always blocks | Run post-agent and the audit script locally; fix failures |
| Dialog never appears | You are on macOS GUI session; not SSH-only; timeout not already fired |
| Deploy blocked without dialog | No GUI → fail closed; use ALLOW_DEPLOY=1 only if you accept the risk |
| Format-on-edit no-op | File extension not in allowlist, or path is generated/vendor |
Related
- Claude Code hooks — mirrored lifecycle for Claude Code
- Claude Code permissions — allow/ask/deny for deploys and secrets
- Architecture decision records