Coding Agent Guards
picket agent guard inspects proposed Codex and Claude prompt or tool input
before the host submits it. The command reads one JSON hook envelope from
standard input and performs local Picket-native detection and structural
validation.
Supported Events
Section titled “Supported Events”The guard accepts these hook events:
| Event | Scanned content |
|---|---|
UserPromptSubmit |
The root prompt string |
PreToolUse |
Every string value below the root tool_input value |
Each tool_input string is scanned independently. Property names and envelope
metadata such as session_id, transcript_path, cwd, model, and turn_id
are not scanned. Unknown envelope properties are accepted so provider metadata
can evolve without changing the guard contract.
The root value must be an object with one hook_event_name property and one
payload property for the selected event. Duplicate required properties,
unsupported events, missing payloads, invalid JSON, and payload type errors
fail closed.
Limits
Section titled “Limits”The default input limit is 1 decimal MB, or 1,000,000 bytes. Set
--max-input-megabytes <n> to a value from 1 through 64 when a workflow needs
to inspect a larger tool request. JSON nesting is limited to 64 levels, and a
single envelope can contain at most 4,096 scanned string values.
Picket enforces the byte limit while reading standard input. It does not buffer an unbounded request before checking the limit.
Exit Contract
Section titled “Exit Contract”| Exit code | Meaning |
|---|---|
0 |
The supported payload was fully inspected and no finding was detected. |
2 |
A finding was detected or Picket could not safely complete inspection. The host must block the operation. |
Clean input produces no standard output or standard error. Standard output is always empty for blocked input. Standard error contains a fixed reason and, for findings, a bounded list of sanitized rule IDs. Prompt text, tool input, matches, source lines, and secret values are never printed.
The guard creates no live validator or remote source client. It performs local rule matching, decoding, predicates, randomness scoring, and offline structural validation.
Rule Selection
Section titled “Rule Selection”The command uses Picket’s native config precedence. --config <path> selects a
custom config and therefore replaces the embedded native default config.
--rule-pack picket-strict and --rule-pack picket-experimental layer those
optional built-in packs over the resolved config. Repeat --rule-pack to enable
both.
Configuration failures return exit 2 with a fixed secret-free reason.
Add both hooks to .codex/hooks.json:
{ "hooks": { "PreToolUse": [ { "hooks": [ { "type": "command", "command": "picket agent guard", "statusMessage": "Scanning tool input" } ] } ], "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "picket agent guard", "statusMessage": "Scanning prompt" } ] } ] }}Codex requires project-local hook definitions to be reviewed before they run.
Use /hooks to inspect and trust the exact command.
Claude Code
Section titled “Claude Code”On Windows, add both hooks to .claude/settings.json and select PowerShell for
each command hook:
{ "hooks": { "PreToolUse": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "picket agent guard; exit $LASTEXITCODE", "shell": "powershell" } ] } ], "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "picket agent guard; exit $LASTEXITCODE", "shell": "powershell" } ] } ] }}Claude Code uses Git Bash for command hooks on Windows when Git Bash is
available. A Windows global .NET tool installation exposes picket.cmd, which
Git Bash does not resolve from the bare picket command. Selecting PowerShell
lets the hook resolve the installed tool and preserves standard input. The
explicit exit $LASTEXITCODE preserves Picket’s exit 2; without it,
PowerShell returns exit 1, which Claude Code treats as a non-blocking error.
On macOS and Linux, omit the shell property so Claude Code uses its default
shell:
{ "hooks": { "PreToolUse": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "picket agent guard" } ] } ], "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "picket agent guard" } ] } ] }}Both configurations rely on the providers’ exit-code contract: exit 0
continues, while exit 2 blocks and displays the fixed standard-error reason.