What Is the Nearest-Marker Capture Policy in ai-memory?
The nearest-marker capture policy in ai-memory is a client-side filtering mechanism that walks upward from the current working directory to locate the closest .ai-memory.toml file and applies its [capture] ignore_paths rules to drop matching file-tool events before they reach the spool, network transport, or server storage.
The akitaonrails/ai-memory repository implements this deterministic configuration hierarchy to give developers granular control over privacy and data capture. By enforcing that only the nearest marker file is authoritative, the system prevents accidental inheritance of exclusion rules from parent directories while ensuring sensitive files never leave the local machine.
How the Nearest-Marker Policy Locates Configuration
When an ai-memory hook executes, it must determine which capture rules apply to the current working context. The resolution follows a strict upward traversal algorithm.
Walking the Directory Tree
The hook begins at the current working directory (cwd) and walks upward toward the user's home directory. It stops immediately upon encountering the first .ai-memory.toml file—this becomes the nearest marker as documented in [docs/marker-file.md](docs/marker-file.md#where-to-put-it). If the cwd resides outside any version-controlled checkout, the traversal terminates at the nearest Git repository root instead.
If no marker exists in the ancestry, the system falls back to examining only the cwd itself with no exclusion rules applied.
Fallback to Git Repository Roots
When the directory tree walk reaches a Git repository boundary before finding a marker file, that repository root serves as the stopping point. This design ensures that repository-specific configurations remain scoped to their respective codebases, preventing leakage of capture policies across unrelated projects.
Applying Capture Rules from the Nearest Marker
Once identified, the nearest marker's [capture] section dictates which file-tool events are discarded locally. This filtering occurs entirely on the client side, meaning excluded paths never traverse the network or persist to server storage.
The ignore_paths Array
The marker file defines exclusions through the ignore_paths array within the [capture] section. Any file-tool event whose path matches one of these glob patterns is dropped locally before reaching the spool or queue.
# .ai-memory.toml in repository root
[capture]
ignore_paths = ["private/**", "~/personal-notes/**", "*.secret"]
Pattern syntax supports standard globs including *, ?, and ** for recursive matching. Paths normalize lexically before comparison, with ~/ expanding to the home directory. Platform behavior differs: POSIX systems perform case-sensitive matching, while Windows uses ASCII case-insensitive comparison.
Client-Side Event Dropping
The implementation in src/ai_memory_hooks/ enforces these exclusions immediately upon event generation. When a file-tool event matches an ignore_paths pattern, the hook discards it before any spool or network activity occurs. Non-file-tool events—such as prompts or metadata—remain unaffected by the capture policy.
If the nearest marker lacks a [capture] section or specifies an empty ignore_paths array, ai-memory retains the default behavior: no paths are excluded.
Why Markers Do Not Merge
The nearest-marker policy enforces single-source authority. Unlike configuration systems that cascade or merge settings from multiple files, ai-memory uses only the closest .ai-memory.toml file and ignores any outer markers. This design guarantees deterministic capture behavior in complex directory structures such as monorepos or multi-client setups.
By preventing policy merging, the system eliminates ambiguity about which rules apply to a given file operation. An inner marker completely overrides parent configurations, ensuring that developers working within nested subdirectories control their own capture boundaries without inheriting unintended exclusions from organizational root directories.
Pattern Syntax and Operational Limits
The capture policy enforces strict resource boundaries to prevent performance degradation:
| Property | Specification |
|---|---|
| Maximum patterns | 128 entries in ignore_paths |
| Pattern length | ≤ 1,024 characters per pattern |
| Path candidates | 32 direct candidates per event |
| Candidate length | ≤ 4,096 characters per candidate path |
| Comparisons | Up to 1,000,000 pattern/candidate comparisons |
Matching events drop immediately; non-matching events proceed through the standard pipeline. If the policy is malformed or the marker unreadable, the system treats the capture policy as ignored and processes the event as metadata-only.
Practical Configuration Examples
Create a marker file in your repository root to exclude sensitive directories from all subdirectories:
cat > .ai-memory.toml <<'EOF'
[capture]
ignore_paths = ["private/**", "~/personal-notes/**"]
EOF
Test the policy with specific tool operations:
# This event is stored (no pattern match)
ai-memory hook --event post-tool-use --agent claude-code \
--tool_name Edit \
--tool_input '{"path":"src/main.rs"}' \
--server-url http://127.0.0.1:49374
# This event is dropped locally (matches private/**)
ai-memory hook --event post-tool-use --agent claude-code \
--tool_name Edit \
--tool_input '{"path":"private/secret.txt"}' \
--server-url http://127.0.0.1:49374
Verify capture decisions without affecting the spool:
printf '{"session_id":"demo","cwd":"/example/workspace","tool_name":"Edit","tool_input":{"path":"private/secret.txt"}}' \
| ai-memory hook --event post-tool-use --agent claude-code \
--server-url http://127.0.0.1:49374 --check-capture
# Output: JSON verdict showing the event was discarded due to capture policy
Implementation Architecture
According to the akitaonrails/ai-memory source code, the capture policy implementation spans several key components:
docs/marker-file.md: Defines the.ai-memory.tomlformat, nearest-marker resolution algorithm, and capture exclusion semantics.src/ai_memory_hooks/: Contains the hook implementation that performs client-side path matching against the nearest marker'signore_paths.docs/windows.mdanddocs/macos.md: Document platform-specific hook commands that enforce the nearest-marker[capture]policy on their respective operating systems.
The hook implementation performs lexical path normalization and glob matching before spooling, ensuring that excluded paths never generate network traffic.
Summary
- The nearest-marker capture policy traverses upward from
cwdto find the first.ai-memory.tomlfile and uses it exclusively, ignoring parent markers. - Client-side dropping occurs when file-tool paths match the
ignore_pathsglobs defined in the marker's[capture]section. - Pattern syntax supports standard globs with platform-specific case sensitivity (POSIX case-sensitive, Windows ASCII case-insensitive).
- Hard limits enforce maximums of 128 patterns, 1,024 characters per pattern, and 1,000,000 comparisons to maintain performance.
- No merging occurs between nested markers; the closest configuration wins completely, ensuring deterministic behavior in monorepos.
Frequently Asked Questions
What happens if no .ai-memory.toml file is found?
If the upward traversal from cwd reaches the home directory (or filesystem root if $HOME is unset) without finding a marker, the hook examines only the cwd itself and applies no capture exclusions. If the directory lies within a Git repository but outside any marked subtree, the walk stops at the repository root, and the event proceeds with default capture behavior.
Does the nearest-marker capture policy affect all ai-memory events?
No. The ignore_paths filtering applies exclusively to file-tool events—operations involving file system paths such as edits, reads, or writes. Non-file-tool events including prompts, chat messages, and metadata transmissions bypass the capture policy entirely and process normally regardless of marker configuration.
How do nested repositories handle conflicting capture policies?
Nested structures enforce strict hierarchy: the innermost .ai-memory.toml file completely overrides any outer markers. Subdirectories do not inherit ignore_paths from parent directories. When working in a subdirectory with its own marker, that marker's [capture] section governs exclusively, preventing accidental exclusion leaks from organizational root configurations while allowing sub-projects to define stricter privacy boundaries.
What is the maximum number of ignore patterns allowed?
The system enforces a hard limit of 128 patterns per marker file, with each pattern restricted to 1,024 characters. Additionally, the implementation limits processing to 32 direct path candidates per event (each ≤ 4,096 characters) and caps pattern-matching computations at 1,000,000 comparisons. Exceeding these limits results in the capture policy being ignored, with events treated as metadata-only to prevent performance degradation.
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 →