Plugin monitor notifications are re-delivered every turn (not once per stdout line)

Resolved 💬 1 comment Opened Jun 8, 2026 by qiankunli Closed Jul 14, 2026

Summary

A plugin monitor (declared in monitors/monitors.json) is documented to deliver
each stdout line from its command to the session as a notification. In practice, a
single stdout line is re-surfaced as a new Monitor event: notification on roughly
every turn
for the lifetime of the session, regardless of whether the command produces
any further output.

The result: a monitor whose command emits at most one line every minute or two still
floods the transcript with many identical Monitor event: lines — because the
multiplication happens in the harness (re-delivery), not in the command's output.

There appears to be no setting/flag/env var to make a monitor's notification deliver
once per stdout line instead of being re-injected each turn, and no way to silence the
re-delivery without silencing the monitor's output entirely.

Environment

  • Claude Code: 2.1.168
  • OS: macOS 26.5.1 (Darwin)

Minimal reproduction

  1. Create a tiny plugin with a single one-shot monitor:

my-plugin/.claude-plugin/plugin.json
``json
{ "name": "monitor-noise-demo", "version": "0.0.1" }
``

my-plugin/monitors/monitors.json
``json
[
{
"name": "noise-demo",
"command": "bash -c 'echo \"monitor fired once\"; sleep 86400'",
"description": "Demo monitor that emits exactly one line, then sleeps"
}
]
``

The command writes exactly one stdout line for the entire session, then sleeps.

  1. Install/enable the plugin and start a session.
  1. Do a few turns of ordinary work (a handful of tool calls / messages).
  1. Watch the transcript.

Expected

The single stdout line (monitor fired once) produces one Monitor event:
notification. Nothing further appears, because the command never writes again.

Actual

Monitor event: "Demo monitor that emits exactly one line, then sleeps" reappears on
~every turn, many times over the session, even though the command emitted only one line.

Two details worth noting:

  • The notification text shown is the monitor's description field, not the actual

stdout content — so every re-delivery looks identical and carries no new information.

  • In the session transcript (.jsonl), these show up as repeated <task-notification>

entries that all share one task-id (the monitor task), interleaved with
queue-operation entries — i.e. the same pending notification is re-queued/re-injected
each turn rather than delivered once.

Measured (real-world, separate from the minimal repro)

In one ~69-minute session, a monitor whose command emits at most one line per ~90s
(and only on a state change, so just a few real emits the whole session) produced
362 identical Monitor event: notifications, all tied to a single monitor task-id —
a sustained ~5 notifications/minute, peaking at ~16/minute. The delivery rate tracked
session/turn activity, not the command's (near-zero) output rate.

Impact

  • Long-lived monitors (the intended use — "watch X for the whole session") become

unusable for any human-visible notification, because a single legitimate event is
amplified into continuous transcript noise.

  • The only workaround is to make the monitor command produce no stdout at all (e.g.

redirect to /dev/null or add a --quiet mode). That removes the noise, but also
removes the wanted one-notification-per-real-change — there is no way to keep the
former without the latter.

Requests (any one would resolve it)

  1. Deliver a monitor's notification once per stdout line, and do not re-inject a

prior notification on subsequent turns.

  1. And/or add a way to suppress/throttle monitor-event re-delivery (a setting,

a per-monitor field, or de-duplication of an already-shown notification) without
suppressing the monitor's output entirely.

Questions

  • Is the per-turn re-delivery intentional, or a side effect of how pending

task-notifications are flushed into the conversation?

  • Is there an existing/undocumented knob to control monitor-notification frequency?

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗