Chock.sh Build your plugin

How Chock works

Stop and resume

How a person stops agents in one repository or on the whole machine with chock stop, chock resume and --everywhere, what reads the stop, and its limits.

A stop is a person's brake on agents. While one is in force, chock's hooks refuse the next tool call, commit or push of an agent in scope. Only a person at a terminal lifts it.

The commands: chock stop and chock resume

Here are both commands, as the engine's parsers print them.

chock stop

Refuse every agent tool call, commit and push here until resume (--agent C for one client)

usage: chock stop [-h] [--repo REPO]
                  [--agent {antigravity,claude_code,codex_cli,cursor,devin,factory_droid,gemini_cli,goose,grok,mistral_vibe,openhands,tabnine,vscode_copilot,windsurf}]
                  [--reason REASON] [--everywhere]

Write `.chock/stop.json`: every tool call, commit and push by an agent in scope is refused until
resume.

options:
  -h, --help            show this help message and exit
  --repo REPO           Repo root (default: cwd)
  --agent {antigravity,claude_code,codex_cli,cursor,devin,factory_droid,gemini_cli,goose,grok,mistral_vibe,openhands,tabnine,vscode_copilot,windsurf}
                        Stop this one client only (default: every agent)
  --reason REASON       Why: the agent is told `stopped: <reason>`
  --everywhere          Stop every agent on this machine, in every repo

chock resume

Lift a stop: agents are judged by the policies again

usage: chock resume [-h] [--repo REPO] [--everywhere]

Remove `.chock/stop.json`: agents' tool calls, commits and pushes are judged by the policies
again.

options:
  -h, --help    show this help message and exit
  --repo REPO   Repo root (default: cwd)
  --everywhere  Lift the machine-wide stop only

In one repository

  • chock stop writes .chock/stop.json: the scope, the reason, who (git user.email) and when. Every tool call, commit and push by an agent in scope is then refused until a person resumes.
  • --agent <client> stops one client. Without it, chock stops every agent. --reason is what chock tells the agent: stopped: <reason>.
  • The file is never committed. Chock keeps a copy in ~/.chock/stops/ for hooks that cannot tell which repository their session is in. The hooks read both copies. If they cannot read a stop file, they refuse every agent.

Sources, at the pinned engine commit:

Only a person changes a stop

  • Chock refuses an agent's chock stop or chock resume, and logs the refusal.
  • chock resume needs a person at their own terminal: stdin and stdout must be a TTY, and the person types the repository's name. If the name does not match, the stop stays in force.

Sources, at the pinned engine commit:

Everywhere: one stop for the machine

  • chock stop --everywhere writes ~/.chock/stops/_everywhere.json. While it exists, every chock hook on the machine refuses every tool call, whatever its repository, session or client. --agent is refused with it: the scope is every agent.
  • chock resume --everywhere is person-only too: it needs stdin and stdout to be a TTY and asks for the word everywhere to be typed. It removes that file only. A per-repository stop stays in force.
  • chock status and chock doctor lead with STOPPED EVERYWHERE while it is in force.

Sources, at the pinned engine commit:

Where chock checks the stop

  • chock sync wires one hook of its own per client, --stop-check, with no matcher, so the stop sees every tool call, reads included. The plugin carries the same entry.
  • At the git hooks, chock refuses an agent's commit or push and lets a person's through. Only the main checkout's .chock/bin/gate.py tells an agent from a person.
  • The MCP gateway refuses each tools/call while a stop reaches it, with an MCP error, and forwards every other method, so the client can still connect and list tools.

Sources, at the pinned engine commit:

Limits

After it writes a stop, chock stop prints its limits in the engine's own words:

It refuses the NEXT action of an agent whose hooks Chock wires; it stops no running process and revokes no credential.
  • It reaches only agents whose hooks chock wires and that the client runs. An agent with no hook is stopped at commit and push only.
  • Devin's hook is best-effort. The vendor runs it so that a hook that errors or times out lets the call through.
  • A person, or an agent working outside this repository's hooks, is not affected, and such an agent can delete the stop files directly.
  • The terminal check is best-effort: an agent that can run a shell may give resume a pseudo-terminal and type the name.

Sources, at the pinned engine commit:

The engine's stop docs, in full: docs/stop.md

From the engine docs: docs/decision-log.md

Stop and override

While a stop is in force (chock stop, Stop), each call it refuses is a block line with "reason": "stopped" and the fields above (actor, session_id, target). A pre-tool refusal names the hook's policy; a commit or push refused at the git dispatcher names chock-stop. chock stop and chock resume each write one chock-stop line, event repo_stop or repo_resume, with scope, who (git user.email) and when. With --everywhere, run inside a repository, the line also carries "everywhere": true.

A person's CHOCK_ALLOW override is an allow line with "override": "CHOCK_ALLOW", the policy_id it answered, and approver: the git user.email of the shell that ran it.

approver and who name a person. They stay in this local log (created 0o600): Chock sends nothing over the network, and chock witness export leaves both out.

Built from engine 5a4b6287a46e and catalog 1e60d211c1bb.