How DesktopCommanderMCP Process Detection Identifies Running, Waiting, and Finished Processes

DesktopCommanderMCP detects process states by analyzing stdout/stderr output against predefined patterns of REPL prompts, completion indicators, and error signatures in src/utils/process-detection.ts.

DesktopCommanderMCP is a Model Context Protocol (MCP) server that enables AI agents to execute terminal commands and interact with REPL environments. The DesktopCommanderMCP process detection system determines whether a spawned process is actively running, blocked waiting for input, or has terminated by implementing a pattern-matching state machine that inspects textual output in real-time.

Core Detection Logic in process-detection.ts

The heart of the detection system resides in src/utils/process-detection.ts, which exports the analyzeProcessState function. This function accepts process output and PID, then returns a ProcessState object indicating whether the process is running, waiting for input, or finished.

REPL Prompt Detection

When a process enters an interactive REPL mode, it typically displays specific prompt characters. The module defines REPL_PROMPTS—a catalogue of common patterns including >>>, >, $, and #.

The analyzeProcessState function extracts the last line of output and checks for these prompts:

// src/utils/process-detection.ts
const allPrompts = Object.values(REPL_PROMPTS).flat();
const detectedPrompt = allPrompts.find(p => lastLine.endsWith(p) || lastLine.includes(p));
if (detectedPrompt) {
  return { isWaitingForInput: true, isFinished: false, isRunning: true, detectedPrompt, lastOutput: output };
}

If a prompt is detected, the process is marked with isWaitingForInput: true, signaling that the process is blocked awaiting user interaction.

Completion Indicator Recognition

To identify normal process termination, the system uses COMPLETION_INDICATORS—strings and regexes that typically appear when commands finish, such as "Process finished" or "Exit code:".

The detection logic scans the entire output buffer for these patterns:

// src/utils/process-detection.ts
const hasCompletionIndicator = COMPLETION_INDICATORS.some(p => p.test(output));
if (hasCompletionIndicator) {
  return { isWaitingForInput: false, isFinished: true, isRunning: false, lastOutput: output };
}

When matched, the function returns isFinished: true, indicating the process lifecycle has ended successfully.

Error-Driven Termination Detection

Many REPLs and scripts terminate by printing error tracebacks rather than clean exit codes. The module defines ERROR_COMPLETION_PATTERNS containing regexes for "Error:", "Exception:", and "Traceback".

If error patterns match the recent output and no REPL prompt follows, the process is marked as finished:

// src/utils/process-detection.ts
const hasErrorCompletion = ERROR_COMPLETION_PATTERNS.some(p => p.test(lastFewLines));
if (hasErrorCompletion) {
  return detectedPrompt
    ? { /* remains waiting */ }
    : { isWaitingForInput: false, isFinished: true, isRunning: false, lastOutput: output };
}

This ensures crashed or errored processes are correctly identified as terminated rather than hanging indefinitely.

Runtime Integration and State Management

The detection logic integrates with DesktopCommanderMCP's runtime through periodic scanning and event-driven checks in the terminal management layer.

TerminalManager Periodic Checks

In src/terminal-manager.ts, the TerminalManager class buffers stdout/stderr data and executes a 100ms periodic check to evaluate process state:

// src/terminal-manager.ts (line 397)
periodicCheck = setInterval(() => {
  if (output.trim()) {
    const processState = analyzeProcessState(output, childProcess.pid);
    if (processState.isWaitingForInput) {
      session.isBlocked = true;
      resolveOnce({ pid: childProcess.pid!, output, isBlocked: true });
    }
  }
}, 100);

When isWaitingForInput becomes true, the manager marks the session as blocked and resolves the command promise early, allowing the AI agent to recognize the interactive state and send appropriate input.

Quick-Pattern Optimization

For performance, the system implements a lightweight regex shortcut />>>\s*$|>\s*$|\$\s*$|#\s*$/ that catches obvious prompts instantly. This bypasses the slower analyzeProcessState function for clear-cut cases, immediately flagging the process as blocked without waiting for the next periodic scan.

Improved Process Tools Integration

Higher-level command handlers in src/tools/improved-process-tools.ts leverage the detection system to determine session lifecycle:

// src/tools/improved-process-tools.ts (excerpt)
const processState = analyzeProcessState(result.output, result.pid);
if (processState.isWaitingForInput) { 
  /* keep session open for REPL interaction */ 
} else { 
  /* treat as completed and close session */ 
}

This integration enables seamless transitions between command execution and interactive REPL sessions.

Process State Reference

The DesktopCommanderMCP process detection system categorizes processes into three mutually exclusive states:

  • Running: isRunning: true, isWaitingForInput: false, isFinished: false — The process is actively emitting output but has not encountered a prompt or completion indicator.
  • Waiting for Input: isWaitingForInput: true — A REPL prompt was recognized in the output buffer; the process is paused awaiting user input.
  • Finished: isFinished: true — Either a completion indicator or error pattern was detected, signaling process termination.

Implementation Examples

Manual State Checking

You can programmatically check process state using the detection utility:

// Example: Manually checking a process's state
import { analyzeProcessState } from './utils/process-detection.js';

const output = `
>>> import os
>>> os.listdir('.')
>>> 
`;
const state = analyzeProcessState(output);
console.log(state.isWaitingForInput); // true

Integration with TerminalManager

The following demonstrates how the detection system surfaces state information through the terminal manager API:

// Example: How TerminalManager uses the detection
import { terminalManager } from './terminal-manager.js';

async function runPython() {
  const result = await terminalManager.executeCommand('python', 5000);
  // `result.isBlocked` will be true because the REPL prompt (>>> ) was detected.
  console.log(result.isBlocked ? 'REPL ready' : 'Command finished');
}
runPython();

Summary

  • DesktopCommanderMCP process detection operates through pattern matching in src/utils/process-detection.ts, specifically the analyzeProcessState function.
  • The system maintains three constant catalogues: REPL_PROMPTS for interactive input detection, COMPLETION_INDICATORS for normal termination, and ERROR_COMPLETION_PATTERNS for crash detection.
  • src/terminal-manager.ts executes periodic 100ms scans to detect state changes in real-time, setting session.isBlocked when REPL prompts are detected.
  • Quick-pattern regex optimization provides immediate detection of common prompts without full buffer analysis overhead.
  • The state machine returns mutually exclusive flags (isRunning, isWaitingForInput, isFinished) that enable accurate lifecycle management across the MCP server.

Frequently Asked Questions

How does DesktopCommanderMCP distinguish between a running process and one waiting for input?

DesktopCommanderMCP scans the last line of stdout/stderr output against the REPL_PROMPTS catalogue in src/utils/process-detection.ts. If the output ends with characters like >>>, >, $, or #, the analyzeProcessState function returns isWaitingForInput: true, distinguishing blocked REPL sessions from actively running processes.

What happens when a process crashes or throws an exception?

The detection system checks output against ERROR_COMPLETION_PATTERNS, which includes regexes for "Error:", "Exception:", and "Traceback". If these patterns match and no REPL prompt follows, analyzeProcessState marks the process as finished with isFinished: true, ensuring error-terminated processes are not left in a running state.

Can the detection system handle custom or non-standard REPL prompts?

While the system ships with common prompts in REPL_PROMPTS, the pattern-based architecture in src/utils/process-detection.ts allows for extension. Developers can modify the REPL_PROMPTS constant or the quick-pattern regex />>>\s*$|>\s*$|\$\s*$|#\s*$/ in src/terminal-manager.ts to recognize domain-specific prompt signatures.

How frequently does DesktopCommanderMCP check process state?

The TerminalManager implements a 100ms interval scan using setInterval to run analyzeProcessState against buffered output. Additionally, a quick-pattern regex check runs immediately on output reception to catch obvious prompts without waiting for the periodic scan cycle.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →