opencode-supermemory 0.1.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.
package/README.md ADDED
@@ -0,0 +1,162 @@
1
+ # opencode-supermemory
2
+
3
+ OpenCode plugin for persistent memory using [Supermemory](https://supermemory.ai).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npx opencode-supermemory setup
9
+ ```
10
+
11
+ Interactive wizard that:
12
+ 1. Installs plugin globally
13
+ 2. Creates `/supermemory-init` command
14
+ 3. Adds plugin to OpenCode config
15
+
16
+ Then set your API key:
17
+
18
+ ```bash
19
+ export SUPERMEMORY_API_KEY="your-api-key" # from console.supermemory.ai
20
+ ```
21
+
22
+ ## Features
23
+
24
+ ### Context Injection
25
+
26
+ On first message, injects:
27
+ - User profile (cross-project preferences)
28
+ - Project memories (all project knowledge)
29
+ - Relevant user memories (semantic search)
30
+
31
+ ```
32
+ [SUPERMEMORY]
33
+
34
+ User Profile:
35
+ - Prefers concise responses
36
+ - Expert in TypeScript
37
+
38
+ Project Knowledge:
39
+ - [100%] Uses Bun, not Node.js
40
+ - [100%] Build: bun run build
41
+
42
+ Relevant Memories:
43
+ - [82%] Build fails if .env.local missing
44
+ ```
45
+
46
+ ### Keyword Detection
47
+
48
+ Say "remember", "save this", "don't forget" etc. and the agent auto-saves to memory.
49
+
50
+ ```
51
+ You: "Remember that this project uses bun"
52
+ Agent: [saves to project memory]
53
+ ```
54
+
55
+ ### Codebase Indexing
56
+
57
+ Run `/supermemory-init` to explore and memorize your codebase structure, patterns, and conventions.
58
+
59
+ ### Preemptive Compaction
60
+
61
+ When context hits 80% capacity:
62
+ 1. Triggers OpenCode's summarization
63
+ 2. Injects project memories into summary context
64
+ 3. Saves session summary as a memory
65
+
66
+ This preserves conversation context across compaction events.
67
+
68
+ ### Privacy
69
+
70
+ ```
71
+ API key is <private>sk-abc123</private>
72
+ ```
73
+
74
+ Content in `<private>` tags is never stored.
75
+
76
+ ## Tool Usage
77
+
78
+ The `supermemory` tool is available to the agent:
79
+
80
+ | Mode | Args | Description |
81
+ |------|------|-------------|
82
+ | `add` | `content`, `type?`, `scope?` | Store memory |
83
+ | `search` | `query`, `scope?` | Search memories |
84
+ | `profile` | `query?` | View user profile |
85
+ | `list` | `scope?`, `limit?` | List memories |
86
+ | `forget` | `memoryId`, `scope?` | Delete memory |
87
+
88
+ **Scopes:** `user` (cross-project), `project` (default)
89
+
90
+ **Types:** `project-config`, `architecture`, `error-solution`, `preference`, `learned-pattern`, `conversation`
91
+
92
+ ## Memory Scoping
93
+
94
+ | Scope | Tag | Persists |
95
+ |-------|-----|----------|
96
+ | User | `opencode_user_{sha256(git email)}` | All projects |
97
+ | Project | `opencode_project_{sha256(directory)}` | This project |
98
+
99
+ ## Configuration
100
+
101
+ Create `~/.config/opencode/supermemory.jsonc`:
102
+
103
+ ```jsonc
104
+ {
105
+ // API key (can also use SUPERMEMORY_API_KEY env var)
106
+ "apiKey": "sm_...",
107
+
108
+ // Min similarity for memory retrieval (0-1)
109
+ "similarityThreshold": 0.6,
110
+
111
+ // Max memories injected per request
112
+ "maxMemories": 5,
113
+
114
+ // Max project memories listed
115
+ "maxProjectMemories": 10,
116
+
117
+ // Max profile facts injected
118
+ "maxProfileItems": 5,
119
+
120
+ // Include user profile in context
121
+ "injectProfile": true,
122
+
123
+ // Prefix for container tags
124
+ "containerTagPrefix": "opencode"
125
+ }
126
+ ```
127
+
128
+ All fields optional. Env var `SUPERMEMORY_API_KEY` takes precedence over config file.
129
+
130
+ API timeout: 5s
131
+
132
+ ## Hooks
133
+
134
+ Registered in `package.json`:
135
+ - `chat.message` - Context injection on first message, keyword detection
136
+ - `event` - Compaction monitoring and summary capture
137
+
138
+ ## Development
139
+
140
+ ```bash
141
+ bun install
142
+ bun run build
143
+ bun run typecheck
144
+ ```
145
+
146
+ Local install:
147
+
148
+ ```jsonc
149
+ {
150
+ "plugin": ["file:///path/to/opencode-supermemory"]
151
+ }
152
+ ```
153
+
154
+ ## Logs
155
+
156
+ ```bash
157
+ tail -f ~/.opencode-supermemory.log
158
+ ```
159
+
160
+ ## License
161
+
162
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,364 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
3
+ var __create = Object.create;
4
+ var __getProtoOf = Object.getPrototypeOf;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __toESM = (mod, isNodeMode, target) => {
9
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
10
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
+ for (let key of __getOwnPropNames(mod))
12
+ if (!__hasOwnProp.call(to, key))
13
+ __defProp(to, key, {
14
+ get: () => mod[key],
15
+ enumerable: true
16
+ });
17
+ return to;
18
+ };
19
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
20
+
21
+ // src/cli.ts
22
+ import { mkdirSync, writeFileSync, readFileSync, existsSync } from "node:fs";
23
+ import { join } from "node:path";
24
+ import { homedir } from "node:os";
25
+ import * as readline from "node:readline";
26
+ var OPENCODE_CONFIG_DIR = join(homedir(), ".config", "opencode");
27
+ var OPENCODE_COMMAND_DIR = join(OPENCODE_CONFIG_DIR, "command");
28
+ var PLUGIN_NAME = "opencode-supermemory@latest";
29
+ var SUPERMEMORY_INIT_COMMAND = `---
30
+ description: Initialize Supermemory with comprehensive codebase knowledge
31
+ ---
32
+
33
+ # Initializing Supermemory
34
+
35
+ You are initializing persistent memory for this codebase. This is not just data collection - you're building context that will make you significantly more effective across all future sessions.
36
+
37
+ ## Understanding Context
38
+
39
+ You are a **stateful** coding agent. Users expect to work with you over extended periods - potentially the entire lifecycle of a project. Your memory is how you get better over time and maintain continuity.
40
+
41
+ ## What to Remember
42
+
43
+ ### 1. Procedures (Rules & Workflows)
44
+ Explicit rules that should always be followed:
45
+ - "Never commit directly to main - always use feature branches"
46
+ - "Always run lint before tests"
47
+ - "Use conventional commits format"
48
+
49
+ ### 2. Preferences (Style & Conventions)
50
+ Project and user coding style:
51
+ - "Prefer functional components over class components"
52
+ - "Use early returns instead of nested conditionals"
53
+ - "Always add JSDoc to exported functions"
54
+
55
+ ### 3. Architecture & Context
56
+ How the codebase works and why:
57
+ - "Auth system was refactored in v2.0 - old patterns deprecated"
58
+ - "The monorepo used to have 3 modules before consolidation"
59
+ - "This pagination bug was fixed before - similar to PR #234"
60
+
61
+ ## Memory Scopes
62
+
63
+ **Project-scoped** (\`scope: "project"\`):
64
+ - Build/test/lint commands
65
+ - Architecture and key directories
66
+ - Team conventions specific to this codebase
67
+ - Technology stack and framework choices
68
+ - Known issues and their solutions
69
+
70
+ **User-scoped** (\`scope: "user"\`):
71
+ - Personal coding preferences across all projects
72
+ - Communication style preferences
73
+ - General workflow habits
74
+
75
+ ## Research Approach
76
+
77
+ This is a **deep research** initialization. Take your time and be thorough (~50+ tool calls). The goal is to genuinely understand the project, not just collect surface-level facts.
78
+
79
+ **What to uncover:**
80
+ - Tech stack and dependencies (explicit and implicit)
81
+ - Project structure and architecture
82
+ - Build/test/deploy commands and workflows
83
+ - Contributors & team dynamics (who works on what?)
84
+ - Commit conventions and branching strategy
85
+ - Code evolution (major refactors, architecture changes)
86
+ - Pain points (areas with lots of bug fixes)
87
+ - Implicit conventions not documented anywhere
88
+
89
+ ## Research Techniques
90
+
91
+ ### File-based
92
+ - README.md, CONTRIBUTING.md, AGENTS.md, CLAUDE.md
93
+ - Package manifests (package.json, Cargo.toml, pyproject.toml, go.mod)
94
+ - Config files (.eslintrc, tsconfig.json, .prettierrc)
95
+ - CI/CD configs (.github/workflows/)
96
+
97
+ ### Git-based
98
+ - \`git log --oneline -20\` - Recent history
99
+ - \`git branch -a\` - Branching strategy
100
+ - \`git log --format="%s" -50\` - Commit conventions
101
+ - \`git shortlog -sn --all | head -10\` - Main contributors
102
+
103
+ ### Explore Agent
104
+ Fire parallel explore queries for broad understanding:
105
+ \`\`\`
106
+ Task(explore, "What is the tech stack and key dependencies?")
107
+ Task(explore, "What is the project structure? Key directories?")
108
+ Task(explore, "How do you build, test, and run this project?")
109
+ Task(explore, "What are the main architectural patterns?")
110
+ Task(explore, "What conventions or patterns are used?")
111
+ \`\`\`
112
+
113
+ ## How to Do Thorough Research
114
+
115
+ **Don't just collect data - analyze and cross-reference.**
116
+
117
+ Bad (shallow):
118
+ - Run commands, copy output
119
+ - List facts without understanding
120
+
121
+ Good (thorough):
122
+ - Cross-reference findings (if inconsistent, dig deeper)
123
+ - Resolve ambiguities (don't leave questions unanswered)
124
+ - Read actual file content, not just names
125
+ - Look for patterns (what do commits tell you about workflow?)
126
+ - Think like a new team member - what would you want to know?
127
+
128
+ ## Saving Memories
129
+
130
+ Use the \`supermemory\` tool for each distinct insight:
131
+
132
+ \`\`\`
133
+ supermemory(mode: "add", content: "...", type: "...", scope: "project")
134
+ \`\`\`
135
+
136
+ **Types:**
137
+ - \`project-config\` - tech stack, commands, tooling
138
+ - \`architecture\` - codebase structure, key components, data flow
139
+ - \`learned-pattern\` - conventions specific to this codebase
140
+ - \`error-solution\` - known issues and their fixes
141
+ - \`preference\` - coding style preferences (use with user scope)
142
+
143
+ **Guidelines:**
144
+ - Save each distinct insight as a separate memory
145
+ - Be concise but include enough context to be useful
146
+ - Include the "why" not just the "what" when relevant
147
+ - Update memories incrementally as you research (don't wait until the end)
148
+
149
+ **Good memories:**
150
+ - "Uses Bun runtime and package manager. Commands: bun install, bun run dev, bun test"
151
+ - "API routes in src/routes/, handlers in src/handlers/. Hono framework."
152
+ - "Auth uses Redis sessions, not JWT. Implementation in src/lib/auth.ts"
153
+ - "Never use \`any\` type - strict TypeScript. Use \`unknown\` and narrow."
154
+ - "Database migrations must be backward compatible - we do rolling deploys"
155
+
156
+ ## Upfront Questions
157
+
158
+ Before diving in, ask:
159
+ 1. "Any specific rules I should always follow?"
160
+ 2. "Preferences for how I communicate? (terse/detailed)"
161
+
162
+ ## Reflection Phase
163
+
164
+ Before finishing, reflect:
165
+ 1. **Completeness**: Did you cover commands, architecture, conventions, gotchas?
166
+ 2. **Quality**: Are memories concise and searchable?
167
+ 3. **Scope**: Did you correctly separate project vs user knowledge?
168
+
169
+ Then ask: "I've initialized memory with X insights. Want me to continue refining, or is this good?"
170
+
171
+ ## Your Task
172
+
173
+ 1. Ask upfront questions (research depth, rules, preferences)
174
+ 2. Check existing memories: \`supermemory(mode: "list", scope: "project")\`
175
+ 3. Research based on chosen depth
176
+ 4. Save memories incrementally as you discover insights
177
+ 5. Reflect and verify completeness
178
+ 6. Summarize what was learned and ask if user wants refinement
179
+ `;
180
+ function createReadline() {
181
+ return readline.createInterface({
182
+ input: process.stdin,
183
+ output: process.stdout
184
+ });
185
+ }
186
+ async function confirm(rl, question) {
187
+ return new Promise((resolve) => {
188
+ rl.question(`${question} (y/n) `, (answer) => {
189
+ resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
190
+ });
191
+ });
192
+ }
193
+ async function installPlugin() {
194
+ const { execSync } = await import("node:child_process");
195
+ let pm = "npm";
196
+ try {
197
+ execSync("bun --version", { stdio: "ignore" });
198
+ pm = "bun";
199
+ } catch {
200
+ try {
201
+ execSync("pnpm --version", { stdio: "ignore" });
202
+ pm = "pnpm";
203
+ } catch {}
204
+ }
205
+ console.log(`Installing ${PLUGIN_NAME} with ${pm}...`);
206
+ try {
207
+ execSync(`${pm} install -g ${PLUGIN_NAME}`, { stdio: "inherit" });
208
+ return true;
209
+ } catch {
210
+ console.error("Failed to install plugin globally.");
211
+ return false;
212
+ }
213
+ }
214
+ function createCommand() {
215
+ mkdirSync(OPENCODE_COMMAND_DIR, { recursive: true });
216
+ const commandPath = join(OPENCODE_COMMAND_DIR, "supermemory-init.md");
217
+ if (existsSync(commandPath)) {
218
+ console.log(`Command already exists at ${commandPath}`);
219
+ return true;
220
+ }
221
+ writeFileSync(commandPath, SUPERMEMORY_INIT_COMMAND);
222
+ console.log(`Created /supermemory-init command`);
223
+ return true;
224
+ }
225
+ function findOpencodeConfig() {
226
+ const candidates = [
227
+ join(OPENCODE_CONFIG_DIR, "config.jsonc"),
228
+ join(OPENCODE_CONFIG_DIR, "config.json")
229
+ ];
230
+ for (const path of candidates) {
231
+ if (existsSync(path)) {
232
+ return path;
233
+ }
234
+ }
235
+ return null;
236
+ }
237
+ function addPluginToConfig(configPath) {
238
+ try {
239
+ const content = readFileSync(configPath, "utf-8");
240
+ if (content.includes("opencode-supermemory")) {
241
+ console.log("Plugin already in config");
242
+ return true;
243
+ }
244
+ const jsonContent = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
245
+ let config;
246
+ try {
247
+ config = JSON.parse(jsonContent);
248
+ } catch {
249
+ console.error("Failed to parse config file");
250
+ return false;
251
+ }
252
+ const plugins = config.plugin || [];
253
+ plugins.push(PLUGIN_NAME);
254
+ config.plugin = plugins;
255
+ if (configPath.endsWith(".jsonc")) {
256
+ if (content.includes('"plugin"')) {
257
+ const newContent = content.replace(/("plugin"\s*:\s*\[)([^\]]*?)(\])/, (_match, start, middle, end) => {
258
+ const trimmed = middle.trim();
259
+ if (trimmed === "") {
260
+ return `${start}
261
+ "${PLUGIN_NAME}"
262
+ ${end}`;
263
+ }
264
+ return `${start}${middle.trimEnd()},
265
+ "${PLUGIN_NAME}"
266
+ ${end}`;
267
+ });
268
+ writeFileSync(configPath, newContent);
269
+ } else {
270
+ const newContent = content.replace(/^(\s*\{)/, `$1
271
+ "plugin": ["${PLUGIN_NAME}"],`);
272
+ writeFileSync(configPath, newContent);
273
+ }
274
+ } else {
275
+ writeFileSync(configPath, JSON.stringify(config, null, 2));
276
+ }
277
+ console.log(`Added ${PLUGIN_NAME} to ${configPath}`);
278
+ return true;
279
+ } catch (err) {
280
+ console.error("Failed to update config:", err);
281
+ return false;
282
+ }
283
+ }
284
+ function createNewConfig() {
285
+ const configPath = join(OPENCODE_CONFIG_DIR, "config.jsonc");
286
+ mkdirSync(OPENCODE_CONFIG_DIR, { recursive: true });
287
+ const config = {
288
+ plugin: [PLUGIN_NAME]
289
+ };
290
+ writeFileSync(configPath, JSON.stringify(config, null, 2));
291
+ console.log(`Created ${configPath} with plugin registered`);
292
+ return true;
293
+ }
294
+ async function setup() {
295
+ const rl = createReadline();
296
+ console.log(`
297
+ opencode-supermemory setup
298
+ `);
299
+ const shouldInstall = await confirm(rl, "Install opencode-supermemory globally?");
300
+ if (!shouldInstall) {
301
+ console.log("Aborted.");
302
+ rl.close();
303
+ process.exit(0);
304
+ }
305
+ const installed = await installPlugin();
306
+ if (!installed) {
307
+ console.log("Aborted.");
308
+ rl.close();
309
+ process.exit(1);
310
+ }
311
+ const shouldCreateCommand = await confirm(rl, "Add /supermemory-init command?");
312
+ if (!shouldCreateCommand) {
313
+ console.log("Aborted.");
314
+ rl.close();
315
+ process.exit(0);
316
+ }
317
+ createCommand();
318
+ const configPath = findOpencodeConfig();
319
+ if (configPath) {
320
+ const shouldModifyConfig = await confirm(rl, `Add plugin to ${configPath}?`);
321
+ if (!shouldModifyConfig) {
322
+ console.log("Aborted.");
323
+ rl.close();
324
+ process.exit(0);
325
+ }
326
+ addPluginToConfig(configPath);
327
+ } else {
328
+ const shouldCreateConfig = await confirm(rl, "No OpenCode config found. Create one?");
329
+ if (!shouldCreateConfig) {
330
+ console.log("Aborted.");
331
+ rl.close();
332
+ process.exit(0);
333
+ }
334
+ createNewConfig();
335
+ }
336
+ console.log(`
337
+ Setup complete!`);
338
+ console.log("Set SUPERMEMORY_API_KEY and restart OpenCode.");
339
+ rl.close();
340
+ }
341
+ function printHelp() {
342
+ console.log(`
343
+ opencode-supermemory CLI
344
+
345
+ Commands:
346
+ setup Interactive setup wizard
347
+
348
+ Examples:
349
+ npx opencode-supermemory setup
350
+ bunx opencode-supermemory setup
351
+ `);
352
+ }
353
+ var args = process.argv.slice(2);
354
+ if (args.length === 0 || args[0] === "help" || args[0] === "--help") {
355
+ printHelp();
356
+ process.exit(0);
357
+ }
358
+ if (args[0] === "setup") {
359
+ setup();
360
+ } else {
361
+ console.error(`Unknown command: ${args.join(" ")}`);
362
+ printHelp();
363
+ process.exit(1);
364
+ }
@@ -0,0 +1,11 @@
1
+ export declare const SUPERMEMORY_API_KEY: string | undefined;
2
+ export declare const CONFIG: {
3
+ similarityThreshold: number;
4
+ maxMemories: number;
5
+ maxProjectMemories: number;
6
+ maxProfileItems: number;
7
+ injectProfile: boolean;
8
+ containerTagPrefix: string;
9
+ };
10
+ export declare function isConfigured(): boolean;
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAiDA,eAAO,MAAM,mBAAmB,oBAAuD,CAAC;AAExF,eAAO,MAAM,MAAM;;;;;;;CAOlB,CAAC;AAEF,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ export declare const SupermemoryPlugin: Plugin;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AAuC/D,eAAO,MAAM,iBAAiB,EAAE,MA6Y/B,CAAC"}