Skip to main content
Working with an agent? Give them a link to this page as markdown.

Required updates for Watcher

Gateway hooks accept the native OpenAI Responses local_shell_call_output.id field. A result with different IDs in id and call_id is rejected.

The Watcher client ignores local tool thresholds below 0 or above 11 and reports a settings error. It uses the next valid value from your settings or the defaults. This can change which calls it flags or denies.

The Watcher client no longer builds or serves its local web app. Opening http://localhost:8228 starts sign-in when the machine is signed out. Otherwise it links to your Analyzer and lists where each of the old app's features moved. The old app's other pages return 404.

Watcher now sends every escalated Claude Code tool call to Claude Code's own permission prompt, and the developer answers it there. Unattended runs and the built-in profiles change too, so check how your agents run before you update.

What's new?​

  • Local-shell results accept the native id or the legacy call_id field.
  • Two different IDs in the same result cause a parsing error.
  • Local flag_threshold and deny_threshold values must be integers from 0 through 11. A value of 0 always triggers that action; 11 disables it.
  • watcher settings show and watcher doctor settings report values outside that range. Organization settings and API overrides keep their existing behavior.
  • Sessions and their tool-call decisions are reviewed in the Analyzer. watcher whoami prints the Analyzer link for the session it runs in. See the command reference.
  • Escalated tool calls are answered in the coding agent's own permission prompt. See Blocking review.
  • Sign in from the macOS menu bar, at http://localhost:8228, or with watcher login. Sign out at http://localhost:8228 or with watcher logout.
  • watcher settings show prints the settings the client applies. watcher doctor settings reports settings problems, and watcher doctor decisions reports decisions that have not reached the Analyzer.
  • Developers edit their own settings in the per-machine settings files, such as ~/.apollo_monitor/settings.local.yaml, or switch settings profiles with watcher profile set, /watcher in Claude Code or $watcher in Codex. Managed client settings work as before.
  • Resetting command rules is a command: watcher settings reset rules removes your command-rule changes, backing each file up first. watcher doctor settings reports settings mistakes that turn off approvals from command rules, and watcher doctor settings --fix repairs the ones it can. See Changing your own settings.
  • watcher rules test replaces the command-rule tester. watcher decisions list lists the tool-call decisions recorded on the machine, including ones that never reach the Analyzer.
  • These features of the old app are gone: the session list and its live status, session groups and names, terminal focus, parking, browser notifications and keyboard shortcuts. To snooze, use the macOS menu bar. Linux has no snooze control. A snooze that is already running still ends on schedule.
  • The agent hooks no longer store the session list's prompt, reply and tool previews, or terminal identifiers such as the tty, in the client's local database. The updated client blanks the values earlier versions stored when it opens that database. Older text that earlier versions overwrote can stay in the file's unused space until SQLite reuses it. The database is ~/.apollo_monitor/db/watcher.db by default, or wherever WATCHER_DB_DIR or APOLLO_MONITOR_HOME puts it.
  • The web app's session, decision, settings, command-rule, grader and browser sign-in endpoints are gone from the client's local port. It still answers health, version and snooze requests, the agent hooks' grading requests, the sign-in and sign-out pages, and the read-only threshold request that an older server's red-team drill makes. Scripts that called the removed endpoints can use watcher doctor, watcher settings show, watcher profile, watcher rules test, watcher decisions list or the Analyzer instead. The client also refuses browser requests other than GET and HEAD, except the Sign out button on its own page.
  • A Claude Code escalation is answered in Claude Code's permission prompt. Codex escalations go to Codex's own approval prompt, as before.
  • In a claude -p run, which cannot show a prompt, Watcher denies an escalated call at once and records it as Watcher's deny. That includes a run that answers prompts through --permission-prompt-tool. The reason suggests the Auto profile (watcher profile set auto). There is no suggestion when the call would escalate under Auto too, as with a tripped denial limit or a command rule that sends calls to a person. When grading failed, as with an expired sign-in, the reason suggests watcher doctor auth and watcher login instead.
  • An answer in the permission prompt counts as a human decision. It resets the denial limits, and the monitors see it as context for the session's next calls. Claude Code's automatic refusals do neither.
  • Escalations from Claude Code subagents, including background ones, appear in the main session's permission prompt too. Once such a call runs, Watcher records the approval as the developer's decision on the developer's machine. The Analyzer does not show it. Watcher does not record a refusal, because subagent calls are not in the session's transcript.
  • Watcher's reason in the permission prompt links to the session in the Analyzer once the session has uploaded.
  • The Default, Human in the Loop and Skip Permissions profiles no longer escalate AskUserQuestion and ExitPlanMode. The agent still asks in its own dialog. The server uses these defaults for gateway hooks too. So it allows the tools mapped to these names instead of escalating them: Codex request_user_input, OpenCode question and plan_exit, Gemini CLI ask_user and exit_plan_mode, and the Qwen Code and Mistral Vibe equivalents. LiteLLM in enforce mode stops withholding them. The Analyzer dashboard now counts these calls among the ones Watcher approved without asking anyone.

Required upgrade steps​

Local-shell result identities

For self-hosted deployments and Watcher Cloud, custom integrations that send both fields must use the same ID for both: the preceding local_shell_call.call_id. Keep the legacy call_id field while updating the server, so the request also works with servers that require it.

Resend a representative hook request containing the corrected call and result. Verify that it no longer returns a parsing error. Follow the server update procedure for self-hosted deployments.

Keep local tool thresholds within the supported range

These steps apply to developers on both self-hosted deployments and Watcher Cloud who have local thresholds outside the supported range.

  1. Before upgrading the client, check your per-machine settings. Check settings.local.yaml, including its inline profiles entries, and each settings.PROFILE.local.yaml file. These files live under ~/.apollo_monitor/ by default.
  2. In each local tool_thresholds entry, replace negative flag_threshold or deny_threshold integers with 0. Replace integers above 11 with 11. This preserves the meaning of those values. Keep values already within the range, and leave organization settings unchanged.
  3. Follow Update Watcher for the rollout.
  4. Run watcher settings show and watcher doctor settings after upgrading. Confirm that no threshold range errors remain and that the effective values match your intended policy. Check each profile you changed with watcher profile set PROFILE, then restore the profile you normally use.

Local web app removed from the Watcher client

These steps apply to self-hosted deployments and Watcher Cloud.

  1. Tell your developers where things moved: sessions to the Analyzer, escalations to the agent's own prompt, and sign-in to the menu bar, http://localhost:8228 or watcher login.
  2. Remove any container relay of the client's port, such as a WATCHER_PUBLISH_UI setting and its socat relay. Keep editor port forwarding in dev containers, because browser sign-in uses it. See The client's local port. A container that signed in through the relay needs another option from Authenticating the container the next time it signs in, such as watcher login inside it.
  3. Roll the new client out with Update Watcher. On self-hosted deployments, update the server before the clients, as that page advises. An older server's red-team drill reads its results from the client's local web app, so on an updated client it finds no decisions and reports no results. No hook reinstall or new sign-in is needed.

To verify a machine, open http://localhost:8228 there while it is signed in. It shows a link to your Analyzer and a list of where the old app's features moved.

Escalations are answered in the coding agent

These steps apply to self-hosted deployments and Watcher Cloud.

  1. Run unattended Claude Code agents with the Auto profile, or run them interactively. watcher profile set auto selects it on each machine or container. The selection lives in the machine's local settings, so a managed-settings update keeps it, unless your organization locks a profile for every machine. See Review posture without a human.

  2. Stop relying on WATCHER_PUBLISH_UI to approve calls from a container. The relayed UI no longer approves calls.

  3. To keep the Default and Human in the Loop profiles escalating the interaction tools, add this to your managed settings now, before the server updates. A flag_threshold of 0 sends every call to the tool to a person without grading. The Auto and Skip Permissions profiles keep allowing these tools, because their own entries take precedence.

    tool_thresholds:
    AskUserQuestion:
    flag_threshold: 0
    deny_threshold: 11
    ExitPlanMode:
    flag_threshold: 0
    deny_threshold: 11
  4. Self-hosted deployments follow Update Watcher. On Watcher Cloud, the server changes apply when the hosted server updates.

  5. On an updated client, trigger one escalation interactively and one in a claude -p run, for example with a command rule whose decision is human. The interactive prompt shows Watcher's reason, and the claude -p run reports Watcher denied this call.