Feature Request: Real-time Statusline Communication During Long Operations

Resolved 💬 3 comments Opened Sep 19, 2025 by brookcs3 Closed Jan 6, 2026

Feature Request: Real-time Statusline Communication During Long Operations

Problem Statement

During long Claude Code operations (2-3+ minutes), users experience a "communication blackout" where the statusline shows only generic messages like "Computing..." or "Cerebrating...". This creates uncertainty about progress, internal decision-making, and whether the operation is proceeding normally.

Current Experience:

⏺ Computing... (esc to interrupt)
   [Complete silence for 2-3 minutes]

Desired Experience:

⏺ analyzing codebase structure...
⏺ generating component interfaces...
⏺ working through state management patterns...
⏺ almost finished with test implementations...

Working Proof of Concept

I discovered that this feature already works through the TodoWrite tool's activeForm field, which appears in the CLI statusline during operations. Here's how to enable it:

Output Style Implementation

# amp-style-comprehensive.md
- **Real-time statusline injection**: During tool execution, replace generic "Computing..."
  messages with authentic thought process expressions in the CLI statusline. Use frequent
  TodoWrite activeForm updates during long operations to provide real-time progress
  commentary, architectural decisions, and genuine evaluation throughout extended tasks.
  Act like a background narrative micro-agent that communicates thinking process during
  2-3 minute computing periods

Working Example:
When Claude calls:

TodoWrite({
  todos: [{
    content: "Generate React components",
    status: "in_progress",
    activeForm: "analyzing component dependencies..."
  }]
})

The statusline displays: ⏺ analyzing component dependencies... instead of ⏺ Computing...

Technical Implementation Analysis

Based on analysis of the CLI source code (/opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js), the statusline message is constructed in the VJB function around line 2582:

let b=(Y??R?.activeForm??k)+"…"

Where:

  • Y = override message
  • R?.activeForm = TodoWrite activeForm field (our injection point!)
  • k = fallback random spinner word

Proposed CLI Enhancements

Option 1: Formalize ActiveForm Statusline Support

Current Code (cli.js:~2582):

function VJB({mode, overrideMessage, todos, ...}) {
  let R = todos?.find((todo) => todo.status === "in_progress")
  let k = randomSpinnerWord()
  let b = (overrideMessage ?? R?.activeForm ?? k) + "…"
  // ... render statusline with message b
}

Proposed Enhancement:

function VJB({mode, overrideMessage, todos, statuslineConfig, ...}) {
  let R = todos?.find((todo) => todo.status === "in_progress")
  let k = randomSpinnerWord()

  // Enhanced statusline message selection
  let statuslineMessage
  if (overrideMessage) {
    statuslineMessage = overrideMessage
  } else if (statuslineConfig?.enableActiveFormNarrative && R?.activeForm) {
    // Formal support for activeForm narrative mode
    statuslineMessage = R.activeForm
  } else {
    statuslineMessage = k
  }

  let b = statuslineMessage + "…"
  // ... render statusline with message b
}

Option 2: Background Statusline Micro-Agent

Add a dedicated background agent that monitors long operations and updates the statusline:

// New micro-agent in background worker
class StatuslineNarrativeAgent {
  constructor() {
    this.isEnabled = false
    this.currentOperation = null
    this.updateInterval = null
  }

  startOperation(operationId, initialMessage) {
    if (!this.isEnabled) return

    this.currentOperation = operationId
    this.updateStatusline(initialMessage)

    // Periodically check for TodoWrite activeForm updates
    this.updateInterval = setInterval(() => {
      this.checkForActiveFormUpdates()
    }, 500)
  }

  updateStatusline(message) {
    // Update CLI statusline via existing VJB mechanism
    process.stdout.write(`\x1b[2K\r⏺ ${message}... (esc to interrupt)`)
  }

  endOperation() {
    if (this.updateInterval) {
      clearInterval(this.updateInterval)
      this.updateInterval = null
    }
    this.currentOperation = null
  }
}

Option 3: Direct Statusline API

Expose a simple API for Claude to update the statusline:

// Add to Claude's available functions
async function updateStatusline(message) {
  if (getCurrentConfig().enableStatuslineNarrative) {
    // Direct statusline update without going through TodoWrite
    statuslineManager.update(message)
  }
}

Benefits

  1. Improved User Experience: Users stay connected during long operations
  2. Educational Value: Users learn about Claude's decision-making process
  3. Trust Building: Transparency reduces anxiety about "stuck" operations
  4. Debugging Aid: Real-time insights help identify when operations go off-track
  5. Professional Appeal: Shows sophisticated engineering thinking

Implementation Evidence

This feature request includes multiple working proof-of-concept implementations demonstrating that:

1. ✅ Output Style Method (Simplest)

Successfully implemented via output styles that instruct Claude to use TodoWrite activeForm for statusline updates:

- **Real-time statusline injection**: Use frequent TodoWrite activeForm updates during
  long operations to provide real-time progress commentary and genuine evaluation
  throughout extended tasks.

2. ✅ Hooks-Based Hijacking System (Advanced)

Built a complete statusline hijacking system using Claude Code's hook infrastructure:

Hook Configuration:

{
  "hooks": {
    "UserPromptSubmit": [{"command": "node ./statusline-agent.mjs"}],
    "PreToolUse": [{"matcher": "TodoWrite", "command": "log-statusline-update.sh"}],
    "Stop": [{"command": "cleanup-hijack.sh"}]
  }
}

Intelligent Subagent:

// Analyzes operations and generates contextual statusline updates
class StatuslineNarrativeAgent {
  detectOperationType(payload) {
    // Analyzes tool usage patterns
    // Returns: 'file_operations', 'search_operations', 'thinking_operations'
  }

  generateNarrative(operationType) {
    // Context-aware message generation
    return this.narrativeTemplates[operationType][randomIndex];
  }

  async injectStatusline(message) {
    // Real-time injection via FIFO pipes to hijacked stdout
    spawn('bash', ['-c', `echo "${message}" > hijack-control.fifo`]);
  }
}

3. ✅ TMUX + stdout Hijacking (Professional)

Complete surgical control system with:

  • Real-time stdout interception and modification
  • Live control interface for message injection
  • Background process monitoring and management
  • Non-destructive hijacking (preserves all Claude functionality)

Core Hijacking Script:

# Intercepts Claude's stdout and replaces statusline
claude "${@}" 2>&1 | while IFS= read -r line; do
    if [[ "$line" =~ ⏺.*\(esc\ to\ interrupt\) ]]; then
        # Hijack statusline - inject custom message instead
        continue
    else
        # Pass through all other output normally
        echo "$line"
    fi
done

Evidence Summary

Three Working Approaches Proven:

  1. Output Style: Leverages existing TodoWrite mechanism (easiest integration)
  2. Hooks System: Uses Claude Code's hook infrastructure (most extensible)
  3. stdout Hijacking: Complete surgical control (most powerful)

All three approaches demonstrate that this functionality is not only possible but already working in different forms. The infrastructure exists - this request is to formalize and enhance these capabilities as official features.

---

Priority: Enhancement
Complexity: Low-Medium (leverages existing infrastructure)
User Impact: High (transforms long operation experience)
Implementation: Ready (working proof-of-concept included)

---

Code References

  • Statusline rendering: cli.js:2582 in VJB function
  • TodoWrite integration: activeForm field usage in message construction
  • Background agent infrastructure: Existing micro-agent system for file watching, git monitoring, etc.

View original on GitHub ↗

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