How ai-memory Captures and Ignores Files: The Complete Configuration Guide
ai-memory uses a TOML marker file containing glob patterns to filter lifecycle events through a three-stage pipeline that compiles exclusion rules and evaluates each tool call against normalized paths to decide whether to keep, drop, or anonymize the data.
ai-memory is a Rust-based telemetry system that records AI agent interactions without blocking IO. The process for capturing and ignoring files is governed by a declarative policy engine defined in crates/ai-memory-hooks/src/capture_policy.rs, which transforms repository-level configuration into compiled pattern matchers that inspect every event.
Understanding the Capture Pipeline
The system implements a pure, IO-free policy engine that processes lifecycle events through three distinct stages:
- Marker resolution: Parsing the
[capture]table from a TOML configuration - Policy compilation: Building a
CapturePolicyfrom validated glob patterns - Event inspection: Evaluating each tool call against compiled patterns to produce a
CaptureDecision
Step 1: Configuring the Marker File
Repositories opt into filtering by placing a marker file (e.g., .ai_memory.toml) at the root. The parser extracts the CaptureConfig struct, which currently supports only the ignore_paths field—a vector of glob patterns defining files or directories to exclude.
The CaptureConfig Structure
In crates/ai-memory-hooks/src/capture_policy.rs, lines 23-29, the configuration structure is defined as:
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
pub struct CaptureConfig {
#[serde(default)]
pub ignore_paths: Vec<String>,
}
Create a marker file at your repository root to activate filtering:
# .ai_memory.toml
[capture]
ignore_paths = [
"secret/**", # ignore everything under ./secret
"~/private/**", # ignore under the user's home dir
"build/*.tmp", # ignore temporary build files
]
Step 2: Choosing a Capture Mode
When no marker file exists, the system falls back to a default behavior defined by CaptureMode. This enum, located at lines 36-45 in capture_policy.rs, supports two strategies:
- Denylist (default): Capture everything unless it matches an ignore pattern
- Allowlist: Capture nothing unless a marker file is present
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
pub enum CaptureMode { #[default] Denylist, Allowlist }
The helper function repository_admits_capture (lines 59-64) implements this logic:
pub const fn repository_admits_capture(mode: CaptureMode, marker_present: bool) -> bool {
match mode {
CaptureMode::Denylist => true,
CaptureMode::Allowlist => marker_present,
}
}
Step 3: Resolving the CapturePolicy
The CapturePolicy::resolve method transforms the parsed configuration into an executable policy. This function, spanning lines 17-42 in capture_policy.rs, accepts the CaptureSource, the marker's directory path, and an optional home directory for expanding ~/ patterns.
pub fn resolve(source: CaptureSource<'_>, marker_dir: &str, home_dir: Option<&str>) -> Self { … }
During resolution, the system validates each glob pattern, expands relative paths against the marker location, and compiles them into CompiledPattern instances. If patterns are invalid or exceed limits, the policy returns Invalid.
Step 4: Inspecting Events and Making Decisions
When a tool event arrives, CapturePolicy::inspect (lines 49-90) extracts relevant metadata including tool family, candidate file paths, and call identifiers via the extract function.
CaptureDisposition Logic
The method returns a CaptureDecision containing a CaptureProtocol sent to the client as _ai_memory_capture. The disposition follows these rules:
- Inactive: If
ignore_pathsis empty, returnKeep - Invalid: If the policy is invalid and tool family is
File, returnMetadataOnly - Active: Match each candidate path against compiled patterns:
- Match found →
Drop(event discarded) - No match →
Keep
- Match found →
Path Normalization and Pattern Matching
Before evaluation, candidate paths undergo normalization via normalize_candidate (lines 85-99) to handle absolute paths, collapse .. segments, and normalize separators for Windows/Posix compatibility.
The actual pattern matching uses glob_match (lines 139-176), which implements limited glob syntax supporting wildcards and recursive patterns (**).
Handling Dropped and Metadata-Only Events
When an event is dropped, the entire payload is discarded. For MetadataOnly disposition, the system constructs a safe replacement using metadata_only_body (lines 44-62), which preserves only:
session_idcwd(current working directory)tool_familytool_name- Optional
tool_call_id - Encoded
CaptureProtocol
use ai_memory_hooks::capture_policy::metadata_only_body;
let meta = metadata_only_body(
Some("session-123"),
Some("/repo"),
&decision,
);
Practical Implementation Example
The following Rust example demonstrates loading a configuration, resolving the policy, and inspecting a tool payload:
use ai_memory_hooks::capture_policy::{
CapturePolicy, CaptureSource, CaptureConfig, CaptureDisposition
};
use ai_memory_core::AgentKind;
use serde_json::json;
// Simulate parsing a marker file
let cfg = CaptureConfig {
ignore_paths: vec!["secret/**".into()]
};
let policy = CapturePolicy::resolve(
CaptureSource::Parsed(&cfg),
"/repo", // marker directory
None, // no home dir expansion needed
);
// Simulated tool payload attempting to edit a sensitive file
let payload = json!({
"tool_name": "edit_file",
"tool_input": { "file_path": "secret/token.txt" }
});
// Evaluate for a Codex agent
let decision = policy.inspect(AgentKind::Codex, &payload, "/repo");
assert_eq!(decision.protocol().disposition(), CaptureDisposition::Drop);
Summary
- ai-memory implements capturing and ignoring files through a marker-based configuration system using TOML files with
[capture]tables. - The
CaptureConfigstruct acceptsignore_pathsas glob patterns, processed byCapturePolicy::resolveincrates/ai-memory-hooks/src/capture_policy.rs. - Two capture modes exist: Denylist (default, capture unless excluded) and Allowlist (capture only when marker exists), implemented via
repository_admits_capture. - The
inspectmethod evaluates tool events against normalized paths, returningKeep,Drop, orMetadataOnlydispositions. - Invalid patterns or excessive entries cause the policy to become
Invalid, triggering metadata-only capture for file operations as a safety fallback.
Frequently Asked Questions
How do I exclude sensitive files from ai-memory logging?
Create a .ai_memory.toml file in your repository root with a [capture] section containing ignore_paths entries. Use glob patterns like "secret/**" or "*.env" to specify files or directories. The system compiles these patterns during CapturePolicy::resolve and applies them via match_paths during event inspection.
What happens if I provide an invalid glob pattern in the ignore_paths list?
If a pattern fails validation during policy resolution, or if the list contains too many entries, CapturePolicy::resolve returns an Invalid policy state. According to the logic in CapturePolicy::inspect, file-related events handled by an invalid policy receive MetadataOnly disposition, ensuring sensitive data is not captured while flagging the configuration error.
Can I use ai-memory in allowlist mode to capture only specific repositories?
Yes. Set CaptureMode::Allowlist to change the default behavior so that repositories without a marker file are completely excluded from capture. When combined with the repository_admits_capture helper, this mode ensures the hook only activates when CaptureConfig is explicitly present, as implemented in lines 59-64 of crates/ai-memory-hooks/src/capture_policy.rs.
What is the difference between Drop and MetadataOnly dispositions?
Drop completely discards the event payload with no storage, triggered when an active policy matches a path against ignore_paths. MetadataOnly, defined in lines 44-62 of the source, replaces the full payload with a minimal JSON object containing session metadata and the CaptureProtocol, preserving observability headers without recording sensitive tool inputs.
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 →