Docs

Reference

Hook events

How each agent's native hook events map to Comity events, what is sent, timeouts, and how answers are rendered.

On this page

Every agent integration runs comity hook --tool <tool> --event <Event> with the host's hook JSON on stdin (the omp extension calls the same code in-process). The CLI maps the native event to a Comity event, sends it to POST /v1/hooks/evaluate, and prints the host's native hook output.

Event mapping

Comity event Claude Code / Copilot CLI Codex Cursor (via Claude hooks) omp
session_start SessionStart SessionStart sessionStart session_start
prompt UserPromptSubmit UserPromptSubmit beforeSubmitPrompt before_agent_start
plan PreToolUse on ExitPlanMode – – –
pre_edit PreToolUse on an edit tool PreToolUse on apply_patch / edit preToolUse on an edit tool tool_call on edit, apply_patch, write
pre_shell PreToolUse on Bash PreToolUse on a shell command preToolUse on Shell tool_call on bash, eval, ast_edit
post_edit PostToolUse on an edit tool or Bash PostToolUse postToolUse tool_result on the same tools
stop Stop Stop stop session_stop
session_end SessionEnd SessionEnd sessionEnd session_shutdown
  • Edit tools: Edit, Write, MultiEdit, NotebookEdit (and Delete where a host has it). Host-specific names are normalized: create/write → Write, edit/str_replace_editor → Edit, Shell/bash/powershell/shell/exec_command → Bash.
  • Codex apply_patch: paths come from the patch envelope (*** Update File: …). A shell command containing *** Begin Patch is treated as an edit of those files.
  • Other tools (reads, searches, web) are ignored and never leave the machine.
  • The matchers comity init writes are Edit|Write|MultiEdit|NotebookEdit|Bash|ExitPlanMode on PreToolUse and Edit|Write|MultiEdit|NotebookEdit|Bash on PostToolUse (Claude Code), and apply_patch|Edit|Write|Bash (Codex). Hooks written by CLI 0.4.0 or older lack ExitPlanMode, so they never send plan; they keep working otherwise, and comity doctor shows "update available" until you rerun comity init. Codex has no plan event.
  • pre_push exists in the protocol but no integration sends it and the server doesn't act on it.

What each event sends

Event Extra fields
session_start Workspace packages (repo.packages, up to 200)
prompt prompt_excerpt: first 2,000 characters of the prompt
plan plan_text (up to 32,768 characters)
pre_edit paths: repo-relative paths about to change (up to 500)
pre_shell shell.command (up to 4,000 characters); paths the command visibly writes (>, >>, tee)
post_edit paths changed (for shell commands: the working-tree diff before/after); analysis: per-file symbols, signature hashes, compatibility, new references
stop status: {excerpt (≤500 chars of the last assistant message), files (touched this turn)}, unless COMITY_SHARE_STATUS=0

Every request also carries session (external_id, tool, model, surface, parent_external_id for subagents), client (cli_version, os, tool_version, machine_id_hash), repo (remote_fingerprints, branch, head_sha, base_sha, worktree_hash, cwd_path), and a dedupe_key so a retried event is evaluated once.

Hooks only run in git repositories with at least one remote. In a folder that contains several repositories (not itself a repo), the CLI sends each file's event to the repo it belongs to, and merges the briefings for up to 8 recently active repos at session start.

Response

JSON
{
  "decision": "warn",
  "reason": "1 coordination warning(s): …",
  "inject_context": "## Comity update — system-generated for `acme/api`\n…",
  "conflicts": [{ "number": 9, "ref": "CF-9", "kind": "symbol_overlap", "severity": "warn" }],
  "intent": { "number": 14, "ref": "INT-14", "status": "active" },
  "session_id": "0192f0c4-7d1e-7a8b-9c2d-3e4f5a6b7c8d",
  "index_version": 412
}

How the CLI renders it for the host:

Result Before a tool call (PreToolUse) Other events
block {"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "<reason>"}} Never happens
warn / context Codex, omp: additionalContext. Claude Code, Cursor, Copilot CLI: queued and added to the next PostToolUse or prompt {"hookSpecificOutput": {"hookEventName": "<Event>", "additionalContext": "<text>"}} on SessionStart, UserPromptSubmit, PostToolUse
allow, nothing to say No output No output

Comity never outputs a native "allow" decision, so the host's own permission prompts still apply. Added context is capped at 6,000 characters per event. The hook always exits 0.

Timeouts

CLI waits for the API Host hook timeout in init config
pre_edit, pre_shell 400 ms 5 s
Other events 1.5 s 5 s (SessionStart, UserPromptSubmit), 10 s (PostToolUse, Stop, SessionEnd; Codex SessionEnd 3 s)
omp extension 600 ms per event, then allows –

If the API doesn't answer in time, errors, or returns an unexpected shape, the hook prints nothing (the agent proceeds) and appends a fail-open line to hook.log in the CLI config folder.

Host detection

Cursor and Copilot CLI run the Claude Code hooks, so --tool claude_code is only a hint. The CLI decides from the payload and environment:

Host Recognized by
Cursor cursor_version or conversation_id in the payload, or CURSOR_VERSION set
Copilot CLI sessionId / toolName / toolArgs in the payload, or the VS Code–compatible payload (ISO timestamp, no transcript_path)
Codex --tool codex or turn_id in the payload
omp --tool omp (only the omp extension sets it)
Claude Code otherwise

If the detected host has its own Comity hook config (for example a .cursor/hooks.json or .github/hooks/*.json that calls comity hook), the invocation from the Claude Code config steps aside so each event is evaluated once.