Problem
Running CodeGraph from several coding-agent sessions on an 8 GB Apple Silicon Mac led to sustained watcher work and memory pressure. Project-local ignore rules should be sufficient to keep generated files out of the graph; maintaining duplicated lists in every agent configuration is not a reliable workaround because the MCP watcher does not receive those settings.
Affected installation: @astudioplus/codegraph-mcp 0.20.1, engine commit 489ccf1612555510f8367e3e673181f6a1275fe4. The relevant paths still have these behaviors on current main, 64f4f306e2a88eaba43eaef05499779d7fe6f75b.
Evidence and root causes
A saved macOS process sample reports a 1.5 GB physical footprint (1.6 GB peak). On the sampled worker, 2,108 samples are inside McpFileWatcher::process_changes; 1,895 descend through QueryBuilder::execute, including substantial time in PropertyMap::get. This establishes the hot path, not an infinite loop, database corruption, or the identity of the triggering files.
Source inspection identifies the following mechanisms:
Minimal reproduction
- Create an otherwise empty workspace with one Rust source file, a
cache/ directory, .gitignore containing /cache/, and .codegraphignore containing **/cache/**.
- Start a regular stdio MCP session with
--workspace <workspace> --graph-only --exclude cache. Call a structural tool once to initialize indexing, keeping stdin open.
- Create several supported source files in
cache/, e.g. .rs files containing uniquely named functions. Wait beyond the two-second debounce, then search for those functions. The watcher admits them despite the initial indexing exclusions. Deleting those files exercises the repeated path-query scans.
- Separately, start the npm wrapper with
CODEGRAPH_ENGINE=1, a fresh socket and --graph-only --profile core --max-files 1 --exclude cache. Its auto-started engine does not preserve those flags. Two simultaneous connections to a cold workspace can duplicate indexing/watchers.
Reproduction result
The regular-MCP reproduction above was also run against the installed 0.20.1 native binary using an isolated temporary home and workspace: after creating 20 ignored Rust files and waiting five seconds, symbol search returned their functions. Its stderr also confirmed MemoryManager::initialize ran despite --graph-only. The reproduction selected the local static embedding backend with an absent model path to avoid downloading/loading a model; the graph-only violation is the attempted initialization itself.
Expected behavior
Use one workspace filter for initial directory indexing and MCP events, including existing project ignore files. Avoid repeating a full-graph path scan for every event. Honor graph-only before any model initialization. Make the existing shared-engine mode preserve resource settings and initialize each workspace once, so users can choose one backend per workspace instead of one per agent session.
Fix and regression tests: #24. No private repository contents or full process dumps are needed to reproduce the source-level issues.
Problem
Running CodeGraph from several coding-agent sessions on an 8 GB Apple Silicon Mac led to sustained watcher work and memory pressure. Project-local ignore rules should be sufficient to keep generated files out of the graph; maintaining duplicated lists in every agent configuration is not a reliable workaround because the MCP watcher does not receive those settings.
Affected installation:
@astudioplus/codegraph-mcp0.20.1, engine commit489ccf1612555510f8367e3e673181f6a1275fe4. The relevant paths still have these behaviors on current main,64f4f306e2a88eaba43eaef05499779d7fe6f75b.Evidence and root causes
A saved macOS process sample reports a 1.5 GB physical footprint (1.6 GB peak). On the sampled worker, 2,108 samples are inside
McpFileWatcher::process_changes; 1,895 descend throughQueryBuilder::execute, including substantial time inPropertyMap::get. This establishes the hot path, not an infinite loop, database corruption, or the identity of the triggering files.Source inspection identifies the following mechanisms:
SKIP_DIRSlist. Its startup call receives noIndexConfig. Consequently--excludeand.codegraphignoreaffect initial indexing but not subsequent MCP file events. The watcher and indexer also do not honor.gitignore.process_changesperforms full-graphquery().property("path", ...).execute()scans repeatedly for changed/deleted/dependent files, including deletions of files that were never indexed. Bursts of generated source-file events multiply that work.graph_only. This can attempt embedding-model initialization despite--graph-only.CODEGRAPH_ENGINE=1shared engine could reduce per-session duplication, but auto-spawn only forwards the embedding model, dropping resource settings such as excludes, max-files, graph-only and profile. Concurrent attaches can also construct and return separate backends for the same workspace; concurrent auto-starts are protected only by a socket probe, before model/workspace loading and binding.Minimal reproduction
cache/directory,.gitignorecontaining/cache/, and.codegraphignorecontaining**/cache/**.--workspace <workspace> --graph-only --exclude cache. Call a structural tool once to initialize indexing, keeping stdin open.cache/, e.g..rsfiles containing uniquely named functions. Wait beyond the two-second debounce, then search for those functions. The watcher admits them despite the initial indexing exclusions. Deleting those files exercises the repeated path-query scans.CODEGRAPH_ENGINE=1, a fresh socket and--graph-only --profile core --max-files 1 --exclude cache. Its auto-started engine does not preserve those flags. Two simultaneous connections to a cold workspace can duplicate indexing/watchers.Reproduction result
The regular-MCP reproduction above was also run against the installed 0.20.1 native binary using an isolated temporary home and workspace: after creating 20 ignored Rust files and waiting five seconds, symbol search returned their functions. Its stderr also confirmed
MemoryManager::initializeran despite--graph-only. The reproduction selected the localstaticembedding backend with an absent model path to avoid downloading/loading a model; the graph-only violation is the attempted initialization itself.Expected behavior
Use one workspace filter for initial directory indexing and MCP events, including existing project ignore files. Avoid repeating a full-graph path scan for every event. Honor graph-only before any model initialization. Make the existing shared-engine mode preserve resource settings and initialize each workspace once, so users can choose one backend per workspace instead of one per agent session.
Fix and regression tests: #24. No private repository contents or full process dumps are needed to reproduce the source-level issues.