Agent safety pattern

UI Review Gate

Review agent plans and diffs in the browser with Plannotator

Plannotator does not replace the coding agent. It adds a browser checkpoint before the agent continues, so you can inspect the plan, diff, or message visually and return exact feedback.

Plans Diffs Messages

A pattern, not just a tool

UI Review Gate is the checkpoint pattern; Plannotator is the tool that implements it.

Review in the browser

Plans, diffs, files, folders, URLs, and the latest agent message all open in a visual review UI.

Feedback goes back to the agent

Approve to continue, or send annotations so the agent fixes the plan or code first.

Why a visual gate

Long plans are hard to review in a terminal

The terminal is a poor surface for reviewing a long plan: there is nowhere to mark a specific spot, and reading a dense wall of text is exhausting. A visual UI fixes both — you read it like a document and annotate exactly where the change belongs.

In the terminal

  • Long plans scroll away

    A multi-step plan or large diff scrolls past in the terminal. You hold the whole thing in your head to keep track.

  • Reviewing a wall of text is tiring

    Reading a dense wall of text with no structure is mentally draining, so real issues slip through.

  • Feedback is retyped from memory

    There is no place to mark a specific line, so you describe the change from memory and hope the agent maps it back.

In Plannotator

  • Annotate right where the fix belongs

    Comment inline, on the exact line or block that needs the change. The note stays anchored to that spot.

  • Long plans become scannable

    The plan or diff opens as a structured, navigable document, so a long review is far easier on the brain.

  • Precise feedback, straight to the agent

    Each annotation carries its location and context, so the agent gets exact feedback instead of a vague summary.

What the gate covers

One pattern, several review surfaces

The same loop applies whether the artifact is a plan, a code diff, a rendered HTML page, a docs folder, or the agent response you just received.

The agent is paused the whole time the review is open. Nothing proceeds until you approve, so the gate is blocking by design — not a notification you can miss.

Plan review gate

Claude Code uses an ExitPlanMode PermissionRequest hook. Codex uses a Stop hook that reads the latest plan from the rollout transcript.

Code and diff review

The review command opens a diff review UI for current changes or a PR/MR URL, then returns feedback to the agent session.

Annotate artifacts

The annotate command covers Markdown, HTML, URLs, and folders; the last command targets the latest assistant message.

Remote-friendly port

Remote mode and a fixed port make the server reachable through forwarded ports, devcontainers, or tunnels.

Revisions and sessions

Plan re-submissions can show diffs. Sessions can be listed, reopened by number, or cleaned when stale.

Share links when appropriate

Small reviews can be shared through URL hash data. Large short links are opt-in and encrypted; sharing can be disabled for sensitive work.

Hook lifecycle

Where Plannotator enters the agent loop

The gate is not just a UI command. Each host wires it into a specific lifecycle point, then Plannotator turns approve/feedback into the native hook response for that host.

Default install favors plan review. File and response review hooks are opt-in recipes.
1

Claude Code

Before Claude leaves plan mode

PermissionRequest -> ExitPlanMode
Role
Blocks the plan handoff, reads tool_input.plan from stdin, opens the browser review gate, then lets Claude continue only after approval.
Enable
Install the Plannotator plugin from the Claude marketplace, or add a PermissionRequest hook matching ExitPlanMode in ~/.claude/settings.json.
Disable
Disable or uninstall the plugin, or remove that PermissionRequest hook entry. Restart Claude Code after changing hooks.
2

Codex

After a Codex turn stops with a plan

Stop
Role
Reads transcript_path, extracts the latest plan or <proposed_plan>, opens review, and returns continuation feedback when annotations are sent.
Enable
Installer auto-enables on macOS/Linux/WSL when ~/.codex exists. Manual setup uses [features] hooks = true plus a Stop hook in hooks.json.
Disable
Remove the Stop hook entry, or turn hooks off for that Codex config layer when you want all Codex hooks disabled there.
3

OpenCode

When the plan agent submits a plan

plan-agent submit_plan
Role
The npm plugin exposes submit_plan to the plan agent by default, so planning can be gated without giving build agents the same tool.
Enable
Add @plannotator/opencode to opencode.json and restart OpenCode. Run the installer too if you want the /plannotator-* commands.
Disable
Remove the plugin or switch workflow to manual for commands-only mode. Use all-agents only when broad tool access is intentional.

Opt-in hook recipes

PostToolUse -> Write

Review every file the agent writes. Useful for sensitive docs, generated HTML, or files where visual copy review matters.

Stop -> annotate-last

Review the agent response at turn end. Approve closes cleanly; annotations send feedback back into the agent loop.

--hook / --gate / --json

--hook makes the command gate and emit hook-native JSON. --gate adds the approval button. --json is for wrappers and logs.

Runtime switches

  • Use PLANNOTATOR_REMOTE=1 when the browser is on another device, VM, devcontainer, or Tailscale URL.
  • Pin PLANNOTATOR_PORT when mobile testing needs a stable QR/link.
  • Set PLANNOTATOR_BROWSER or BROWSER when the hook should open a specific browser.
  • Set PLANNOTATOR_SHARE=disabled when the gate must stay local-only.
  • Re-run the installer or remove hook config when switching between automatic gates and commands-only workflow.

Install and setup

Set it up in three steps

One installer covers every agent. Run it, finish the one step your agent needs, then try a command. No deep config required.

  1. 1

    Run the installer

    It adds the plannotator binary, auto-detects your installed agents, and wires up their hooks, skills, and slash commands.

    macOS / Linux / WSL

    Run this in your terminal.

    macOS / Linux / WSL
    curl -fsSL https://plannotator.ai/install.sh | bash

    Windows PowerShell

    Run this in PowerShell.

    Windows PowerShell
    irm https://plannotator.ai/install.ps1 | iex
  2. 2

    Set up your agent

    Find your agent below and do its one step. Agents marked auto need nothing after the installer.

    Claude Code

    Add the marketplace plugin, then install plannotator@plannotator, and restart.

    Codex auto

    Nothing. Auto via the experimental Stop hook (macOS/Linux/WSL; off on Windows). $plannotator-* skills included.

    Gemini CLI auto

    Nothing — hook, policy, and slash commands are auto-configured. Requires Gemini CLI 0.36.0+.

    OpenCode

    Add @plannotator/opencode@latest to the plugin list in opencode.json, then restart.

    Copilot CLI

    Add the marketplace, install plannotator-copilot@plannotator. Plan review runs in plan mode (Shift+Tab).

    Amp

    Copy plannotator.ts into ~/.config/amp/plugins/ and reload. Workflows live in the command palette.

    Droid

    Add the marketplace, then install plannotator@plannotator. Commands only, no plan interception yet.

    Kiro CLI auto

    Nothing — skills and an example agent install automatically. Try kiro-cli chat --agent plannotator.

    Pi

    Skip the installer: pi install npm:@plannotator/pi-extension. Start with --plan or toggle /plannotator.

    Claude Code: manual hook (without the plugin system)

    Use this fallback only when the Claude Code plugin path is unavailable. Merge the block into ~/.claude/settings.json, keep your existing settings, then restart Claude Code. To test it, enter the built-in plan mode and leave plan mode; Plannotator should open automatically.

    ~/.claude/settings.json
    {
      "hooks": {
        "PermissionRequest": [
          {
            "matcher": "ExitPlanMode",
            "hooks": [
              { "type": "command", "command": "plannotator", "timeout": 345600 }
            ]
          }
        ]
      }
    }
  3. 3

    Try it

    Invoke one command yourself when needed. Automatic plan review does not apply to every plan; it only runs in flows where a Plannotator hook is already enabled. For example, in the built-in plan mode, leaving plan mode triggers the review automatically. CK plan files should be opened manually for review.

    Last assistant reply

    Open the latest assistant message for comments.

    try it
    /plannotator-last

    Current diff

    Review your working tree like a small PR.

    try it
    /plannotator-review

    CK plan file

    Open a ClaudeKit plan file manually when it was saved to disk.

    try it
    /plannotator-annotate plans/<plan>/plan.md

    Any artifact

    Annotate Markdown, HTML, a folder, or a URL.

    try it
    /plannotator-annotate report.html

Mobile approval

Remote control and Plannotator UI are separate channels

Codex or Claude Code mobile can approve agent actions through their own remote-control path. Plannotator approval happens in a browser pointed at the Plannotator server, so the phone must be able to reach that server.

1

Start the review on desktop

Plannotator runs beside the agent and exposes a browser UI.

2

Open the reachable URL on phone

Use LAN IP on the same Wi-Fi, or a tunnel when networks differ.

3

Approve or comment from mobile

The decision goes back to the desktop agent session.

Host setup

Expose the Plannotator server from the agent host

Set PLANNOTATOR_REMOTE and PLANNOTATOR_PORT where your host agent reads environment variables.

Claude Code

~/.claude/settings.json

Use user settings for every project, or .claude/settings.local.json for one repo only.

json · Claude Code env
{
  "env": {
    "PLANNOTATOR_REMOTE": "1",
    "PLANNOTATOR_PORT": "9999"
  }
}

Codex

~/.codex/config.toml

Use user config for every project, or .codex/config.toml inside a trusted repo. Merge into the existing table if it already exists.

toml · Codex command env
[shell_environment_policy]
inherit = "core"
set = { PLANNOTATOR_REMOTE = "1", PLANNOTATOR_PORT = "9999" }

After editing provider config, restart the host agent session so new Plannotator commands inherit the variables.

Verify it works

The phone should show the Plannotator review UI. Approve or add comments there; the decision is sent back to the desktop agent session.

Phone route

Open a reachable URL from the phone browser

Choose the shortest route first. Same Wi-Fi is simplest; Tailscale, VPN, or a tunnel is for different networks.

Same Wi-Fi

Open the host LAN URL. 127.0.0.1 points to the phone itself.

Different network

Use Tailscale, VPN, or a tunnel. The link lives only while that session runs.

Same Wi-Fi

Use the host LAN address

Find the host LAN IP first, then open the Plannotator URL from the phone browser.

1

Find the host IP

Run one command that matches the host OS.

macOS
ipconfig getifaddr en0
Linux / WSL
hostname -I | awk '{print $1}'
Windows PowerShell
ipconfig | findstr IPv4
2

Open on phone

Replace the placeholder with the IP from step 1.

phone browser URL
http://<host-lan-ip>:9999

Different network

Expose the port through a private route

Use this when the phone is not on the same Wi-Fi as the agent host.

1

Publish the local port

Use a private route from the host machine.

Tailscale
tailscale ip -4
tailscale serve --bg --tcp=10000 9999
2

Open on phone

Use the route IP while the tunnel is active.

phone browser URL
http://<tailscale-ip>:10000/

Troubleshooting checklist

  • Port not listening: start a fresh Plannotator session and check the printed URL/port.
  • Phone cannot connect: confirm same Wi-Fi, firewall rules, or that Tailscale/VPN is connected on both devices.
  • MagicDNS fails: use the raw Tailscale IP first, then fix DNS later.
  • HTTP vs HTTPS: local Plannotator URLs are usually HTTP unless your tunnel adds TLS.
  • Stale sessions: run plannotator sessions --clean, then open a new review.

ClaudeKit fit

Yes — run it beside ClaudeKit

They do different jobs, so they pair cleanly. ClaudeKit drives the work — plan, cook, review, test. Plannotator is the human review gate: the browser surface where you inspect what CK produced and send precise feedback. Auto-blocking only happens when the host lifecycle hook fires.

Rule of thumb: Claude Code ExitPlanMode, Codex Stop, OpenCode submit_plan, and Pi plan mode can auto-open Plannotator. A normal ClaudeKit /ck:plan run is a plan-producing command, so treat Plannotator as an explicit review step.

How to use them together

  1. 1

    Plan with ClaudeKit, then gate the artifact

    /ck:plan → /plannotator-annotate plans/.../plan.md

    /ck:plan creates a CK plan artifact; it is not automatically the same as host plan mode. Open the generated plan.md file in Plannotator when you want a browser review gate.

  2. 2

    Implement, then review the diff

    /ck:cook → /plannotator-review

    Let /ck:cook handle the approved plan. Before you commit, open the diff with /plannotator-review and comment inline on the exact lines.

  3. 3

    Review docs and artifacts

    /plannotator-annotate ./docs

    Annotate Markdown, HTML, or folders such as ./docs with the same review surface, no extra setup.

Review the CK plan artifact

After `/ck:plan` writes a plan file, open that exact `plan.md` with Plannotator. When you send feedback in the browser, annotations return to the current agent session and the agent should revise the plan before implementation starts. Ask again only if the review happened outside this session.

claude code · plan gate
# 1) Ask ClaudeKit to produce the plan artifact
/ck:plan "Build the feature and save a phased implementation plan"

# 2) Use the real path printed by /ck:plan
/plannotator-annotate plans/<plan-slug>/plan.md

# 3) In the browser, comment on:
# - requirements, scope, assumptions, risks
# - phase order and acceptance criteria per phase
# - missing tests, rollback, docs impact
# - unresolved questions before implementation

# 4) Send feedback / finish the browser review
# The annotations return to this agent session.
# The agent should revise the plan from those notes before implementation.

Use the same gate for later flows

The same pattern works after cook, test, code review, or docs generation. Open the diff or artifact that needs human judgement, annotate it, then send the feedback back to the agent.

claude code · downstream gates
# After the approved plan, let ClaudeKit implement
/ck:cook

# Review the actual working-tree diff before commit
/plannotator-review

# Review other artifacts CK or the agent produced
/plannotator-annotate reports/<run>/test-report.md
/plannotator-annotate reports/<run>/review.md
/plannotator-annotate ./docs

Keep them as separate tools. Use Plannotator beside ClaudeKit, not merged into it — that keeps CK free of a UI server and browser state, and lets each update on its own schedule.

When not to use it

Use a gate only when the pause is worth it

  • Do not use a browser gate for tiny, reversible edits where the diff is easier to read inline.
  • Do not share sensitive plans unless sharing is disabled or your team accepts the URL/short-link privacy model.
  • Do not treat approval as a test result. Still run tests, builds, and source checks after the agent changes code.