@skepsun/pi-loom
Long-term memory plugin for pi with Dream Engine for insight generation — designed to collaborate with pi-esr
Package details
Install @skepsun/pi-loom from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@skepsun/pi-loom- Package
@skepsun/pi-loom- Version
0.5.0- Published
- Jul 9, 2026
- Downloads
- 466/mo · 87/wk
- Author
- skepsun
- License
- MIT
- Types
- extension
- Size
- 835.8 KB
- Dependencies
- 4 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"./src/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@skepsun/pi-loom —— Long-Term Memory for AI Agents 
A long-term memory plugin for AI coding agents. Remembers what happened across sessions, surfaces relevant context when needed, and discovers patterns via Dream Engine insight generation.
v0.5.0 — Native agent hooks · Operator CLI · 5-signal RRF retrieval
What problem does it solve?
AI coding agents forget. Close the terminal, start a new session, and the agent has no memory of yesterday's work — what was decided, what failed, why the architecture ended up this way. @skepsun/pi-loom solves this by:
- Storing memories — explicitly (
loom_store) or automatically (tool event capture) - Recalling relevant context — via 5-signal RRF fusion: FTS5 + vector KNN + recency + entity graph + cross-session boost
- Generating insights — Dream Engine finds patterns across memories
- Injecting context —
[PI_LOOM]block in the system prompt before every turn
Where it fits
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ context-mode │ │ @skepsun/pi-loom │ │ pi-esr │
│ "don't flood" │ │ "don't forget" │ │ "don't drift" │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ Context window │ │ Long-term │ │ Structured │
│ optimization │ │ memory │ │ state graph │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ 16 platforms │ │ Pi + MCP (5) │ │ │
│ HN #1 │ │ 88.4% judge │ │ │
│ │ │ 49% tokens of FC │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
Layers of memory:
| Layer | Plugin | What it remembers | Time horizon |
|---|---|---|---|
| Session | context-mode | Tool calls, file edits, errors, decisions — this conversation | Current session |
| Long-term | @skepsun/pi-loom | Facts, patterns, architecture decisions — cross-session | Weeks to months |
| Structural | pi-esr | Tasks, artifacts, evaluations, constraints — the state graph | Project lifetime |
Private Coding Benchmark
Evaluated on 5 real coding scenarios with a strict LLM-judge (LoCoMo-Refined prompt). Each scenario simulates multi-session development work with ground-truth facts and questions.
Aggregate Results (Phase 9, v4-pro judge)
| Baseline | Precision@10 | Recall@10 | Judge Score | Avg Tokens |
|---|---|---|---|---|
| @skepsun/pi-loom | 49.3% | 100% | 88.4% | 4,712 |
| full-context | 36.5% | 98.3% | 73.3% | 9,713 |
| grep | 6.8% | 42.5% | 22.7% | 3,522 |
@skepsun/pi-loom beats full-context by +15.1pp on judge score while using 49% of the tokens.
Per-Scenario Results (Phase 10, v4-flash)
| Scenario | Type | FC Judge | @skepsun/pi-loom Judge | Δ | @skepsun/pi-loom Tok |
|---|---|---|---|---|---|
| dedup-tags | 2 sessions, 7 Q | 71.4% | 86.2% | +14.8pp | 4,075 |
| bug-fix | 2 sessions, 4 Q | 80.0% | 90.0% | +10.0pp | 1,884 |
| dream-evo | 3 sessions, 4 Q | 87.5% | 95.0% | +7.5pp | 2,729 |
| perf-tuning | 6 sessions, 12 Q | 77.0% | 63.9% | -13.1pp | 13,062 |
| recmem | 3 sessions, 2 Q | 63.3% | 100.0% | +36.7pp | 1,925 |
Ablation: 4-Run Evolution on perf-tuning
| Run | @skepsun/pi-loom | FC | Δ | Key change |
|---|---|---|---|---|
| R1 base | 85.6% | 79.2% | +6.4 | Compact ingest + prompt compression |
| R2 +graph | 86.1% | 75.8% | +10.3 | Tool output inline, graph de-tuned (0.12) |
| R3 +fact-entity | 86.5% | 79.5% | +7.0 | Required_fact entity_ids in entity recall |
| R4 +edge-prompt | 88.4% | 73.3% | +15.1 | Entity edges serialized in answer prompt |
| R5 +graph-boost | 63.9% | 75.5% | -11.6 | Hop-aware graph boost, dynamic token budget |
R5's -11.6pp gap is a model effect — v4-flash underperforms v4-pro on multi-hop answer synthesis. With v4-pro, perf-tuning hit 70.3% (-4.1pp) in R4. R5's precision jumped from 26.7% to 45.0% (+68%) — the retrieval pipeline is working, but v4-flash answer quality lags.
Implementation Phases
| Phase | Description | Status |
|---|---|---|
| 0 | Private Benchmark: 5 scenarios, 3 baselines, 95% CI | ✅ |
| 1.1 | Three-way Hybrid Retrieval: FTS5 + sqlite-vec + recency RRF | ✅ |
| 1.2 | Temporal KG + ESR: episodes, entity_edges, BFS graph traversal | ✅ |
| 2.1 | Raw Event Log + Session Summary (two-layer, 30d TTL) | ✅ |
| 2.2 | Cross-Session Recurrence Boost (Signal 5) | ✅ |
| 3 | Symbolic Injection + Progressive Disclosure (~520 tok index) | ✅ |
| 4 | RecMem: subconscious layer + consolidation engine | ✅ |
| 5 | Dream→ESR reverse edge generation | ✅ |
| 6 | Benchmark CI: 95% confidence interval reporting | ✅ |
| 7 | Token Efficiency + Judge Gap: compact ingest, fact-indexed | ✅ |
| 8 | Entity Graph Boost: hop-aware BFS for multi-hop retrieval | ✅ |
| 9 | Per-Question Dynamic Token Budget: multi-hop gets 1000 chars | ✅ |
Install
Prerequisites
Node.js ≥ 18. On Windows: VS Build Tools. macOS: xcode-select --install. Linux: build-essential.
A. Pi (recommended)
git clone <repo> && cd @skepsun/pi-loom
npm install && npx tsc
pi install . # register as local extension
# /reload in pi to activate
B. Codex / Claude Code / Cursor (standalone MCP)
git clone <repo> && cd @skepsun/pi-loom
npm install && npx tsc
codex mcp add @skepsun/pi-loom -- node "$(pwd)/dist/mcp-server.js"
claude mcp add @skepsun/pi-loom -- node "$(pwd)/dist/mcp-server.js"
Cursor: add to .cursor/mcp.json:
{ "mcpServers": { "@skepsun/pi-loom": { "command": "node", "args": ["dist/mcp-server.js"] } } }
C. Native Agent Hooks
Codex and Claude Code can also receive Loom context without asking the model to call MCP first. The bundled hook bridges are intentionally small: SessionStart injects the compact [PI_LOOM] block, PostToolUse stores deterministic low-cost observations, and Stop records the final assistant message as a raw event.
npm install -g @skepsun/pi-loom
codex plugin marketplace add "$(npm root -g)/@skepsun/pi-loom"
# Then install pi-loom from /plugins and restart Codex.
Claude Code uses the bundled .claude-plugin manifest and plugin/hooks/hooks.json. It follows the same direct SQLite path as Codex; no worker daemon is started by default.
For local development, build first and use the bundled plugin directory:
npm install && npm run build
codex plugin marketplace add "$(pwd)"
The hook bridge is non-blocking: if Loom cannot open its local DB, the agent continues without memory injection. Set PI_LOOM_CODEX_HOOK_DISABLE=true, PI_LOOM_CLAUDE_HOOK_DISABLE=true, or PI_LOOM_HOOK_DISABLE=true to disable native hooks while keeping MCP available.
D. Library (npm)
npm install @skepsun/pi-loom
import { LoomStore, openDb, buildLoomContext } from "@skepsun/pi-loom";
const db = openDb();
const store = new LoomStore(db);
store.store({ content: "hello world", importance: 0.8 });
E. Operator CLI
pi-loom remains the MCP stdio server for backward compatibility. Use pi-loom-cli for local inspection and lightweight operations:
pi-loom-cli doctor
pi-loom-cli status --json
pi-loom-cli context --max-total-chars 1200
pi-loom-cli search "release procedure" --limit 5
pi-loom-cli store "Run retrieval precision before publishing" --importance 0.8 --tags procedure
pi-loom-cli install codex
The CLI does not start a worker daemon and does not mutate ~/.claude / ~/.codex settings automatically. Install commands print the minimal steps for the selected agent.
F. Minimal HTTP/HTTPS Service
Run pi-loom as a small tenant-isolated service when the extension process should not own the memory database directly.
npm run build
PI_LOOM_DATA_DIR=.pi-loom-service \
PI_LOOM_SERVICE_TOKEN=dev-token \
npm run service
For multiple tenants, map bearer tokens to tenant IDs:
PI_LOOM_DATA_DIR=.pi-loom-service \
PI_LOOM_SERVICE_PORT=8787 \
PI_LOOM_SERVICE_TOKENS='{"alice-token":"alice","bob-token":"bob"}' \
npm run service
To start HTTPS directly, provide a key and certificate:
PI_LOOM_SERVICE_TOKEN=dev-token \
PI_LOOM_SERVICE_TLS_KEY=/path/to/tls.key \
PI_LOOM_SERVICE_TLS_CERT=/path/to/tls.crt \
npm run service
Each tenant gets a separate SQLite store under <PI_LOOM_DATA_DIR>/<tenant>/loom.db. The service intentionally exposes only the core memory path:
curl -H "Authorization: Bearer dev-token" \
-H "Content-Type: application/json" \
-d '{"content":"Use SQLite as source of truth","importance":0.8}' \
http://localhost:8787/v1/tools/loom_store
curl -H "Authorization: Bearer dev-token" \
-H "Content-Type: application/json" \
-d '{"query":"SQLite","limit":5}' \
http://localhost:8787/v1/tools/loom_recall
Available service tools: loom_store, loom_recall, loom_search, loom_context, loom_review, loom_apply, loom_status, loom_insights, loom_profile, and loom_evidence.
Environment Variables
| Variable | Purpose |
|---|---|
PI_LOOM_DIR |
Data directory (default: .pi-loom/). Set to a shared path for cross-project memory. |
PI_LOOM_DATA_DIR |
Service data root for per-tenant stores (default: .pi-loom-service/). |
PI_LOOM_SERVICE_HOST / PI_LOOM_SERVICE_PORT |
HTTP/HTTPS service bind address (defaults: 0.0.0.0:8787). |
PI_LOOM_SERVICE_TOKEN |
Single-tenant bearer token, mapped to tenant default. |
PI_LOOM_SERVICE_TOKENS |
JSON object mapping bearer tokens to tenant IDs, e.g. {"token":"alice"}. |
PI_LOOM_SERVICE_ALLOW_ANON |
Set true only for trusted local development; uses X-Loom-Tenant or default. |
PI_LOOM_SERVICE_TLS_KEY / PI_LOOM_SERVICE_TLS_CERT |
Enable direct HTTPS service with the given private key and certificate paths. |
PI_LOOM_SERVICE_TLS_CA |
Optional CA bundle path for HTTPS. |
PI_LOOM_CODEX_HOOK_DISABLE |
Set true to disable native Codex hooks while keeping MCP/service modes available. |
PI_LOOM_CLAUDE_HOOK_DISABLE |
Set true to disable native Claude Code hooks while keeping MCP/service modes available. |
PI_LOOM_HOOK_DISABLE |
Set true to disable all native agent hooks while keeping MCP/service modes available. |
PI_LOOM_CODEX_MAX_TOKENS / PI_LOOM_CODEX_MAX_TOTAL_CHARS |
Budget controls for Codex hook context injection. |
PI_LOOM_CLAUDE_MAX_TOKENS / PI_LOOM_CLAUDE_MAX_TOTAL_CHARS |
Budget controls for Claude Code hook context injection. |
PI_LOOM_HOOK_MAX_TOKENS / PI_LOOM_HOOK_MAX_TOTAL_CHARS |
Shared budget fallback for native hook context injection. |
PI_LOOM_CODEX_SCOPE_TYPE / PI_LOOM_CODEX_SCOPE_ID |
Optional scope filter for Codex hook context injection. |
PI_LOOM_CLAUDE_SCOPE_TYPE / PI_LOOM_CLAUDE_SCOPE_ID |
Optional scope filter for Claude Code hook context injection. |
PI_LOOM_HOOK_SCOPE_TYPE / PI_LOOM_HOOK_SCOPE_ID |
Shared scope fallback for native hook context injection. |
EMBED_API_KEY |
API key for semantic embeddings (OpenAI-compatible). Falls back to local n-gram TF if unset. |
EMBED_API_BASE |
Embedding API base URL |
EMBED_MODEL |
Embedding model (default: text-embedding-3-small) |
EMBED_LOCAL_MODEL |
HF model for local embedding (requires @xenova/transformers) |
PI_DREAM_MODEL |
Model for Dream Engine, e.g. deepseek/deepseek-v3.1 |
PI_FACT_MODEL |
Model for fact extraction |
RAW_EVENT_TTL_DAYS |
Raw event retention (default: 30) |
BENCHMARK_RECMEM |
Enable RecMem consolidation mode in eval |
Security Boundary
pi-loom's scope and visibility fields are agent-governance controls, not a hard multi-user security boundary. By default, recall, context, Dream sampling, views, and apply paths exclude visibility="private" unless explicitly requested, which prevents accidental leakage inside a trusted local workspace.
For real multi-user isolation, run separate stores per user/project, for example by setting a per-user PI_LOOM_DIR, or place pi-loom behind a trusted service that enforces identity, authorization, filesystem isolation, audit logs, and encryption. A local pi extension shares the caller's process and filesystem permissions, so any user or tool with direct access to .pi-loom/loom.db can bypass in-process filters.
Tools
| Tool | Description |
|---|---|
loom_store |
Store a memory with importance, expiration, entity anchoring |
loom_recall |
Recall memories by entity, text search, or list all active |
loom_search |
5-signal hybrid search: keyword / semantic / hybrid modes |
loom_detail |
Full content of a memory by ID |
loom_timeline |
Chronological timeline for an entity |
loom_episode |
Full session summary (decisions, errors, changes, unfinished) |
loom_dream |
Run Dream Engine for insight generation |
loom_insights |
View generated insights, optionally filtered by entity |
loom_manage_insight |
Update or delete an insight |
loom_extract |
Extract atomic facts from memories |
loom_consolidate |
Consolidate recurring subconscious memories |
loom_link |
Create typed relation between two entities |
loom_related |
List all entities related to an entity |
loom_graph |
BFS graph traversal from an entity |
loom_audit |
View raw tool event logs |
loom_summarize_session |
Generate LLM summary of a session |
loom_stats |
Memory statistics |
loom_status |
Lightweight session status check |
loom_constrain |
Create a path-conditioned constraint |
loom_check_path |
Check runtime guardrail violations |
loom_offload |
Offload large text to external file, return [REF:node_id] |
loom_offload_recall |
Retrieve offloaded content by node_id |
loom_mermaid |
Generate Mermaid task graph from offloaded session refs |
loom_context |
Build context injection block [PI_LOOM] |
loom_profile |
Generate or view entity profiles |
loom_setup |
Setup assistant: verifies DB + embedding config |
loom_evidence |
Query-time evidence distillation with source citations |
loom_views |
Export read-only Markdown views from MemoryNode rows |
Recommended default path: loom_setup → loom_recall/loom_context → loom_review → loom_apply. Use the other tools only when the session needs specialized extraction, consolidation, profiles, offloading, or graph traversal.
Dream Engine
- Weighted sampling — importance (70%) × recency (30%) with exponential decay
- Conflict detection — contradictory memory pairs on same entity
- Shuffle — randomize to eliminate positional bias
- LLM generation — concise insights with supporting memory references
- Auto edge suggestion — co-mentioned entities get RELATES_TO edges
Design Principles
- Long-term memory layer — between context-mode (session) and ESR (state graph)
- Unified memory graph — facts, decisions, procedures, handoffs, profiles, and insights are all MemoryNodes; relationships are MemoryEdges
- Independent but collaborative — entity_id is opaque string, no cross-plugin schema knowledge
- Restrained by design — expiration as core mechanism against unbounded growth
- Dual intake — explicit
loom_store+ implicit auto-capture, two layers no duplication - Format-stable context — deterministic
[PI_LOOM]block for LLM prefix-cache efficiency - No echo loops — insights are output-only; Dream Engine only samples raw memories
- Hop-aware retrieval — entity graph BFS ensures multi-hop facts aren't buried by keyword ranking
Memory Graph Runtime
pi-loom keeps the architecture small: one memories table for MemoryNodes, one generic memory_edges table for relations, and view-based recall. Specialized behavior is metadata, not a separate subsystem:
kind:memory,fact,decision,procedure,profile,insight,constraint,handoffscope:user,repo,task,session,entityvisibility:private,project,sharedrelation:derives_from,supports,contradicts,supersedes,applies_to,mentions
visibility is intentionally simple: default reads see project/shared memory, while explicit visibility="private" reads only private memory. It is a reliable local policy for trusted agents, not authentication or tenant isolation.
loom_review uses the same graph model to produce maintenance proposals such as merge, supersede, contradiction-linking, and promote-to-procedure. It is proposal-only by design; memory is changed only by explicit loom_apply follow-up actions.
loom_recall(view=...) provides specialized views without specialized storage: procedures, handoffs, profiles, insights, and decisions all read from the same MemoryNode table.
loom_context(scope_type, scope_id) is a deterministic context planner. Within the token budget it prioritizes handoffs, procedures, profiles, insights, decisions/errors, then recent high-signal facts for the requested scope.
loom_views(scope_type, scope_id) exports deterministic Markdown projections under .pi-loom/views/ (index.md, procedures.md, handoffs.md, decisions.md, profiles.md, insights.md, edges.md). These files are for inspection and handoff only; SQLite remains the source of truth.
See Memory Graph Runtime Roadmap for the current improvement boundary and next steps.
Collaboration with pi-esr
Agent calls esr_promote_task("loom-arch-eval", "stable")
→ ESR: updates entity state, validates closure
→ @skepsun/pi-loom (auto-capture): stores "ESR task → stable"
→ @skepsun/pi-loom: auto-link entities from co-occurrence
Agent calls loom_search("multi-hop entity chain")
→ @skepsun/pi-loom: FTS5 + vec + recency + graph BFS → top-10
→ Entity edges serialized in answer context
Agent calls esr_get_context()
→ ESR: returns entity graph
→ @skepsun/pi-loom: [PI_LOOM] block shows insights anchored to active entities
License
MIT