claude-code - 💡(How to fix) Fix Channel plugins (iMessage) start one instance per session, causing echo loops and runaway API spend [2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#54122Fetched 2026-04-28 06:38:39
View on GitHub
Comments
2
Participants
3
Timeline
7
Reactions
0
Timeline (top)
labeled ×4commented ×2cross-referenced ×1

Channel plugins designed as "one listener only" (e.g. the official iMessage plugin) are started once per Claude Code session via enabledPlugins. Opening multiple sessions simultaneously spawns multiple plugin instances that all watch the same data source, creating echo loops that generate massive unexpected API costs.

Error Message

enabledPlugins starts the plugin process once per Claude Code session. Channel plugins like iMessage are designed to be singletons (the iMessage plugin README and system prompt both warn "one listener only"), but the plugin framework provides no architectural enforcement of this constraint. The warning exists; the guardrail does not.

Root Cause

enabledPlugins starts the plugin process once per Claude Code session. Channel plugins like iMessage are designed to be singletons (the iMessage plugin README and system prompt both warn "one listener only"), but the plugin framework provides no architectural enforcement of this constraint. The warning exists; the guardrail does not.

Fix Action

Fix / Workaround

Workaround applied

RAW_BUFFERClick to expand / collapse

Summary

Channel plugins designed as "one listener only" (e.g. the official iMessage plugin) are started once per Claude Code session via enabledPlugins. Opening multiple sessions simultaneously spawns multiple plugin instances that all watch the same data source, creating echo loops that generate massive unexpected API costs.

What happened

Opening 2–3 Claude Code sessions in the morning (normal workflow — different terminal windows / projects) started 3 simultaneous iMessage plugin instances. Each instance watched the same chat.db. Any message or Claude response was seen by all three listeners simultaneously, each attempting to handle it. The cascade generated:

  • 34.5 million cache-write tokens
  • 51.8 million cache-read tokens
  • ~$182 in API-equivalent cost
  • Rate limit hit after just 2–3 conversation turns

This was invisible from the user's perspective — it looked like normal sessions.

Root cause

enabledPlugins starts the plugin process once per Claude Code session. Channel plugins like iMessage are designed to be singletons (the iMessage plugin README and system prompt both warn "one listener only"), but the plugin framework provides no architectural enforcement of this constraint. The warning exists; the guardrail does not.

Expected behavior

Channel plugins should either:

  1. Run as a single system-level daemon independent of individual Claude Code sessions (preferred), or
  2. Have the framework enforce singleton behavior — detect an existing instance and refuse to start a second one, rather than silently starting and causing loops

Workaround applied

  • Disabled the iMessage plugin in enabledPlugins until needed
  • Added a PID lock file to the iMessage server.ts so a second instance detects a live first instance and exits immediately
  • Added an flock-based singleton lock to compile-session.py (Stop hook) which also spawns claude -p and was stacking on simultaneous session closes

Why this matters

The failure mode is silent and financially severe. A user doing nothing wrong (opening multiple terminal windows) can burn their entire daily rate-limit allowance in minutes with no warning. The "one listener only" note buried in a system prompt is not an acceptable substitute for architectural enforcement when the failure mode is runaway spend.

Environment

  • Claude Code CLI
  • macOS
  • iMessage plugin: imessage@claude-plugins-official v0.1.0
  • Plan: Max ($200/month)

extent analysis

TL;DR

To prevent echo loops and massive API costs, ensure that channel plugins like iMessage run as singletons, either by implementing a system-level daemon or enforcing singleton behavior within the plugin framework.

Guidance

  • Review the plugin framework to identify why it does not enforce singleton behavior for channel plugins, and consider implementing a mechanism to detect and prevent multiple instances of the same plugin.
  • Implement a PID lock file or a similar locking mechanism in the plugin code to prevent multiple instances from running simultaneously.
  • Consider modifying the compile-session.py script to use a locking mechanism, such as flock, to prevent simultaneous sessions from spawning multiple plugin instances.
  • Evaluate the feasibility of running channel plugins as system-level daemons, independent of individual Claude Code sessions, to prevent multiple instances from running.

Example

// server.ts
const pidLockFile = '/path/to/pid.lock';

if (fs.existsSync(pidLockFile)) {
  console.log('Another instance is already running. Exiting.');
  process.exit(1);
}

fs.writeFileSync(pidLockFile, process.pid);

Notes

The provided workaround, which includes disabling the iMessage plugin and implementing PID lock files, may not be a long-term solution and may require additional modifications to the plugin framework or the Claude Code CLI.

Recommendation

Apply workaround: Implement a locking mechanism, such as PID lock files or flock, to prevent multiple instances of channel plugins from running simultaneously, until a more robust solution can be implemented in the plugin framework.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Channel plugins should either:

  1. Run as a single system-level daemon independent of individual Claude Code sessions (preferred), or
  2. Have the framework enforce singleton behavior — detect an existing instance and refuse to start a second one, rather than silently starting and causing loops

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING