Source: xai-org/grok-build (Apache-2.0), crate xai-grok-hooks + xai-grok-agent plugins adapter.
Synced for oh-my-grok v1.1.0 adaptation.
| Event | Blocking? | stdout used? |
|---|---|---|
| PreToolUse | Yes (only one) | Yes — {"decision":"deny"|"allow","reason"?} or exit 2 = deny |
| SessionStart | No | Ignored (exit code only) |
| UserPromptSubmit | No | Ignored |
| PostToolUse | No | Ignored |
| Stop / StopFailure | No | Ignored |
| SessionEnd | No | Ignored |
| SubagentStart / SubagentEnd | No | Ignored |
Fail-open: PreTool timeouts/crashes/malformed JSON → allow (tool continues).
Implications for oh-my-grok:
- Hard discipline that works in TUI: PreTool gates (agent-guard, plan-mode, hashline, skill-gate, comment deny).
- Stop
{decision:block}/ UserPromptadditionalContext: still emitted for tests + future hosts; current Grok runner does not re-prompt or inject from stdout. Side effects (write.omgstate) still run and help SessionStart resume / next PreTool. - Sisyphus text not in
/hooksUI: expected — non-blocking stdout is not displayed or injected by the runner.
hooks_adapter.rs pre-filters plugin hooks.json to:
SessionStart, PreToolUse, PostToolUse, SessionEnd,
Notification, Stop, UserPromptSubmit,
SubagentStart, SubagentEnd
Not loaded from plugins (skipped with warning): PostToolUseFailure, PermissionDenied, PreCompact, PostCompact, StopFailure, SubagentStop (use SubagentEnd).
Flattened JSON on stdin, e.g.:
{
"hookEventName": "pre_tool_use",
"sessionId": "...",
"cwd": "...",
"workspaceRoot": "...",
"timestamp": "...",
"toolName": "Write",
"toolUseId": "...",
"toolInput": { },
"toolResult": { },
"subagentType": "explore",
"prompt": "...",
"reason": "..."
}PostTool uses toolResult, not toolOutput. oh-my-grok maps both.
GROK_HOOK_EVENT, GROK_HOOK_NAME, GROK_SESSION_ID, GROK_WORKSPACE_ROOT, CLAUDE_PROJECT_DIR
Plugin: GROK_PLUGIN_ROOT, GROK_PLUGIN_DATA (+ Claude aliases).
- Parse
toolResult+subagentType+ native envelope fields. - Register SubagentStart / SubagentEnd → arm / clear spawn follow-through (host lifecycle, not assistant prose).
- Contract docs match source (PreTool = only host-enforced gate).
- Keep Stop/UserPrompt handlers for state + offline tests.
SubagentStart is fired on the parent session (updates.rs → self.fire_hook).
Do not setSessionAgentRole(subagentType) there or on PostTool spawn — sticky explore poisons parent AGENT_GUARD when the host omits agentName on later Write tools.
SubagentEnd means the child process finished, not that the parent integrated findings.
Clearing spawn follow-through on End lets the parent idle-stop without get_task_output.
End only marks childFinished; clear via recovery tools / progress / recovered language.
Simple-form matcher strings (only [A-Za-z0-9_|-]) are exact equality per | term — not regex, not case-insensitive.
List both search_replace and SearchReplace (and similar) or the host will skip the hook.
v1.1.33: OpenCode-style tool packs use bare read, todowrite, bash — host matchers must list those lowercase ids or PostTool Hashline / Skill Gate load / todo mirror / ULW shell never fire.
| Host tool id | oh-my-grok |
|---|---|
task |
spawn matcher + isSpawnTool |
get_task_output / recovery aliases |
clear spawn follow-through |
enter_plan_mode / exit_plan_mode |
activateHostPlanMode / endPlanMode |
todo_write |
post-tool-todo |
search_replace / read_file |
Pre/Post matchers |
read_file line format N→… |
Hashline strips before old_string match (v1.1.10) |