.memtraceignore
Control what Memtrace indexes: gitignore rules, a built-in noise baseline, your repo-root .memtraceignore, and hard skips for dependencies, binaries, and oversized files.
Memtrace's filesystem walker is gitignore-aware out of the box. For paths you want git to track but Memtrace to skip, add a .memtraceignore file at the repo root. A built-in noise baseline and hard skip lists also run on every index — no configuration required.
Overview#
| Layer | Honoured by default? | Configurable? |
|---|---|---|
.gitignore (any level), .git/info/exclude, global gitignore | ✅ yes | Turn off with no_ignore_vcs on index_directory (MCP) |
| Default noise baseline (benchmarks, fixtures, lock files, generated configs, …) | ✅ always on | Override with !path rules in .memtraceignore |
.memtraceignore (repo root) | ✅ when present | Edit the file |
| Hard directory skips (node_modules, target, dist, .memdb, …) | ✅ always on | Not user-configurable |
| Extension / filename skips (binaries, lock files, .env*, …) | ✅ always on | Not user-configurable |
| Max file size (512 KB) | ✅ always on | Not user-configurable |
If a path is excluded by any layer, it is not indexed.
When to use .memtraceignore#
Use .gitignore when a path should not be in version control. Use .memtraceignore when a path should stay in git but should not pollute the symbol graph or burn embedding budget:
- Generated protobuf / GraphQL / OpenAPI bindings checked in for review
- Large test fixtures and snapshot directories
- Committed vendored dependencies you do not want analysed
- Agent runtime directories (e.g.
.claude/,.codex/) that duplicate source under new paths - Repository docs or marketing sites that are not application source
Check .memtraceignore into the repo so every teammate and CI run indexes the same surface. The file uses standard gitignore syntax — no Memtrace-specific extensions.
Syntax and examples#
Place .memtraceignore at the repo root. Syntax matches .gitignore: * globs, **/ for any depth, leading ! for negation, trailing / for directory-only matches.
# Generated bindings: in source control, but huge and uninteresting generated/ *.pb.go *.pb.ts # Auto-emitted route trees and migration SQL src/routeTree.gen.ts drizzle/migrations/ # Test fixtures with megabyte JSON blobs tests/fixtures/large/ # Vendored dependency you committed but don't want analysed third_party/legacy-sdk/ # Agent worktrees and transcripts (defence-in-depth on top of built-in skips) .claude/ .codex/
Common patterns
| Goal | Pattern |
|---|---|
| Index only one package in a monorepo | packages/*/ !packages/api/ |
| Skip vendored / external deps | third_party/ deps/ external/ |
| Skip generated clients | *.pb.go *.pb.ts src/__generated__/ src/graphql/generated/ |
| Re-include one file under a noise path | !tests/fixtures/special-config.yaml
|
Memtrace re-reads .memtraceignore on every index_directory call. With file watching enabled (memtrace start), changes take effect on the next reindex of affected paths.
How the layers stack#
Layer 1 — Git ignores
The walker uses Rust's ignore crate (same family as ripgrep), so every git ignore source is honoured: nested .gitignore files, .git/info/exclude, and your global excludes file. If git already ignores a path, Memtrace skips it too — no extra configuration needed.
git check-ignore -v path/to/file # Prints the matching rule, or exits non-zero if NOT ignored.
Layer 2 — Default noise baseline
Shipped with the binary and always applied under your .memtraceignore. It targets obvious noise that generic config parsers would otherwise turn into thousands of low-signal ConfigKey nodes: benchmark fixtures, dataset dumps, generated configs, lock files, and editor state.
User patterns overlay the baseline — !path re-includes work the same way as in gitignore. See Default noise baseline for the full list.
Layer 3 — Your .memtraceignore
Repo-root .memtraceignore is the knob you control. Patterns apply on top of the baseline; negation rules can pull specific paths back into the index.
Layer 4 — Built-in hard skips
Even with no ignore files, the walker always skips known dependency trees, build output, caches, Memtrace's own state directories, and non-source file types. See Built-in skips.
Default noise baseline#
Always-on patterns (representative subset):
**/benchmarks/** **/benchmark/** **/datasets/** **/test_data/** **/tests/fixtures/** **/__fixtures__/** **/*.gen.json **/*.gen.ts **/*.gen.go **/*.gen.py **/*.gen.rs **/package-lock.json **/yarn.lock **/pnpm-lock.yaml **/.vscode/** **/.idea/** **/.DS_Store
Filename-gated scanners (Cargo.toml, package.json, pyproject.toml, GitHub workflow YAML, Terraform *.tf, SQL migrations) still run even when a file lives under a default-ignored directory. A package.json inside tests/fixtures/sample-pkg/ still emits scripts and dependencies. The baseline only suppresses generic config-key extraction that would emit one node per key: value pair.
Built-in skips#
Directory names
Skipped wherever they appear: node_modules, target, dist, .next, coverage, __pycache__, .venv, .terraform, .git, .memdb, .memtrace, .claude, and other dependency / build / cache / IDE directories. These are not overridable — the intent is that they are never meaningful to index.
Extensions and filenames
Binary and media extensions (images, video, archives, compiled artefacts), database blobs, office documents, certificates, and source maps are skipped by extension. Exact filename matches skip lock files, .env* variants, licence files, changelogs, and common linter/config dotfiles.
Max file size
Files larger than 512 KB are skipped. Minified bundles and single-file generated artefacts typically exceed this and contribute little structural signal.
The smallest unit Memtrace can ignore is a file. To exclude one function inside a large file, extract it to a separate file you can list in .memtraceignore.
Verify what is indexed#
If a path you expected is missing from the graph:
- Check git first.
git check-ignore -v <path>— if it matches, gitignore is filtering it. - Check .memtraceignore. Look for a pattern that matches the path in your repo root file.
- Check built-in skips. Paths under
node_modules/,target/,dist/, etc. are hard-skipped. - Check size and type. Files >512 KB, binaries, lock files, and
.env*files are never indexed by design.
After indexing, memtrace status prints skip counters when the sum is > 0:
Indexed: 1,247 files Skipped by default ignore: 42 files Skipped by user .memtraceignore: 8 files Skipped by scanner gate: 18 files
memtrace status --json exposes the same numbers under noise_filter: walker_skipped_by_default_ignore, walker_skipped_by_user_memtraceignore, and scanner_skipped_by_gate. Counters are process-lifetime on the running daemon — a one-shot status run against a cold backend often shows zero even if the live daemon skipped plenty during indexing.
From the dashboard#
In the dashboard Explorer Files tab, select a single repository and use Add to .memtraceignore on any file. This appends the repo-relative path to .memtraceignore and evicts matching symbols from the live graph — no manual edit or full reindex required for that file.
The action is disabled in all-repositories view; pick one repo first. The pattern is deduplicated if it is already present.
After changing ignore rules#
New ignore rules apply on the next walk. Files that were already indexed stay in the graph until evicted or cleaned up:
- Dashboard ignore action — evicts matching paths immediately (see above).
- Incremental reindex — memtrace index or
index_directorywithincremental: truedetects deletions and removes orphaned symbols. This is usually enough when adding a few new patterns. - Full rebuild —
memtrace index --clearorindex_directorywithclear_existing: truedrops the prior graph for that repo and reindexes from scratch. - Targeted scrub —
cleanup_stale_records(MCP) can remove orphan records for deleted or now-ignored files; usedry_run: falseto mutate.
See also Data directories for where .memdb lives, memtrace index for one-shot indexing, and MCP tools for index_directory and watch_directory.