Skip to main content
Use --hook when a host hook must block on submitted annotations. In this mode, both Approve and Close let the hook pass. Use direct --gate --json --require-approval when success requires explicit approval. Use --json when your wrapper must distinguish approved, dismissed, and annotated decisions.
--hook implies --gate, so the review UI includes an Approve action.
In hook-native mode, both Approve and Close produce empty output, so either action lets the host hook pass. Use direct --gate --json --require-approval when Close must be a failed gate rather than a pass.

Output contracts

The contracts apply to annotate and annotate-last.

Hook-native output

This contract works directly with Claude Code and Codex PostToolUse or Stop command-hook protocols that treat a block decision as feedback for the agent. If --hook and --json are both present, the hook-native contract wins.

Structured JSON

--json does not add the Approve action by itself. Add --gate if approval is part of your wrapper’s contract.

Require explicit approval

Use the strict options when an automation should succeed only after approval:
Strict options apply only to direct annotate --gate --json runs. They reject annotate-last, --hook, and calls without both --gate and --json. Without --require-approval, completed user decisions keep the existing exit status of 0. --result-file writes the same newline-terminated JSON bytes as stdout. The path is resolved from the current working directory. Its parent must exist, and the destination must not exist, including as a dangling symlink. Plannotator writes stdout first, then atomically publishes an owner-readable and owner-writable file without overwriting an existing path. Publication is atomic but not guaranteed to survive a system crash before the parent directory is flushed.

Plain text

Without --json or --hook, submitted annotations are printed as feedback. Approval prints the exact line The user approved. and closing prints nothing. Outside strict approval mode, completed user decisions exit with status 0. Invalid input and startup failures can exit nonzero. Wrappers must inspect both the process status and standard output.

Pass input safely

The path to review must come from the hook event or from a trusted wrapper argument. Quote it as one shell argument:
Hook event schemas differ by agent and version. Do not copy an input-field name from another host. Use the host’s current hook documentation to extract the file path, then call the CLI contract above. For a host that sends content rather than a file path, pipe it to annotate-last --stdin:
Avoid expanding untrusted hook content as shell code. Pass values as quoted arguments or standard input.

Installed plan hooks

The full installer and agent plugins configure plan review for supported hosts. For example, the Claude Code plugin ships:
  • a PreToolUse hook on EnterPlanMode that calls plannotator improve-context
  • a PermissionRequest hook on ExitPlanMode that calls plannotator and waits for the review decision
Codex uses its experimental Stop hook on macOS, Linux, and WSL. Copilot CLI uses its plugin’s pre-tool hook for exit_plan_mode. Those plan hooks use host-specific event schemas and should normally be managed by the installer or plugin. Restart the agent after changing hook configuration. Desktop applications may not inherit your shell PATH; use the absolute path to the Plannotator binary if a hook reports that the command is missing.

Timeouts

A review is intentionally long-running. The shipped plan hooks use a timeout of 345600 seconds. If you write a custom hook, choose a timeout that allows a person to review without leaving an orphaned process. Last verified on July 31, 2026, using Plannotator product commit 7cd023c. Maintained by the Plannotator project.
Last modified on August 9, 2026