New to Claude Skills? Learn how to install them →

What Claude Code's Monitor Tool Does

Monitor lets Claude Code watch a log, a CI job, a directory or a WebSocket feed in the background and react the moment something changes, instead of you re-prompting on a timer.

August 19, 2026
Get Claude Skills
9 min read

Watching without waiting

Most of what Claude Code does happens inside a single turn: you ask, it works, it answers. Monitor is built for the cases that don't fit that shape, where the thing you care about hasn't happened yet, or happens on its own schedule outside your control. A deploy that takes ten minutes to finish. A CI job that might pass or might not. A log file that stays quiet for hours and then floods with errors. Monitor lets Claude watch for that kind of event in the background and interject the moment it fires, rather than you either sitting and waiting or having to re-ask on a timer.

The tool is documented in Claude Code's own tools reference, and its job description is short: watch something in the background, react when it changes, without pausing the conversation. Concretely, that covers:

  • Tailing a log file and flagging errors as they appear
  • Polling a pull request or CI job and reporting when its status changes
  • Watching a directory for file changes
  • Tracking output from any long-running script you point it at
  • Connecting to a WebSocket feed and reporting each message as it arrives

For most of those, Claude writes a small script itself, runs it in the background, and receives each output line as it's produced. For a source that already pushes events on its own, a server with a live feed rather than a file you have to poll, Claude can open a WebSocket connection directly instead of writing a polling loop around it.

What it feels like in a session

You keep working in the same session while a monitor runs. Claude interjects when an event arrives, rather than the conversation staying silent until you check back in. Stopping a monitor is conversational too: ask Claude to cancel it, or simply end the session, and the watch stops with it.

Permissions follow the tool it's built on. When Monitor runs a command, it's governed by the same permission rules as Bash, so any allow or deny patterns you've already set for Bash apply to what Monitor is allowed to run too. The WebSocket path has its own separate approval prompt, which auto mode's classifier decides on your behalf when auto mode is active.

The WebSocket source, in detail

Opening a WebSocket instead of polling makes sense whenever the thing you're watching already streams events on its own, rather than exposing state you'd otherwise have to poll for. This path has been available since Claude Code v2.1.195, and it behaves distinctly from the command-based path in a few specific ways:

Socket activityWhat Claude receives
Text messageOne event per message, even if it spans multiple lines
Binary messageNot passed through; a placeholder line such as [binary frame, 512 bytes]
Message over 1 MiBThe watch ends; subscribe to a filtered feed instead if this happens
Socket closeThe watch ends; Claude receives the close code

A WebSocket watch takes a ws input in place of command, and a single Monitor call can't combine the two. The ws input itself has two fields:

url        required   ws:// or wss:// endpoint, ASCII only, no embedded credentials or whitespace
protocols  optional    WebSocket subprotocol names offered during the handshake, no duplicates

The timeout_ms and persistent inputs behave identically whether you're watching a command or a socket: the watch ends at the deadline unless persistent is set, and the TaskStop tool cancels it early either way.

Opening a WebSocket triggers its own approval prompt, decided by the classifier when auto mode is on, and that prompt notably doesn't offer an option to skip future prompts for the same host, unlike some other tool approvals. Claude Code also refuses to connect to a URL pointing at a private, link-local, or cloud-metadata address, including any hostname that resolves to one, and refuses any host listed in sandbox.network.deniedDomains. When an organisation sets allowManagedDomainsOnly in managed settings, that refusal extends to any host outside the managed allowlist entirely.

Monitor vs a self-paced /loop

Both Monitor and /loop let Claude act on something without you re-prompting, but they solve it differently. /loop re-runs a prompt on an interval, either fixed (/loop 5m check the deploy) or chosen dynamically by Claude each iteration when you omit the interval. Each iteration is a fresh check: Claude looks, decides what to do, and waits again.

Monitor doesn't wait on an interval at all. It watches continuously and only interjects when an actual event fires. Anthropic's own documentation draws the connection explicitly for self-paced loops: when you ask for a dynamic /loop schedule, Claude may use the Monitor tool directly, since running a background script that streams output back avoids polling altogether and is often more token-efficient and more responsive than re-running a prompt on a timer.

That makes the two complementary rather than competing. A dynamically scheduled /loop is the outer structure, deciding when to check back in and for how long the whole task should keep running; Monitor is one of the mechanisms Claude can reach for inside that structure when the thing being watched supports a continuous feed rather than needing to be actively polled each time.

Availability and restrictions

Monitor is not available everywhere Claude Code runs. It's unavailable on Amazon Bedrock, Google Cloud's Agent Platform, and Microsoft Foundry. It's also unavailable when you set either DISABLE_TELEMETRY or CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, since Monitor's background streaming falls under the non-essential traffic those flags turn off.

Plugins can declare monitors of their own that start automatically the moment the plugin is active, rather than requiring you to ask Claude to start one by hand each session. That's documented separately under plugin monitors in the plugins reference, which is worth checking if you're distributing a plugin to a team and want a watch to come alive without a manual step.

A worked example

Asking Claude to watch a deploy might look like this in practice:

watch the deploy log at ./logs/deploy.log and tell me the moment
it either finishes or errors out

Claude typically responds by starting a background tail of the file through Monitor, then continuing to work with you in the same session. When a matching line appears (a completion marker, an error trace, whatever the log actually produces) Claude interjects with what it saw, without you having needed to ask again or check a second terminal.

The same pattern extends to CI: pointing Monitor at a job's status endpoint, or at a webhook your CI already emits, means the moment a build goes red, Claude can pull the failing job log and start diagnosing without a separate polling prompt from you. For a way to push that kind of event into a session directly rather than having Claude poll for it, see Claude Code Channels, which takes the complementary approach: an external system pushes the event in, instead of Claude watching for it.

Command watches vs the WebSocket source

It's worth being explicit about when to reach for which, since Monitor supports both and they suit different sources. A command watch is the right default for anything that doesn't already push updates on its own: a log file that only grows when something writes to it, a directory you want watched for new files, a status endpoint you'd otherwise have to poll by re-requesting it. Claude writes a small script for these and Monitor streams each line of that script's output back as an event.

The WebSocket source is for the narrower case where the thing you're watching already maintains an open connection and pushes updates itself, a live dashboard's data feed, an internal service that emits events over wss://, a chat platform's real-time API. Reaching for a WebSocket watch there avoids writing and maintaining a polling script for something that was never designed to be polled in the first place. If you're unsure which applies, the practical test is simple: if the source already has a ws:// or wss:// endpoint documented, use that; otherwise let Claude write a script against whatever interface the source actually exposes.

Permissions in practice

Because a command-based Monitor watch runs through the same permission rules as Bash, anything you've already locked down for Bash carries over automatically. A rule like this in your settings:

{
  "permissions": {
    "allow": ["Bash(git status)", "Bash(npm run *)"],
    "ask": ["Bash(rm *)"]
  }
}

applies the same way to a script Monitor runs in the background as it would to a command Claude ran directly in the foreground. That matters because a background watch isn't a separate trust boundary from ordinary Bash use, so it's worth reviewing your existing Bash rules with background, unattended execution in mind, not just interactive use where you're watching each command as it runs.

Troubleshooting

A monitor seems to have stopped reporting. Check whether it hit its timeout_ms deadline. Watches end at their configured timeout unless persistent was set when the monitor started; ask Claude to restart the watch with persistent if you want it to keep running indefinitely.

Monitor won't start at all. Confirm you're not running on Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry, where the tool is unavailable entirely, and check whether DISABLE_TELEMETRY or CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC is set in your environment, since either one disables it.

A WebSocket watch ends unexpectedly. The most likely causes are a single message exceeding 1 MiB, which ends the watch outright, or the far end closing the socket, which also ends it and hands Claude the close code. If the feed is naturally chatty or sends large payloads, ask whether the source offers a filtered or lower-volume subscription instead of the full feed.

A WebSocket URL gets refused before the watch even starts. Claude Code blocks connections to private, link-local, or cloud-metadata addresses, including hostnames that resolve to one, and to any host your organisation has denied via sandbox.network.deniedDomains or excluded from a managed allowlist. This is a safety boundary, not a bug, so check the URL against those categories before assuming something else is wrong.

A plugin's declared monitor doesn't seem to be running. Confirm the plugin is actually active for the session, plugin monitors start when the plugin itself is active, not merely installed. If you disabled or didn't load the plugin for this session, its declared monitors won't start either.

Where to go next

For running a prompt on a timer instead of watching for a specific event, see Claude Code Routines vs /loop. For pushing external events, like a CI failure, straight into a running session rather than having Claude poll for them, see Claude Code Channels. For keeping a session working toward a verifiable end state across turns, see how Claude Code's /goal command works. Browse the current catalogue at getclaudeskills.com/platforms/claude-code.

Frequently asked questions