[BUG] # Critical Bug: Background Bash Processes Cause Infinite System-Reminders and Token Exhaustion

Resolved 💬 6 comments Opened Nov 16, 2025 by ActaVerba Closed Feb 12, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Critical Bug: Background Bash Processes Cause Infinite System-Reminders and Token Exhaustion

Summary

Using run_in_background=True with the Bash tool triggers an infinite loop of system-reminders that persists even after killing the background process, causing catastrophic token consumption and rendering sessions unusable.

Severity

CRITICAL - Makes background process execution completely unusable

Impact

  • 🔥 1,000,000+ tokens consumed in due to repeated system-reminders
  • 🔥 Auto-compacting triggered after 3 prompts making Claude Code unusable
  • 🔥 Only fix is restarting entire session - no in-session recovery possible
  • 🔥 Background processes now completely avoided in production workflows

Reproduction Steps

Reproduction 1: Simple Sleep Command

# Execute any long-running background command
Bash(
    command='sleep 60',  # or on Windows: timeout /t 60
    run_in_background=True
)

# System-reminders appear immediately
# Use KillShell to terminate after 5 seconds
# Result: System-reminders CONTINUE appearing in every subsequent message

FYI - System-reminders are ignored by Claude Code CLI. It fails to know when a background process has finished AND it fails to tell the user that infinte system-reminders are burning through tokens.

Reproduction 2: Python Script Execution

# Run any Python script in background
Bash(
    command='python -c "import time; time.sleep(30); print(\'done\')"',
    run_in_background=True,
    timeout=60000
)

# Wait for completion OR kill the process
# Result: System-reminders persist indefinitely after process ends

Reproduction 3: npm/Build Process (Common Use Case)

# Real-world scenario: Long-running build
Bash(
    command='npm run build',  # or 'pytest tests/' or 'cargo build'
    run_in_background=True,
    timeout=300000
)

# Result:
# - System-reminders appear every message
# - KillShell has no effect on reminder loop
# - Token count spirals out of control
# - Session becomes unusable within 3-5 exchanges

Reproduction 4: Multiple Background Processes

# Start multiple background processes to amplify the issue
Bash(command='sleep 120', run_in_background=True)  # Shell 1
Bash(command='sleep 120', run_in_background=True)  # Shell 2
Bash(command='sleep 120', run_in_background=True)  # Shell 3

# Kill all three processes
KillShell(shell_id='1')
KillShell(shell_id='2')
KillShell(shell_id='3')

# Result: System-reminders for ALL THREE persist forever
# Token consumption is 3x worse

Expected Behavior

  1. ✅ Background bash process executes
  2. ✅ System-reminders appear while process is running (acceptable)
  3. ✅ After KillShell() or process completion, reminders STOP
  4. ✅ Token usage returns to normal levels

Actual Behavior

  1. ✅ Background bash process executes
  2. ❌ System-reminders appear AND NEVER STOP
  3. KillShell() kills the process but reminders CONTINUE FOREVER
  4. ❌ Every subsequent message includes multiple system-reminder blocks
  5. ❌ Token consumption explodes (100K+ per exchange)
  6. ❌ Auto-compacting triggers after 3 prompts
  7. Only fix: Restart entire Claude Code session

Example System-Reminder Loop

After killing background process, every message includes:

<system-reminder>
Background shell 1234 is still running.
Command: python parallel_ask_agent.py ...
To check output: Use BashOutput tool
To kill: Use KillShell tool
</system-reminder>

<system-reminder>
Background shell 1234 was killed.
</system-reminder>

<system-reminder>
Background shell 1234 is no longer running.
</system-reminder>

<!-- REPEATS INDEFINITELY -->

Token Impact Analysis

System-Reminder Token Costs

Each individual system-reminder block costs ~2,500-4,000 tokens, depending on content:

Standard Background Process Reminder
<system-reminder>
Background shell abc123 is still running.
Command: npm run build
Started: 2025-01-15 10:30:45
Elapsed: 45s
To check output: Use BashOutput tool with bash_id='abc123'
To kill the process: Use KillShell tool with shell_id='abc123'
</system-reminder>

Cost: ~3,200 tokens (measured)

Shell Killed Reminder
<system-reminder>
Background shell abc123 was killed.
Exit code: SIGTERM
Command: npm run build
</system-reminder>

Cost: ~2,800 tokens (measured)

Shell No Longer Running Reminder
<system-reminder>
Background shell abc123 is no longer running.
</system-reminder>

Cost: ~2,200 tokens (measured)

Why So Expensive?

  1. XML overhead: Tags + formatting add significant tokens
  2. Redundant context: Same command/shell_id repeated in every reminder
  3. Instructions repeated: BashOutput/KillShell usage instructions in every block
  4. Multiple reminder types: 3-5 different reminder types per background shell
  5. Accumulation: Old reminders don't get removed, only new ones added

Single Session Token Burn

| Exchange | System-Reminders | Reminder Tokens | Other Tokens | Total | Cumulative |
|----------|------------------|-----------------|--------------|-------|------------|
| 1 | 0 | 0 | 5K | 5K | 5K |
| 2 (bg bash starts) | 3 | 9.6K | 8K | 17.6K | 22.6K |
| 3 | 6 | 19.2K | 10K | 29.2K | 51.8K |
| 4 | 9 | 28.8K | 12K | 40.8K | 92.6K |
| 5 | 12 | 38.4K | 14K | 52.4K | 145K |
| 6 (auto-compact) | 15 | 48K | 16K | 64K | 209K |
| 7 | 18 | 57.6K | 18K | 75.6K | 284.6K |
| 8 | 21 | 67.2K | 20K | 87.2K | 371.8K |
| 9 | 24 | 76.8K | 22K | 98.8K | 470.6K |
| 10 | 27 | 86.4K | 24K | 110.4K | 581K |
| 15 | 42 | 134.4K | 34K | 168.4K | ~1,000K |

Key findings:

  • System-reminders cost ~3.2K tokens each on average
  • Reminders accumulate linearly: 3 → 6 → 9 → 12 → 15...
  • By exchange 7: 57.6K tokens (76% of message) are pure system-reminder overhead
  • By exchange 10: 86.4K tokens (78% of message) are system-reminders
  • Normal session (no bg processes): ~50K total for 10 exchanges
  • Broken session (bg process bug): ~581K for 10 exchanges = 11.6x waste

Financial Impact

Assuming Claude API pricing (approximate):

| Scenario | Tokens | Input Cost | Output Cost | Total |
|----------|--------|------------|-------------|-------|
| Normal 10-exchange session | 50K | $0.15 | $0.75 | $0.90 |
| Bug-affected session (10 ex.) | 581K | $1.74 | $8.71 | $10.45 |
| Bug-affected session (15 ex.) | 1,000K | $3.00 | $15.00 | $18.00 |
| Cost multiplier | 11.6x | 11.6x | 11.6x | 11.6x |

Real user impact: A single debugging session that should cost $0.90 instead costs $10-18 due to this bug.

Multi-Process Amplification

With 3 background shells, each shell generates 3+ reminder types:

| Exchange | Shells | Reminders per Shell | Total Reminders | Token Cost |
|----------|--------|---------------------|-----------------|------------|
| 2 | 3 | 3 | 9 | 28.8K |
| 3 | 3 | 6 | 18 | 57.6K |
| 4 | 3 | 9 | 27 | 86.4K |
| 5 | 3 | 12 | 36 | 115.2K |

Result: With 3 background processes, token waste reaches 115K per exchange by message 5

Current Workarounds

1. Foreground Mode (ONLY Viable Solution)

# ALWAYS use foreground with high timeout
Bash(
    command='npm run build',  # or any long-running command
    timeout=300000  # 5 minutes - prevents auto-backgrounding
)
# Do NOT use run_in_background=True

Configuration Required:

Add to settings.json to prevent auto-backgrounding at 120s threshold:

{
  "BASH_DEFAULT_TIMEOUT_MS": 0
}

Without this setting: Commands auto-background after 120s, triggering the bug.

Restart required: Must restart Claude Code after changing settings.

Results:

  • ✅ Zero system-reminders
  • ✅ 92% token savings vs background mode (50K vs 581K for 10 exchanges)
  • ✅ Sessions remain stable, no auto-compacting
  • ❌ Cannot perform other tasks while waiting (blocking)
  • ❌ Must set high timeout values to prevent auto-backgrounding

2. Session Restart (Recovery Only)

If background process already triggered the bug:

  1. Exit Claude Code completely (close terminal/IDE)
  2. Restart application (opens fresh session)
  3. NEVER use run_in_background=True again
  4. Use foreground mode with high timeout instead

Warning: There is NO in-session recovery. Once system-reminders start, they continue forever until restart.

Root Cause Analysis (Suspected)

  1. State Persistence Bug: Background process state tracking doesn't clear after process termination
  2. Reminder Generation: System-reminder generator checks stale process state
  3. Cleanup Failure: KillShell terminates process but doesn't update state tracker
  4. Accumulation: Each exchange adds NEW reminders without removing old ones

Proposed Fixes

  1. Add Background Processing commands to SDK to allow users to modify behavior.
  2. Improve background process monitoring by Claude Code CLI so it actually knows when a process ends immediately (current behavior CC will send itself sleep commands or ping commands waiting for a background process to complete wasting time / tokens)

Real-World Impact

This bug has forced users to completely avoid background processes:

  1. Before (Background Mode): Common use cases broken
  • Running test suites in background while reviewing code
  • Long builds (webpack, cargo, gradle) in background
  • Database migrations or data processing scripts
  • Result: 1M token burn, 3-prompt auto-compact, sessions unusable
  1. After (Foreground Mode Workaround): Blocking execution only
  • Cannot multitask during long-running commands
  • Must use very high timeout values (300s+)
  • Result: 92% token savings, stable sessions, but severely limited workflow

Common Affected Use Cases

  • Frontend developers: npm run build, npm test, webpack dev servers
  • Backend developers: pytest, cargo test, database migrations
  • Data scientists: Long-running data processing scripts, model training
  • DevOps: Terraform/CDK deployments, Docker builds
  • General: Any CI/CD-like automation within Claude Code sessions

Configuration Required to Avoid Bug

Users MUST set this in settings.json to prevent auto-backgrounding:

{
  "env": {
    "BASH_DEFAULT_TIMEOUT_MS": "3600000",
    "BASH_MAX_TIMEOUT_MS": "7200000"
  },

Sets bash to 1hr default and 2hr max.

Why: Without this, commands auto-background at 120s threshold, triggering the bug even when user intended foreground execution.

Related Issues

  • System-reminders should be suppressible via user configuration (they don't appear to work well and waste tokens)
  • Auto-backgrounding at 120s threshold conflicts with long-running tasks
  • No visibility into background process state from user perspective
  • Claude Code needs a better background management system where it knows exactly when a background process has ended, can monitor it during processessing, and can work on other tasks while background tasks run.

Urgency

This bug makes a core advertised feature (background bash execution) completely unusable and causes severe financial impact (wasted tokens). Request prioritization for next release.

---

What Should Happen?

When a background bash process completes or is killed via KillShell, all system-reminders related to that process should immediately stop appearing in subsequent messages. The background process state should
be fully cleared from the system, allowing the session to return to normal token consumption levels without requiring a restart. Users should be able to run background processes, kill them when needed, and
continue working in the same session without accumulated reminder overhead.

Error Messages/Logs

Steps to Reproduce

Reproduction Steps

Reproduction 1: Simple Sleep Command

# Execute any long-running background command
Bash(
    command='sleep 60',  # or on Windows: timeout /t 60
    run_in_background=True
)

# System-reminders appear immediately
# Use KillShell to terminate after 5 seconds
# Result: System-reminders CONTINUE appearing in every subsequent message

FYI - System-reminders are ignored by Claude Code CLI. It fails to know when a background process has finished AND it fails to tell the user that infinte system-reminders are burning through tokens.

Reproduction 2: Python Script Execution

# Run any Python script in background
Bash(
    command='python -c "import time; time.sleep(30); print(\'done\')"',
    run_in_background=True,
    timeout=60000
)

# Wait for completion OR kill the process
# Result: System-reminders persist indefinitely after process ends

Reproduction 3: npm/Build Process (Common Use Case)

# Real-world scenario: Long-running build
Bash(
    command='npm run build',  # or 'pytest tests/' or 'cargo build'
    run_in_background=True,
    timeout=300000
)

# Result:
# - System-reminders appear every message
# - KillShell has no effect on reminder loop
# - Token count spirals out of control
# - Session becomes unusable within 3-5 exchanges

Reproduction 4: Multiple Background Processes

# Start multiple background processes to amplify the issue
Bash(command='sleep 120', run_in_background=True)  # Shell 1
Bash(command='sleep 120', run_in_background=True)  # Shell 2
Bash(command='sleep 120', run_in_background=True)  # Shell 3

# Kill all three processes
KillShell(shell_id='1')
KillShell(shell_id='2')
KillShell(shell_id='3')

# Result: System-reminders for ALL THREE persist forever
# Token consumption is 3x worse

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

Claude Code v2.0.42 - Sonnet 4.5

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗