How Semantic Memory Is Managed in Munder Difflin: A Deep Dive into the MemoryManager Class

Munder Difflin manages semantic memory through a dedicated MemoryManager class that maintains a vector-indexed MemPalace outside the standard markdown hive, periodically mining agent memory.md files into embeddings while exposing asynchronous search and wake-up APIs via IPC channels.

Munder Difflin is an open-source knowledge management system that extends beyond static markdown storage by implementing semantic memory management through a specialized vector indexing subsystem. Unlike traditional file-based storage, the application maintains a separate "palace" of vector embeddings that enables semantic search across agent memories. This article examines the technical implementation of this system, focusing on the MemoryManager class in src/main/memory.ts and its integration with the broader application architecture.

The MemoryManager Core Architecture

The MemoryManager class serves as the central nervous system for semantic memory operations. It orchestrates CLI detection, environment configuration, and lifecycle management for the external MemPalace vector index.

CLI Detection and Binary Resolution

Before any semantic operations can occur, the manager must locate the mempalace CLI binary. The bin() method implements a comprehensive search strategy:

  • where/which command execution – Scans the system PATH for the executable
  • Fallback directory probing – Checks ~/.local/bin, Homebrew installations, and pip package locations
  • Result caching – Stores the discovered path to avoid repeated filesystem scans

This detection logic resides in src/main/memory.ts (lines 38-74) and represents the first gate in the semantic memory initialization sequence.

Environment Variable Injection

Once the CLI is located, the manager ensures all agent processes access the same vector index. The env() and childEnv() methods inject critical environment variables:

  • MEMPALACE_PALACE_PATH – Points to the shared vector index directory
  • Embedding model configuration – Specifies the chosen model (default: minilm) and compute device

This guarantees consistency across the application boundary, ensuring that every subprocess operates against the same semantic palace.

Status Monitoring

The status() method (lines 84-95) aggregates system state into a MemoryStatus object that reports three critical conditions:

  1. CLI availability (binary found in PATH)
  2. User-enabled configuration flag (semanticMemory in config)
  3. Existence of the palace directory on disk

This tri-state check enables the UI to display accurate initialization states and allows the system to gracefully degrade when dependencies are missing.

Semantic Memory Lifecycle and Mining Loop

The semantic memory subsystem operates on a continuous lifecycle: initialization, periodic mining, and on-demand retrieval.

Palace Initialization and Garbage Collection

During start() (lines 23-34), the manager performs initial housekeeping:

  • Quarantine reaping – Calls reapPalace() to remove stray temporary copies left by MemPalace’s rename-aside mechanism
  • Directory validation – Confirms the palace home folder exists before attempting operations
  • Mining loop activation – Begins the background process that synchronizes markdown changes into vector embeddings

The reapPalace() function specifically targets directories listed in quarantineDirsToReap, cleaning up orphaned segments that could otherwise consume disk space.

The Mining Process

The core synchronization mechanism runs every MINE_INTERVAL_MS (10 minutes) via startMineLoop(). The process follows this sequence:

  1. Change detection – Scans hive/agents/*/memory.md for modifications since the last cycle
  2. Serialized execution – Uses a mining flag to prevent concurrent mempalace mine processes
  3. Per-agent processing – Executes mempalace mine <agentDir> --wing <id> --agent <id> for each changed file
  4. Timeout handling – Aborts operations exceeding 10 minutes to prevent system hangs
  5. Backoff logic – If quarantine directories are detected, nextMineDelayMs (imported from palaceReap.ts) extends the interval up to MINE_BACKOFF_MAX_MS (30 minutes)

The mineNow() method (lines 89-113) exposes this functionality for manual triggering, handling the full lifecycle including .gitignore rule application.

Search and Wake-up Operations

The manager exposes two primary retrieval APIs that wrap CLI calls:

search(query, options) – Executes mempalace search with configurable result limits:

import { memory } from './index';   // singleton from src/main/index.ts

async function semanticSearch(query: string) {
  const result = await memory.search(query, { results: 10 });
  if (result.ok) {
    console.log('Search results:\n', result.output);
  } else {
    console.error('Search failed:', result.error);
  }
}

wakeUp(wingId?) – Retrieves a concise digest (600-900 tokens) of the entire palace or a specific wing:

async function wakeUpForWing(wingId: string) {
  const { ok, output, error } = await memory.wakeUp(wingId);
  if (ok) {
    // output contains condensed palace summary
    return output;
  }
  throw new Error(error);
}

Both methods utilize the internal runCli() wrapper to spawn subprocesses and parse stdout/stderr streams.

Dynamic Refresh Capabilities

The refresh() method (lines 58-62) enables hot-reloading of the semantic memory subsystem. When users toggle the feature in settings or install the CLI after application startup, this function:

  • Clears the binary cache via resetBinCache()
  • Re-evaluates CLI availability
  • Restarts the mining loop if conditions are met

This adaptability ensures the system responds to configuration changes without requiring a full application restart.

Configuration and UI Integration

Semantic memory management is tightly integrated with the application's configuration layer and renderer process.

Configuration Schema

The feature flag resides in src/main/config.ts (lines 18-21):

/** Enable semantic memory (MemPalace CLI). No-op if mempalace isn't installed. */
semanticMemory: boolean;

When true (the default), the system attempts to activate the memory manager during bootstrap. The configuration also specifies the embedding model via embeddingModel, defaulting to minilm if unspecified.

Singleton Instantiation

In src/main/index.ts (lines 6-9), the application creates a single MemoryManager instance:

const memory = new MemoryManager(
  () => readConfig().harnessHome,
  () => ({
    enabled: c.semanticMemory !== false,
    model: c.embeddingModel ?? 'minilm'
  })
);

This singleton pattern ensures consistent state across the main process while allowing lazy evaluation of configuration values.

Settings Modal and IPC Wiring

The renderer communicates with the memory subsystem through IPC channels defined in src/main/realtimeActions.ts (lines 156-162). The Settings component (src/renderer/src/components/SettingsModal.tsx, lines 306-312) provides the user interface:

// Renderer – SettingsModal.tsx (simplified)
const toggleSemantic = async (next: boolean) => {
  await window.cth.updateConfig({ semanticMemory: next });
  setSemMemOn(next);
};

When toggled, the configuration update propagates to the main process, triggering MemoryManager.refresh() to re-arm or suspend the mining loop accordingly.

Practical Implementation Examples

Manually Triggering a Re-mine

For development or debugging scenarios, you can force an immediate mining cycle:

// Exposed via IPC or dev console
memory.mineNow().then(() => console.log('Mining cycle completed'));

This runs the full mineNow() implementation, respecting timeouts and quarantine detection while bypassing the standard interval timer.

Checking Semantic Memory Availability

Before performing operations, verify the subsystem is ready:

const status = await memory.status();
if (status.available) {
  console.log(`Palace located at: ${process.env.MEMPALACE_PALACE_PATH}`);
} else {
  console.warn('Semantic memory unavailable - install mempalace CLI');
}

Environment-Aware Process Spawning

When spawning agents that need semantic access, use the manager's environment injection:

const childEnv = memory.childEnv();
const agentProcess = spawn('agent-binary', [], {
  env: { ...process.env, ...childEnv }
});

This ensures the subprocess inherits MEMPALACE_PALACE_PATH and embedding model configurations.

Summary

  • Munder Difflin implements semantic memory through the MemoryManager class in src/main/memory.ts, which orchestrates an external MemPalace vector index.
  • The system detects the mempalace CLI via the bin() method, searching PATH and common installation directories with fallback logic.
  • A background mining loop runs every 10 minutes (with 30-minute backoff capability) to convert agent memory.md files into vector embeddings via mineNow().
  • Environment variables (MEMPALACE_PALACE_PATH) ensure consistent palace access across all agent processes.
  • The search() and wakeUp() APIs provide semantic retrieval capabilities, returning ranked results or condensed palace digests.
  • Configuration is controlled by the semanticMemory boolean in src/main/config.ts, accessible through the Settings modal with hot-reload support via refresh().
  • Garbage collection via reapPalace() prevents disk pollution from temporary quarantine directories.

Frequently Asked Questions

What is the MemPalace CLI and why does Munder Difflin require it?

The MemPalace CLI is an external dependency that provides vector indexing and semantic search capabilities. Munder Difflin delegates embedding generation and similarity search to this tool rather than implementing vector operations internally. The MemoryManager acts as a Node.js wrapper, spawning mempalace subprocesses for mining, searching, and wake-up operations. If the CLI is not installed, the semantic memory subsystem gracefully degrades to a no-op state while the rest of the application continues functioning.

How often does the MemoryManager mine agent memories?

By default, the mining loop executes every 10 minutes (MINE_INTERVAL_MS). However, if the system detects quarantine directories (temporary files left by MemPalace operations), the nextMineDelayMs backoff logic extends this interval up to a maximum of 30 minutes (MINE_BACKOFF_MAX_MS). Developers can also trigger immediate mining via the mineNow() method without waiting for the interval.

What happens if the MemPalace CLI is installed after Munder Difflin starts?

The application handles late CLI installation through the refresh() mechanism. When the user toggles semantic memory in settings or the system detects a configuration change, MemoryManager.refresh() clears the binary cache, re-scans for the CLI, and starts the mining loop if the binary is now available. This dynamic adaptation eliminates the need to restart the application when installing dependencies.

Can semantic memory be enabled for specific agents only?

Currently, the semanticMemory configuration flag operates globally across the entire hive. The mining process automatically discovers all agents through the hive/agents/*/memory.md glob pattern, processing every changed file regardless of individual agent settings. While the search() and wakeUp() APIs accept optional wing parameters to filter results, the underlying vector index includes embeddings from all agents whose memory files have been mined.

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 →