Chock.sh Build your plugin

How Chock works

Where policies run

Where a compiled policy runs: each hook point as chock's docs describe it, the engine emitter that writes it, and the agents that have it.

A hook point is where a compiled control runs. Chock's docs and code call it a surface. The first table is chock's own, from its docs. The site reads the second from the engine's compiler at the pinned commit, so it changes when the code does.

The hook points

Chock's own table of the hook points, from its docs at the pinned commit:

From the engine docs: docs/enforcement-surfaces.md

SurfaceDeterminismBypassable?What it is
git-hookHard, at commit/pushYes (--no-verify)Pre-commit / pre-merge-commit / pre-push guard
ci-gateHard, un-bypassableNo, once marked a required status check -- see the branch-protection gap: the workflow file itself is tracked content a PR can delete, so ci-gate's un-bypassable claim rests on a server-side branch-protection setting nothing in this repository can editThe backstop for a skipped git hook
ambient-ruleAdvisoryYesCompiled AGENTS.md block the agent is asked to follow
pre-tool-useHard, pre-executionNoBlocks a command before the agent runs it, in each client's own deny dialect — every matrix-blocking vendor with a repo-level config (see the Cursor caveat)
stopHard, post-executionNo, but it fires after the tool calls it judgesReads what the turn left in the worktree and refuses to end the turn. Credited with no coverage word -- see the backstop note below
agent-hooksHard, pre-executionNoThe same exit-2 deny for Copilot CLI + VS Code agent mode, from .github/hooks/chock.json (witnessed blocking on both, 2026-08-23). A content gate also gets a PreToolUse entry over Edit|Write there (a top-level permissionDecision deny stopped an Edit in VS Code agent mode, 2026-09-28), and its turn-end gate is a Stop entry in the same file
managed-settingHard, org-levelNoAdmin-deployed allow/ask/deny rules
gatewayHard, un-circumventableNoBudget/egress backstop — modeled now, emitted later
mcp-gatewayHard, MCP-routed tools onlyYes (P3c)A stdio proxy the client launches instead of the real MCP server; refuses matching tools/call payloads. Emitted today; credits no agent until the per-client config witness ships

Where each hook point comes from in the engine

The site reads this table from the engine at the pinned commit. For each hook point it shows the compiler's emitter (EMITTERS in chock.compile.compiler), the agents the engine gives it, by the engine's agent names (SURFACE_AGENTS), and whether it is left out of every coverage word (UNCREDITED_SURFACES). The build fails when the hook points in chock's table and in its code differ.

Hook pointEmitterAgentsHeld out of coverage
ambient-rulesrc/chock/compile/emitters/ambient.pyaider, antigravity, claude, cline, codex, copilot, cursor, devin, factory-droid, gemini, goose, grok, junie, kimi-code, mistral-vibe, openhands, replit, tabnine, vscode, windsurfno
git-hooksrc/chock/compile/emitters/git_hook.pyaider, antigravity, claude, cline, codex, copilot, cursor, devin, factory-droid, gemini, goose, grok, junie, kimi-code, mistral-vibe, openhands, replit, tabnine, vscode, windsurfno
ci-gatesrc/chock/compile/emitters/ci.pyaider, antigravity, claude, cline, codex, copilot, cursor, devin, factory-droid, gemini, goose, grok, junie, kimi-code, mistral-vibe, openhands, replit, tabnine, vscode, windsurfno
pre-tool-usesrc/chock/compile/emitters/in_agent.pyantigravity, claude, codex, cursor, devin, factory-droid, gemini, goose, grok, mistral-vibe, openhands, tabnine, windsurfno
stopsrc/chock/compile/emitters/in_agent.pyantigravity, claude, codex, copilot, cursor, devin, factory-droid, gemini, goose, mistral-vibe, openhands, tabnine, vscodeyes
managed-settingsrc/chock/compile/emitters/claude_managed.pyclaudeno
gatewayNone: not emittednoneno
mcp-gatewaysrc/chock/compile/emitters/mcp_gateway.pynoneno
agent-hookssrc/chock/compile/emitters/in_agent.pycopilot, vscodeno

From the engine docs: docs/enforcement-surfaces.md

How a policy picks its surfaces

A hook that must stop a command targets git-hook + ci-gate (the universal floor) and, where available, pre-tool-use + managed-setting. A hook whose on: includes tool_use is compiled to the pre-tool-use surface on agents that support it (thirteen of them, Claude Code and Cursor among them; Copilot CLI and VS Code get the same guard via agent-hooks, and a content gate's write check as a PreToolUse entry over Edit|Write there). A hook whose on: includes tool_call (a content_regex or script gate with params.tools, globs over tool names such as mcp__Firecrawl__* or WebFetch) gates PreToolUse for any tool by name, on the nine agents whose vendor facts record a tool vocabulary (Claude Code, Codex CLI, Cursor, Gemini CLI, Factory Droid, goose, Mistral Vibe, OpenHands, and Copilot via agent-hooks); the others get no tool_call entry and are credited nothing for it. A gate's outside_repo globs let its PreToolUse write check see declared files outside the repository (the turn-end check cannot). A script gate on tool_call also keeps a local per-session tool-call log under .chock/state/ that its script can read; see spec/session-log.md. A best-practice rule with no deterministic check compiles only to ambient-rule. The compiler always pairs a control with the strongest available backstop — e.g. a git hook plus a CI gate, because a git hook alone can be skipped with --no-verify.

Gate runner semantics

At commit time the vendored runner scans the staged files git reports as added, copied, modified, renamed, or type-changed. It disables core.quotePath for its diff calls, so non-ASCII paths arrive unescaped and are scanned like any other file. dependency_allowlist gates match their watched manifest basenames (e.g. package.json) anywhere in the tree, not only at the repo root. In CI range mode, a base ref that cannot be resolved fails closed — the gate exits 2 rather than passing an unscanned range. A compiled gate never judges chock's generated tree (.chock/) or its own policy's folder (.agents/policies/<id>/): that folder's evals and references show the very content the gate refuses, so judging them refused the policy's own adoption commit. Every other path, another policy's folder included, is judged as before.

Built from engine 5a4b6287a46e and catalog 1e60d211c1bb.