@stackmemoryai/stackmemory 0.5.24 → 0.5.26

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.
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * OpenCode-SM CLI Launcher (ESM)
4
+ * Delegates to built CLI in dist without requiring tsx.
5
+ */
6
+ import('../dist/cli/opencode-sm.js');
@@ -0,0 +1,448 @@
1
+ #!/usr/bin/env node
2
+ import { fileURLToPath as __fileURLToPath } from 'url';
3
+ import { dirname as __pathDirname } from 'path';
4
+ const __filename = __fileURLToPath(import.meta.url);
5
+ const __dirname = __pathDirname(__filename);
6
+ import { config as loadDotenv } from "dotenv";
7
+ loadDotenv({ override: true });
8
+ import { spawn, execSync, execFileSync } from "child_process";
9
+ import * as fs from "fs";
10
+ import * as path from "path";
11
+ import * as os from "os";
12
+ import { program } from "commander";
13
+ import { v4 as uuidv4 } from "uuid";
14
+ import chalk from "chalk";
15
+ import { initializeTracing, trace } from "../core/trace/index.js";
16
+ const DEFAULT_SM_CONFIG = {
17
+ defaultWorktree: false,
18
+ defaultTracing: true
19
+ };
20
+ function getConfigPath() {
21
+ return path.join(os.homedir(), ".stackmemory", "opencode-sm.json");
22
+ }
23
+ function loadSMConfig() {
24
+ try {
25
+ const configPath = getConfigPath();
26
+ if (fs.existsSync(configPath)) {
27
+ const content = fs.readFileSync(configPath, "utf8");
28
+ return { ...DEFAULT_SM_CONFIG, ...JSON.parse(content) };
29
+ }
30
+ } catch {
31
+ }
32
+ return { ...DEFAULT_SM_CONFIG };
33
+ }
34
+ function saveSMConfig(config) {
35
+ const configPath = getConfigPath();
36
+ const dir = path.dirname(configPath);
37
+ if (!fs.existsSync(dir)) {
38
+ fs.mkdirSync(dir, { recursive: true });
39
+ }
40
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
41
+ }
42
+ class OpencodeSM {
43
+ config;
44
+ stackmemoryPath;
45
+ smConfig;
46
+ constructor() {
47
+ this.smConfig = loadSMConfig();
48
+ this.config = {
49
+ instanceId: this.generateInstanceId(),
50
+ useWorktree: this.smConfig.defaultWorktree,
51
+ contextEnabled: true,
52
+ tracingEnabled: this.smConfig.defaultTracing,
53
+ verboseTracing: false,
54
+ sessionStartTime: Date.now()
55
+ };
56
+ this.stackmemoryPath = this.findStackMemory();
57
+ }
58
+ generateInstanceId() {
59
+ return uuidv4().substring(0, 8);
60
+ }
61
+ findStackMemory() {
62
+ const possiblePaths = [
63
+ path.join(os.homedir(), ".stackmemory", "bin", "stackmemory"),
64
+ "/usr/local/bin/stackmemory",
65
+ "/opt/homebrew/bin/stackmemory",
66
+ "stackmemory"
67
+ ];
68
+ for (const smPath of possiblePaths) {
69
+ try {
70
+ execFileSync("which", [smPath], { stdio: "ignore" });
71
+ return smPath;
72
+ } catch {
73
+ }
74
+ }
75
+ return "stackmemory";
76
+ }
77
+ isGitRepo() {
78
+ try {
79
+ execSync("git rev-parse --git-dir", { stdio: "ignore" });
80
+ return true;
81
+ } catch {
82
+ return false;
83
+ }
84
+ }
85
+ getCurrentBranch() {
86
+ try {
87
+ return execSync("git rev-parse --abbrev-ref HEAD", {
88
+ encoding: "utf8"
89
+ }).trim();
90
+ } catch {
91
+ return "main";
92
+ }
93
+ }
94
+ hasUncommittedChanges() {
95
+ try {
96
+ const status = execSync("git status --porcelain", { encoding: "utf8" });
97
+ return status.length > 0;
98
+ } catch {
99
+ return false;
100
+ }
101
+ }
102
+ resolveOpencodeBin() {
103
+ if (this.config.opencodeBin && this.config.opencodeBin.trim()) {
104
+ return this.config.opencodeBin.trim();
105
+ }
106
+ const envBin = process.env["OPENCODE_BIN"];
107
+ if (envBin && envBin.trim()) return envBin.trim();
108
+ const possiblePaths = [
109
+ path.join(os.homedir(), ".opencode", "bin", "opencode"),
110
+ "/usr/local/bin/opencode",
111
+ "/opt/homebrew/bin/opencode"
112
+ ];
113
+ for (const binPath of possiblePaths) {
114
+ if (fs.existsSync(binPath)) {
115
+ return binPath;
116
+ }
117
+ }
118
+ try {
119
+ execSync("which opencode", { stdio: "ignore" });
120
+ return "opencode";
121
+ } catch {
122
+ }
123
+ return null;
124
+ }
125
+ setupWorktree() {
126
+ if (!this.config.useWorktree || !this.isGitRepo()) {
127
+ return null;
128
+ }
129
+ console.log(chalk.blue("Setting up isolated worktree..."));
130
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
131
+ const branch = this.config.branch || `opencode-${this.config.task || "work"}-${timestamp}-${this.config.instanceId}`;
132
+ const repoName = path.basename(process.cwd());
133
+ const worktreePath = path.join(
134
+ path.dirname(process.cwd()),
135
+ `${repoName}--${branch}`
136
+ );
137
+ try {
138
+ const cmd = `git worktree add -b "${branch}" "${worktreePath}"`;
139
+ execSync(cmd, { stdio: "inherit" });
140
+ console.log(chalk.green(`Worktree created: ${worktreePath}`));
141
+ console.log(chalk.gray(`Branch: ${branch}`));
142
+ const configPath = path.join(worktreePath, ".opencode-instance.json");
143
+ const configData = {
144
+ instanceId: this.config.instanceId,
145
+ worktreePath,
146
+ branch,
147
+ task: this.config.task,
148
+ created: (/* @__PURE__ */ new Date()).toISOString(),
149
+ parentRepo: process.cwd()
150
+ };
151
+ fs.writeFileSync(configPath, JSON.stringify(configData, null, 2));
152
+ const envFiles = [".env", ".env.local", ".mise.toml", ".tool-versions"];
153
+ for (const file of envFiles) {
154
+ const srcPath = path.join(process.cwd(), file);
155
+ if (fs.existsSync(srcPath)) {
156
+ fs.copyFileSync(srcPath, path.join(worktreePath, file));
157
+ }
158
+ }
159
+ return worktreePath;
160
+ } catch (err) {
161
+ console.error(chalk.red("Failed to create worktree:"), err);
162
+ return null;
163
+ }
164
+ }
165
+ saveContext(message, metadata = {}) {
166
+ if (!this.config.contextEnabled) return;
167
+ try {
168
+ const contextData = {
169
+ message,
170
+ metadata: {
171
+ ...metadata,
172
+ instanceId: this.config.instanceId,
173
+ worktree: this.config.worktreePath,
174
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
175
+ tool: "opencode"
176
+ }
177
+ };
178
+ const cmd = `${this.stackmemoryPath} context save --json '${JSON.stringify(contextData)}'`;
179
+ execSync(cmd, { stdio: "ignore" });
180
+ } catch {
181
+ }
182
+ }
183
+ loadContext() {
184
+ if (!this.config.contextEnabled) return;
185
+ try {
186
+ console.log(chalk.blue("Loading previous context..."));
187
+ const cmd = `${this.stackmemoryPath} context show`;
188
+ const output = execSync(cmd, {
189
+ encoding: "utf8",
190
+ stdio: ["pipe", "pipe", "pipe"]
191
+ });
192
+ const lines = output.trim().split("\n").filter((l) => l.trim());
193
+ if (lines.length > 3) {
194
+ console.log(chalk.gray("Context stack loaded"));
195
+ }
196
+ } catch {
197
+ }
198
+ }
199
+ detectMultipleInstances() {
200
+ try {
201
+ const lockDir = path.join(process.cwd(), ".opencode-worktree-locks");
202
+ if (!fs.existsSync(lockDir)) return false;
203
+ const locks = fs.readdirSync(lockDir).filter((f) => f.endsWith(".lock"));
204
+ const activeLocks = locks.filter((lockFile) => {
205
+ const lockPath = path.join(lockDir, lockFile);
206
+ const lockData = JSON.parse(fs.readFileSync(lockPath, "utf8"));
207
+ const lockAge = Date.now() - new Date(lockData.created).getTime();
208
+ return lockAge < 24 * 60 * 60 * 1e3;
209
+ });
210
+ return activeLocks.length > 0;
211
+ } catch {
212
+ return false;
213
+ }
214
+ }
215
+ suggestWorktreeMode() {
216
+ if (this.hasUncommittedChanges()) {
217
+ console.log(chalk.yellow("Uncommitted changes detected"));
218
+ console.log(chalk.gray("Consider using --worktree to work in isolation"));
219
+ }
220
+ if (this.detectMultipleInstances()) {
221
+ console.log(chalk.yellow("Other OpenCode instances detected"));
222
+ console.log(
223
+ chalk.gray("Using --worktree is recommended to avoid conflicts")
224
+ );
225
+ }
226
+ }
227
+ async run(args) {
228
+ const opencodeArgs = [];
229
+ let i = 0;
230
+ while (i < args.length) {
231
+ const arg = args[i];
232
+ switch (arg) {
233
+ case "--worktree":
234
+ case "-w":
235
+ this.config.useWorktree = true;
236
+ break;
237
+ case "--no-worktree":
238
+ case "-W":
239
+ this.config.useWorktree = false;
240
+ break;
241
+ case "--no-context":
242
+ this.config.contextEnabled = false;
243
+ break;
244
+ case "--no-trace":
245
+ this.config.tracingEnabled = false;
246
+ break;
247
+ case "--verbose-trace":
248
+ this.config.verboseTracing = true;
249
+ break;
250
+ case "--branch":
251
+ case "-b":
252
+ i++;
253
+ this.config.branch = args[i];
254
+ break;
255
+ case "--task":
256
+ case "-t":
257
+ i++;
258
+ this.config.task = args[i];
259
+ break;
260
+ case "--opencode-bin":
261
+ i++;
262
+ this.config.opencodeBin = args[i];
263
+ process.env["OPENCODE_BIN"] = this.config.opencodeBin;
264
+ break;
265
+ case "--auto":
266
+ case "-a":
267
+ if (this.isGitRepo()) {
268
+ this.config.useWorktree = this.hasUncommittedChanges() || this.detectMultipleInstances();
269
+ }
270
+ break;
271
+ default:
272
+ opencodeArgs.push(arg);
273
+ }
274
+ i++;
275
+ }
276
+ if (this.config.tracingEnabled) {
277
+ process.env["DEBUG_TRACE"] = "true";
278
+ process.env["STACKMEMORY_DEBUG"] = "true";
279
+ process.env["TRACE_OUTPUT"] = "file";
280
+ process.env["TRACE_MASK_SENSITIVE"] = "true";
281
+ if (this.config.verboseTracing) {
282
+ process.env["TRACE_VERBOSITY"] = "full";
283
+ process.env["TRACE_PARAMS"] = "true";
284
+ process.env["TRACE_RESULTS"] = "true";
285
+ process.env["TRACE_MEMORY"] = "true";
286
+ } else {
287
+ process.env["TRACE_VERBOSITY"] = "summary";
288
+ process.env["TRACE_PARAMS"] = "true";
289
+ process.env["TRACE_RESULTS"] = "false";
290
+ }
291
+ initializeTracing();
292
+ trace.command(
293
+ "opencode-sm",
294
+ {
295
+ instanceId: this.config.instanceId,
296
+ worktree: this.config.useWorktree,
297
+ task: this.config.task
298
+ },
299
+ async () => {
300
+ }
301
+ );
302
+ }
303
+ console.log(chalk.magenta("OpenCode + StackMemory"));
304
+ console.log();
305
+ if (this.isGitRepo()) {
306
+ const branch = this.getCurrentBranch();
307
+ console.log(chalk.gray(`Branch: ${branch}`));
308
+ if (!this.config.useWorktree) {
309
+ this.suggestWorktreeMode();
310
+ }
311
+ }
312
+ if (this.config.useWorktree) {
313
+ const worktreePath = this.setupWorktree();
314
+ if (worktreePath) {
315
+ this.config.worktreePath = worktreePath;
316
+ process.chdir(worktreePath);
317
+ this.saveContext("Created worktree for OpenCode instance", {
318
+ action: "worktree_created",
319
+ path: worktreePath,
320
+ branch: this.config.branch
321
+ });
322
+ }
323
+ }
324
+ this.loadContext();
325
+ process.env["OPENCODE_INSTANCE_ID"] = this.config.instanceId;
326
+ if (this.config.worktreePath) {
327
+ process.env["OPENCODE_WORKTREE_PATH"] = this.config.worktreePath;
328
+ }
329
+ console.log(chalk.gray(`Instance: ${this.config.instanceId}`));
330
+ console.log(chalk.gray(`Working in: ${process.cwd()}`));
331
+ if (this.config.tracingEnabled) {
332
+ console.log(
333
+ chalk.gray(`Tracing enabled (logs to ~/.stackmemory/traces/)`)
334
+ );
335
+ }
336
+ console.log();
337
+ console.log(chalk.gray("Starting OpenCode..."));
338
+ console.log(chalk.gray("-".repeat(40)));
339
+ const opencodeBin = this.resolveOpencodeBin();
340
+ if (!opencodeBin) {
341
+ console.error(chalk.red("OpenCode CLI not found."));
342
+ console.log(
343
+ chalk.gray(
344
+ "Install OpenCode or set an override:\n export OPENCODE_BIN=/path/to/opencode\n opencode-sm --help"
345
+ )
346
+ );
347
+ process.exit(1);
348
+ return;
349
+ }
350
+ const opencode = spawn(opencodeBin, opencodeArgs, {
351
+ stdio: "inherit",
352
+ env: process.env
353
+ });
354
+ opencode.on("error", (err) => {
355
+ console.error(chalk.red("Failed to launch OpenCode CLI."));
356
+ if (err.code === "ENOENT") {
357
+ console.error(
358
+ chalk.gray("Not found. Set OPENCODE_BIN or install opencode.")
359
+ );
360
+ } else {
361
+ console.error(chalk.gray(`${err.message}`));
362
+ }
363
+ process.exit(1);
364
+ });
365
+ opencode.on("exit", async (code) => {
366
+ this.saveContext("OpenCode session ended", {
367
+ action: "session_end",
368
+ exitCode: code
369
+ });
370
+ if (this.config.tracingEnabled) {
371
+ const summary = trace.getExecutionSummary();
372
+ console.log();
373
+ console.log(chalk.gray("-".repeat(40)));
374
+ console.log(chalk.magenta("Trace Summary:"));
375
+ console.log(chalk.gray(summary));
376
+ }
377
+ if (this.config.worktreePath) {
378
+ console.log();
379
+ console.log(chalk.gray("-".repeat(40)));
380
+ console.log(chalk.magenta("Session ended in worktree:"));
381
+ console.log(chalk.gray(` ${this.config.worktreePath}`));
382
+ }
383
+ process.exit(code || 0);
384
+ });
385
+ process.on("SIGINT", () => {
386
+ this.saveContext("OpenCode session interrupted", {
387
+ action: "session_interrupt"
388
+ });
389
+ opencode.kill("SIGINT");
390
+ });
391
+ process.on("SIGTERM", () => {
392
+ this.saveContext("OpenCode session terminated", {
393
+ action: "session_terminate"
394
+ });
395
+ opencode.kill("SIGTERM");
396
+ });
397
+ }
398
+ }
399
+ program.name("opencode-sm").description("OpenCode with StackMemory context and worktree isolation").version("1.0.0");
400
+ const configCmd = program.command("config").description("Manage opencode-sm defaults");
401
+ configCmd.command("show").description("Show current default settings").action(() => {
402
+ const config = loadSMConfig();
403
+ console.log(chalk.magenta("opencode-sm defaults:"));
404
+ console.log(
405
+ ` defaultWorktree: ${config.defaultWorktree ? chalk.green("true") : chalk.gray("false")}`
406
+ );
407
+ console.log(
408
+ ` defaultTracing: ${config.defaultTracing ? chalk.green("true") : chalk.gray("false")}`
409
+ );
410
+ console.log(chalk.gray(`
411
+ Config: ${getConfigPath()}`));
412
+ });
413
+ configCmd.command("set <key> <value>").description("Set a default (e.g., set worktree true)").action((key, value) => {
414
+ const config = loadSMConfig();
415
+ const boolValue = value === "true" || value === "1" || value === "on";
416
+ const keyMap = {
417
+ worktree: "defaultWorktree",
418
+ tracing: "defaultTracing"
419
+ };
420
+ const configKey = keyMap[key];
421
+ if (!configKey) {
422
+ console.log(chalk.red(`Unknown key: ${key}`));
423
+ console.log(chalk.gray("Valid keys: worktree, tracing"));
424
+ process.exit(1);
425
+ }
426
+ config[configKey] = boolValue;
427
+ saveSMConfig(config);
428
+ console.log(chalk.green(`Set ${key} = ${boolValue}`));
429
+ });
430
+ configCmd.command("worktree-on").description("Enable worktree mode by default").action(() => {
431
+ const config = loadSMConfig();
432
+ config.defaultWorktree = true;
433
+ saveSMConfig(config);
434
+ console.log(chalk.green("Worktree mode enabled by default"));
435
+ });
436
+ configCmd.command("worktree-off").description("Disable worktree mode by default").action(() => {
437
+ const config = loadSMConfig();
438
+ config.defaultWorktree = false;
439
+ saveSMConfig(config);
440
+ console.log(chalk.green("Worktree mode disabled by default"));
441
+ });
442
+ program.option("-w, --worktree", "Create isolated worktree for this instance").option("-W, --no-worktree", "Disable worktree (override default)").option("-a, --auto", "Automatically detect and apply best settings").option("-b, --branch <name>", "Specify branch name for worktree").option("-t, --task <desc>", "Task description for context").option("--opencode-bin <path>", "Path to opencode CLI (or use OPENCODE_BIN)").option("--no-context", "Disable StackMemory context integration").option("--no-trace", "Disable debug tracing (enabled by default)").option("--verbose-trace", "Enable verbose debug tracing with full details").helpOption("-h, --help", "Display help").allowUnknownOption(true).action(async (_options) => {
443
+ const opencodeSM = new OpencodeSM();
444
+ const args = process.argv.slice(2);
445
+ await opencodeSM.run(args);
446
+ });
447
+ program.parse(process.argv);
448
+ //# sourceMappingURL=opencode-sm.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cli/opencode-sm.ts"],
4
+ "sourcesContent": ["#!/usr/bin/env node\n\n/**\n * opencode-sm: OpenCode wrapper with StackMemory and worktree integration\n * Automatically manages context persistence and instance isolation\n */\n\nimport { config as loadDotenv } from 'dotenv';\nloadDotenv({ override: true });\n\nimport { spawn, execSync, execFileSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { program } from 'commander';\nimport { v4 as uuidv4 } from 'uuid';\nimport chalk from 'chalk';\nimport { initializeTracing, trace } from '../core/trace/index.js';\n\ninterface OpencodeSMConfig {\n defaultWorktree: boolean;\n defaultTracing: boolean;\n}\n\ninterface OpencodeConfig {\n instanceId: string;\n worktreePath?: string;\n useWorktree: boolean;\n contextEnabled: boolean;\n branch?: string;\n task?: string;\n tracingEnabled: boolean;\n verboseTracing: boolean;\n opencodeBin?: string;\n sessionStartTime: number;\n}\n\nconst DEFAULT_SM_CONFIG: OpencodeSMConfig = {\n defaultWorktree: false,\n defaultTracing: true,\n};\n\nfunction getConfigPath(): string {\n return path.join(os.homedir(), '.stackmemory', 'opencode-sm.json');\n}\n\nfunction loadSMConfig(): OpencodeSMConfig {\n try {\n const configPath = getConfigPath();\n if (fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, 'utf8');\n return { ...DEFAULT_SM_CONFIG, ...JSON.parse(content) };\n }\n } catch {\n // Ignore errors, use defaults\n }\n return { ...DEFAULT_SM_CONFIG };\n}\n\nfunction saveSMConfig(config: OpencodeSMConfig): void {\n const configPath = getConfigPath();\n const dir = path.dirname(configPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2));\n}\n\nclass OpencodeSM {\n private config: OpencodeConfig;\n private stackmemoryPath: string;\n private smConfig: OpencodeSMConfig;\n\n constructor() {\n this.smConfig = loadSMConfig();\n\n this.config = {\n instanceId: this.generateInstanceId(),\n useWorktree: this.smConfig.defaultWorktree,\n contextEnabled: true,\n tracingEnabled: this.smConfig.defaultTracing,\n verboseTracing: false,\n sessionStartTime: Date.now(),\n };\n\n this.stackmemoryPath = this.findStackMemory();\n }\n\n private generateInstanceId(): string {\n return uuidv4().substring(0, 8);\n }\n\n private findStackMemory(): string {\n const possiblePaths = [\n path.join(os.homedir(), '.stackmemory', 'bin', 'stackmemory'),\n '/usr/local/bin/stackmemory',\n '/opt/homebrew/bin/stackmemory',\n 'stackmemory',\n ];\n\n for (const smPath of possiblePaths) {\n try {\n execFileSync('which', [smPath], { stdio: 'ignore' });\n return smPath;\n } catch {\n // Continue searching\n }\n }\n\n return 'stackmemory';\n }\n\n private isGitRepo(): boolean {\n try {\n execSync('git rev-parse --git-dir', { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n }\n\n private getCurrentBranch(): string {\n try {\n return execSync('git rev-parse --abbrev-ref HEAD', {\n encoding: 'utf8',\n }).trim();\n } catch {\n return 'main';\n }\n }\n\n private hasUncommittedChanges(): boolean {\n try {\n const status = execSync('git status --porcelain', { encoding: 'utf8' });\n return status.length > 0;\n } catch {\n return false;\n }\n }\n\n private resolveOpencodeBin(): string | null {\n if (this.config.opencodeBin && this.config.opencodeBin.trim()) {\n return this.config.opencodeBin.trim();\n }\n const envBin = process.env['OPENCODE_BIN'];\n if (envBin && envBin.trim()) return envBin.trim();\n\n // Check common OpenCode locations\n const possiblePaths = [\n path.join(os.homedir(), '.opencode', 'bin', 'opencode'),\n '/usr/local/bin/opencode',\n '/opt/homebrew/bin/opencode',\n ];\n\n for (const binPath of possiblePaths) {\n if (fs.existsSync(binPath)) {\n return binPath;\n }\n }\n\n // Try PATH\n try {\n execSync('which opencode', { stdio: 'ignore' });\n return 'opencode';\n } catch {\n // Not found\n }\n return null;\n }\n\n private setupWorktree(): string | null {\n if (!this.config.useWorktree || !this.isGitRepo()) {\n return null;\n }\n\n console.log(chalk.blue('Setting up isolated worktree...'));\n\n const timestamp = new Date()\n .toISOString()\n .replace(/[:.]/g, '-')\n .substring(0, 19);\n const branch =\n this.config.branch ||\n `opencode-${this.config.task || 'work'}-${timestamp}-${this.config.instanceId}`;\n const repoName = path.basename(process.cwd());\n const worktreePath = path.join(\n path.dirname(process.cwd()),\n `${repoName}--${branch}`\n );\n\n try {\n const cmd = `git worktree add -b \"${branch}\" \"${worktreePath}\"`;\n execSync(cmd, { stdio: 'inherit' });\n\n console.log(chalk.green(`Worktree created: ${worktreePath}`));\n console.log(chalk.gray(`Branch: ${branch}`));\n\n const configPath = path.join(worktreePath, '.opencode-instance.json');\n const configData = {\n instanceId: this.config.instanceId,\n worktreePath,\n branch,\n task: this.config.task,\n created: new Date().toISOString(),\n parentRepo: process.cwd(),\n };\n fs.writeFileSync(configPath, JSON.stringify(configData, null, 2));\n\n // Copy environment files\n const envFiles = ['.env', '.env.local', '.mise.toml', '.tool-versions'];\n for (const file of envFiles) {\n const srcPath = path.join(process.cwd(), file);\n if (fs.existsSync(srcPath)) {\n fs.copyFileSync(srcPath, path.join(worktreePath, file));\n }\n }\n\n return worktreePath;\n } catch (err: unknown) {\n console.error(chalk.red('Failed to create worktree:'), err);\n return null;\n }\n }\n\n private saveContext(\n message: string,\n metadata: Record<string, unknown> = {}\n ): void {\n if (!this.config.contextEnabled) return;\n\n try {\n const contextData = {\n message,\n metadata: {\n ...metadata,\n instanceId: this.config.instanceId,\n worktree: this.config.worktreePath,\n timestamp: new Date().toISOString(),\n tool: 'opencode',\n },\n };\n\n const cmd = `${this.stackmemoryPath} context save --json '${JSON.stringify(contextData)}'`;\n execSync(cmd, { stdio: 'ignore' });\n } catch {\n // Silently fail\n }\n }\n\n private loadContext(): void {\n if (!this.config.contextEnabled) return;\n\n try {\n console.log(chalk.blue('Loading previous context...'));\n const cmd = `${this.stackmemoryPath} context show`;\n const output = execSync(cmd, {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n const lines = output\n .trim()\n .split('\\n')\n .filter((l) => l.trim());\n if (lines.length > 3) {\n console.log(chalk.gray('Context stack loaded'));\n }\n } catch {\n // Silently continue\n }\n }\n\n private detectMultipleInstances(): boolean {\n try {\n const lockDir = path.join(process.cwd(), '.opencode-worktree-locks');\n if (!fs.existsSync(lockDir)) return false;\n\n const locks = fs.readdirSync(lockDir).filter((f) => f.endsWith('.lock'));\n const activeLocks = locks.filter((lockFile) => {\n const lockPath = path.join(lockDir, lockFile);\n const lockData = JSON.parse(fs.readFileSync(lockPath, 'utf8'));\n const lockAge = Date.now() - new Date(lockData.created).getTime();\n return lockAge < 24 * 60 * 60 * 1000;\n });\n\n return activeLocks.length > 0;\n } catch {\n return false;\n }\n }\n\n private suggestWorktreeMode(): void {\n if (this.hasUncommittedChanges()) {\n console.log(chalk.yellow('Uncommitted changes detected'));\n console.log(chalk.gray('Consider using --worktree to work in isolation'));\n }\n\n if (this.detectMultipleInstances()) {\n console.log(chalk.yellow('Other OpenCode instances detected'));\n console.log(\n chalk.gray('Using --worktree is recommended to avoid conflicts')\n );\n }\n }\n\n public async run(args: string[]): Promise<void> {\n const opencodeArgs: string[] = [];\n let i = 0;\n\n while (i < args.length) {\n const arg = args[i];\n\n switch (arg) {\n case '--worktree':\n case '-w':\n this.config.useWorktree = true;\n break;\n case '--no-worktree':\n case '-W':\n this.config.useWorktree = false;\n break;\n case '--no-context':\n this.config.contextEnabled = false;\n break;\n case '--no-trace':\n this.config.tracingEnabled = false;\n break;\n case '--verbose-trace':\n this.config.verboseTracing = true;\n break;\n case '--branch':\n case '-b':\n i++;\n this.config.branch = args[i];\n break;\n case '--task':\n case '-t':\n i++;\n this.config.task = args[i];\n break;\n case '--opencode-bin':\n i++;\n this.config.opencodeBin = args[i];\n process.env['OPENCODE_BIN'] = this.config.opencodeBin;\n break;\n case '--auto':\n case '-a':\n if (this.isGitRepo()) {\n this.config.useWorktree =\n this.hasUncommittedChanges() || this.detectMultipleInstances();\n }\n break;\n default:\n opencodeArgs.push(arg);\n }\n i++;\n }\n\n // Initialize tracing if enabled\n if (this.config.tracingEnabled) {\n process.env['DEBUG_TRACE'] = 'true';\n process.env['STACKMEMORY_DEBUG'] = 'true';\n process.env['TRACE_OUTPUT'] = 'file';\n process.env['TRACE_MASK_SENSITIVE'] = 'true';\n\n if (this.config.verboseTracing) {\n process.env['TRACE_VERBOSITY'] = 'full';\n process.env['TRACE_PARAMS'] = 'true';\n process.env['TRACE_RESULTS'] = 'true';\n process.env['TRACE_MEMORY'] = 'true';\n } else {\n process.env['TRACE_VERBOSITY'] = 'summary';\n process.env['TRACE_PARAMS'] = 'true';\n process.env['TRACE_RESULTS'] = 'false';\n }\n\n initializeTracing();\n\n trace.command(\n 'opencode-sm',\n {\n instanceId: this.config.instanceId,\n worktree: this.config.useWorktree,\n task: this.config.task,\n },\n async () => {}\n );\n }\n\n // Show header\n console.log(chalk.magenta('OpenCode + StackMemory'));\n console.log();\n\n if (this.isGitRepo()) {\n const branch = this.getCurrentBranch();\n console.log(chalk.gray(`Branch: ${branch}`));\n\n if (!this.config.useWorktree) {\n this.suggestWorktreeMode();\n }\n }\n\n // Setup worktree if requested\n if (this.config.useWorktree) {\n const worktreePath = this.setupWorktree();\n if (worktreePath) {\n this.config.worktreePath = worktreePath;\n process.chdir(worktreePath);\n\n this.saveContext('Created worktree for OpenCode instance', {\n action: 'worktree_created',\n path: worktreePath,\n branch: this.config.branch,\n });\n }\n }\n\n this.loadContext();\n\n // Setup environment\n process.env['OPENCODE_INSTANCE_ID'] = this.config.instanceId;\n if (this.config.worktreePath) {\n process.env['OPENCODE_WORKTREE_PATH'] = this.config.worktreePath;\n }\n\n console.log(chalk.gray(`Instance: ${this.config.instanceId}`));\n console.log(chalk.gray(`Working in: ${process.cwd()}`));\n\n if (this.config.tracingEnabled) {\n console.log(\n chalk.gray(`Tracing enabled (logs to ~/.stackmemory/traces/)`)\n );\n }\n\n console.log();\n console.log(chalk.gray('Starting OpenCode...'));\n console.log(chalk.gray('-'.repeat(40)));\n\n const opencodeBin = this.resolveOpencodeBin();\n if (!opencodeBin) {\n console.error(chalk.red('OpenCode CLI not found.'));\n console.log(\n chalk.gray(\n 'Install OpenCode or set an override:\\n' +\n ' export OPENCODE_BIN=/path/to/opencode\\n' +\n ' opencode-sm --help'\n )\n );\n process.exit(1);\n return;\n }\n\n const opencode = spawn(opencodeBin, opencodeArgs, {\n stdio: 'inherit',\n env: process.env,\n });\n\n opencode.on('error', (err: NodeJS.ErrnoException) => {\n console.error(chalk.red('Failed to launch OpenCode CLI.'));\n if (err.code === 'ENOENT') {\n console.error(\n chalk.gray('Not found. Set OPENCODE_BIN or install opencode.')\n );\n } else {\n console.error(chalk.gray(`${err.message}`));\n }\n process.exit(1);\n });\n\n opencode.on('exit', async (code) => {\n this.saveContext('OpenCode session ended', {\n action: 'session_end',\n exitCode: code,\n });\n\n if (this.config.tracingEnabled) {\n const summary = trace.getExecutionSummary();\n console.log();\n console.log(chalk.gray('-'.repeat(40)));\n console.log(chalk.magenta('Trace Summary:'));\n console.log(chalk.gray(summary));\n }\n\n if (this.config.worktreePath) {\n console.log();\n console.log(chalk.gray('-'.repeat(40)));\n console.log(chalk.magenta('Session ended in worktree:'));\n console.log(chalk.gray(` ${this.config.worktreePath}`));\n }\n\n process.exit(code || 0);\n });\n\n process.on('SIGINT', () => {\n this.saveContext('OpenCode session interrupted', {\n action: 'session_interrupt',\n });\n opencode.kill('SIGINT');\n });\n\n process.on('SIGTERM', () => {\n this.saveContext('OpenCode session terminated', {\n action: 'session_terminate',\n });\n opencode.kill('SIGTERM');\n });\n }\n}\n\n// CLI interface\nprogram\n .name('opencode-sm')\n .description('OpenCode with StackMemory context and worktree isolation')\n .version('1.0.0');\n\n// Config subcommand\nconst configCmd = program\n .command('config')\n .description('Manage opencode-sm defaults');\n\nconfigCmd\n .command('show')\n .description('Show current default settings')\n .action(() => {\n const config = loadSMConfig();\n console.log(chalk.magenta('opencode-sm defaults:'));\n console.log(\n ` defaultWorktree: ${config.defaultWorktree ? chalk.green('true') : chalk.gray('false')}`\n );\n console.log(\n ` defaultTracing: ${config.defaultTracing ? chalk.green('true') : chalk.gray('false')}`\n );\n console.log(chalk.gray(`\\nConfig: ${getConfigPath()}`));\n });\n\nconfigCmd\n .command('set <key> <value>')\n .description('Set a default (e.g., set worktree true)')\n .action((key: string, value: string) => {\n const config = loadSMConfig();\n const boolValue = value === 'true' || value === '1' || value === 'on';\n\n const keyMap: Record<string, keyof OpencodeSMConfig> = {\n worktree: 'defaultWorktree',\n tracing: 'defaultTracing',\n };\n\n const configKey = keyMap[key];\n if (!configKey) {\n console.log(chalk.red(`Unknown key: ${key}`));\n console.log(chalk.gray('Valid keys: worktree, tracing'));\n process.exit(1);\n }\n\n config[configKey] = boolValue;\n saveSMConfig(config);\n console.log(chalk.green(`Set ${key} = ${boolValue}`));\n });\n\nconfigCmd\n .command('worktree-on')\n .description('Enable worktree mode by default')\n .action(() => {\n const config = loadSMConfig();\n config.defaultWorktree = true;\n saveSMConfig(config);\n console.log(chalk.green('Worktree mode enabled by default'));\n });\n\nconfigCmd\n .command('worktree-off')\n .description('Disable worktree mode by default')\n .action(() => {\n const config = loadSMConfig();\n config.defaultWorktree = false;\n saveSMConfig(config);\n console.log(chalk.green('Worktree mode disabled by default'));\n });\n\n// Main command\nprogram\n .option('-w, --worktree', 'Create isolated worktree for this instance')\n .option('-W, --no-worktree', 'Disable worktree (override default)')\n .option('-a, --auto', 'Automatically detect and apply best settings')\n .option('-b, --branch <name>', 'Specify branch name for worktree')\n .option('-t, --task <desc>', 'Task description for context')\n .option('--opencode-bin <path>', 'Path to opencode CLI (or use OPENCODE_BIN)')\n .option('--no-context', 'Disable StackMemory context integration')\n .option('--no-trace', 'Disable debug tracing (enabled by default)')\n .option('--verbose-trace', 'Enable verbose debug tracing with full details')\n .helpOption('-h, --help', 'Display help')\n .allowUnknownOption(true)\n .action(async (_options) => {\n const opencodeSM = new OpencodeSM();\n const args = process.argv.slice(2);\n await opencodeSM.run(args);\n });\n\nprogram.parse(process.argv);\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackmemoryai/stackmemory",
3
- "version": "0.5.24",
3
+ "version": "0.5.26",
4
4
  "description": "Lossless memory runtime for AI coding tools - organizes context as a call stack instead of linear chat logs, with team collaboration and infinite retention",
5
5
  "engines": {
6
6
  "node": ">=20.0.0",
@@ -12,7 +12,8 @@
12
12
  "stackmemory": "dist/cli/index.js",
13
13
  "codex-sm": "dist/cli/codex-sm.js",
14
14
  "claude-sm": "bin/claude-sm",
15
- "claude-smd": "bin/claude-smd"
15
+ "claude-smd": "bin/claude-smd",
16
+ "opencode-sm": "bin/opencode-sm"
16
17
  },
17
18
  "types": "dist/src/index.d.ts",
18
19
  "files": [
@@ -43,8 +44,8 @@
43
44
  "persistence"
44
45
  ],
45
46
  "scripts": {
46
- "start": "node dist/servers/railway/index.js",
47
- "start:full": "node dist/servers/railway/index.js",
47
+ "start": "node dist/integrations/mcp/server.js",
48
+ "start:full": "node dist/integrations/mcp/server.js",
48
49
  "setup": "npm install && npm run build && npm run init",
49
50
  "postinstall": "node scripts/install-claude-hooks-auto.js || true",
50
51
  "init": "node dist/scripts/initialize.js",
@@ -67,11 +68,6 @@
67
68
  "status": "node dist/scripts/status.js",
68
69
  "linear:sync": "node scripts/sync-linear-graphql.js",
69
70
  "linear:mirror": "node scripts/sync-linear-graphql.js --mirror",
70
- "railway:setup": "./scripts/setup-railway-deployment.sh",
71
- "railway:deploy": "railway up --detach",
72
- "railway:migrate": "tsx src/cli/commands/migrate.ts",
73
- "railway:schema:verify": "tsx scripts/verify-railway-schema.ts",
74
- "railway:logs": "railway logs",
75
71
  "claude:setup": "node scripts/setup-claude-integration.js",
76
72
  "daemons:start": "node scripts/claude-sm-autostart.js",
77
73
  "daemons:status": "node scripts/claude-sm-autostart.js status",
@@ -1,87 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Debug Railway build issues
5
- */
6
-
7
- import fs from 'fs';
8
- import path from 'path';
9
- import { fileURLToPath } from 'url';
10
-
11
- const __filename = fileURLToPath(import.meta.url);
12
- const __dirname = path.dirname(__filename);
13
-
14
- console.log('šŸ” Railway Build Debugger');
15
- console.log('========================\n');
16
-
17
- // Check for server files
18
- const serverDir = path.join(__dirname, '..', 'dist', 'servers', 'railway');
19
- const srcDir = path.join(__dirname, '..', 'src', 'servers', 'railway');
20
-
21
- console.log('šŸ“ Checking dist/servers/railway:');
22
- if (fs.existsSync(serverDir)) {
23
- const files = fs.readdirSync(serverDir);
24
- files.forEach(file => {
25
- const stats = fs.statSync(path.join(serverDir, file));
26
- console.log(` - ${file} (${stats.size} bytes, modified: ${stats.mtime.toISOString()})`);
27
-
28
- // Check for minimal server references
29
- if (file === 'index.js') {
30
- const content = fs.readFileSync(path.join(serverDir, file), 'utf-8');
31
- if (content.includes('Minimal')) {
32
- console.log(` āš ļø Contains "Minimal" references`);
33
- }
34
- if (content.includes('/auth/signup')) {
35
- console.log(` āœ… Contains auth endpoints`);
36
- }
37
- }
38
- });
39
- } else {
40
- console.log(' āŒ Directory does not exist');
41
- }
42
-
43
- console.log('\nšŸ“ Checking src/servers/railway:');
44
- if (fs.existsSync(srcDir)) {
45
- const files = fs.readdirSync(srcDir);
46
- files.forEach(file => {
47
- const stats = fs.statSync(path.join(srcDir, file));
48
- console.log(` - ${file} (${stats.size} bytes)`);
49
- });
50
- } else {
51
- console.log(' āŒ Directory does not exist');
52
- }
53
-
54
- // Check package.json scripts
55
- console.log('\nšŸ“¦ Package.json start scripts:');
56
- const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8'));
57
- Object.entries(packageJson.scripts).forEach(([key, value]) => {
58
- if (key.includes('start')) {
59
- console.log(` ${key}: ${value}`);
60
- }
61
- });
62
-
63
- // Check Dockerfile
64
- console.log('\n🐳 Dockerfile CMD:');
65
- const dockerfile = fs.readFileSync(path.join(__dirname, '..', 'Dockerfile'), 'utf-8');
66
- const cmdMatch = dockerfile.match(/CMD\s+\[.*\]/g);
67
- if (cmdMatch) {
68
- cmdMatch.forEach(cmd => {
69
- console.log(` ${cmd}`);
70
- });
71
- }
72
-
73
- // Check Railway config
74
- console.log('\nšŸš‚ Railway.json:');
75
- const railwayConfig = path.join(__dirname, '..', 'railway.json');
76
- if (fs.existsSync(railwayConfig)) {
77
- const config = JSON.parse(fs.readFileSync(railwayConfig, 'utf-8'));
78
- console.log(JSON.stringify(config, null, 2));
79
- } else {
80
- console.log(' āŒ railway.json not found');
81
- }
82
-
83
- console.log('\nšŸ’” Recommendations:');
84
- console.log('1. Railway may be using a cached build layer');
85
- console.log('2. Try changing the base image in Dockerfile to force rebuild');
86
- console.log('3. Check Railway dashboard for any override settings');
87
- console.log('4. Consider contacting Railway support about cache issues');