smaran
v0.1.3
Published
Smaran (Sanskrit: remembrance) — local-first professional memory for AI agents over MCP. Typed writes, append-only audit log, and an undo button. No Docker, no API keys, no account.
Maintainers
Readme
smaran
Professional memory for AI agents — with an undo button.
Smaran (स्मरण) is Sanskrit for remembrance — not just storing something, but the act of holding it with care.
Data is a retrieval problem. Memory is a write problem — what gets in, on what basis, and whether you can take it back. That's why it's called memory, not data.
Every memory tool promises your agent will remember. The real problem is what agents write: guesses saved as facts, duplicates, stale state — then recalled with perfect confidence forever. smaran is a local MCP memory server built around the write path:
- Typed writes — agents can't dump arbitrary text; a memory is a decision, a preference, a task, an event, with structure
- Refuse by default — writes against unknown projects/people are rejected; creation is explicit and audited
- Append-only audit log — every write records before/after state and which app made it
- Undo —
revert_writereverses any write; the history of the revert is itself kept - Supersede, don't delete — when a fact changes, the old one is replaced, never silently lost
Local-first: one SQLite file on your machine (~/.smaran/memory.db). No Docker, no API keys, no account, no open ports, no telemetry.
Install (one command)
npx smaran initThis detects every AI tool on your machine — Claude Code, Codex, Cursor, Gemini CLI, Windsurf — and connects them all to the same memory. It registers the MCP server in each tool's config (user-wide, so it works in every folder) and, for tools that don't load MCP instructions (Codex), writes the agent contract into AGENTS.md. It prints exactly what it changed, changes nothing twice, and you can re-run it any time you install a new tool.
That's it. Ask your agent to "create a project for X and remember that we decided Y", then in a new session — or a different AI tool — ask "what do you know about project X?"
Claude Code: claude mcp add --scope user memory -- npx -y smaran
Claude Desktop / Cursor / Windsurf — add to your MCP config:
{
"mcpServers": {
"memory": { "command": "npx", "args": ["-y", "smaran"] }
}
}Codex — add to ~/.codex/config.toml, and see "The agent contract" below for what to put in ~/.codex/AGENTS.md:
[mcp_servers.memory]
command = "npx"
args = ["-y", "smaran"]Custom database location: npx smaran --db /path/to/memory.db or set SMARAN_DB.
Use it from claude.ai in the browser: npx smaran serve
The stdio server only works for tools that can spawn a local process. For cloud clients, npx smaran serve runs the same server (same DB, same tools, same contract) over Streamable HTTP with token auth:
npx smaran serve # http://127.0.0.1:7676/mcp/<token>
ngrok http 7676 # or: cloudflared tunnel --url http://127.0.0.1:7676Then in claude.ai → Settings → Connectors → Add custom connector, paste https://<tunnel-host>/mcp/<token>. Your browser Claude now reads and writes the same memory as your terminal agents.
The token is generated once and kept in ~/.smaran/serve-token (0600) — the URL embeds it because claude.ai's connector form has no header field, so treat the URL like a password. Clients that support headers can use https://<host>/mcp with Authorization: Bearer <token> instead. Gemini Enterprise custom MCP connectors (Streamable HTTP only) work the same way; the consumer Gemini web app doesn't support custom MCP servers yet — use Gemini CLI locally via npx smaran init.
See your memory: npx smaran ui
Opens a local browser UI (127.0.0.1 only — nothing is exposed to the network): your projects with focus and open tasks, recent decisions with rationale and confidence, full-text search, and the complete audit trail. Every write shows which app made it — and has a revert button. Reverts from the UI are logged as human actions, so the history stays honest.
Tools
| Read | Write | Audit |
|---|---|---|
| search_memories (BM25) | create_project | list_recent_writes |
| list_projects / list_people / list_companies | add_person / add_company | revert_write |
| get_project_context | store_decision | |
| get_person_context | log_event | |
| get_company_context | update_project_state | |
| get_recent_decisions | save_preference | |
| get_open_loops | set_next_step / mark_done | |
| prepare_task_brief | append_note | |
Entity tools accept ids or names (get_project_context("atlas")), because that's how models actually call them.
Why keyword search instead of embeddings?
The caller is an LLM. If a search misses, it retries with synonyms or browses with the context tools — the semantic understanding lives in the model, not the index. At personal scale (thousands of memories, not millions), BM25 over typed content retrieves what matters, with zero API keys and zero setup. Typed entities are the source of truth; the search index is regenerated from them and safe to rebuild.
The agent contract
Add this to your agent instructions (CLAUDE.md, Cursor rules, custom instructions):
Before starting work, call
prepare_task_brieforget_project_contextto load relevant context. After finishing, store only durable outcomes: decisions made, status changes, preferences learned, promises, blockers, next steps. Use the most specific tool available. Never store speculation, drafts, or chain-of-thought. When a stored fact is no longer true, supersede it — don't ignore it.
Recovering from bad writes
you : what did you save to memory this session?
agent: [calls list_recent_writes] I stored 3 things: …
you : the second one is wrong, undo it
agent: [calls revert_write] Done — reverted, and the revert is logged.The audit log is append-only. Reverts never erase history; they add to it.
Roadmap
- Hosted sync (same typed schema, cloud endpoint for browser ChatGPT/Claude/Gemini and cross-device memory)
- Smart reconciliation: fuzzy dedupe, conflict detection, memory-quality sweeps
- Optional local embeddings for semantic search
MIT licensed.
