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:
- Frontend Request: The renderer calls
ipcRenderer.invoke('tools:status'). - Backend Returns: An array of
ToolStatusobjects withfoundbooleans andinstallCommandstrings. - Filter Missing: The UI filters for
found === falseto identify gaps. - Prompt Generation: Calls
setupPrompt(missing)to produce a human-readable checklist. - Manual Execution: The user runs the displayed commands (e.g.,
curl … | shfor UV,winget install …for Git). - Re-verification: After installation, the UI re-invokes
tools:statusto 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.tsdefines tools viaToolSpec, including platform-specificinstall.posixandinstall.win32commands. - Runtime Probe: The
tools:statusIPC handler insrc/main/index.tsusesresolveCliCommand(fromsrc/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
setupPromptfunction 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →