惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
博客园_首页
博客园 - 三生石上(FineUI控件)
V
Visual Studio Blog
Hugging Face - Blog
Hugging Face - Blog
美团技术团队
小众软件
小众软件
T
Tailwind CSS Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
月光博客
月光博客
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
罗磊的独立博客
V
V2EX
酷 壳 – CoolShell
酷 壳 – CoolShell
IT之家
IT之家
量子位
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Announcements
Recent Announcements
M
MIT News - Artificial intelligence
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
prism-mem: Automatic Knowledge Extraction for AI Coding A...
Rahul Reddy Talatala · 2026-06-01 · via DEV Community

AI coding agents are stateless between sessions. Every time you start a new session, the agent knows nothing about what you built yesterday, why you made certain decisions, or what you explicitly decided to stop doing. You write a CLAUDE.md by hand, it goes stale after a few sessions, and you spend the first few minutes of every session re-explaining context the agent should already know.

In a 3-session demo on a real project, prism-mem compressed 411,463 bytes of raw Claude Code transcripts into 11,707 characters of structured, queryable knowledge -- a 35x reduction -- with zero manual updates. The agent that started session 4 had accurate context from everything that happened in sessions 1, 2, and 3, including a database migration it never witnessed.

prism-mem does this by reading what actually happened instead of asking you to write it down.


🤔 The Problem With Manual Context Files

Here is what typically happens on a real project:

  • Session 1: You write a clean CLAUDE.md. Tech stack, decisions, conventions. It is accurate.
  • Session 3: You migrated from SQLite to PostgreSQL. You forgot to update CLAUDE.md.
  • Session 5: The agent confidently uses SQLite APIs because that is what the context file says.

Manual context files are snapshots. They reflect what you thought was important enough to write down at the moment you wrote them. They do not capture the dozens of small decisions that happen during a session: the library you tried and abandoned, the architecture pattern you switched away from, the refactor that changed the data model.

prism-mem reads session transcripts and git diffs after every commit, extracts structured knowledge as (subject, predicate, object) triples, links them into a graph, automatically detects when old facts are contradicted by new ones, and regenerates your context files. No manual input at any step.


📖 Where the Idea Comes From

Two research papers shaped how prism-mem works.

Memori (arXiv:2603.19935, March 2026) showed that storing memories as semantic triples instead of raw text blobs leads to 67% fewer tokens consumed at retrieval and more precise answers. The core insight: when an agent needs context, it does not need the full transcript of what happened. It needs the facts extracted from that transcript, in a compact structured form. Triples are that form.

A-MEM (arXiv:2502.12110, NeurIPS 2025) introduced the idea that memories should evolve and link to each other rather than just accumulate. It draws from the Zettelkasten method: every new note connects to existing notes, and old notes get updated when new information contradicts them. prism-mem's graph edge creation and staleness detection come directly from this idea. When snap-url uses PostgreSQL arrives, the old snap-url uses SQLite triple does not get deleted. It gets marked stale, and an edge connects the two, preserving the history of the decision change.

Neither paper had a cross-agent, open-source, installable implementation. prism-mem is the attempt to build one.


⚙️ How It Works

The main entry point is the prism crystallize command in prism_mem/cli.py. It runs four phases in sequence. Each phase is self-contained and testable independently.

Phase 1: Ingest

prism reads from two sources: Claude Code session transcripts and git history.

Session transcripts are handled by read_latest_session() in prism_mem/ingestion/session_reader.py. Claude Code stores every session as a .jsonl file under ~/.claude/projects/<encoded-path>/. Each line in the file is a JSON object representing a single event: a user message, an assistant response, a tool call result, or a summary. prism parses all of these, extracts the text and thinking blocks, and also merges in any subagent transcripts found at <session-uuid>/subagents/*.jsonl. The final output is a flat list of chunks, each with role, content_type, content, timestamp, session_id, and source.

Critically, prism uses watermark-based incremental ingestion. The session_watermarks table in SQLite stores the last processed timestamp for each session file. On subsequent runs, get_session_watermark() retrieves this timestamp and read_latest_session() skips any chunks with an earlier timestamp. This means you never re-process content you have already seen, and the pipeline stays fast even on long-running projects.

Git history is handled by read_git_diff(), read_git_log(), and read_git_head() in prism_mem/ingestion/git_reader.py. These run git diff HEAD~1 HEAD, git log --oneline -20, and git rev-parse HEAD as subprocesses. The HEAD commit hash is checked against the processed_commits table. If it is already there, the git phase is skipped entirely. The hash is recorded after successful processing via mark_commit_processed().

Phase 2: Extract

extract_triples() in prism_mem/extraction/extractor.py passes the combined session and git text to kg-gen, a library built specifically for extracting knowledge graphs from unstructured text. kg-gen handles chunking (8,000 characters per chunk), LLM calls via LiteLLM, and entity clustering. The output is a list of (subject, predicate, object) tuples.

A triple from a real session looks like this:

("snap-url", "uses", "PostgreSQL")
("snap-url API", "handles", "authentication via JWT")
("Redis", "stores", "rate limiting state")
("prism-mem", "embeds triples using", "all-MiniLM-L6-v2")

kg-gen runs with cluster=True by default. Clustering groups similar entity names so "PostgreSQL", "Postgres", and "the database" all resolve to the same canonical entity. If the LLM returns a malformed entity (which triggers a Pydantic validation error in kg-gen), extract_triples() catches the exception and retries the same chunk with cluster=False. Triples are still extracted cleanly in the fallback path, and cosine similarity linking in the next phase handles residual duplication.

Phase 3: Store and Link 🔗

This is where the knowledge graph actually gets built. For each extracted triple, ingest_triple() in prism_mem/linking/linker.py runs three operations in a specific order.

Step 1 (Store): store_triple() in prism_mem/storage/db.py inserts the triple into the triples table and calls embed() to compute a 384-dimensional vector embedding using sentence-transformers/all-MiniLM-L6-v2. The model runs entirely locally, no API call needed, and returns normalized float32 vectors. The embedding is stored as a binary blob in the embeddings table using struct pack format (384f). vec_from_bytes() unpacks it back to a numpy array at query time.

The choice of numpy over sqlite-vec is intentional. sqlite-vec requires enable_load_extension which is disabled in many Python builds including pyenv installs and the system Python on macOS. At prism's scale (thousands of triples), a numpy O(n) cosine scan takes around 50ms. The portability cost of sqlite-vec is not worth the index speed at this scale.

Step 2 (Link): search_similar() loads all existing embeddings from the database into a numpy matrix and computes cosine similarity against the new triple's embedding in a single matrix dot product. Because the embeddings are pre-normalized, the dot product is equivalent to cosine similarity. Pairs above the similarity threshold get recorded as edges in the edges table via create_edge(), with the similarity score stored as the edge weight.

Step 3 (Stale detection): check_and_mark_stale() queries for triples that share the same subject and predicate but have a different object. When it finds one, it calls mark_stale() to flip the stale boolean on the old triple. This is how prism knows that snap-url uses SQLite is no longer current after snap-url uses PostgreSQL is ingested.

The ordering here matters. Linking runs before staleness marking, so edges are created while the old triple is still active. This preserves the graph structure: the connection between the old SQLite triple and the new PostgreSQL triple stays visible in the graph as evidence of the migration.

Phase 4: Generate 📄

write_constitution() in prism_mem/constitution/generator.py calls select_top_triples() first. This filters all non-stale triples and scores each one using:

score = 1 / (1 + age_seconds / 86400) + confidence

The recency component decays once per day. The confidence component is set by kg-gen during extraction based on how many chunks corroborated the triple. The top 30 triples by score are selected, formatted as a bullet list of (subject) [predicate] (object) facts, and passed to the LLM via _call_haiku().

The LLM is called three times with different prompts, producing three files:

  • CLAUDE.md: Full structured documentation covering project description, tech stack, architecture, decisions, and conventions
  • .cursorrules: Under 40 lines of imperative bullets for Cursor IDE
  • AGENTS.md: Agent-oriented guide with repo layout, build commands, and behavioral rules

All three files are written to the project root. Every session that follows reads a context file derived from the actual current state of the project.


📊 Demo Results: 3 Sessions on snap-url

snap-url is a URL shortening service built with FastAPI and Python. You POST a long URL, get a 6-character short code back, and the redirect path hits Redis first for sub-millisecond cache lookups with a fallback to PostgreSQL. Click analytics are recorded asynchronously via background tasks without adding latency to the redirect.

The project was built across three sessions:

  • Session 1: Core API. POST /shorten generates short codes from a 62-symbol alphabet, GET /{code} handles redirects, SQLAlchemy models backed by SQLite for local development
  • Session 2: Click analytics. Added a Click model, a record_click background task, and a GET /stats/{code} endpoint that returns total clicks, last-24h count, and per-click metadata
  • Session 3: Redis caching layer and a PostgreSQL migration. Added cache.py with a 0.5-second timeout and graceful DB fallback, then swapped SQLite out for PostgreSQL in production

That last session is where the staleness story gets interesting.

Here are the numbers after running prism across all three sessions:

411,463 bytes of raw transcripts in. 11,707 characters of structured knowledge out. That is a 35x compression ratio.

Metric Value
Raw session transcript size 411,463 bytes
Structured knowledge (active triples) 11,707 characters
Compression ratio 35x
Total triples extracted 700
Active triples 380
Stale triples (auto-detected contradictions) 320 (45.7%)
Graph edges (cross-session links) 416
Pipeline time 5 min 7 sec

What the 35x compression actually means: A raw session transcript is full of tool call outputs, retried commands, syntax errors, intermediate reasoning, and large file reads. prism throws all of that away and keeps only the structured facts: what the project uses, what was decided, and what changed. The 11,707-character output is what an agent actually needs at session start.

What 320 stale triples means: Nearly half of everything extracted was eventually superseded by newer information. This is not a signal of poor extraction. It is proof that the graph is tracking decisions over time. A flat CLAUDE.md would have accumulated all 700 facts with no way to tell which ones were still true. The staleness mechanism is what separates a live knowledge graph from a snapshot.

What 416 edges means: Facts from different sessions are linked by semantic similarity. A triple about the PostgreSQL migration connects to the schema design triple from two sessions earlier. A triple about Redis connects to the caching strategy decision. These links make the graph queryable across time, not just within a single session.

🔄 The Staleness Proof

This is the clearest way to see what prism actually does:

After session 1:

(snap-url) [uses] (SQLite)   ← active

After session 3 (PostgreSQL migration):

(snap-url) [uses] (SQLite)       ← stale, automatically detected
(snap-url) [uses] (PostgreSQL)   ← active
(snap-url) [uses] (Redis)        ← active

When check_and_mark_stale() encountered snap-url uses PostgreSQL, it found the existing triple snap-url uses SQLite matching on the same subject and predicate with a different object. It marked the old triple stale without any manual input, config change, or prompt engineering.

The CLAUDE.md written after session 3 says PostgreSQL. The one written after session 1 said SQLite. Neither required a human to update it.


🔌 Using prism Across Agents

prism ships a Model Context Protocol (MCP) server in prism_mem/server/mcp_server.py built with FastMCP. It exposes exactly three tools:

Tool What it does
get_context() Returns the current CLAUDE.md content for injection at session start
query_knowledge(question) Embeds the question, runs search_similar() over the triple graph, returns top-5 triples with cosine similarity scores
crystallize(session_id) Spawns prism crystallize as a background subprocess and returns immediately

query_knowledge is the most useful for mid-session use. An agent can ask "what database does this project use?" and get back a ranked list of relevant triples instead of having to read the whole context file.

Claude Code:

claude mcp add prism -- prism serve --project /path/to/your/project

Cursor (.cursor/mcp.json):

{
  "mcpServers": {
    "prism": {
      "command": "prism",
      "args": ["serve", "--project", "/path/to/your/project"]
    }
  }
}

Codex and other MCP-compatible agents: The protocol is the same. Point the server config at prism serve and the three tools are available.

The Graph UI

prism ui --project /path/to/your/project starts a FastAPI server at http://localhost:7823 with three views:

  • /constitution: The current CLAUDE.md with a Regenerate button to rebuild it on demand
  • /memory: A searchable table of all triples, filterable by text, with active and stale badges and truncated session IDs
  • /graph: An interactive force-directed graph rendered by Pyvis + vis.js. Click any node to see a sidebar with all contributing session IDs and the active/stale status of each connected triple

The graph view is especially useful for debugging extraction quality: you can see which triples are well-connected (high confidence, corroborated across sessions) and which are isolated (extracted once, low confidence).


🚀 Install and Setup

Install:

pip install prism-mem

Configure your LLM provider (Anthropic, OpenAI, Gemini, Ollama, and 20+ others via LiteLLM):

prism config set provider anthropic
prism config set model claude-haiku-4-5-20251001
prism config set api-key <your-api-key>

Run the first crystallization manually:

prism crystallize --project /path/to/your/project

This takes 3-10 minutes depending on session length. The bottleneck is kg-gen's LLM calls for extraction. On subsequent runs, watermark caching skips content that was already processed, so incremental runs are much faster.

Install the post-commit hook so crystallization runs automatically after every commit:

prism hook install --project /path/to/your/project

The hook calls prism crystallize in the background (&) so it does not block your commit. prism hook uninstall removes only the prism block, leaving any other hook content intact.

Start the MCP server for your agent:

prism serve --project /path/to/your/project

Open the graph UI:

prism ui --project /path/to/your/project

Storage layout:

~/.prism/
└── projects/
    └── <project-hash>/
        └── graph.db     ← SQLite, five tables, one per project

Everything lives locally. No cloud service, no telemetry, no shared state.


What This Enables

An agent that starts a new session and calls get_context gets back a CLAUDE.md that was built from what actually happened in previous sessions, scored by recency and confidence, with stale facts already removed. It does not matter if the last session was on Claude Code and this one is on Cursor. The knowledge graph is independent of the agent.

The 35x compression and 45.7% staleness detection rate from the snap-url demo are not the interesting numbers. The interesting number is zero: the number of times a human had to manually update a context file across three sessions and a database migration.

The agent that starts tomorrow does not start from scratch.


🛣️ What's Next

The current version handles one developer, one machine, post-commit extraction from Claude Code sessions. Here is what would make it significantly more useful:

Multi-agent ingestion. Right now prism only reads Claude Code .jsonl transcripts. Cursor, Codex, Gemini CLI, and Windsurf all produce their own session formats. Supporting them on the ingestion side (not just the MCP read side) would make the knowledge graph richer without any extra work from the user.

Retrieval frequency scoring. The current triple scoring formula uses recency and confidence. The original design also included retrieval_count -- how often an agent queried a given triple via query_knowledge. Triples that get looked up repeatedly are clearly load-bearing. Adding this signal would push the most-referenced facts to the top of the constitution more reliably than recency alone.

Cross-project knowledge. Each project currently lives in its own isolated graph.db. If two projects share a library, a pattern, or a team convention, there is no way to surface that. A lightweight cross-project index could let you query "have I solved this problem before?" across your entire project history.

Constitution diff view. After each crystallization, the only way to see what changed is to open CLAUDE.md and read it. A diff view showing which triples were added, which went stale, and how the constitution changed between runs would make it much easier to verify the pipeline is working correctly and trust the output.

Team support. The v1 scope is deliberately single-user, single-machine. The obvious next step is merging knowledge graphs from multiple developers on the same project -- each developer's sessions contribute triples, conflicts are resolved by staleness and confidence, and the team shares one constitution. This is the harder problem but also the most valuable one for larger projects.

Smarter conflict resolution. Right now staleness is binary: same subject and predicate, different object, the old triple loses. This works well for clear-cut migrations (SQLite to PostgreSQL) but less well for nuanced decisions where both old and new triples might be partially true. A confidence-weighted resolution that surfaces conflicts for human review rather than auto-marking would reduce false staleness on ambiguous facts.


prism-mem is open source. Source at github.com/rahult18/prism-mem. Install via pip install prism-mem.