{"id":45729541,"url":"https://github.com/byk/opencode-lore","last_synced_at":"2026-03-02T13:22:51.954Z","repository":{"id":339831181,"uuid":"1162699133","full_name":"BYK/opencode-lore","owner":"BYK","description":"Stop re-explaining your codebase — Lore automatically curates the project knowledge that makes your AI coding agent smarter every session","archived":false,"fork":false,"pushed_at":"2026-02-25T07:15:00.000Z","size":900,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-25T12:31:55.467Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BYK.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-20T15:31:39.000Z","updated_at":"2026-02-25T07:15:03.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/BYK/opencode-lore","commit_stats":null,"previous_names":["byk/opencode-lore"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/BYK/opencode-lore","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BYK%2Fopencode-lore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BYK%2Fopencode-lore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BYK%2Fopencode-lore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BYK%2Fopencode-lore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BYK","download_url":"https://codeload.github.com/BYK/opencode-lore/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BYK%2Fopencode-lore/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29892063,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T09:48:51.284Z","status":"ssl_error","status_checked_at":"2026-02-27T09:48:43.992Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-25T09:07:00.887Z","updated_at":"2026-03-02T13:22:51.942Z","avatar_url":"https://github.com/BYK.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# opencode-lore\n\n\u003e **Experimental** — This plugin is under active development. APIs, storage format, and behavior may change.\n\nAn implementation of [Sanity's Nuum](https://www.sanity.io/blog/how-we-solved-the-agent-memory-problem) memory architecture and [Mastra's Observational Memory](https://mastra.ai/research/observational-memory) system as a plugin for [OpenCode](https://opencode.ai). Both projects pioneered the idea that coding agents need **distillation, not summarization** — preserving operational intelligence (file paths, error messages, exact decisions) rather than narrative summaries that lose the details agents need to keep working. This plugin brings those ideas to OpenCode.\n\n## Why\n\nCoding agents forget. Once a conversation exceeds the context window, earlier decisions, bug fixes, and architectural choices vanish. The default approach — summarize-and-compact — loses exactly the operational details agents need. After a few compaction passes, the agent knows you \"discussed authentication\" but can't actually continue the work.\n\n## How it works\n\nLore uses a three-tier memory architecture (following [Nuum's design](https://www.sanity.io/blog/how-we-solved-the-agent-memory-problem)):\n\n1. **Temporal storage** — every message is stored in a local SQLite FTS5 database, searchable on demand via the `recall` tool.\n\n2. **Distillation** — messages are incrementally distilled into an observation log (dated, timestamped, priority-tagged entries), following [Mastra's observer/reflector pattern](https://mastra.ai/research/observational-memory). When segments accumulate, older distillations are recursively merged to prevent unbounded growth. The observer prompt is tuned to preserve exact numbers, bug fixes, file paths, and assistant-generated content.\n\n3. **Long-term knowledge** — a curated knowledge base of facts, patterns, decisions, and gotchas that matter across projects, maintained by a background curator agent.\n\nA **gradient context manager** decides how much of each tier to include in each turn, using a 4-layer safety system that calibrates overhead dynamically from real API token counts. This handles the unpredictable context consumption of coding agents (large tool outputs, system prompts, injected instructions) better than a fixed-budget approach.\n\n## Benchmarks\n\n\u003e Scores below are on Claude Sonnet 4 (claude-sonnet-4-6). Results may vary with other models.\n\n### Coding session recall\n\n20 questions across 2 real coding sessions (113K and 353K tokens), targeting specific facts at varying depths. Default mode simulates OpenCode's actual behavior: compaction of early messages + 80K-token tail window. Lore mode uses on-the-fly distillation + the `recall` tool for searching raw message history.\n\n**Accuracy:**\n\n| Mode    | Score     | Accuracy   |\n|---------|-----------|------------|\n| Default | 10/20     | 50.0%      |\n| Lore    | **17/20** | **85.0%**  |\n\n**By question depth** (where in the session the answer lives):\n\n| Depth        | Default  | Lore        | Gap     |\n|--------------|----------|-------------|---------|\n| Early detail | 1/7      | **6/7**     | +71pp   |\n| Mid detail   | 3/5      | **5/5**     | +40pp   |\n| Late detail  | 6/7      | 6/7         | tied    |\n\nEarly and mid details — specific numbers, file paths, design decisions, error messages — are what compaction loses and distillation preserves. Late details are in both modes' context windows, so they tie.\n\n**Cost:**\n\n| Metric             | Default    | Lore       | Factor       |\n|--------------------|------------|------------|--------------|\n| Avg input/question | 126K tok   | 50K tok    | 2.5x less    |\n| Total cost         | $8.14      | $1.87      | 4.4x cheaper |\n| Cost/correct       | $0.81      | **$0.11**  | 7.4x cheaper |\n\nLore's distilled context is smaller and more cacheable than raw tail windows, making it both more accurate and cheaper per correct answer.\n\n**Distillation compression:**\n\n| Session            | Messages | Tokens | Distilled to     | Compression |\n|--------------------|----------|--------|------------------|-------------|\n| cli-sentry-issue   | 318      | 113K   | ~6K tokens       | 19x         |\n| cli-nightly        | 898      | 353K   | ~19K tokens      | 19x         |\n\nThe eval is self-contained and reproducible: session transcripts are stored as JSON files with no database dependency. See [`eval/`](eval/) for the harness and data.\n\n## How we got here\n\nThis plugin was built in a few intense sessions. Some highlights:\n\n**v1 — structured distillation.** The initial version used Nuum's `{ narrative, facts }` JSON format. It worked well for single-session preference recall (+40pp over baseline) but *regressed* on multi-session and temporal reasoning — the structured format was too rigid and lost temporal context.\n\n**Markdown injection.** Property-based testing with fast-check revealed that user-generated content in facts (code fences, heading markers, thematic breaks) could break the markdown structure of the injected context, confusing the model.\n\n**v2 — observation logs.** Switching to Mastra's observer/reflector architecture with plain-text timestamped observation logs was the breakthrough. The key insight: dated event logs preserve temporal relationships that structured JSON destroys.\n\n**Prompt refinements.** The push from 80% to 93.3% on the initial coding recall eval came from two observer prompt additions: \"EXACT NUMBERS — NEVER APPROXIMATE\" (the observer was rounding counts) and \"BUG FIXES — ALWAYS RECORD\" (early-session fixes were being compressed away during reflection).\n\n**v3 — gradient fixes, caching, and proper eval.** A month of fixes (per-session gradient state, current-turn protection, cache.write calibration, prefix caching, LTM relevance scoring) shipped alongside a new self-contained eval harness. The old coding eval used DB-resident sessions that degraded over time as temporal pruning deleted messages. The new eval extracts full session transcripts into portable JSON files, distills on the fly with the current production prompt, seeds the DB for recall tool access, and compares against OpenCode's actual compaction behavior. This moved the coding eval from 15 questions on degraded data to 20 questions on clean 113K-353K token sessions — and confirmed the +35pp accuracy gap and 7x cost efficiency advantage.\n\n## Installation\n\n### Prerequisites\n\n- [OpenCode](https://opencode.ai)\n\n### Setup\n\nAdd `opencode-lore` to the `plugin` array in your project's `opencode.json`:\n\n```json\n{\n  \"plugin\": [\n    \"opencode-lore\"\n  ]\n}\n```\n\nRestart OpenCode and the plugin will be installed automatically.\n\n#### Development setup\n\nTo use a local clone instead of the published package:\n\n```json\n{\n  \"plugin\": [\n    \"file:///absolute/path/to/opencode-lore\"\n  ]\n}\n```\n\n## Configuration\n\nCreate a `.lore.json` file in your project root to customize behavior. All fields are optional — defaults are shown below:\n\n```jsonc\n{\n  // Disable long-term knowledge entirely. Temporal storage, distillation,\n  // gradient context management, and the recall tool (for conversation search)\n  // remain active. Only the curator, knowledge injection, and AGENTS.md sync\n  // are turned off.\n  \"knowledge\": { \"enabled\": true },\n\n  // Tune the curator that extracts knowledge from conversations.\n  \"curator\": {\n    \"enabled\": true,        // set false to stop extracting knowledge entries\n    \"onIdle\": true,         // run curation when a session goes idle\n    \"afterTurns\": 10,       // run curation after N user turns\n    \"maxEntries\": 25        // consolidate when entries exceed this count\n  },\n\n  // AGENTS.md export/import — the universal agents file format.\n  \"agentsFile\": {\n    \"enabled\": true,        // set false to disable AGENTS.md sync\n    \"path\": \"AGENTS.md\"     // change to e.g. \"CLAUDE.md\" or \".cursor/rules/lore.md\"\n  },\n\n  // Context budget fractions (of usable context window).\n  \"budget\": {\n    \"distilled\": 0.25,      // distilled history prefix\n    \"raw\": 0.4,             // recent raw messages\n    \"output\": 0.25,         // reserved for model output\n    \"ltm\": 0.10             // long-term knowledge in system prompt (2-30%)\n  },\n\n  // Distillation thresholds.\n  \"distillation\": {\n    \"minMessages\": 8,       // min undistilled messages before distilling\n    \"maxSegment\": 50        // max messages per distillation chunk\n  },\n\n  // Temporal message pruning.\n  \"pruning\": {\n    \"retention\": 120,       // days to keep distilled messages\n    \"maxStorage\": 1024      // max storage in MB before emergency pruning\n  },\n\n  // Include cross-project knowledge entries. Default: true.\n  \"crossProject\": true\n}\n```\n\n### Disabling long-term knowledge\n\nIf you prefer to manage context manually and only want conversation search capabilities, set:\n\n```json\n{\n  \"knowledge\": { \"enabled\": false }\n}\n```\n\nThis disables:\n- **Knowledge extraction** — the curator won't extract patterns, decisions, or gotchas from conversations\n- **Knowledge injection** — no knowledge entries are added to the system prompt\n- **AGENTS.md sync** — no import/export of the agents file\n\nThis keeps active:\n- **Temporal storage** — all messages are still stored and searchable\n- **Distillation** — conversations are still distilled for context management\n- **Gradient context manager** — context window is still managed automatically\n- **The `recall` tool** — the agent can still search conversation history and distillations (knowledge search is skipped)\n\n## What to expect\n\nOnce Lore is active, you should notice several changes:\n\n- **Higher cache reuse** — Lore keeps your context stable across turns, so the provider cache hits more often. You'll see higher cache read rates and lower costs.\n- **No more compactions** — Lore disables the built-in compaction system and replaces it with incremental distillation. Your context never gets wiped and rebuilt from a lossy summary.\n- **Steady context usage around 70–80%** — the gradient context manager dynamically balances distilled history, raw messages, and knowledge to keep you in the sweet spot — enough room for the model to work, but no wasted context.\n- **Agent doesn't degrade in long sessions** — instead of getting progressively dumber as compaction loses details, the agent stays sharp because distillation preserves the operational facts that matter.\n- **Better recall across and within sessions** — the agent remembers specific details from earlier in the conversation and from previous sessions, including file paths, decisions, error messages, and why things were done a certain way.\n- **Automatic `AGENTS.md` export** — Lore periodically exports curated knowledge to an `AGENTS.md` file in your repo. This is the [universal format](https://agenticaistandard.org/) read by 16+ AI coding tools (Codex, Jules, Cursor, Copilot, Windsurf, and more), so the knowledge benefits every tool — not just OpenCode.\n\n## What gets stored\n\nAll data lives locally in `~/.local/share/opencode-lore/lore.db`:\n\n- **Session observations** — timestamped event log of each conversation: what was asked, what was done, decisions made, errors found\n- **Long-term knowledge** — patterns, gotchas, and architectural decisions curated across sessions and projects\n- **Raw messages** — full message history in FTS5-indexed SQLite for the `recall` tool\n\n## The `recall` tool\n\nThe assistant gets a `recall` tool that searches across stored messages and knowledge. It's used automatically when the distilled context doesn't have enough detail:\n\n- \"What did we decide about auth last week?\"\n- \"What was the error from the migration?\"\n- \"What's my database schema convention?\"\n\n## Standing on the shoulders of\n\n- [How we solved the agent memory problem](https://www.sanity.io/blog/how-we-solved-the-agent-memory-problem) — Simen Svale at Sanity on the Nuum memory architecture: three-tier storage, distillation not summarization, recursive compression. The foundation this plugin is built on.\n- [Mastra Observational Memory](https://mastra.ai/research/observational-memory) — the observer/reflector architecture and the switch from structured JSON to timestamped observation logs that made v2 work.\n- [Mastra Memory source](https://github.com/mastra-ai/mastra/tree/main/packages/memory) — reference implementation.\n- [OpenCode](https://opencode.ai) — the coding agent this plugin extends.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbyk%2Fopencode-lore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbyk%2Fopencode-lore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbyk%2Fopencode-lore/lists"}