| Crates.io | shodh-memory |
| lib.rs | shodh-memory |
| version | 0.1.75 |
| created_at | 2025-12-06 13:43:17.226771+00 |
| updated_at | 2026-01-25 17:30:23.009925+00 |
| description | Persistent memory for AI agents and edge devices - 3-tier memory, Hebbian learning, knowledge graph. Single binary, runs offline. |
| homepage | https://github.com/varun29ankuS/shodh-memory |
| repository | https://github.com/varun29ankuS/shodh-memory |
| max_upload_size | |
| id | 1970164 |
| size | 4,705,144 |
Persistent cognitive memory for AI agents. Local-first. Runs offline.
Give your AI agents memory that persists across sessions, learns from experience, and runs entirely on your hardware.
[dependencies]
shodh-memory = "0.1"
On first use, models (~37MB) download automatically to ~/.cache/shodh-memory/.
use shodh_memory::memory::{
MemorySystem, MemoryConfig, Experience, ExperienceType, Query, ForgetCriteria
};
use anyhow::Result;
fn main() -> Result<()> {
// Create memory system with default config
let config = MemoryConfig {
storage_path: "./my_agent_data".into(),
..Default::default()
};
let memory = MemorySystem::new(config)?;
// Store a memory
let experience = Experience {
content: "User prefers dark mode for all applications".to_string(),
experience_type: ExperienceType::Decision,
..Default::default()
};
let memory_id = memory.remember(experience, None)?;
println!("Stored memory: {:?}", memory_id);
// Semantic search
let query = Query::builder()
.query_text("user interface preferences")
.max_results(5)
.build();
let results = memory.recall(&query)?;
for mem in results {
println!("{} (importance: {:.2})", mem.experience.content, mem.importance());
}
// Flush to disk
memory.flush_storage()?;
Ok(())
}
pub enum ExperienceType {
Conversation, // Chat interactions
Decision, // Choices made (+0.30 importance)
Error, // Failures/bugs (+0.25)
Learning, // New knowledge (+0.25)
Discovery, // Found something (+0.20)
Pattern, // Recurring behavior (+0.20)
Task, // Work items (+0.15)
Context, // Background info (+0.10)
CodeEdit, // Code changes
FileAccess, // File operations
Search, // Search queries
Command, // Commands executed
Observation, // General notes (+0.05, default)
}
remember)// Basic storage
let experience = Experience {
content: "The API uses JWT for authentication".to_string(),
experience_type: ExperienceType::Learning,
..Default::default()
};
let id = memory.remember(experience, None)?;
// With metadata and tags
let experience = Experience {
content: "User prefers Rust over Python".to_string(),
experience_type: ExperienceType::Observation,
metadata: [("source".to_string(), "conversation".to_string())].into(),
..Default::default()
};
memory.remember(experience, None)?;
// With custom timestamp
use chrono::Utc;
memory.remember(experience, Some(Utc::now()))?;
recall)// Semantic search
let query = Query::builder()
.query_text("authentication methods")
.max_results(10)
.build();
let results = memory.recall(&query)?;
// Filter by type
let query = Query::builder()
.query_text("errors")
.experience_types(vec![ExperienceType::Error])
.build();
let results = memory.recall(&query)?;
// Filter by importance
let query = Query::builder()
.importance_threshold(0.5)
.max_results(20)
.build();
let results = memory.recall(&query)?;
// Convenience methods for common queries
// Recall by tags (returns all memories with ANY matching tag)
let results = memory.recall_by_tags(&["auth".to_string(), "security".to_string()], 20)?;
// Recall by date range
use chrono::{Utc, Duration};
let now = Utc::now();
let start = now - Duration::days(7);
let results = memory.recall_by_date(start, now, 50)?;
// Pagination
let query = Query::builder()
.query_text("preferences")
.max_results(10)
.offset(20) // Skip first 20
.build();
let paginated = memory.paginated_recall(&query)?;
println!("Has more: {}", paginated.has_more);
use shodh_memory::memory::types::MemoryId;
// Delete by ID
memory.forget(ForgetCriteria::ById(memory_id))?;
// Delete old memories (older than N days)
memory.forget(ForgetCriteria::OlderThan(30))?;
// Delete low-importance memories
memory.forget(ForgetCriteria::LowImportance(0.1))?;
// Delete by regex pattern
memory.forget(ForgetCriteria::Pattern(r"test.*".to_string()))?;
// Delete by tags
memory.forget(ForgetCriteria::ByTags(vec!["temporary".to_string()]))?;
// Delete by date range
use chrono::{Utc, Duration};
let end = Utc::now();
let start = end - Duration::days(7);
memory.forget(ForgetCriteria::ByDateRange { start, end })?;
// GDPR: Delete everything
memory.forget(ForgetCriteria::All)?;
// Get stats
let stats = memory.stats();
println!("Total memories: {}", stats.total_memories);
println!("Long-term: {}", stats.long_term_memory_count);
println!("Vector indexed: {}", stats.vector_index_count);
// Storage stats
let storage_stats = memory.get_storage_stats()?;
// Flush to disk
memory.flush_storage()?;
// Run maintenance (decay old memories)
let processed = memory.run_maintenance(0.95)?;
// Index health
let health = memory.index_health();
println!("Healthy: {}", health.healthy);
let config = MemoryConfig {
// Storage location
storage_path: "./data".into(),
// Working memory: hot cache for recent memories
working_memory_size: 100, // entries
// Session memory: warm cache
session_memory_size_mb: 500, // MB
// Per-user heap limit (prevents OOM)
max_heap_per_user_mb: 256, // MB
// Auto-compress old memories
auto_compress: true,
compression_age_days: 30,
// Importance threshold for long-term storage
importance_threshold: 0.3,
};
Environment variables:
SHODH_MEMORY_PATH=./data
SHODH_OFFLINE=true # Disable auto-download
RUST_LOG=info
Working Memory ──overflow──> Session Memory ──importance──> Long-Term Memory
(100 items) (500 MB) (RocksDB)
Cognitive processing:
Measured on Intel i7-1355U (10 cores, 1.7GHz):
| Operation | Latency |
|---|---|
remember() |
55-60ms |
recall() semantic |
34-58ms |
recall_by_tags() |
~1ms |
recall_by_date() |
~2ms |
| Entity lookup | 763ns |
| Hebbian strengthen | 5.7µs |
| Graph traversal (3-hop) | 30µs |
| Platform | Status |
|---|---|
| Linux x86_64 | Supported |
| macOS ARM64 | Supported |
| macOS x86_64 | Supported |
| Windows x86_64 | Supported |
| Linux ARM64 | Coming soon |
Apache 2.0