Imported from RyanWillie/mimir (
AGENTS.md). Install upstream withnpx skills add RyanWillie/mimir. Copyright stays with the author.
AGENTS.md - AI Agent Guide for Mimir Repository
Purpose: This document provides comprehensive guidance for AI agents (LLMs) working on the Mimir codebase to ensure consistent, safe, and effective contributions.
๐๏ธ Project Architecture Overview
Core Concept
Mimir is a local-first, zero-knowledge AI memory vault that provides privacy-preserving memory management for AI applications. The architecture follows a modular design with clear separation of concerns.
Workspace Structure
mimir/
โโโ crates/ # Core Rust components (Apache-2.0)
โ โโโ mimir-core/ # Shared types, errors, config
โ โโโ mimir/ # Main daemon + MCP server
โ โโโ mimir-vector/ # Vector store (HNSW)
โ โโโ mimir-db/ # Encrypted SQLite database
โ โโโ mimir-guardrails/ # PII detection & classification
โ โโโ mimir-compression/ # Memory summarization
โ โโโ mimir-sdk/ # Client library
โ โโโ mimir-cli/ # Command-line interface
โ โโโ mimir-tray/ # Desktop UI (AGPL-3.0)
โโโ bindings/ # Language bindings
โ โโโ python/ # PyO3 Python bindings
โ โโโ nodejs/ # napi-rs Node.js bindings
โ โโโ wasm/ # WebAssembly bindings
โโโ docs/ # Documentation
โโโ examples/ # Usage examples
โโโ tests/ # Integration tests
๐ง Development Guidelines for AI Agents
1. Before Making Changes
ALWAYS perform these checks:
# Check current compilation status
cargo check --workspace
# Run tests to understand current state
cargo test --workspace
# Check for linting issues
cargo clippy --workspace
# Verify formatting
cargo fmt --all --check
2. Understanding Dependencies
Workspace Dependencies: All crates share dependencies defined in root Cargo.toml
[workspace.dependencies]
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
# ... etc
Crate Dependencies: Reference workspace deps like:
[dependencies]
tokio.workspace = true
serde.workspace = true
mimir-core = { path = "../mimir-core" }
3. Core Types and Patterns
Primary Types (in mimir-core/src/types.rs):
Memory- Core memory object with content, class, metadataMemoryClass- Classification (Personal, Work, Health, Financial, Other)MemoryIngestion- Input structure for storing memoriesMemoryQuery- Query structure for retrieving memoriesMemoryResult- Search result with score
Error Handling (in mimir-core/src/error.rs):
use mimir_core::{Result, MimirError};
fn example_function() -> Result<String> {
// Use Result<T> = std::result::Result<T, MimirError>
Ok("success".to_string())
}
Configuration (in mimir-core/src/config.rs):
let config = MimirConfig::default(); // Provides sensible defaults
๐ Security Considerations for AI Agents
Critical Security Principles
- Never log sensitive data - Memory content, keys, personal information
- Use proper error handling - Don't leak sensitive info in error messages
- Follow encryption patterns - Use established crypto utilities
- Validate inputs - Always sanitize external inputs
- Respect access control - Honor app permissions and memory classes
Safe Patterns
// โ
GOOD: Safe error handling
match decrypt_memory(&encrypted_content) {
Ok(content) => process_content(content),
Err(_) => return Err(MimirError::Encryption("Failed to decrypt".to_string())),
}
// โ BAD: Leaking sensitive information
match decrypt_memory(&encrypted_content) {
Ok(content) => process_content(content),
Err(e) => return Err(MimirError::Encryption(format!("Failed: {}", e))), // May leak keys!
}
๐งช Testing Patterns
Test Structure
- Unit tests: In
src/files using#[cfg(test)] - Integration tests: In
tests/directory - Documentation tests: In
///doc comments - Benchmarks: In
benches/directory
Common Test Patterns
#[cfg(test)]
mod tests {
use super::*;
use mimir_core::{MemoryClass, Memory};
#[test]
fn test_memory_creation() {
let memory = Memory {
id: uuid::Uuid::new_v4(),
content: "test content".to_string(),
class: MemoryClass::Personal,
// ... other fields
};
assert_eq!(memory.class, MemoryClass::Personal);
}
#[tokio::test]
async fn test_async_operation() {
// Use tokio::test for async tests
let result = some_async_function().await;
assert!(result.is_ok());
}
}
๐ Common Tasks and Patterns
Adding a New Crate
-
Create directory structure:
mkdir -p crates/new-crate/src -
Create Cargo.toml:
[package] name = "mimir-new-crate" version.workspace = true edition.workspace = true license.workspace = true # ... other workspace fields [dependencies] mimir-core = { path = "../mimir-core" } # ... other deps -
Add to workspace:
# In root Cargo.toml [workspace] members = [ # ... existing crates "crates/new-crate", ] -
Create lib.rs with documentation:
//! Brief description of the crate //! //! Longer description with usage examples. use mimir_core::{Result, MimirError}; /// Main struct for this crate pub struct NewComponent { // fields } impl NewComponent { /// Create a new instance pub fn new() -> Result<Self> { Ok(Self {}) } }
Adding New API Endpoints (for mimir daemon)
-
Define in server.rs:
use axum::{Json, extract::Query}; use mimir_core::{MemoryQuery, MemoryResult}; async fn handle_memory_query( Query(query): Query<MemoryQuery> ) -> Result<Json<Vec<MemoryResult>>, MimirError> { // Implementation Ok(Json(vec![])) } -
Add route in router setup:
let app = Router::new() .route("/memories/search", get(handle_memory_query)) // ... other routes
Adding Language Bindings
Python (PyO3):
use pyo3::prelude::*;
#[pyclass]
struct PyMemory {
inner: mimir_core::Memory,
}
#[pymethods]
impl PyMemory {
#[new]
fn new(content: String) -> Self {
// Implementation
}
}
Node.js (napi-rs):
use napi_derive::napi;
#[napi]
pub struct JsMemory {
inner: mimir_core::Memory,
}
#[napi]
impl JsMemory {
#[napi(constructor)]
pub fn new(content: String) -> Self {
// Implementation
}
}
๐ Code Quality Standards
Formatting and Linting
# Format code (required before commits)
cargo fmt --all
# Check linting (must pass)
cargo clippy --workspace -- -D warnings
# Run tests (must pass)
cargo test --workspace
Documentation Standards
- Public APIs: Always document with
/// - Examples: Include usage examples in docs
- Errors: Document when functions can panic or return errors
- Safety: Document any unsafe code blocks
/// Retrieves memories matching the given query.
///
/// # Arguments
/// * `query` - The search query parameters
///
/// # Returns
/// * `Ok(Vec<MemoryResult>)` - Matching memories with relevance scores
/// * `Err(MimirError)` - If search fails or access is denied
///
/// # Examples
/// ```
/// use mimir_core::{MemoryQuery, MemoryClass};
///
/// let query = MemoryQuery {
/// query: "coffee preferences".to_string(),
/// class_filter: Some(vec![MemoryClass::Personal]),
/// top_k: 5,
/// // ... other fields
/// };
/// let results = memory_store.search(query).await?;
/// ```
pub async fn search(&self, query: MemoryQuery) -> Result<Vec<MemoryResult>> {
// Implementation
}
๐จ Error Handling Patterns
Result Types
use mimir_core::{Result, MimirError};
// Function that can fail
fn process_memory(content: &str) -> Result<ProcessedMemory> {
if content.is_empty() {
return Err(MimirError::Guardrails("Empty content".to_string()));
}
// ... processing
Ok(processed)
}
// Async function that can fail
async fn store_memory(memory: Memory) -> Result<()> {
// Use ? operator for error propagation
let processed = process_memory(&memory.content)?;
database.store(processed).await?;
Ok(())
}
Error Creation
// Use appropriate error variants
return Err(MimirError::Database(anyhow::anyhow!("Connection failed")));
return Err(MimirError::VectorStore("Index corrupted".to_string()));
return Err(MimirError::AccessDenied("App not permitted".to_string()));
๐ File Organization Patterns
Crate Structure
crate-name/
โโโ Cargo.toml
โโโ src/
โ โโโ lib.rs # Public API and module declarations
โ โโโ error.rs # Crate-specific errors (if needed)
โ โโโ types.rs # Crate-specific types
โ โโโ config.rs # Configuration structures
โ โโโ module_name.rs # Feature modules
โโโ tests/ # Integration tests
โ โโโ integration_test.rs
โโโ benches/ # Benchmarks (if needed)
โโโ benchmark.rs
Module Declaration Pattern
// lib.rs
pub mod types;
pub mod config;
pub mod engine;
pub use types::*;
pub use engine::Engine;
// Re-export important types
๐ Development Workflow
Before Implementing Features
- Read existing code to understand patterns
- Check PROJECT_STATUS.md for current implementation status
- Review ROADMAP.md for feature priorities
- Understand dependencies between components
Implementation Process
- Start with stub implementation that compiles
- Add comprehensive tests before full implementation
- Implement incrementally with frequent testing
- Document as you go - don't leave it for later
- Run full test suite before considering complete
Validation Checklist
- Code compiles without warnings
- All tests pass (
cargo test --workspace) - Clippy passes (
cargo clippy --workspace) - Code is formatted (
cargo fmt --all) - Documentation is complete
- No security anti-patterns introduced
- Integration with existing components works
๐ฏ Component-Specific Guidance
mimir-core
- Role: Shared types, errors, configuration
- Key Files:
types.rs,error.rs,config.rs - Principle: Stable API, minimal dependencies
- Changes: Require careful consideration of impact on all other crates
mimir
- Role: Main daemon process with MCP server
- Key Files:
main.rs,server.rs,mcp.rs - Principle: Robust, secure, performant
- Changes: Focus on reliability and security
mimir-vector
- Role: Vector similarity search with HNSW
- Key Pattern: Async operations, performance-critical
- Focus: Memory efficiency, search speed
mimir-db
- Role: Encrypted database operations
- Key Pattern: Secure by default, transaction safety
- Focus: Data integrity, access control
mimir-guardrails
- Role: Content analysis and PII detection
- Key Pattern: ML model integration, privacy-preserving
- Focus: Accuracy, performance, privacy
Language Bindings
- Python: Use PyO3 patterns, async-compatible
- Node.js: Use napi-rs patterns, Promise-based
- WASM: Use wasm-bindgen, browser-compatible
๐ง Troubleshooting Common Issues
Compilation Errors
- Missing dependencies: Check workspace vs. crate-specific deps
- Version conflicts: Ensure all crates use workspace versions
- Feature flags: Some dependencies may need specific features
Test Failures
- Async tests: Ensure using
#[tokio::test] - Integration tests: May need test data setup
- Timing issues: Use appropriate timeouts for async operations
Clippy Warnings
- Dead code: May be stub implementations (acceptable during development)
- Complexity: Consider breaking down large functions
- Performance: Address suggestions for hot paths
๐ Additional Resources
- CONTRIBUTING.md - Detailed contribution guidelines
- SECURITY.md - Security policies and reporting
- PROJECT_STATUS.md - Current implementation status
- docs/ROADMAP.md - Development timeline and priorities
- Rust docs:
cargo doc --workspace --open
๐ค AI Agent Best Practices
- Read before writing - Understand existing patterns
- Start small - Make incremental, testable changes
- Follow conventions - Use established patterns and naming
- Test thoroughly - Write tests for new functionality
- Document everything - Future agents (and humans) will thank you
- Security first - Always consider privacy and security implications
- Ask for clarification - When in doubt, request more context
This document is maintained to ensure AI agents can work effectively within the Mimir codebase. Update when new patterns or conventions are established.