How the Munder Difflin Prerequisites Checker Detects and Installs Missing Tools

The Munder Difflin prerequisites checker combines a static ToolSpec catalog with runtime PATH probing to detect missing binaries and generate platform-specific installation commands for manual execution.

Munder Difflin is an Electron-based development harness that relies on external binaries—UV, Git, Node—and the MemPalace semantic-memory service. The prerequisites checker ensures the host environment contains these dependencies before agents begin work. According to the chaitanyagiri/munder-difflin source code, the system uses a declarative catalog in src/shared/toolCatalog.ts and a runtime probe via the tools:status IPC handler to identify gaps and provide exact installation instructions.

Static Tool Catalog Definition

All external dependencies are declared in src/shared/toolCatalog.ts. Each entry follows the ToolSpec interface, which encodes detection rules and platform-aware install commands.

ToolSpec Structure

Every tool in the catalog specifies metadata and installation logic:

interface ToolSpec {
  id: string;           // Stable identifier (e.g., 'uv', 'git')
  bin: string | null;   // Binary name to probe on PATH
  kind: 'prerequisite' | 'memory' | 'engine';
  essential: boolean;   // Required for core functionality
  install: {
    posix: string;      // macOS/Linux command
    win32: string;      // Windows command
  };
  why: string;          // User-facing impact description
}

The checker filters for kind === 'prerequisite' when validating the environment.

Platform-Specific Install Commands

The catalog provides exact shell commands for each platform. For example, UV and Git entries include conditional installation scripts:

{
  id: 'uv',
  bin: 'uv',
  kind: 'prerequisite',
  essential: true,
  install: {
    posix: 'curl -LsSf https://astral.sh/uv/install.sh | sh',
    win32: 'powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"'
  },
  docsUrl: 'https://docs.astral.sh/uv/'
},
{
  id: 'git',
  bin: 'git',
  kind: 'prerequisite',
  essential: true,
  install: {
    posix: 'xcode-select --install   # macOS · or: sudo apt install git',

    win32: 'winget install --id Git.Git -e'
  }
}

Source: [src/shared/toolCatalog.ts](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/shared/toolCatalog.ts#L44-L82)

Runtime Detection via IPC

When the UI requests the current environment state, the Electron main process handles the tools:status channel in src/main/index.ts. This handler probes the host machine and returns a ToolStatus array indicating presence or absence.

Probing PATH with resolveCliCommand

For standard prerequisites, the handler uses resolveCliCommand (a wrapper around which on POSIX and where on Windows) to locate binaries:

ipcMain.handle('tools:status', (): ToolStatus[] => {
  const win = process.platform === 'win32';
  
  return toolCatalog().map((spec): ToolStatus => {
    const installCommand = win ? spec.install.win32 : spec.install.posix;
    
    // Probe ordinary prerequisites
    if (!spec.bin) return { ...spec, installCommand, found: false, path: null };
    
    let path: string | null = null;
    try {
      const resolved = resolveCliCommand(spec.bin);
      if (resolved !== spec.bin && existsSync(resolved)) {
        path = resolved;
      }
    } catch { /* Silent failure never crashes the panel */ }
    
    return { ...spec, installCommand, found: !!path, path };
  });
});

Source: [src/main/index.ts](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/index.ts#L65-L88)

The resolveCliCommand utility originates from src/main/shellEnv.ts and normalizes PATH resolution across platforms.

Special Handling for MemPalace

The MemPalace service (spec.id === 'mempalace') bypasses standard PATH probing. Its status derives from the memory subsystem via memory.status(), which checks both binary availability and palace initialization state:

if (spec.id === 'mempalace') {
  const mem = memory.status(); // Returns { available, initialized, bin }
  return {
    ...spec,
    installCommand,
    found: !!mem?.available,
    path: mem?.bin ?? null,
    detail: mem?.available
      ? (mem.initialized ? 'palace initialised' : 'installed — palace not built yet')
      : undefined
  };
}

This ensures the semantic-memory service reports readiness separately from simple binary presence.

Generating Installation Prompts

Once detection completes, the setupPrompt function in src/shared/toolCatalog.ts converts missing tools into actionable instructions. It formats a bullet list containing the install command and any additional notes:

export function setupPrompt(missing: ToolStatus[]): string {
  if (missing.length === 0) return '';
  
  const lines = missing.map(t => {
    const cmd = t.installCommand ? `\n  install: ${t.installCommand}` : '';
    const note = t.note ? `\n  note: ${t.note}` : '';
    return `- ${t.label} (${t.id})${cmd}${note}`;
  });
  
  return [
    'Set up my missing local tooling:',
    '',
    ...lines,
    '',
    'For each one: run the install command …'
  ].join('\n');
}

Source: [src/shared/toolCatalog.ts](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/shared/toolCatalog.ts#L46-L66)

Important: The system does not automatically execute these commands. The UI displays the prompt to the user (or sends it to the "Michael" agent), requiring manual execution and subsequent verification.

Practical Installation Flow

The complete detection and installation workflow follows these steps:

  1. Frontend Request: The renderer calls ipcRenderer.invoke('tools:status').
  2. Backend Returns: An array of ToolStatus objects with found booleans and installCommand strings.
  3. Filter Missing: The UI filters for found === false to identify gaps.
  4. Prompt Generation: Calls setupPrompt(missing) to produce a human-readable checklist.
  5. Manual Execution: The user runs the displayed commands (e.g., curl … | sh for UV, winget install … for Git).
  6. Re-verification: After installation, the UI re-invokes tools:status to confirm the tools are now present.

Example: Fetching Prerequisites in a Renderer Process

async function checkAndPrompt() {
  // Fetch status from main process
  const status: ToolStatus[] = await window.ipc.invoke('tools:status');
  
  // Isolate missing prerequisites
  const missing = status.filter(t => !t.found && t.kind === 'prerequisite');
  
  if (missing.length === 0) {
    console.log('All prerequisites satisfied');
    return;
  }
  
  // Generate installation instructions
  const prompt = setupPrompt(missing);
  displayModal(prompt); // Present to user for manual execution
}

Summary

  • Static Catalog: src/shared/toolCatalog.ts defines tools via ToolSpec, including platform-specific install.posix and install.win32 commands.
  • Runtime Probe: The tools:status IPC handler in src/main/index.ts uses resolveCliCommand (from src/main/shellEnv.ts) to check PATH for each binary.
  • MemPalace Exception: Semantic-memory status comes from memory.status(), not standard PATH resolution.
  • Manual Installation: The setupPrompt function generates explicit shell commands, but the user must execute them manually and re-verify.

Frequently Asked Questions

How does the prerequisites checker distinguish between macOS and Windows install commands?

The tools:status handler checks process.platform === 'win32' and selects the appropriate command from the ToolSpec.install object. For Windows, it uses spec.install.win32; for all other platforms (macOS, Linux), it uses spec.install.posix.

Does Munder Difflin automatically install missing tools?

No. The prerequisites checker detects missing tools and generates installation prompts via setupPrompt, but it never executes the install commands automatically. The user must copy and run the displayed commands (e.g., curl … | sh or winget install …) manually, then trigger a re-check.

What happens if a binary is not found on PATH?

If resolveCliCommand fails to locate the binary (or returns a path that fails existsSync), the handler sets found: false and path: null in the ToolStatus object. The frontend then includes this tool in the missing list passed to setupPrompt, which surfaces the pre-defined install command for that platform.

How is MemPalace handled differently from other prerequisites?

Unlike standard tools probed via resolveCliCommand, MemPalace status derives from the memory.status() method, which checks both binary availability and initialization state. This allows the UI to distinguish between "binary installed" and "semantic memory palace initialized," providing granular feedback to the user.

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 →