Skip to content

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).

CLI — universal, works everywhere

Any agent that can run a shell command can use Sigil with zero client-specific integration:

Terminal window
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.


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.

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.

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?”


A search query runs this pipeline in a single SQL statement:

  1. Vector search — pgvector cosine similarity on the query embedding against all stored fact and chunk embeddings.
  2. Keyword search — PostgreSQL tsvector BM25 match on the same query.
  3. 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.
  4. 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).
  5. Hebbian boost — facts that have been retrieved together before get a small co-retrieval boost, modelling associative memory.
  6. 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.


Four hooks run automatically in every Claude Code session:

HookTriggerWhat it does
UserPromptSubmitBefore Claude reads your messageSearch → inject top-K facts as additionalContext
PostToolUseAfter Edit / Write / BashCapture observation; SHA-256 dedup against 5-min window
StopAfter your message is sentClassify → extract facts + entities → AUDM against existing memory
SessionEndSession closeSummarize 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.


~/.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