How Codebase-Memory-MCP Detects Code Changes: Git-Based Watcher Architecture

Codebase-Memory-MCP detects code changes through a lightweight Git-based watcher that polls repositories, compares HEAD commits, checks working tree dirty states, and triggers adaptive re-indexing.

The DeusData/codebase-memory-mcp project implements a local-first approach to keeping its knowledge graph synchronized with your codebase. Understanding how Codebase-Memory-MCP detects code changes reveals a sophisticated polling mechanism that balances resource efficiency with real-time awareness.

Project Registration and Baseline Initialization

Before detecting changes, the system must establish a monitoring baseline for each repository.

Registering Projects with cbm_watcher_watch()

Projects enter the watch list via cbm_watcher_watch() in src/watcher/watcher.c (lines 85-95). This function allocates a project_state_t structure for each indexed project, storing metadata required for subsequent change detection cycles.

Initializing Baselines with init_baseline()

When a project is first registered, init_baseline() performs three critical validations:

  1. Repository verification – Calls is_git_repo() to confirm the root directory contains a valid Git repository
  2. HEAD capture – Records the current commit hash via internal Git operations
  3. File counting – Executes git_file_count() to determine the repository size for adaptive polling calculations

This initialization occurs in src/watcher/watcher.c (lines 60-78), establishing the reference point against which all future changes are measured.

Adaptive Polling Mechanism

The watcher employs an intelligent polling strategy that scales with repository size.

Dynamic Interval Calculation

The polling interval adapts based on tracked file count to prevent resource exhaustion. The calculation follows: base 5 seconds + 1 second per 500 files, capped at a maximum of 60 seconds. This logic appears in src/watcher/watcher.c (lines 64-68), ensuring large monorepos do not trigger excessive Git operations.

The Background Run Loop

The cbm_watcher_run() function implements the continuous monitoring loop (lines 21-30 and 31-46). It repeatedly calls cbm_watcher_poll_once() and sleeps in small chunks to enable rapid service shutdown. This architecture ensures the MCP server remains responsive while maintaining vigilance over registered projects.

Git-Based Change Detection

Every poll cycle executes check_changes() to determine if the knowledge graph requires updating.

Detecting HEAD Movement

The primary change detection mechanism compares the stored baseline against the current repository state:

  • git_head() – Retrieves the current HEAD commit hash to detect new commits, checkouts, or pulls (lines 91-99)
  • Hash comparison – If the returned hash differs from the stored project_state_t baseline, the system identifies a committed change

Checking Working Tree Status

Beyond committed changes, the watcher detects uncommitted modifications:

  • git_is_dirty() – Examines the working tree for unstaged or uncommitted changes, including submodule dirty states (lines 137-154)
  • Comprehensive coverage – This captures developer work-in-progress that has not yet been committed but affects code semantics

Re-indexing and Synchronization

When check_changes() identifies modifications, the system triggers automatic knowledge graph updates.

Triggering the Index Pipeline

Upon change detection, the watcher invokes the registered index_fn callback (lines 44-51 and 45-53). This function pointer drives the full indexing pipeline, parsing modified files and updating the graph database. Successful re-indexing updates the stored HEAD hash and recalculates the adaptive polling interval for the next cycle.

Auto-Index Configuration

Users can enable automatic indexing via the configuration command:

codebase-memory-mcp config set auto_index true

When enabled, new projects receive immediate baseline initialization upon first open, and the background watcher maintains continuous synchronization without manual intervention.

Explicit Change Detection Tool

Beyond automatic polling, Codebase-Memory-MCP exposes a callable RPC for agents requiring immediate change impact analysis.

The detect_changes MCP tool maps Git diffs onto the knowledge graph, returning affected symbols and risk classifications. This tool, implemented in src/mcp/tools/detect_changes.c, wraps the same Git-status checks used by the watcher but provides granular visibility into specific modifications.


# Query symbols impacted by current git diff

codebase-memory-mcp cli detect_changes '{"project":"myproject"}'

Practical Usage Examples

Trigger manual re-indexing when you need immediate updates outside the polling cycle:

codebase-memory-mcp cli index_repository '{"repo_path":"/path/to/my/project"}'

Enable persistent automatic indexing for all future sessions:

codebase-memory-mcp config set auto_index true

Check specific project changes through the MCP tool interface:

codebase-memory-mcp cli detect_changes '{"project":"myproject"}'

Summary

  • Git-native detection – Codebase-Memory-MCP relies on Git operations (git_head(), git_is_dirty()) rather than filesystem hooks, ensuring compatibility across platforms
  • Adaptive polling – Intervals scale from 5 seconds to 60 seconds based on repository file count, optimizing CPU usage
  • Dual-change detection – Monitors both committed HEAD movement and uncommitted working tree dirty states
  • Automatic re-indexing – The index_fn callback triggers full pipeline reprocessing when changes are detected
  • Local-first architecture – All operations run within the src/watcher/watcher.c implementation without external service dependencies

Frequently Asked Questions

How does Codebase-Memory-MCP detect code changes without filesystem watchers?

The system uses a polling-based architecture centered in src/watcher/watcher.c rather than inotify or FSEvents. Every cbm_watcher_poll_once() cycle executes Git commands to compare the current HEAD against the stored baseline and check dirty states. This approach avoids platform-specific filesystem notification APIs while maintaining cross-platform consistency.

What triggers a re-index in Codebase-Memory-MCP?

Re-indexing occurs when check_changes() detects either a moved HEAD (new commits, pull operations, or branch checkouts) or a dirty working tree (uncommitted modifications). The watcher then calls the registered index_fn to rebuild the knowledge graph. Users can also trigger manual re-indexing via the index_repository CLI command.

How does the adaptive polling interval work?

The interval calculation in src/watcher/watcher.c (lines 64-68) starts at 5 seconds and adds 1 second for every 500 tracked files, capped at 60 seconds. This ensures small repositories receive near-real-time updates while massive monorepos do not overwhelm system resources with excessive Git operations.

Can I disable automatic change detection and run updates manually?

Yes. Set auto_index to false using codebase-memory-mcp config set auto_index false. With automatic polling disabled, the background watcher skips registered projects, and you must explicitly call index_repository or detect_changes to synchronize the knowledge graph with your codebase.

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 →