@stackmemoryai/stackmemory 0.3.17 → 0.3.19

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 (234) hide show
  1. package/dist/cli/claude-sm.js +51 -5
  2. package/dist/cli/claude-sm.js.map +2 -2
  3. package/dist/cli/codex-sm.js +52 -19
  4. package/dist/cli/codex-sm.js.map +2 -2
  5. package/dist/cli/commands/db.js +143 -0
  6. package/dist/cli/commands/db.js.map +7 -0
  7. package/dist/cli/commands/login.js +50 -0
  8. package/dist/cli/commands/login.js.map +7 -0
  9. package/dist/cli/commands/migrate.js +178 -0
  10. package/dist/cli/commands/migrate.js.map +7 -0
  11. package/dist/cli/commands/onboard.js +158 -2
  12. package/dist/cli/commands/onboard.js.map +2 -2
  13. package/dist/cli/commands/skills.js +15 -2
  14. package/dist/cli/commands/skills.js.map +2 -2
  15. package/dist/cli/index.js +118 -834
  16. package/dist/cli/index.js.map +3 -3
  17. package/dist/core/context/dual-stack-manager.js +1 -1
  18. package/dist/core/context/dual-stack-manager.js.map +1 -1
  19. package/dist/core/context/frame-database.js +1 -0
  20. package/dist/core/context/frame-database.js.map +2 -2
  21. package/dist/core/context/frame-manager.js +59 -2
  22. package/dist/core/context/frame-manager.js.map +2 -2
  23. package/dist/core/database/database-adapter.js +6 -1
  24. package/dist/core/database/database-adapter.js.map +2 -2
  25. package/dist/core/database/sqlite-adapter.js +60 -2
  26. package/dist/core/database/sqlite-adapter.js.map +2 -2
  27. package/dist/integrations/claude-code/subagent-client.js +106 -3
  28. package/dist/integrations/claude-code/subagent-client.js.map +2 -2
  29. package/dist/servers/railway/config.js +51 -0
  30. package/dist/servers/railway/config.js.map +7 -0
  31. package/dist/servers/railway/index-enhanced.js +156 -0
  32. package/dist/servers/railway/index-enhanced.js.map +7 -0
  33. package/dist/servers/railway/index.js +843 -82
  34. package/dist/servers/railway/index.js.map +3 -3
  35. package/dist/servers/railway/minimal.js +48 -3
  36. package/dist/servers/railway/minimal.js.map +2 -2
  37. package/dist/servers/railway/storage-test.js +455 -0
  38. package/dist/servers/railway/storage-test.js.map +7 -0
  39. package/dist/skills/claude-skills.js +13 -12
  40. package/dist/skills/claude-skills.js.map +2 -2
  41. package/dist/skills/recursive-agent-orchestrator.js +27 -18
  42. package/dist/skills/recursive-agent-orchestrator.js.map +2 -2
  43. package/dist/skills/unified-rlm-orchestrator.js.map +2 -2
  44. package/package.json +13 -21
  45. package/scripts/README-TESTING.md +186 -0
  46. package/scripts/analyze-cli-security.js +288 -0
  47. package/scripts/archive/add-phase-tasks-to-linear.js +163 -0
  48. package/scripts/archive/analyze-linear-duplicates.js +214 -0
  49. package/scripts/archive/analyze-remaining-duplicates.js +230 -0
  50. package/scripts/archive/analyze-sta-duplicates.js +292 -0
  51. package/scripts/archive/analyze-sta-graphql.js +399 -0
  52. package/scripts/archive/cancel-duplicate-tasks.ts +246 -0
  53. package/scripts/archive/check-all-duplicates.ts +419 -0
  54. package/scripts/archive/clean-duplicate-tasks.js +114 -0
  55. package/scripts/archive/cleanup-duplicate-tasks.ts +286 -0
  56. package/scripts/archive/create-phase-tasks.js +387 -0
  57. package/scripts/archive/delete-linear-duplicates.js +182 -0
  58. package/scripts/archive/delete-remaining-duplicates.js +158 -0
  59. package/scripts/archive/delete-sta-duplicates.js +201 -0
  60. package/scripts/archive/delete-sta-oauth.js +201 -0
  61. package/scripts/archive/export-sta-tasks.js +62 -0
  62. package/scripts/archive/install-auto-sync.js +266 -0
  63. package/scripts/archive/install-chromadb-hooks.sh +133 -0
  64. package/scripts/archive/install-enhanced-clear-hooks.sh +431 -0
  65. package/scripts/archive/install-post-task-hooks.sh +289 -0
  66. package/scripts/archive/install-stackmemory-hooks.sh +420 -0
  67. package/scripts/archive/merge-linear-duplicates-safe.ts +362 -0
  68. package/scripts/archive/merge-linear-duplicates.ts +180 -0
  69. package/scripts/archive/remove-sta-tasks.js +70 -0
  70. package/scripts/archive/setup-background-sync.sh +168 -0
  71. package/scripts/archive/setup-claude-auto-triggers.sh +181 -0
  72. package/scripts/archive/setup-claude-autostart.sh +305 -0
  73. package/scripts/archive/setup-git-hooks.sh +25 -0
  74. package/scripts/archive/setup-linear-oauth.sh +46 -0
  75. package/scripts/archive/setup-mcp.sh +113 -0
  76. package/scripts/archive/setup-railway-deployment.sh +81 -0
  77. package/scripts/auto-handoff.sh +262 -0
  78. package/scripts/background-sync-manager.js +416 -0
  79. package/scripts/benchmark-performance.ts +57 -0
  80. package/scripts/check-redis.ts +48 -0
  81. package/scripts/chromadb-auto-loader.sh +128 -0
  82. package/scripts/chromadb-context-loader.js +479 -0
  83. package/scripts/claude-chromadb-hook.js +460 -0
  84. package/scripts/claude-code-wrapper.sh +66 -0
  85. package/scripts/claude-linear-skill.js +455 -0
  86. package/scripts/claude-pre-commit.sh +302 -0
  87. package/scripts/claude-sm-autostart.js +532 -0
  88. package/scripts/claude-sm-setup.sh +367 -0
  89. package/scripts/claude-with-chromadb.sh +69 -0
  90. package/scripts/claude-worktree-manager.sh +323 -0
  91. package/scripts/claude-worktree-monitor.sh +371 -0
  92. package/scripts/claude-worktree-setup.sh +327 -0
  93. package/scripts/clean-linear-backlog.js +273 -0
  94. package/scripts/cleanup-old-sessions.sh +57 -0
  95. package/scripts/codex-wrapper.sh +88 -0
  96. package/scripts/create-sandbox.sh +269 -0
  97. package/scripts/debug-linear-update.js +174 -0
  98. package/scripts/delete-linear-tasks.js +167 -0
  99. package/scripts/deploy.sh +89 -0
  100. package/scripts/deployment/railway.sh +352 -0
  101. package/scripts/deployment/test-deployment.js +194 -0
  102. package/scripts/detect-and-rehydrate.js +162 -0
  103. package/scripts/detect-and-rehydrate.mjs +165 -0
  104. package/scripts/development/create-demo-tasks.js +143 -0
  105. package/scripts/development/debug-frame-test.js +16 -0
  106. package/scripts/development/demo-auto-sync.js +128 -0
  107. package/scripts/development/fix-all-imports.js +213 -0
  108. package/scripts/development/fix-imports.js +229 -0
  109. package/scripts/development/fix-lint-loop.cjs +103 -0
  110. package/scripts/development/fix-project-id.ts +161 -0
  111. package/scripts/development/fix-strict-mode-issues.ts +291 -0
  112. package/scripts/development/reorganize-structure.sh +228 -0
  113. package/scripts/development/test-persistence-direct.js +148 -0
  114. package/scripts/development/test-persistence.js +114 -0
  115. package/scripts/development/test-tasks.js +93 -0
  116. package/scripts/development/update-imports.js +212 -0
  117. package/scripts/fetch-linear-status.js +125 -0
  118. package/scripts/git-hooks/README.md +310 -0
  119. package/scripts/git-hooks/branch-context-manager.sh +342 -0
  120. package/scripts/git-hooks/post-checkout-stackmemory.sh +63 -0
  121. package/scripts/git-hooks/post-commit-stackmemory.sh +305 -0
  122. package/scripts/git-hooks/pre-commit-stackmemory.sh +275 -0
  123. package/scripts/hooks/cleanup-shell.sh +130 -0
  124. package/scripts/hooks/task-complete.sh +114 -0
  125. package/scripts/initialize.ts +129 -0
  126. package/scripts/install-claude-hooks-auto.js +104 -0
  127. package/scripts/install-claude-hooks.sh +133 -0
  128. package/scripts/install-global.sh +296 -0
  129. package/scripts/install.sh +235 -0
  130. package/scripts/linear-auto-sync.js +262 -0
  131. package/scripts/linear-auto-sync.sh +161 -0
  132. package/scripts/linear-sync-daemon.js +150 -0
  133. package/scripts/linear-task-review.js +237 -0
  134. package/scripts/list-linear-tasks.ts +178 -0
  135. package/scripts/mcp-proxy.js +66 -0
  136. package/scripts/opencode-wrapper.sh +85 -0
  137. package/scripts/publish-local.js +74 -0
  138. package/scripts/query-chromadb.ts +201 -0
  139. package/scripts/railway-env-setup.sh +39 -0
  140. package/scripts/reconcile-local-tasks.js +170 -0
  141. package/scripts/recreate-frames-db.js +89 -0
  142. package/scripts/setup/claude-integration.js +138 -0
  143. package/scripts/setup/configure-alias.js +125 -0
  144. package/scripts/setup/configure-codex-alias.js +161 -0
  145. package/scripts/setup/configure-opencode-alias.js +175 -0
  146. package/scripts/setup-claude-integration.js +204 -0
  147. package/scripts/setup-claude-integration.sh +183 -0
  148. package/scripts/setup-railway-deployment.sh +37 -0
  149. package/scripts/setup.sh +31 -0
  150. package/scripts/show-linear-summary.ts +172 -0
  151. package/scripts/stackmemory-auto-handoff.sh +231 -0
  152. package/scripts/stackmemory-daemon.sh +40 -0
  153. package/scripts/start-linear-sync-daemon.sh +141 -0
  154. package/scripts/start-temporal-paradox.sh +214 -0
  155. package/scripts/status.ts +159 -0
  156. package/scripts/sync-and-clean-tasks.js +258 -0
  157. package/scripts/sync-frames-from-railway.js +228 -0
  158. package/scripts/sync-linear-graphql.js +303 -0
  159. package/scripts/sync-linear-tasks.js +186 -0
  160. package/scripts/test-auto-triggers.sh +57 -0
  161. package/scripts/test-browser-mcp.js +74 -0
  162. package/scripts/test-chromadb-full.js +115 -0
  163. package/scripts/test-chromadb-hooks.sh +28 -0
  164. package/scripts/test-chromadb-sync.ts +245 -0
  165. package/scripts/test-cli-security.js +293 -0
  166. package/scripts/test-hooks-persistence.sh +220 -0
  167. package/scripts/test-installation-scenarios.sh +359 -0
  168. package/scripts/test-installation.sh +224 -0
  169. package/scripts/test-mcp.js +163 -0
  170. package/scripts/test-pre-publish-quick.sh +75 -0
  171. package/scripts/test-quality-gates.sh +263 -0
  172. package/scripts/test-railway-db.js +222 -0
  173. package/scripts/test-redis-storage.ts +490 -0
  174. package/scripts/test-rlm-basic.sh +122 -0
  175. package/scripts/test-rlm-comprehensive.sh +260 -0
  176. package/scripts/test-rlm-e2e.sh +268 -0
  177. package/scripts/test-rlm-simple.js +90 -0
  178. package/scripts/test-rlm.js +110 -0
  179. package/scripts/test-session-handoff.sh +165 -0
  180. package/scripts/test-shell-integration.sh +275 -0
  181. package/scripts/testing/ab-test-runner.ts +508 -0
  182. package/scripts/testing/collect-metrics.ts +457 -0
  183. package/scripts/testing/quick-effectiveness-demo.js +187 -0
  184. package/scripts/testing/real-performance-test.js +422 -0
  185. package/scripts/testing/run-effectiveness-tests.sh +176 -0
  186. package/scripts/testing/scripts/testing/ab-test-runner.js +363 -0
  187. package/scripts/testing/scripts/testing/collect-metrics.js +292 -0
  188. package/scripts/testing/simple-effectiveness-test.js +310 -0
  189. package/scripts/testing/src/core/context/context-bridge.js +253 -0
  190. package/scripts/testing/src/core/context/frame-manager.js +746 -0
  191. package/scripts/testing/src/core/context/shared-context-layer.js +437 -0
  192. package/scripts/testing/src/core/database/database-adapter.js +54 -0
  193. package/scripts/testing/src/core/errors/index.js +291 -0
  194. package/scripts/testing/src/core/errors/recovery.js +268 -0
  195. package/scripts/testing/src/core/monitoring/logger.js +145 -0
  196. package/scripts/testing/src/core/retrieval/context-retriever.js +516 -0
  197. package/scripts/testing/src/core/session/index.js +1 -0
  198. package/scripts/testing/src/core/session/session-manager.js +323 -0
  199. package/scripts/testing/src/core/trace/cli-trace-wrapper.js +140 -0
  200. package/scripts/testing/src/core/trace/db-trace-wrapper.js +251 -0
  201. package/scripts/testing/src/core/trace/debug-trace.js +398 -0
  202. package/scripts/testing/src/core/trace/index.js +120 -0
  203. package/scripts/testing/src/core/trace/linear-api-wrapper.js +204 -0
  204. package/scripts/update-linear-status.js +268 -0
  205. package/scripts/update-linear-tasks-fixed.js +284 -0
  206. package/scripts/verify-railway-schema.ts +35 -0
  207. package/templates/claude-hooks/hooks.json +5 -0
  208. package/templates/claude-hooks/on-clear.js +56 -0
  209. package/templates/claude-hooks/on-startup.js +56 -0
  210. package/templates/claude-hooks/tool-use-trace.js +67 -0
  211. package/dist/features/tui/components/analytics-panel.js +0 -157
  212. package/dist/features/tui/components/analytics-panel.js.map +0 -7
  213. package/dist/features/tui/components/frame-visualizer.js +0 -377
  214. package/dist/features/tui/components/frame-visualizer.js.map +0 -7
  215. package/dist/features/tui/components/pr-tracker.js +0 -135
  216. package/dist/features/tui/components/pr-tracker.js.map +0 -7
  217. package/dist/features/tui/components/session-monitor.js +0 -299
  218. package/dist/features/tui/components/session-monitor.js.map +0 -7
  219. package/dist/features/tui/components/subagent-fleet.js +0 -395
  220. package/dist/features/tui/components/subagent-fleet.js.map +0 -7
  221. package/dist/features/tui/components/task-board.js +0 -1139
  222. package/dist/features/tui/components/task-board.js.map +0 -7
  223. package/dist/features/tui/index.js +0 -408
  224. package/dist/features/tui/index.js.map +0 -7
  225. package/dist/features/tui/services/data-service.js +0 -641
  226. package/dist/features/tui/services/data-service.js.map +0 -7
  227. package/dist/features/tui/services/linear-task-reader.js +0 -102
  228. package/dist/features/tui/services/linear-task-reader.js.map +0 -7
  229. package/dist/features/tui/services/websocket-client.js +0 -162
  230. package/dist/features/tui/services/websocket-client.js.map +0 -7
  231. package/dist/features/tui/terminal-compat.js +0 -220
  232. package/dist/features/tui/terminal-compat.js.map +0 -7
  233. package/dist/features/tui/types.js +0 -1
  234. package/dist/features/tui/types.js.map +0 -7
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs';
4
+ import os from 'os';
5
+ import path from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ import { dirname, join } from 'path';
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+
12
+ const ALIAS_NAME = 'claude-sm';
13
+ const WRAPPER_SCRIPT = 'claude-code-wrapper.sh';
14
+
15
+ function getShellConfigFiles() {
16
+ const shell = process.env.SHELL || '';
17
+ const home = os.homedir();
18
+ const files = [];
19
+
20
+ if (shell.includes('zsh')) {
21
+ files.push(path.join(home, '.zshrc'));
22
+ // Also check .zprofile for some systems
23
+ const zprofile = path.join(home, '.zprofile');
24
+ if (fs.existsSync(zprofile)) {
25
+ files.push(zprofile);
26
+ }
27
+ }
28
+
29
+ if (shell.includes('bash') || !shell.includes('zsh')) {
30
+ const profilePath = path.join(home, '.bash_profile');
31
+ const rcPath = path.join(home, '.bashrc');
32
+ if (fs.existsSync(profilePath)) files.push(profilePath);
33
+ if (fs.existsSync(rcPath)) files.push(rcPath);
34
+ }
35
+
36
+ if (shell.includes('fish')) {
37
+ files.push(path.join(home, '.config', 'fish', 'config.fish'));
38
+ }
39
+
40
+ return files.length > 0 ? files : [path.join(home, '.bashrc')];
41
+ }
42
+
43
+ function setupAlias() {
44
+ try {
45
+ const wrapperPath = join(dirname(__dirname), 'scripts', WRAPPER_SCRIPT);
46
+
47
+ if (!fs.existsSync(wrapperPath)) {
48
+ console.log(`āš ļø Wrapper script not found at ${wrapperPath}`);
49
+ console.log(
50
+ ' Please ensure claude-code-wrapper.sh exists in the scripts directory'
51
+ );
52
+ return;
53
+ }
54
+
55
+ const configFiles = getShellConfigFiles();
56
+ const aliasLine = `alias ${ALIAS_NAME}="${wrapperPath}"`;
57
+ const marker = '# StackMemory Claude alias';
58
+ let alreadyConfigured = false;
59
+ let configuredIn = [];
60
+
61
+ for (const configFile of configFiles) {
62
+ let config = '';
63
+ if (fs.existsSync(configFile)) {
64
+ config = fs.readFileSync(configFile, 'utf8');
65
+ }
66
+
67
+ // Check if already has the alias (with marker or just the alias itself)
68
+ if (config.includes(marker) || config.includes(`alias ${ALIAS_NAME}=`)) {
69
+ configuredIn.push(configFile);
70
+ alreadyConfigured = true;
71
+ continue;
72
+ }
73
+
74
+ // Only add to primary shell config (first in the list)
75
+ if (configuredIn.length === 0 && configFiles.indexOf(configFile) === 0) {
76
+ const aliasBlock = `\n${marker}\n${aliasLine}\n`;
77
+ fs.appendFileSync(configFile, aliasBlock);
78
+ configuredIn.push(configFile);
79
+ console.log(`āœ… Added ${ALIAS_NAME} alias to ${configFile}`);
80
+ }
81
+ }
82
+
83
+ if (alreadyConfigured && configuredIn.length > 0) {
84
+ console.log(
85
+ `āœ“ ${ALIAS_NAME} alias already configured in: ${configuredIn.join(', ')}`
86
+ );
87
+ } else if (configuredIn.length > 0) {
88
+ console.log(
89
+ ` Run 'source ${configuredIn[0]}' or restart your terminal to use it`
90
+ );
91
+ console.log(` You can then use: ${ALIAS_NAME} [your message]`);
92
+ }
93
+ } catch (error) {
94
+ console.error('Error setting up alias:', error.message);
95
+ console.log('\nManual setup:');
96
+ console.log(`Add this line to your shell config file:`);
97
+ console.log(
98
+ `alias ${ALIAS_NAME}="${join(dirname(__dirname), 'scripts', WRAPPER_SCRIPT)}"`
99
+ );
100
+ }
101
+ }
102
+
103
+ if (process.argv.includes('--check')) {
104
+ const configFiles = getShellConfigFiles();
105
+ let found = false;
106
+
107
+ for (const configFile of configFiles) {
108
+ if (fs.existsSync(configFile)) {
109
+ const config = fs.readFileSync(configFile, 'utf8');
110
+ if (config.includes(`alias ${ALIAS_NAME}=`)) {
111
+ console.log(`āœ“ ${ALIAS_NAME} alias is configured in ${configFile}`);
112
+ found = true;
113
+ break;
114
+ }
115
+ }
116
+ }
117
+
118
+ if (!found) {
119
+ console.log(`āœ— ${ALIAS_NAME} alias not found`);
120
+ process.exit(1);
121
+ }
122
+ process.exit(0);
123
+ }
124
+
125
+ setupAlias();
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs';
4
+ import os from 'os';
5
+ import path, { dirname, join } from 'path';
6
+ import { fileURLToPath } from 'url';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+
11
+ const ALIAS_NAME = 'codex-sm';
12
+ const WRAPPER_SCRIPT = 'codex-wrapper.sh';
13
+
14
+ function getShellConfigFiles() {
15
+ const shell = process.env.SHELL || '';
16
+ const home = os.homedir();
17
+ const files = [];
18
+
19
+ if (shell.includes('zsh')) {
20
+ files.push(path.join(home, '.zshrc'));
21
+ const zprofile = path.join(home, '.zprofile');
22
+ if (fs.existsSync(zprofile)) files.push(zprofile);
23
+ }
24
+
25
+ if (shell.includes('bash') || !shell.includes('zsh')) {
26
+ const profilePath = path.join(home, '.bash_profile');
27
+ const rcPath = path.join(home, '.bashrc');
28
+ if (fs.existsSync(profilePath)) files.push(profilePath);
29
+ if (fs.existsSync(rcPath)) files.push(rcPath);
30
+ }
31
+
32
+ if (shell.includes('fish')) {
33
+ files.push(path.join(home, '.config', 'fish', 'config.fish'));
34
+ }
35
+
36
+ return files.length > 0 ? files : [path.join(home, '.bashrc')];
37
+ }
38
+
39
+ function setupAlias() {
40
+ try {
41
+ const scriptsDir = dirname(__dirname);
42
+ const repoRoot = dirname(scriptsDir);
43
+ const distBin = join(repoRoot, 'dist', 'src', 'cli', 'codex-sm.js');
44
+ const wrapperPath = join(scriptsDir, WRAPPER_SCRIPT);
45
+
46
+ // Prefer TypeScript bin (built file); fallback to shell wrapper
47
+ const targetCmd = fs.existsSync(distBin)
48
+ ? `node ${distBin}`
49
+ : (fs.existsSync(wrapperPath)
50
+ ? `${wrapperPath}`
51
+ : null);
52
+
53
+ if (!targetCmd) {
54
+ console.log('āš ļø Neither built TS bin nor wrapper script found.');
55
+ console.log(' Build first: npm run build');
56
+ console.log(` Or ensure ${WRAPPER_SCRIPT} exists in scripts/`);
57
+ return;
58
+ }
59
+
60
+ const configFiles = getShellConfigFiles();
61
+ const aliasLine = `alias ${ALIAS_NAME}="${targetCmd}"`;
62
+ const marker = '# StackMemory Codex alias';
63
+ let updatedOrConfigured = false;
64
+ const touched = [];
65
+
66
+ for (const configFile of configFiles) {
67
+ let config = '';
68
+ if (fs.existsSync(configFile)) config = fs.readFileSync(configFile, 'utf8');
69
+
70
+ // If already present, replace existing alias line in-place
71
+ if (config.includes(`alias ${ALIAS_NAME}=`)) {
72
+ const newConfig = config.replace(
73
+ new RegExp(`^.*alias\\s+${ALIAS_NAME}=.*$`, 'm'),
74
+ aliasLine
75
+ );
76
+ if (newConfig !== config) {
77
+ fs.writeFileSync(configFile, newConfig, 'utf8');
78
+ console.log(`āœ… Updated ${ALIAS_NAME} alias in ${configFile}`);
79
+ updatedOrConfigured = true;
80
+ touched.push(configFile);
81
+ continue;
82
+ }
83
+ }
84
+
85
+ // Otherwise, add once to the first config file available
86
+ if (!updatedOrConfigured && configFiles.indexOf(configFile) === 0) {
87
+ const aliasBlock = `\n${marker}\n${aliasLine}\n`;
88
+ fs.appendFileSync(configFile, aliasBlock);
89
+ console.log(`āœ… Added ${ALIAS_NAME} alias to ${configFile}`);
90
+ updatedOrConfigured = true;
91
+ touched.push(configFile);
92
+ }
93
+ }
94
+
95
+ if (touched.length > 0) {
96
+ console.log(` Run 'source ${touched[0]}' or restart your terminal to use it`);
97
+ console.log(` You can then use: ${ALIAS_NAME} [your message]`);
98
+ } else {
99
+ console.log(`ā„¹ļø No suitable shell config found to modify.`);
100
+ }
101
+
102
+ console.log(`\nšŸ“– Usage:`);
103
+ console.log(` ${ALIAS_NAME} # Start Codex with StackMemory`);
104
+ console.log(` ${ALIAS_NAME} --auto-sync # With Linear auto-sync`);
105
+ console.log(` ${ALIAS_NAME} --sync-interval=10 # Custom sync interval (minutes)`);
106
+ } catch (error) {
107
+ console.error('Error setting up alias:', error.message);
108
+ console.log('\nManual setup:');
109
+ console.log(`Add this line to your shell config file:`);
110
+ console.log(`alias ${ALIAS_NAME}="${join(dirname(__dirname), WRAPPER_SCRIPT)}"`);
111
+ }
112
+ }
113
+
114
+ if (process.argv.includes('--check')) {
115
+ const configFiles = getShellConfigFiles();
116
+ let found = false;
117
+ for (const configFile of configFiles) {
118
+ if (fs.existsSync(configFile)) {
119
+ const config = fs.readFileSync(configFile, 'utf8');
120
+ if (config.includes(`alias ${ALIAS_NAME}=`)) {
121
+ console.log(`āœ“ ${ALIAS_NAME} alias is configured in ${configFile}`);
122
+ found = true;
123
+ break;
124
+ }
125
+ }
126
+ }
127
+ if (!found) {
128
+ console.log(`āœ— ${ALIAS_NAME} alias not found`);
129
+ process.exit(1);
130
+ }
131
+ process.exit(0);
132
+ }
133
+
134
+ if (process.argv.includes('--remove')) {
135
+ const configFiles = getShellConfigFiles();
136
+ let removed = false;
137
+ for (const configFile of configFiles) {
138
+ if (fs.existsSync(configFile)) {
139
+ let config = fs.readFileSync(configFile, 'utf8');
140
+ const marker = '# StackMemory Codex alias';
141
+ if (config.includes(marker) || config.includes(`alias ${ALIAS_NAME}=`)) {
142
+ const lines = config.split('\n');
143
+ const newLines = [];
144
+ let skipNext = false;
145
+ for (const line of lines) {
146
+ if (line.includes(marker)) { skipNext = true; continue; }
147
+ if (skipNext && line.includes(`alias ${ALIAS_NAME}=`)) { skipNext = false; continue; }
148
+ skipNext = false;
149
+ newLines.push(line);
150
+ }
151
+ fs.writeFileSync(configFile, newLines.join('\n'));
152
+ console.log(`āœ… Removed ${ALIAS_NAME} alias from ${configFile}`);
153
+ removed = true;
154
+ }
155
+ }
156
+ }
157
+ if (!removed) console.log(`āœ— ${ALIAS_NAME} alias not found in any config file`);
158
+ process.exit(0);
159
+ }
160
+
161
+ setupAlias();
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs';
4
+ import os from 'os';
5
+ import path from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ import { dirname, join } from 'path';
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+
12
+ const ALIAS_NAME = 'opencode-sm';
13
+ const WRAPPER_SCRIPT = 'opencode-wrapper.sh';
14
+
15
+ function getShellConfigFiles() {
16
+ const shell = process.env.SHELL || '';
17
+ const home = os.homedir();
18
+ const files = [];
19
+
20
+ if (shell.includes('zsh')) {
21
+ files.push(path.join(home, '.zshrc'));
22
+ // Also check .zprofile for some systems
23
+ const zprofile = path.join(home, '.zprofile');
24
+ if (fs.existsSync(zprofile)) {
25
+ files.push(zprofile);
26
+ }
27
+ }
28
+
29
+ if (shell.includes('bash') || !shell.includes('zsh')) {
30
+ const profilePath = path.join(home, '.bash_profile');
31
+ const rcPath = path.join(home, '.bashrc');
32
+ if (fs.existsSync(profilePath)) files.push(profilePath);
33
+ if (fs.existsSync(rcPath)) files.push(rcPath);
34
+ }
35
+
36
+ if (shell.includes('fish')) {
37
+ files.push(path.join(home, '.config', 'fish', 'config.fish'));
38
+ }
39
+
40
+ return files.length > 0 ? files : [path.join(home, '.bashrc')];
41
+ }
42
+
43
+ function setupAlias() {
44
+ try {
45
+ const wrapperPath = join(dirname(__dirname), WRAPPER_SCRIPT);
46
+
47
+ if (!fs.existsSync(wrapperPath)) {
48
+ console.log(`āš ļø Wrapper script not found at ${wrapperPath}`);
49
+ console.log(
50
+ ' Please ensure opencode-wrapper.sh exists in the scripts directory'
51
+ );
52
+ return;
53
+ }
54
+
55
+ const configFiles = getShellConfigFiles();
56
+ const aliasLine = `alias ${ALIAS_NAME}="${wrapperPath}"`;
57
+ const marker = '# StackMemory OpenCode alias';
58
+ let alreadyConfigured = false;
59
+ let configuredIn = [];
60
+
61
+ for (const configFile of configFiles) {
62
+ let config = '';
63
+ if (fs.existsSync(configFile)) {
64
+ config = fs.readFileSync(configFile, 'utf8');
65
+ }
66
+
67
+ // Check if already has the alias (with marker or just the alias itself)
68
+ if (config.includes(marker) || config.includes(`alias ${ALIAS_NAME}=`)) {
69
+ configuredIn.push(configFile);
70
+ alreadyConfigured = true;
71
+ continue;
72
+ }
73
+
74
+ // Only add to primary shell config (first in the list)
75
+ if (configuredIn.length === 0 && configFiles.indexOf(configFile) === 0) {
76
+ const aliasBlock = `\n${marker}\n${aliasLine}\n`;
77
+ fs.appendFileSync(configFile, aliasBlock);
78
+ configuredIn.push(configFile);
79
+ console.log(`āœ… Added ${ALIAS_NAME} alias to ${configFile}`);
80
+ }
81
+ }
82
+
83
+ if (alreadyConfigured && configuredIn.length > 0) {
84
+ console.log(
85
+ `āœ“ ${ALIAS_NAME} alias already configured in: ${configuredIn.join(', ')}`
86
+ );
87
+ } else if (configuredIn.length > 0) {
88
+ console.log(
89
+ ` Run 'source ${configuredIn[0]}' or restart your terminal to use it`
90
+ );
91
+ console.log(` You can then use: ${ALIAS_NAME} [your message]`);
92
+ }
93
+
94
+ console.log(`\nšŸ“– Usage:`);
95
+ console.log(
96
+ ` ${ALIAS_NAME} # Start OpenCode with StackMemory`
97
+ );
98
+ console.log(` ${ALIAS_NAME} --auto-sync # With Linear auto-sync`);
99
+ console.log(
100
+ ` ${ALIAS_NAME} --sync-interval=10 # Custom sync interval (minutes)`
101
+ );
102
+ } catch (error) {
103
+ console.error('Error setting up alias:', error.message);
104
+ console.log('\nManual setup:');
105
+ console.log(`Add this line to your shell config file:`);
106
+ console.log(
107
+ `alias ${ALIAS_NAME}="${join(dirname(__dirname), WRAPPER_SCRIPT)}"`
108
+ );
109
+ }
110
+ }
111
+
112
+ if (process.argv.includes('--check')) {
113
+ const configFiles = getShellConfigFiles();
114
+ let found = false;
115
+
116
+ for (const configFile of configFiles) {
117
+ if (fs.existsSync(configFile)) {
118
+ const config = fs.readFileSync(configFile, 'utf8');
119
+ if (config.includes(`alias ${ALIAS_NAME}=`)) {
120
+ console.log(`āœ“ ${ALIAS_NAME} alias is configured in ${configFile}`);
121
+ found = true;
122
+ break;
123
+ }
124
+ }
125
+ }
126
+
127
+ if (!found) {
128
+ console.log(`āœ— ${ALIAS_NAME} alias not found`);
129
+ process.exit(1);
130
+ }
131
+ process.exit(0);
132
+ }
133
+
134
+ if (process.argv.includes('--remove')) {
135
+ const configFiles = getShellConfigFiles();
136
+ let removed = false;
137
+
138
+ for (const configFile of configFiles) {
139
+ if (fs.existsSync(configFile)) {
140
+ let config = fs.readFileSync(configFile, 'utf8');
141
+ const marker = '# StackMemory OpenCode alias';
142
+
143
+ if (config.includes(marker)) {
144
+ // Remove the alias block
145
+ const lines = config.split('\n');
146
+ const newLines = [];
147
+ let skipNext = false;
148
+
149
+ for (const line of lines) {
150
+ if (line.includes(marker)) {
151
+ skipNext = true;
152
+ continue;
153
+ }
154
+ if (skipNext && line.includes(`alias ${ALIAS_NAME}=`)) {
155
+ skipNext = false;
156
+ continue;
157
+ }
158
+ skipNext = false;
159
+ newLines.push(line);
160
+ }
161
+
162
+ fs.writeFileSync(configFile, newLines.join('\n'));
163
+ console.log(`āœ… Removed ${ALIAS_NAME} alias from ${configFile}`);
164
+ removed = true;
165
+ }
166
+ }
167
+ }
168
+
169
+ if (!removed) {
170
+ console.log(`āœ— ${ALIAS_NAME} alias not found in any config file`);
171
+ }
172
+ process.exit(0);
173
+ }
174
+
175
+ setupAlias();
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * StackMemory Claude Code Integration Setup
4
+ * Automatically configures Claude Code to use StackMemory MCP server
5
+ */
6
+
7
+ import { execSync } from 'child_process';
8
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
9
+ import { join } from 'path';
10
+ import { homedir } from 'os';
11
+
12
+ const CLAUDE_CONFIG_DIR = join(homedir(), '.claude');
13
+ const CLAUDE_CONFIG_FILE = join(CLAUDE_CONFIG_DIR, 'config.json');
14
+ const STACKMEMORY_MCP_CONFIG = join(CLAUDE_CONFIG_DIR, 'stackmemory-mcp.json');
15
+ const HOOKS_DIR = join(CLAUDE_CONFIG_DIR, 'hooks');
16
+ const STACKMEMORY_HOOK = join(HOOKS_DIR, 'stackmemory_init.sh');
17
+
18
+ console.log('šŸš€ Setting up StackMemory + Claude Code integration...\n');
19
+
20
+ // 1. Create Claude config directory
21
+ if (!existsSync(CLAUDE_CONFIG_DIR)) {
22
+ console.log('šŸ“ Creating ~/.claude directory...');
23
+ mkdirSync(CLAUDE_CONFIG_DIR, { recursive: true });
24
+ }
25
+
26
+ // 2. Create hooks directory
27
+ if (!existsSync(HOOKS_DIR)) {
28
+ console.log('šŸ“ Creating ~/.claude/hooks directory...');
29
+ mkdirSync(HOOKS_DIR, { recursive: true });
30
+ }
31
+
32
+ // 3. Create StackMemory MCP configuration
33
+ console.log('āš™ļø Creating StackMemory MCP configuration...');
34
+ const mcpConfig = {
35
+ mcpServers: {
36
+ stackmemory: {
37
+ command: "stackmemory",
38
+ args: ["mcp-server"],
39
+ env: {
40
+ NODE_ENV: "production"
41
+ }
42
+ }
43
+ }
44
+ };
45
+
46
+ writeFileSync(STACKMEMORY_MCP_CONFIG, JSON.stringify(mcpConfig, null, 2));
47
+ console.log(`āœ… Created: ${STACKMEMORY_MCP_CONFIG}`);
48
+
49
+ // 4. Create session initialization hook
50
+ console.log('šŸŖ Creating StackMemory session hook...');
51
+ const hookScript = `#!/bin/bash
52
+ # StackMemory Session Initialization Hook
53
+ # Automatically loads context and starts frame tracking
54
+
55
+ if [ -d "./.stackmemory" ]; then
56
+ echo "🧠 StackMemory context tracking active"
57
+
58
+ # Show current stack status
59
+ STACK_STATUS=$(stackmemory status --project 2>/dev/null)
60
+ if echo "$STACK_STATUS" | grep -q "Stack depth: 0"; then
61
+ echo "šŸ“ Starting fresh work session"
62
+ else
63
+ echo "šŸ“š Resuming context stack:"
64
+ echo "$STACK_STATUS" | grep -E "(Stack depth|Active frames|└─)" | head -5
65
+ fi
66
+
67
+ # Quick context summary
68
+ ACTIVE_TASKS=$(stackmemory status --project 2>/dev/null | grep -c "└─" || echo "0")
69
+ if [ "$ACTIVE_TASKS" -gt 0 ]; then
70
+ echo "šŸ“‹ $ACTIVE_TASKS active frames loaded"
71
+ fi
72
+ fi
73
+ `;
74
+
75
+ writeFileSync(STACKMEMORY_HOOK, hookScript);
76
+ execSync(`chmod +x "${STACKMEMORY_HOOK}"`);
77
+ console.log(`āœ… Created: ${STACKMEMORY_HOOK}`);
78
+
79
+ // 4b. Create startup hook with Linear sync
80
+ const STARTUP_HOOK = join(HOOKS_DIR, 'on-startup');
81
+ console.log('šŸŖ Creating StackMemory startup hook with Linear sync...');
82
+ const startupHookScript = `#!/bin/bash
83
+ # Auto-start StackMemory monitor on Claude Code startup
84
+
85
+ # Start monitor if project has StackMemory
86
+ if [ -d ".stackmemory" ]; then
87
+ stackmemory monitor --start 2>/dev/null || true
88
+ echo "šŸ” StackMemory monitor started"
89
+ fi
90
+
91
+ # Load previous handoff if exists
92
+ if [ -d ".stackmemory/handoffs" ]; then
93
+ stackmemory handoff --load 2>/dev/null || true
94
+ fi
95
+
96
+ # Check and restore from ledger if needed
97
+ stackmemory clear --restore 2>/dev/null || true
98
+
99
+ # Trigger Linear sync on StackMemory instance loading
100
+ if [ -d ".stackmemory" ] && [ -f "scripts/sync-linear-graphql.js" ]; then
101
+ echo "šŸ”„ Triggering Linear sync..."
102
+ npm run linear:sync >/dev/null 2>&1 || node scripts/sync-linear-graphql.js >/dev/null 2>&1 || true
103
+ echo "āœ… Linear sync triggered"
104
+ fi
105
+ `;
106
+
107
+ writeFileSync(STARTUP_HOOK, startupHookScript);
108
+ execSync(`chmod +x "${STARTUP_HOOK}"`);
109
+ console.log(`āœ… Created: ${STARTUP_HOOK}`);
110
+
111
+ // 5. Update or create Claude config.json
112
+ console.log('šŸ“ Updating Claude Code configuration...');
113
+
114
+ let claudeConfig = {};
115
+ if (existsSync(CLAUDE_CONFIG_FILE)) {
116
+ try {
117
+ const existing = readFileSync(CLAUDE_CONFIG_FILE, 'utf-8');
118
+ claudeConfig = JSON.parse(existing);
119
+ console.log(' Found existing config, merging...');
120
+ } catch (error) {
121
+ console.log(' Existing config invalid, creating new...');
122
+ }
123
+ }
124
+
125
+ // Merge configuration
126
+ if (!claudeConfig.mcp) {
127
+ claudeConfig.mcp = {};
128
+ }
129
+
130
+ if (!claudeConfig.mcp.configFiles) {
131
+ claudeConfig.mcp.configFiles = [];
132
+ }
133
+
134
+ // Add StackMemory MCP config if not already present
135
+ if (!claudeConfig.mcp.configFiles.includes(STACKMEMORY_MCP_CONFIG)) {
136
+ claudeConfig.mcp.configFiles.push(STACKMEMORY_MCP_CONFIG);
137
+ }
138
+
139
+ // Update session start hook
140
+ if (!claudeConfig.hooks) {
141
+ claudeConfig.hooks = {};
142
+ }
143
+
144
+ if (!claudeConfig.hooks.session_start) {
145
+ claudeConfig.hooks.session_start = [];
146
+ } else if (typeof claudeConfig.hooks.session_start === 'string') {
147
+ claudeConfig.hooks.session_start = [claudeConfig.hooks.session_start];
148
+ }
149
+
150
+ // Add StackMemory hook if not already present
151
+ if (!claudeConfig.hooks.session_start.includes(STACKMEMORY_HOOK)) {
152
+ claudeConfig.hooks.session_start.unshift(STACKMEMORY_HOOK);
153
+ }
154
+
155
+ writeFileSync(CLAUDE_CONFIG_FILE, JSON.stringify(claudeConfig, null, 2));
156
+ console.log(`āœ… Updated: ${CLAUDE_CONFIG_FILE}`);
157
+
158
+ // 6. Verify setup
159
+ console.log('\nšŸ” Verifying setup...');
160
+
161
+ try {
162
+ // Check if stackmemory command is available
163
+ execSync('stackmemory --version', { stdio: 'ignore' });
164
+ console.log('āœ… StackMemory CLI available');
165
+ } catch {
166
+ console.log('āš ļø StackMemory CLI not in PATH - you may need to restart your terminal');
167
+ }
168
+
169
+ try {
170
+ // Check if Claude Code is available
171
+ execSync('claude --help', { stdio: 'ignore' });
172
+ console.log('āœ… Claude Code available');
173
+ } catch {
174
+ console.log('āš ļø Claude Code not found - install from https://claude.ai/code');
175
+ }
176
+
177
+ // 7. Usage instructions
178
+ console.log(`
179
+ šŸŽ‰ Setup complete!
180
+
181
+ šŸ“‹ To use StackMemory with Claude Code:
182
+
183
+ 1. Initialize StackMemory in your project:
184
+ cd your-project
185
+ stackmemory init
186
+
187
+ 2. Start Claude Code (will auto-load StackMemory):
188
+ claude
189
+
190
+ 3. Or explicitly load StackMemory MCP:
191
+ claude --mcp-config ~/.claude/stackmemory-mcp.json
192
+
193
+ šŸ“š Available MCP tools in Claude Code:
194
+ • start_frame, close_frame - Frame lifecycle
195
+ • create_task, get_active_tasks - Task management
196
+ • linear_sync, linear_status - Linear integration
197
+ • get_context, add_decision - Context management
198
+
199
+ šŸ“– Full documentation: docs/claude-code-integration.md
200
+
201
+ šŸ”§ To reconfigure: npm run claude:setup
202
+ `);
203
+
204
+ console.log('✨ Integration setup successful!');