How it works
Sigil is a local-first memory infrastructure. It stores knowledge in your own Postgres database and exposes it through two interfaces: a CLI (for agents with shell access) and an MCP server (for agents that prefer structured tool calls).
The two interfaces
Section titled “The two interfaces”CLI — universal, works everywhere
Any agent that can run a shell command can use Sigil with zero client-specific integration:
sigil search "JWT auth setup"sigil remember "we use jose, not jsonwebtoken"Claude Code’s Bash tool, Codex CLI, Hermes, CI scripts — all use this path today. If the agent can run git, it can run sigil.
MCP server — structured, for clients that prefer it
The same memory is exposed as a 9-tool MCP server. Cursor, Continue, Cline, Windsurf, and any other MCP-spec client use this path. sigil register --print outputs the config.
The two interfaces share the same storage, the same search pipeline, and the same memory model. They’re different surfaces on one brain.
Three storage layers
Section titled “Three storage layers”1. Facts
Section titled “1. Facts”Atomic statements with metadata: confidence score, importance (1–5), temporal validity (valid_from / valid_to), supersession links (which older fact this one replaced), and pod attribution (which session or project generated it).
A fact looks like: “We use Postgres LISTEN/NOTIFY for event delivery, not Redis pubsub — recorded in project sigil, confidence 0.95, importance 3, valid from 2024-11-01.”
Facts are the primary memory unit. Most queries retrieve facts.
2. Chunks
Section titled “2. Chunks”Raw 512-token blocks of ingested documents, with embeddings from your chosen provider. Used for document-level retrieval when you ingest files, URLs, or directories with sigil ingest.
3. Entity graph
Section titled “3. Entity graph”Typed nodes (person, project, service, tool, …) with relations between them. Built automatically as facts mention entities. Traversed via recursive CTEs for graph queries (search_entity, traverse_graph).
The entity graph answers questions like: “What do I know about the platform team?” or “What services does the auth service depend on?”
Retrieval pipeline
Section titled “Retrieval pipeline”A search query runs this pipeline in a single SQL statement:
- Vector search — pgvector cosine similarity on the query embedding against all stored fact and chunk embeddings.
- Keyword search — PostgreSQL
tsvectorBM25 match on the same query. - Reciprocal Rank Fusion (RRF) — combine the two ranked lists into one fused ranking. RRF is robust to score scale differences and consistently outperforms score averaging.
- ACT-R activation re-ranking — multiply each result’s RRF score by its ACT-R activation: a function of recency and retrieval frequency (borrowed from cognitive science models of human memory).
- Hebbian boost — facts that have been retrieved together before get a small co-retrieval boost, modelling associative memory.
- Pod-aware blending — hot-context slots are filled by combining facts from the active session pod, the current project pod, relevant person pods, and vital (high-importance) facts, each with declared budget limits.
The full pipeline lives in src/memory/search/hybrid.js and src/memory/search/hybrid-sql.js.
How Claude Code auto-captures memory
Section titled “How Claude Code auto-captures memory”Four hooks run automatically in every Claude Code session:
| Hook | Trigger | What it does |
|---|---|---|
UserPromptSubmit | Before Claude reads your message | Search → inject top-K facts as additionalContext |
PostToolUse | After Edit / Write / Bash | Capture observation; SHA-256 dedup against 5-min window |
Stop | After your message is sent | Classify → extract facts + entities → AUDM against existing memory |
SessionEnd | Session close | Summarize session → promote sticky facts |
AUDM (Add / Update / Delete / Merge) is the deduplication brain. When the Stop hook extracts a new fact, AUDM decides: is this new information, an update to something we already know, a contradiction that should delete the old fact, or a near-duplicate that should be merged? This prevents pile-up as thousands of facts accumulate.
What lives where
Section titled “What lives where”~/.sigil/├── .env — config, API keys, Postgres connection├── CLAUDE.md — hot-context snapshot (top 20 facts, refreshed periodically)├── .hook-errors.log — append-only hook error log└── .last-clean-doctor — ack timestamp for proactive warnings
Postgres (your database):├── sigil_facts — atomic facts with metadata├── sigil_chunks — document chunks with embeddings├── sigil_entities — entity graph nodes├── sigil_relations — entity graph edges├── sigil_pods — pod registry└── sigil_documents — ingested document metadata