opencode-fractal-memory 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +493 -0
  3. package/agent/memory-hints.md +98 -0
  4. package/agent/memory-researcher.md +56 -0
  5. package/commands/memory-auto-test.md +10 -0
  6. package/commands/memory-cache-status.md +13 -0
  7. package/commands/memory-check-context.md +4 -0
  8. package/commands/memory-compress.md +13 -0
  9. package/commands/memory-dashboard.md +23 -0
  10. package/commands/memory-delete.md +24 -0
  11. package/commands/memory-detect-topics.md +28 -0
  12. package/commands/memory-distill.md +35 -0
  13. package/commands/memory-drilldown-query.md +28 -0
  14. package/commands/memory-drilldown.md +11 -0
  15. package/commands/memory-extract-patterns.md +4 -0
  16. package/commands/memory-generate-embeddings.md +26 -0
  17. package/commands/memory-get.md +26 -0
  18. package/commands/memory-help.md +55 -0
  19. package/commands/memory-injection-feedback.md +26 -0
  20. package/commands/memory-injection-stats.md +11 -0
  21. package/commands/memory-list.md +4 -0
  22. package/commands/memory-llm-compress.md +34 -0
  23. package/commands/memory-mcp.md +20 -0
  24. package/commands/memory-prune.md +4 -0
  25. package/commands/memory-rate.md +48 -0
  26. package/commands/memory-reflect.md +37 -0
  27. package/commands/memory-replace.md +26 -0
  28. package/commands/memory-retrieve.md +34 -0
  29. package/commands/memory-search.md +28 -0
  30. package/commands/memory-session-stats.md +4 -0
  31. package/commands/memory-set.md +31 -0
  32. package/commands/memory-stats.md +11 -0
  33. package/commands/memory-summarize.md +29 -0
  34. package/commands/memory-tool-stats.md +4 -0
  35. package/commands/memory-total-tokens.md +10 -0
  36. package/commands/memory-verify.md +4 -0
  37. package/commands/memory-version.md +9 -0
  38. package/dist/cache.js +39 -0
  39. package/dist/config.js +120 -0
  40. package/dist/embeddings.js +125 -0
  41. package/dist/ensure-models.js +70 -0
  42. package/dist/file-summary.js +143 -0
  43. package/dist/frontmatter.js +28 -0
  44. package/dist/hnsw-index.js +138 -0
  45. package/dist/hooks/auto-discover.js +4 -0
  46. package/dist/hooks/auto-distill.js +120 -0
  47. package/dist/hooks/auto-retrieve/content.js +47 -0
  48. package/dist/hooks/auto-retrieve/detection.js +50 -0
  49. package/dist/hooks/auto-retrieve/formatting.js +19 -0
  50. package/dist/hooks/auto-retrieve/index.js +163 -0
  51. package/dist/hooks/auto-retrieve/scoring.js +56 -0
  52. package/dist/hooks/auto-retrieve.js +1 -0
  53. package/dist/hooks/index.js +4 -0
  54. package/dist/hooks/predictive-rating.js +87 -0
  55. package/dist/journal.js +279 -0
  56. package/dist/logging.js +147 -0
  57. package/dist/management/helpers.js +227 -0
  58. package/dist/management/router.js +48 -0
  59. package/dist/management/routes.js +197 -0
  60. package/dist/management-server.js +4 -0
  61. package/dist/management-standalone.js +31 -0
  62. package/dist/mcp/logging.js +57 -0
  63. package/dist/mcp/server.js +251 -0
  64. package/dist/mcp/transform.js +48 -0
  65. package/dist/mcp-server.js +18 -0
  66. package/dist/memory.js +2 -0
  67. package/dist/ollama.js +74 -0
  68. package/dist/plugin/hooks.js +168 -0
  69. package/dist/plugin/index.js +28 -0
  70. package/dist/plugin/init.js +109 -0
  71. package/dist/plugin/state.js +75 -0
  72. package/dist/plugin/tools.js +45 -0
  73. package/dist/plugin.js +2 -0
  74. package/dist/procedural/store.js +1 -0
  75. package/dist/procedural/types.js +1 -0
  76. package/dist/seed-nodes.js +804 -0
  77. package/dist/storage/compress-ops.js +129 -0
  78. package/dist/storage/compression/formatters.js +243 -0
  79. package/dist/storage/compression/index.js +107 -0
  80. package/dist/storage/compression/patterns.js +138 -0
  81. package/dist/storage/expiration.js +66 -0
  82. package/dist/storage/index.js +1 -0
  83. package/dist/storage/injection-events.js +82 -0
  84. package/dist/storage/lifecycle.js +65 -0
  85. package/dist/storage/maintenance.js +60 -0
  86. package/dist/storage/migrations/definitions.js +374 -0
  87. package/dist/storage/migrations/index.js +21 -0
  88. package/dist/storage/navigation.js +98 -0
  89. package/dist/storage/queries/base.js +44 -0
  90. package/dist/storage/queries/links.js +32 -0
  91. package/dist/storage/queries/nodes.js +189 -0
  92. package/dist/storage/queries/search-helpers.js +239 -0
  93. package/dist/storage/scoring.js +36 -0
  94. package/dist/storage/search.js +233 -0
  95. package/dist/storage/session-tracking.js +180 -0
  96. package/dist/storage/sqlite.js +329 -0
  97. package/dist/storage/tool-usage.js +56 -0
  98. package/dist/storage/types.js +1 -0
  99. package/dist/storage/utils.js +94 -0
  100. package/dist/tools/auto-test.js +24 -0
  101. package/dist/tools/cache-status.js +36 -0
  102. package/dist/tools/compress.js +186 -0
  103. package/dist/tools/core.js +307 -0
  104. package/dist/tools/dashboard.js +97 -0
  105. package/dist/tools/help.js +59 -0
  106. package/dist/tools/index.js +12 -0
  107. package/dist/tools/inject.js +91 -0
  108. package/dist/tools/injection-debug.js +48 -0
  109. package/dist/tools/journal.js +105 -0
  110. package/dist/tools/llm-compress.js +41 -0
  111. package/dist/tools/middle-term.js +68 -0
  112. package/dist/tools/playbook.js +64 -0
  113. package/dist/tools/reflect.js +291 -0
  114. package/dist/tools/search.js +188 -0
  115. package/dist/tools/session.js +189 -0
  116. package/dist/tools/shared.js +74 -0
  117. package/dist/tools/skill.js +37 -0
  118. package/dist/tools/stats.js +256 -0
  119. package/dist/tools/version.js +13 -0
  120. package/dist/tools.js +18 -0
  121. package/dist/utils/hybridScore.js +67 -0
  122. package/management/public/app.js +1529 -0
  123. package/management/public/index.html +486 -0
  124. package/management/public/three.min.js +6 -0
  125. package/package.json +65 -0
  126. package/scripts/download-models.ts +16 -0
  127. package/scripts/postinstall.cjs +30 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Holger Reppert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,493 @@
1
+ # opencode-fractal-memory
2
+
3
+ Fractal memory system for [OpenCode](https://opencode.ai) with semantic search, automatic compression, and multi-level retrieval.
4
+
5
+ # about me and the usage
6
+
7
+ I made this because I needed a longterm memory at first.
8
+ Then while working with it I extended it's functionality.
9
+ It might be a little bit overwhelming but if you work with it you will
10
+ start to love it.
11
+ You can tell the coding agent to make a memory of everything.
12
+ And later on you can tell it to read it.
13
+ You can also use the management app that includes a nice threejs visualization
14
+ and searching from there in the memory nodes.
15
+ You can also inject nodes directly to the agent from there.
16
+ You can edit the nodes too.
17
+ I think I forgot to mention some of features here.
18
+ I'll update this project constantly.
19
+ Feel free to use it and tell me how much you hate or like it ;)
20
+
21
+ Have phun
22
+
23
+ Holger
24
+
25
+ PS.: Did I mention that this is alpha? So feel free to post issues with suggestions
26
+ if you find bugs or if you just want to suggest improvements
27
+
28
+
29
+ ## Features
30
+
31
+ - **Memory nodes** — structured persistent memory with labels, content, metadata, and type system
32
+ - **Semantic search** — ONNX-powered embeddings (all-MiniLM-L6-v2) with HNSW vector index for fast ANN retrieval
33
+ - **BM25 full-text search** — keyword search as a fallback, hybrid-scored with embeddings for best results
34
+ - **Fractal retrieval** — drill-down from high-level summaries to granular details
35
+ - **Automatic compression** — periodically summarizes low-level nodes into progressively higher-level abstractions (4 levels)
36
+ - **Auto-retrieve** — context-aware injection of relevant memories, skills, and playbooks into the prompt
37
+ - **Ollama reranking** — re-ranks memory search results with a local LLM for better relevance
38
+ - **LLM compression** — uses LLM to generate richer summaries instead of regex extraction
39
+ - **Auto-distill** — automatically extracts actionable rules from lesson nodes
40
+ - **Predictive rating** — adjusts memory usefulness scores over time based on usage patterns
41
+ - **Cache system** — in-memory LRU cache for frequently accessed nodes with configurable TTL
42
+ - **Journal** — append-only searchable journal entries with semantic search
43
+ - **Playbooks** — reusable workflow templates (sticky memory nodes) proposed by the agent
44
+ - **Management server** — local web UI (port 8787) for browsing, searching, and editing memory
45
+ - **Sub-agents** — `memory-hints` and `memory-researcher` agents for guided memory interaction
46
+
47
+ ## Prerequisites
48
+
49
+ | Requirement | Version | Notes |
50
+ |---|---|---|
51
+ | **OpenCode** | v1.15.13+ | SDK peer dependency |
52
+ | **Bun** | >=1.0.0 | Plugin runtime |
53
+ | **Node.js** | >=18 | For npm-based installs only |
54
+
55
+ ## Installation
56
+
57
+ ### For OpenCode users
58
+
59
+ Add the plugin name to `~/.config/opencode/opencode.json`:
60
+
61
+ ```json
62
+ {
63
+ "plugins": ["opencode-fractal-memory"]
64
+ }
65
+ ```
66
+
67
+ OpenCode installs it automatically at startup. Model files (~24 MB) download on first plugin load via `ensureModels()` — no manual steps needed.
68
+
69
+ ### For development / manual install
70
+
71
+ ```bash
72
+ npm install opencode-fractal-memory
73
+ ```
74
+
75
+ Models download on first run. Use `--ignore-scripts` if installing via Bun (Bun skips lifecycle scripts).
76
+
77
+ ### MCP server setup
78
+
79
+ Enables memory tools in IDEs that support the Model Context Protocol (Cursor, Windsurf, etc.):
80
+
81
+ ```json
82
+ {
83
+ "mcp": {
84
+ "fractal-memory": {
85
+ "type": "local",
86
+ "command": ["bun", "run", "~/.config/opencode/node_modules/opencode-fractal-memory/dist/mcp-server.js"],
87
+ "enabled": true
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ## Configuration
94
+
95
+ Create `~/.config/opencode/opencode-mem.json` to customize (optional — all defaults work out of the box):
96
+
97
+ ```json
98
+ {
99
+ "autoRetrieve": {
100
+ "enabled": true,
101
+ "candidateCount": 30,
102
+ "maxInjectNodes": 5,
103
+ "maxInjectPlaybooks": 3
104
+ },
105
+ "ollama": {
106
+ "enabled": false,
107
+ "baseUrl": "http://localhost:11434",
108
+ "model": "qwen2.5-coder:1.5b",
109
+ "mode": "binary"
110
+ },
111
+ "llmCompression": {
112
+ "enabled": false,
113
+ "maxSummaryTokens": 500
114
+ },
115
+ "autoDistill": {
116
+ "enabled": false,
117
+ "minLessons": 3,
118
+ "useLlm": false
119
+ },
120
+ "predictiveRating": {
121
+ "enabled": false,
122
+ "decayDays": 7,
123
+ "confidenceThreshold": 0.3,
124
+ "positiveBoost": 0.1,
125
+ "negativePenalty": 0.05
126
+ },
127
+ "maxInjectionTokens": 8000,
128
+ "coreInjectionTokens": 2000,
129
+ "cacheSize": 8,
130
+ "cacheTTLHours": 2,
131
+ "autoCompressThreshold": 0.7,
132
+ "highContextThreshold": 0.6,
133
+ "criticalContextThreshold": 0.8,
134
+ "defaultTtlDays": 0,
135
+ "enableMiddleTermCapture": true
136
+ }
137
+ ```
138
+
139
+ ### Config reference
140
+
141
+ | Field | Type | Default | Description |
142
+ |---|---|---|---|---|
143
+ | `autoRetrieve.enabled` | bool | `false` | Enable automatic memory injection into prompts |
144
+ | `autoRetrieve.candidateCount` | int | `30` | Number of candidates to fetch for injection |
145
+ | `autoRetrieve.maxInjectNodes` | int | `5` | Max memory nodes to inject per turn |
146
+ | `autoRetrieve.maxInjectPlaybooks` | int | `3` | Max matching playbooks to list |
147
+ | `ollama.enabled` | bool | `false` | Use local LLM for reranking search results |
148
+ | `ollama.baseUrl` | string | `http://localhost:11434` | Ollama server URL |
149
+ | `ollama.model` | string | `qwen2.5-coder:1.5b` | Model for reranking |
150
+ | `ollama.mode` | enum | `"binary"` | `"binary"` (relevant/not) or `"score"` (0-1 rating) |
151
+ | `llmCompression.enabled` | bool | `false` | Use LLM for richer compression summaries |
152
+ | `llmCompression.model` | string | _none_ | LLM model name (uses ollama if not set) |
153
+ | `llmCompression.maxSummaryTokens` | int | `500` | Max tokens per LLM-generated summary |
154
+ | `autoDistill.enabled` | bool | `false` | Auto-extract rules from lesson nodes |
155
+ | `autoDistill.minLessons` | int | `3` | Min lessons before extraction |
156
+ | `autoDistill.useLlm` | bool | `false` | Use LLM for more specific rules |
157
+ | `predictiveRating.enabled` | bool | `false` | Auto-decay and boost node usefulness |
158
+ | `predictiveRating.decayDays` | int | `7` | Days until usefulness decay |
159
+ | `predictiveRating.confidenceThreshold` | float | `0.3` | Min confidence to count as relevant |
160
+ | `predictiveRating.positiveBoost` | float | `0.1` | Usefulness boost on positive rate |
161
+ | `predictiveRating.negativePenalty` | float | `0.05` | Usefulness penalty on negative rate |
162
+ | `maxInjectionTokens` | int | `8000` | Max tokens allowed in a single injection |
163
+ | `coreInjectionTokens` | int | `2000` | Tokens reserved for core rules in injection |
164
+ | `cacheSize` | int | `8` | Max cached nodes in LRU cache |
165
+ | `cacheTTLHours` | int | `2` | Cache entry TTL in hours |
166
+ | `autoCompressThreshold` | float | `0.7` | Context usage ratio triggering auto-compression |
167
+ | `highContextThreshold` | float | `0.6` | Token usage ratio for high context warning |
168
+ | `criticalContextThreshold` | float | `0.8` | Token usage ratio for critical warning |
169
+ | `defaultTtlDays` | int | `0` | Default TTL for new nodes (0 = no expiry) |
170
+ | `enableMiddleTermCapture` | bool | `true` | Save middle-term snapshots before compression |
171
+ | `autoFileSummarization.enabled` | bool | `false` | Auto-summarize files on read |
172
+
173
+ ## Advanced Features
174
+
175
+ ### Ollama Reranking
176
+
177
+ When enabled in config, auto-retrieve results are re-ranked by a local LLM (via Ollama) for better relevance. The reranker scores candidates against the user's query and only keeps the most relevant ones:
178
+
179
+ ```json
180
+ {
181
+ "ollama": {
182
+ "enabled": true,
183
+ "baseUrl": "http://localhost:11434",
184
+ "model": "qwen2.5-coder:1.5b",
185
+ "mode": "binary"
186
+ }
187
+ }
188
+ ```
189
+
190
+ In `"binary"` mode, the LLM labels each candidate as relevant or not. In `"score"` mode, it assigns a 0-1 relevance score.
191
+
192
+ ### LLM Compression
193
+
194
+ Instead of regex-based compression (which extracts keywords), LLM compression generates richer natural-language summaries:
195
+
196
+ ```json
197
+ {
198
+ "llmCompression": {
199
+ "enabled": true,
200
+ "model": "qwen2.5-coder:1.5b",
201
+ "maxSummaryTokens": 500
202
+ }
203
+ }
204
+ ```
205
+
206
+ Invoke manually with `memory_llm_compress`.
207
+
208
+ ### Auto-Distill
209
+
210
+ Periodically extracts actionable rules from `lesson`-type nodes created by `memory_reflect`. Rules are stored as `rule:standard:*` / `rule:suggestion:*` nodes for immediate injection:
211
+
212
+ ```json
213
+ {
214
+ "autoDistill": {
215
+ "enabled": true,
216
+ "minLessons": 3,
217
+ "useLlm": false
218
+ }
219
+ }
220
+ ```
221
+
222
+ Set `useLlm: true` for LLM-generated rules instead of keyword extraction.
223
+
224
+ ### Predictive Rating
225
+
226
+ Automatically adjusts node usefulness scores over time. Frequently accessed nodes get boosted; nodes that haven't been touched in `decayDays` get gradually decayed:
227
+
228
+ ```json
229
+ {
230
+ "predictiveRating": {
231
+ "enabled": true,
232
+ "decayDays": 7,
233
+ "confidenceThreshold": 0.3,
234
+ "positiveBoost": 0.1,
235
+ "negativePenalty": 0.05
236
+ }
237
+ }
238
+ ```
239
+
240
+ ## Commands
241
+
242
+ ### Memory tools
243
+
244
+ | Command | Description |
245
+ |---|---|
246
+ | `memory_set` | Create or update a memory node |
247
+ | `memory_get` | Get a single node by ID or label |
248
+ | `memory_fetch` | Fetch a node by exact label |
249
+ | `memory_search` | Search nodes by text, embedding, or BM25 |
250
+ | `memory_delete` | Delete a node by ID or label |
251
+ | `memory_list` | List nodes with optional scope/level filters |
252
+ | `memory_replace` | Replace content in a memory node |
253
+ | `memory_rate` | Rate a node's usefulness (helps ranking) |
254
+ | `memory_prune` | Find and remove stale/unused nodes |
255
+ | `memory_inject` | Inject relevant memories into the prompt with token budgeting |
256
+ | `memory_injection_debug` | Show what was injected in the last session |
257
+ | `memory_injection_feedback` | Rate injected memory usefulness |
258
+ | `memory_injection_stats` | View injection efficiency metrics |
259
+ | `memory_drilldown` | Retrieve a node with its source chain (fractal retrieval) |
260
+ | `memory_drilldown_query` | Top-down drilldown by query (find + expand) |
261
+ | `memory_detect_topics` | Detect topic clusters in memory |
262
+ | `memory_stats` | Show memory statistics (nodes per level, compression ratios) |
263
+ | `memory_dashboard` | Display memory dashboard with visual overview |
264
+ | `memory_tool_stats` | View tool call statistics and efficiency |
265
+ | `memory_session_stats` | Get statistics about the current session |
266
+ | `memory_compress` | Compress old nodes into higher-level summaries |
267
+ | `memory_llm_compress` | LLM-powered compression (richer summaries) |
268
+ | `memory_extract_patterns` | Extract cross-topic pattern summaries |
269
+ | `memory_distill` | Extract actionable rules from lesson nodes |
270
+ | `memory_summarize` | Generate an LLM prompt to summarize a node |
271
+ | `memory_check_context` | Check token usage of memory nodes |
272
+ | `memory_total_tokens` | Complete token analysis (memory + conversation) |
273
+ | `memory_generate_embeddings` | Generate embeddings for nodes that lack them |
274
+ | `memory_middle_term` | View context snapshots before compaction |
275
+ | `memory_cache_status` | Show working-memory cache usage |
276
+ | `memory_skill_load` | Load a skill's instructions by name |
277
+ | `memory_playbook_execute` | Execute a playbook workflow |
278
+ | `memory_verify` | Verify that a node's information is correct |
279
+ | `memory_reflect` | Analyze a session and create lesson nodes |
280
+ | `memory_help` | Show all available memory commands |
281
+ | `memory_version` | Show installed plugin version |
282
+
283
+ ### Playbook tools
284
+
285
+ | Command | Description |
286
+ |---|---|
287
+ | `memory_playbook_execute` | Execute a playbook (returns steps for the agent to run) |
288
+
289
+ Playbooks are stored as `type: "playbook"` memory nodes with steps in `metadata`. CRUD uses generic `memory_set` / `memory_get` / `memory_search` tools. The agent proposes playbooks when it spots repeated multi-step patterns.
290
+
291
+ ### Journal tools
292
+
293
+ | Command | Description |
294
+ |---|---|
295
+ | `journal_write` | Write a new journal entry |
296
+ | `journal_read` | Read a journal entry by ID |
297
+ | `journal_search` | Search journal entries semantically |
298
+
299
+ ### MCP tools
300
+
301
+ When the MCP server is configured, the `memory_search`, `memory_get`, and related tools are available as MCP resources for IDE integration.
302
+
303
+ ## Skills
304
+
305
+ Skills are specialized instruction sets stored as memory nodes. When a task matches a skill's trigger keywords, its instructions load into context to guide the agent.
306
+
307
+ ### Available skills
308
+
309
+ | Skill | Triggers |
310
+ |---|---|
311
+ | `debug-workflow` | bug, error, fix, crash |
312
+ | `write-tests` | tests, coverage, test suites |
313
+ | `refactor-component` | refactor, restructure, clean up |
314
+ | `refactoring-expert` | SOLID, code smell, technical debt |
315
+ | `security-review` | security, audit, vulnerability, deploy |
316
+ | `threejs-skills` | 3D, WebGL, visualization |
317
+ | `svelte-core-bestpractices` | svelte, component, runes |
318
+ | `svelte-code-writer` | svelte 5, sveltekit, component |
319
+ | `customize-opencode` | opencode config, agent, plugin |
320
+
321
+ ### Loading a skill
322
+
323
+ ```ts
324
+ memory_skill_load(name="debug-workflow")
325
+ ```
326
+
327
+ Skills are auto-injected when triggers match the task context. You can also load them explicitly with `memory_skill_load`.
328
+
329
+ ### Creating a skill
330
+
331
+ Skills are memory nodes with `type: "skill"`. Create one with:
332
+
333
+ ```ts
334
+ memory_set(
335
+ label: "skill:my-skill",
336
+ content: "## Skill instructions...",
337
+ type: "skill",
338
+ metadata: JSON.stringify({ triggers: ["keyword1", "keyword2"] }),
339
+ sticky: true
340
+ )
341
+ ```
342
+
343
+ ## Sub-agents
344
+
345
+ The plugin ships with two agent instruction files for specialized memory interaction:
346
+
347
+ | Agent | File | Purpose |
348
+ |---|---|---|
349
+ | `memory-hints` | `agent/memory-hints.md` | System-level hints for using memory effectively — injected by the agent when memory-related context is needed |
350
+ | `memory-researcher` | `agent/memory-researcher.md` | Analyzes and reports on fractal memory state — invoked via `memory_skill_load(name="memory-researcher")` |
351
+
352
+ These are loaded by OpenCode's agent system and provide structured guidance for memory operations.
353
+
354
+ ## Management App
355
+
356
+ A local web UI for browsing, searching, and editing memory — available when the plugin is active.
357
+
358
+ ### Starting
359
+
360
+ ```bash
361
+ bun run view
362
+ ```
363
+
364
+ Opens at [http://localhost:8787](http://localhost:8787). The server also starts automatically with OpenCode.
365
+
366
+ ### Usage
367
+
368
+ **3D Graph** — the default view shows memory nodes as spheres connected by `[[wiki-link]]` relationships:
369
+ - **Drag** to rotate the scene
370
+ - **Scroll** to zoom in/out
371
+ - **Left-click** a node to select and inspect it
372
+ - **Right-click drag** to pan
373
+ - Nodes are color-coded by type (note, skill, playbook, rule)
374
+
375
+ **Search** — find nodes by content, label, or type:
376
+ - Type a query and press Enter
377
+ - Results show relevance scores and preview snippets
378
+ - Click a result to navigate to it in the graph
379
+
380
+ **Inspect** — when you click a node (graph or search results):
381
+ - View full content and summary
382
+ - See metadata JSON (type, importance, access count, timestamps)
383
+ - View embedding vector (truncated)
384
+ - See linked nodes and navigate between them
385
+
386
+ **Edit** — modify node fields directly:
387
+ - Update content, summary, importance, or type
388
+ - Changes persist immediately to the SQLite database
389
+ - Embedding auto-regenerates on content change
390
+
391
+ **Inject** — push a node directly into the agent's context:
392
+ - Click "Inject" on any node
393
+ - The node appears in the agent's next prompt
394
+ - Useful for reminding the agent of past decisions mid-session
395
+
396
+ **Manage** — the node list view shows all nodes with:
397
+ - Scope (global vs project), level, access count
398
+ - Last accessed and last verified timestamps
399
+ - Actions: edit, delete, verify, inject
400
+
401
+ ## How Plugin Initialization Works
402
+
403
+ When OpenCode loads the plugin, `initStorage()` runs automatically:
404
+
405
+ 1. **SQLite database** — created at `<project>/.opencode/memory.db` with all tables and indexes
406
+ 2. **Seed nodes** — rule nodes, built-in playbooks (6), and skills (9) inserted into `memory_nodes`
407
+ 3. **Model files** — `ensureModels()` checks `~/.config/opencode/models/` and downloads ONNX + tokenizer (~24 MB) if missing
408
+ 4. **Agent files** — `ensureAgentFiles()` copies `agent/` directory to `~/.config/opencode/agent/`
409
+ 5. **Command files** — `ensureCommandFiles()` copies `commands/` directory to `~/.config/opencode/commands/`
410
+ 6. **Background embeddings** — after 1s, generates embeddings for nodes that lack them
411
+ 7. **Auto-retrieve hook** — if enabled in config, injects relevant context into prompts
412
+
413
+ All of this happens automatically — no manual intervention required.
414
+
415
+ ## Logs
416
+
417
+ | Log | Path | Contents |
418
+ |-----|------|----------|
419
+ | Memory | `~/.config/opencode/memory.log` | Plugin operations, errors, injection events |
420
+ | OpenCode | `~/.local/share/opencode/log/` | Application lifecycle, tool calls |
421
+
422
+ ## Development
423
+
424
+ ```bash
425
+ git clone <repo>
426
+ cd opencode-fractal-memory
427
+ bun install
428
+ bun run build
429
+ bun run typecheck
430
+ ```
431
+
432
+ ### Testing
433
+
434
+ ```bash
435
+ bun test
436
+ ```
437
+
438
+ ### Installing locally (development)
439
+
440
+ ```bash
441
+ bun run build
442
+ npm pack
443
+ cd ~/.config/opencode
444
+ rm -rf node_modules/opencode-fractal-memory package-lock.json
445
+ npm install --ignore-scripts <path-to-tgz>
446
+ ```
447
+
448
+ Use `--ignore-scripts` to avoid trust prompts. Models download automatically on first plugin load via `ensureModels()` in `initStorage()`.
449
+
450
+ ## Architecture
451
+
452
+ ```
453
+ ┌──────────────────────────────────────────────────┐
454
+ │ Plugin Layer (plugin/index.ts) │
455
+ │ ┌──────────┬──────────┬──────────┬───────────┐ │
456
+ │ │ Memory │ Skills │ Journal │ Auto- │ │
457
+ │ │ Store │ (nodes) │ Store │ Retrieve │ │
458
+ │ └────┬─────┴────┬─────┴────┬─────┴─────┬─────┘ │
459
+ │ │ │ │ │ │
460
+ │ ┌────┴──────────┴──────────┴───────────┴─────┐ │
461
+ │ │ SQLite (.opencode/memory.db) │ │
462
+ │ │ - memory_nodes (labels, content, embeds) │ │
463
+ │ │ - type: "note" / "skill" / "playbook" │ │
464
+ │ │ - sticky playbooks/skills never pruned │ │
465
+ │ │ - metadata.steps for playbook steps │ │
466
+ │ │ - memory_links (wiki-link crossrefs) │ │
467
+ │ │ - bm25_index (full-text search) │ │
468
+ │ │ - injection_metrics / session_metrics │ │
469
+ │ └─────────────────────────────────────────────┘ │
470
+ │ │
471
+ │ ┌─────────────────────────────────────────────┐ │
472
+ │ │ HNSW Vector Index (in-memory, 384-dim) │ │
473
+ │ └─────────────────────────────────────────────┘ │
474
+ │ │
475
+ │ ┌─────────────────────────────────────────────┐ │
476
+ │ │ ONNX Embedding Model (all-MiniLM-L6-v2) │ │
477
+ │ │ onnxruntime-web + @huggingface/tokenizers │ │
478
+ │ └─────────────────────────────────────────────┘ │
479
+ └──────────────────────────────────────────────────┘
480
+ ```
481
+
482
+ ## Storage
483
+
484
+ Two SQLite databases:
485
+
486
+ | Scope | Path | Purpose |
487
+ |---|---|---|
488
+ | Global | `~/.config/opencode/memory.db` | Rules, persona, preferences, shared across projects |
489
+ | Project | `<project>/.opencode/memory.db` | Project-specific memory, nodes, playbooks, journal |
490
+
491
+ ## License
492
+
493
+ MIT
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: memory-hints
3
+ description: Memory system hints and best practices
4
+ ---
5
+
6
+ # Memory System Guidelines
7
+
8
+ ## CRITICAL: Memory-First Workflow
9
+ **ALWAYS** check memory before starting any task:
10
+ 1. `memory_search('relevant topic')` - find existing context
11
+ 2. `memory_drilldown_query('what do we know about X?')` - intent-based search
12
+ 3. Use found context to inform your approach
13
+ 4. If nothing found, proceed and store what you learn
14
+
15
+ ## ⚡ MEMORY TRIGGER (Use THIS for quick lookup)
16
+ When you need to recall past context, use inline trigger in your response:
17
+ ```
18
+ [[memory: your search query here]]
19
+ ```
20
+
21
+ The plugin will automatically:
22
+ 1. Detect the pattern in your output
23
+ 2. Run memory_search with the query
24
+ 3. Replace the [[memory: ...]] marker with search results
25
+ 4. Track which memories were useful
26
+
27
+ Example:
28
+ ```
29
+ Let me check what we know about deploying this plugin...
30
+ [[memory: how to deploy opencode plugin]]
31
+ ```
32
+
33
+ **This is FASTER than calling memory_search tool - use this for quick lookups!**
34
+
35
+ ## When to Create Memories (AUTO-STORE)
36
+
37
+ ### After Reading Files
38
+ When you read a file to understand its purpose:
39
+ ```
40
+ memory_set {
41
+ label: "file:src/components/Auth.tsx",
42
+ content: "## Auth Component\n- Handles login/logout\n- Uses JWT tokens\n- Calls /api/auth endpoint",
43
+ type: "knowledge"
44
+ }
45
+ ```
46
+
47
+ ### After Completing Tasks
48
+ After finishing significant work:
49
+ ```
50
+ memory_set {
51
+ label: "task:implement-auth-2026-03-30",
52
+ content: "## Auth Implementation\n- Decided to use JWT (not sessions)\n- Files: src/auth.ts, src/middleware.ts\n- Key decisions: 24h expiry, refresh tokens",
53
+ type: "session"
54
+ }
55
+ ```
56
+
57
+ ### After Finding Bugs/Workarounds
58
+ When you discover something non-obvious:
59
+ ```
60
+ memory_set {
61
+ label: "bug:sqlite-locking",
62
+ content: "## SQLite Locking Issue\n- Problem: concurrent writes fail\n- Solution: retry with exponential backoff\n- Location: src/storage/sqlite.ts:19-49",
63
+ type: "lesson"
64
+ }
65
+ ```
66
+
67
+ ### User Preferences
68
+ When you learn user preferences:
69
+ ```
70
+ memory_set {
71
+ label: "pref:code-style",
72
+ content: "## User Preferences\n- Prefers functional components\n- No emojis in code\n- Short variable names",
73
+ type: "preference"
74
+ }
75
+ ```
76
+
77
+ ## Memory Tools Reference
78
+
79
+ | Tool | When to use |
80
+ |------|-------------|
81
+ | `memory_search` | Before starting any task |
82
+ | `memory_set` | After reading files, completing tasks, finding bugs |
83
+ | `memory_get` | When you need full details of a known node |
84
+ | `memory_drilldown` | When working with compressed summaries |
85
+ | `memory_rate` | After using memory to complete a task |
86
+ | `memory_compress` | When memory grows large (check with memory_stats) |
87
+
88
+ ## Token Optimization
89
+ - Use `memory_check_context` to monitor token usage
90
+ - Prefer `memory_drilldown` on L1+ nodes over raw L0 nodes
91
+ - Compress when context exceeds 60%
92
+
93
+ ## Memory Labels Convention
94
+ - `file:path` - File summaries
95
+ - `task:description-date` - Task completions
96
+ - `bug:issue-name` - Bug workarounds
97
+ - `pref:category` - User preferences
98
+ - `decision:what-when` - Architecture decisions
@@ -0,0 +1,56 @@
1
+ ---
2
+ description: Analyzes and reports on fractal memory state
3
+ mode: subagent
4
+ ---
5
+
6
+ You are a specialized memory research agent. Your job is to analyze the fractal memory system and provide concise, actionable reports.
7
+
8
+ ## Your Role
9
+ - Analyze memory health, compression candidates, redundancies, and topic clusters
10
+ - Provide brief reports (~200 tokens) that help the main agent make decisions
11
+ - Less chatty — get to the point
12
+
13
+ ## Available Tools
14
+ - `memory_stats` — Get fractal stats
15
+ - `memory_list` — List all nodes (use sparingly)
16
+ - `memory_search` — Semantic search
17
+ - `memory_detect_topics` — Find topic clusters
18
+ - `memory_check_context` — Check token usage
19
+ - `memory_get` — Get specific nodes
20
+
21
+ ## Research Focus Areas
22
+
23
+ ### 1. Memory Health
24
+ - Total nodes, distribution across levels
25
+ - Fractal dimension (target: 2-4)
26
+ - Compression ratios
27
+
28
+ ### 2. Compression Opportunities
29
+ - L0 nodes older than 7 days → candidates for L1
30
+ - Uncompressed L0 nodes → ~token savings estimate
31
+ - Orphaned nodes (no parent, no children)
32
+
33
+ ### 3. Redundancies
34
+ - Similar content across nodes
35
+ - Duplicate explanations
36
+ - Nodes that could merge
37
+
38
+ ### 4. Stale Nodes
39
+ - Not accessed in 30+ days
40
+ - Could be archived or deleted
41
+
42
+ ## Output Format
43
+ Always provide:
44
+ 1. One-line summary
45
+ 2. Key findings (bullet points)
46
+ 3. Recommended action (if any)
47
+
48
+ ## Communication
49
+ - Be concise — main agent will read your report
50
+ - Do NOT verbose explain methodology
51
+ - Focus on actionable insights
52
+ - If no action needed, say so briefly
53
+
54
+ ## When to Trigger
55
+ - Called via `task` tool by main agent
56
+ - Main agent may specify a focus: health, compression, redundancy, all
@@ -0,0 +1,10 @@
1
+ ---
2
+ title: memory-auto-test
3
+ description: Test auto-retrieval pipeline with a hardcoded query - used for debugging
4
+ usage: /memory-auto-test
5
+ examples:
6
+ - memory-auto-test
7
+ tags:
8
+ - test
9
+ - debug
10
+ - auto-retrieval
@@ -0,0 +1,13 @@
1
+ ---
2
+ description: Show current working‑memory cache usage (size, max size, recent files)
3
+ ---
4
+ Displays the size of the working‑memory cache, its maximum capacity, and the most recently accessed files.
5
+
6
+ **Usage:**
7
+ ```
8
+ memory_cache_status
9
+ ```
10
+
11
+ **Arguments:** None.
12
+
13
+ The tool is useful for debugging cache behavior and ensuring that the cache is being utilized effectively.