@stackmemoryai/stackmemory 0.3.16 โ†’ 0.3.18

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 (213) hide show
  1. package/README.md +48 -2
  2. package/dist/cli/commands/skills.js +15 -2
  3. package/dist/cli/commands/skills.js.map +2 -2
  4. package/dist/cli/index.js +113 -834
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/core/context/dual-stack-manager.js +1 -1
  7. package/dist/core/context/dual-stack-manager.js.map +1 -1
  8. package/dist/core/context/frame-manager.js +3 -0
  9. package/dist/core/context/frame-manager.js.map +2 -2
  10. package/dist/integrations/claude-code/subagent-client.js +106 -3
  11. package/dist/integrations/claude-code/subagent-client.js.map +2 -2
  12. package/dist/servers/railway/config.js +51 -0
  13. package/dist/servers/railway/config.js.map +7 -0
  14. package/dist/servers/railway/index-enhanced.js +156 -0
  15. package/dist/servers/railway/index-enhanced.js.map +7 -0
  16. package/dist/servers/railway/minimal.js +48 -3
  17. package/dist/servers/railway/minimal.js.map +2 -2
  18. package/dist/servers/railway/storage-test.js +455 -0
  19. package/dist/servers/railway/storage-test.js.map +7 -0
  20. package/dist/skills/claude-skills.js +13 -12
  21. package/dist/skills/claude-skills.js.map +2 -2
  22. package/dist/skills/recursive-agent-orchestrator.js +27 -18
  23. package/dist/skills/recursive-agent-orchestrator.js.map +2 -2
  24. package/dist/skills/unified-rlm-orchestrator.js.map +2 -2
  25. package/package.json +6 -18
  26. package/scripts/README-TESTING.md +186 -0
  27. package/scripts/analyze-cli-security.js +288 -0
  28. package/scripts/archive/add-phase-tasks-to-linear.js +163 -0
  29. package/scripts/archive/analyze-linear-duplicates.js +214 -0
  30. package/scripts/archive/analyze-remaining-duplicates.js +230 -0
  31. package/scripts/archive/analyze-sta-duplicates.js +292 -0
  32. package/scripts/archive/analyze-sta-graphql.js +399 -0
  33. package/scripts/archive/cancel-duplicate-tasks.ts +246 -0
  34. package/scripts/archive/check-all-duplicates.ts +419 -0
  35. package/scripts/archive/clean-duplicate-tasks.js +114 -0
  36. package/scripts/archive/cleanup-duplicate-tasks.ts +286 -0
  37. package/scripts/archive/create-phase-tasks.js +387 -0
  38. package/scripts/archive/delete-linear-duplicates.js +182 -0
  39. package/scripts/archive/delete-remaining-duplicates.js +158 -0
  40. package/scripts/archive/delete-sta-duplicates.js +201 -0
  41. package/scripts/archive/delete-sta-oauth.js +201 -0
  42. package/scripts/archive/export-sta-tasks.js +62 -0
  43. package/scripts/archive/install-auto-sync.js +266 -0
  44. package/scripts/archive/install-chromadb-hooks.sh +133 -0
  45. package/scripts/archive/install-enhanced-clear-hooks.sh +431 -0
  46. package/scripts/archive/install-post-task-hooks.sh +289 -0
  47. package/scripts/archive/install-stackmemory-hooks.sh +420 -0
  48. package/scripts/archive/merge-linear-duplicates-safe.ts +362 -0
  49. package/scripts/archive/merge-linear-duplicates.ts +180 -0
  50. package/scripts/archive/remove-sta-tasks.js +70 -0
  51. package/scripts/archive/setup-background-sync.sh +168 -0
  52. package/scripts/archive/setup-claude-auto-triggers.sh +181 -0
  53. package/scripts/archive/setup-claude-autostart.sh +305 -0
  54. package/scripts/archive/setup-git-hooks.sh +25 -0
  55. package/scripts/archive/setup-linear-oauth.sh +46 -0
  56. package/scripts/archive/setup-mcp.sh +113 -0
  57. package/scripts/archive/setup-railway-deployment.sh +81 -0
  58. package/scripts/auto-handoff.sh +262 -0
  59. package/scripts/background-sync-manager.js +416 -0
  60. package/scripts/benchmark-performance.ts +57 -0
  61. package/scripts/check-redis.ts +48 -0
  62. package/scripts/chromadb-auto-loader.sh +128 -0
  63. package/scripts/chromadb-context-loader.js +479 -0
  64. package/scripts/claude-chromadb-hook.js +460 -0
  65. package/scripts/claude-code-wrapper.sh +66 -0
  66. package/scripts/claude-linear-skill.js +455 -0
  67. package/scripts/claude-pre-commit.sh +302 -0
  68. package/scripts/claude-sm-autostart.js +532 -0
  69. package/scripts/claude-sm-setup.sh +367 -0
  70. package/scripts/claude-with-chromadb.sh +69 -0
  71. package/scripts/claude-worktree-manager.sh +323 -0
  72. package/scripts/claude-worktree-monitor.sh +371 -0
  73. package/scripts/claude-worktree-setup.sh +327 -0
  74. package/scripts/clean-linear-backlog.js +273 -0
  75. package/scripts/cleanup-old-sessions.sh +57 -0
  76. package/scripts/codex-wrapper.sh +88 -0
  77. package/scripts/create-sandbox.sh +269 -0
  78. package/scripts/debug-linear-update.js +174 -0
  79. package/scripts/delete-linear-tasks.js +167 -0
  80. package/scripts/deploy.sh +89 -0
  81. package/scripts/deployment/railway.sh +352 -0
  82. package/scripts/deployment/test-deployment.js +194 -0
  83. package/scripts/detect-and-rehydrate.js +162 -0
  84. package/scripts/detect-and-rehydrate.mjs +165 -0
  85. package/scripts/development/create-demo-tasks.js +143 -0
  86. package/scripts/development/debug-frame-test.js +16 -0
  87. package/scripts/development/demo-auto-sync.js +128 -0
  88. package/scripts/development/fix-all-imports.js +213 -0
  89. package/scripts/development/fix-imports.js +229 -0
  90. package/scripts/development/fix-lint-loop.cjs +103 -0
  91. package/scripts/development/fix-project-id.ts +161 -0
  92. package/scripts/development/fix-strict-mode-issues.ts +291 -0
  93. package/scripts/development/reorganize-structure.sh +228 -0
  94. package/scripts/development/test-persistence-direct.js +148 -0
  95. package/scripts/development/test-persistence.js +114 -0
  96. package/scripts/development/test-tasks.js +93 -0
  97. package/scripts/development/update-imports.js +212 -0
  98. package/scripts/fetch-linear-status.js +125 -0
  99. package/scripts/git-hooks/README.md +310 -0
  100. package/scripts/git-hooks/branch-context-manager.sh +342 -0
  101. package/scripts/git-hooks/post-checkout-stackmemory.sh +63 -0
  102. package/scripts/git-hooks/post-commit-stackmemory.sh +305 -0
  103. package/scripts/git-hooks/pre-commit-stackmemory.sh +275 -0
  104. package/scripts/hooks/cleanup-shell.sh +130 -0
  105. package/scripts/hooks/task-complete.sh +114 -0
  106. package/scripts/initialize.ts +129 -0
  107. package/scripts/install-claude-hooks-auto.js +104 -0
  108. package/scripts/install-claude-hooks.sh +133 -0
  109. package/scripts/install-global.sh +296 -0
  110. package/scripts/install.sh +235 -0
  111. package/scripts/linear-auto-sync.js +262 -0
  112. package/scripts/linear-auto-sync.sh +161 -0
  113. package/scripts/linear-sync-daemon.js +150 -0
  114. package/scripts/linear-task-review.js +237 -0
  115. package/scripts/list-linear-tasks.ts +178 -0
  116. package/scripts/mcp-proxy.js +66 -0
  117. package/scripts/opencode-wrapper.sh +85 -0
  118. package/scripts/publish-local.js +74 -0
  119. package/scripts/query-chromadb.ts +201 -0
  120. package/scripts/railway-env-setup.sh +39 -0
  121. package/scripts/reconcile-local-tasks.js +170 -0
  122. package/scripts/recreate-frames-db.js +89 -0
  123. package/scripts/setup/claude-integration.js +138 -0
  124. package/scripts/setup/configure-alias.js +125 -0
  125. package/scripts/setup/configure-codex-alias.js +161 -0
  126. package/scripts/setup/configure-opencode-alias.js +175 -0
  127. package/scripts/setup-claude-integration.js +204 -0
  128. package/scripts/setup-claude-integration.sh +183 -0
  129. package/scripts/setup.sh +31 -0
  130. package/scripts/show-linear-summary.ts +172 -0
  131. package/scripts/stackmemory-auto-handoff.sh +231 -0
  132. package/scripts/stackmemory-daemon.sh +40 -0
  133. package/scripts/start-linear-sync-daemon.sh +141 -0
  134. package/scripts/start-temporal-paradox.sh +214 -0
  135. package/scripts/status.ts +159 -0
  136. package/scripts/sync-and-clean-tasks.js +258 -0
  137. package/scripts/sync-frames-from-railway.js +228 -0
  138. package/scripts/sync-linear-graphql.js +303 -0
  139. package/scripts/sync-linear-tasks.js +186 -0
  140. package/scripts/test-auto-triggers.sh +57 -0
  141. package/scripts/test-browser-mcp.js +74 -0
  142. package/scripts/test-chromadb-full.js +115 -0
  143. package/scripts/test-chromadb-hooks.sh +28 -0
  144. package/scripts/test-chromadb-sync.ts +245 -0
  145. package/scripts/test-cli-security.js +293 -0
  146. package/scripts/test-hooks-persistence.sh +220 -0
  147. package/scripts/test-installation-scenarios.sh +359 -0
  148. package/scripts/test-installation.sh +224 -0
  149. package/scripts/test-mcp.js +163 -0
  150. package/scripts/test-pre-publish-quick.sh +75 -0
  151. package/scripts/test-quality-gates.sh +263 -0
  152. package/scripts/test-railway-db.js +222 -0
  153. package/scripts/test-redis-storage.ts +490 -0
  154. package/scripts/test-rlm-basic.sh +122 -0
  155. package/scripts/test-rlm-comprehensive.sh +260 -0
  156. package/scripts/test-rlm-e2e.sh +268 -0
  157. package/scripts/test-rlm-simple.js +90 -0
  158. package/scripts/test-rlm.js +110 -0
  159. package/scripts/test-session-handoff.sh +165 -0
  160. package/scripts/test-shell-integration.sh +275 -0
  161. package/scripts/testing/ab-test-runner.ts +508 -0
  162. package/scripts/testing/collect-metrics.ts +457 -0
  163. package/scripts/testing/quick-effectiveness-demo.js +187 -0
  164. package/scripts/testing/real-performance-test.js +422 -0
  165. package/scripts/testing/run-effectiveness-tests.sh +176 -0
  166. package/scripts/testing/scripts/testing/ab-test-runner.js +363 -0
  167. package/scripts/testing/scripts/testing/collect-metrics.js +292 -0
  168. package/scripts/testing/simple-effectiveness-test.js +310 -0
  169. package/scripts/testing/src/core/context/context-bridge.js +253 -0
  170. package/scripts/testing/src/core/context/frame-manager.js +746 -0
  171. package/scripts/testing/src/core/context/shared-context-layer.js +437 -0
  172. package/scripts/testing/src/core/database/database-adapter.js +54 -0
  173. package/scripts/testing/src/core/errors/index.js +291 -0
  174. package/scripts/testing/src/core/errors/recovery.js +268 -0
  175. package/scripts/testing/src/core/monitoring/logger.js +145 -0
  176. package/scripts/testing/src/core/retrieval/context-retriever.js +516 -0
  177. package/scripts/testing/src/core/session/index.js +1 -0
  178. package/scripts/testing/src/core/session/session-manager.js +323 -0
  179. package/scripts/testing/src/core/trace/cli-trace-wrapper.js +140 -0
  180. package/scripts/testing/src/core/trace/db-trace-wrapper.js +251 -0
  181. package/scripts/testing/src/core/trace/debug-trace.js +398 -0
  182. package/scripts/testing/src/core/trace/index.js +120 -0
  183. package/scripts/testing/src/core/trace/linear-api-wrapper.js +204 -0
  184. package/scripts/update-linear-status.js +268 -0
  185. package/scripts/update-linear-tasks-fixed.js +284 -0
  186. package/templates/claude-hooks/hooks.json +5 -0
  187. package/templates/claude-hooks/on-clear.js +56 -0
  188. package/templates/claude-hooks/on-startup.js +56 -0
  189. package/templates/claude-hooks/tool-use-trace.js +67 -0
  190. package/dist/features/tui/components/analytics-panel.js +0 -157
  191. package/dist/features/tui/components/analytics-panel.js.map +0 -7
  192. package/dist/features/tui/components/frame-visualizer.js +0 -377
  193. package/dist/features/tui/components/frame-visualizer.js.map +0 -7
  194. package/dist/features/tui/components/pr-tracker.js +0 -135
  195. package/dist/features/tui/components/pr-tracker.js.map +0 -7
  196. package/dist/features/tui/components/session-monitor.js +0 -299
  197. package/dist/features/tui/components/session-monitor.js.map +0 -7
  198. package/dist/features/tui/components/subagent-fleet.js +0 -395
  199. package/dist/features/tui/components/subagent-fleet.js.map +0 -7
  200. package/dist/features/tui/components/task-board.js +0 -1139
  201. package/dist/features/tui/components/task-board.js.map +0 -7
  202. package/dist/features/tui/index.js +0 -408
  203. package/dist/features/tui/index.js.map +0 -7
  204. package/dist/features/tui/services/data-service.js +0 -641
  205. package/dist/features/tui/services/data-service.js.map +0 -7
  206. package/dist/features/tui/services/linear-task-reader.js +0 -102
  207. package/dist/features/tui/services/linear-task-reader.js.map +0 -7
  208. package/dist/features/tui/services/websocket-client.js +0 -162
  209. package/dist/features/tui/services/websocket-client.js.map +0 -7
  210. package/dist/features/tui/terminal-compat.js +0 -220
  211. package/dist/features/tui/terminal-compat.js.map +0 -7
  212. package/dist/features/tui/types.js +0 -1
  213. package/dist/features/tui/types.js.map +0 -7
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import dotenv from 'dotenv';
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+
10
+ dotenv.config({
11
+ path: path.join(__dirname, '..', '.env'),
12
+ silent: true
13
+ });
14
+
15
+ async function queryLinear(query, variables = {}) {
16
+ const response = await fetch('https://api.linear.app/graphql', {
17
+ method: 'POST',
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ 'Authorization': process.env.LINEAR_API_KEY
21
+ },
22
+ body: JSON.stringify({ query, variables })
23
+ });
24
+
25
+ const data = await response.json();
26
+ if (data.errors) {
27
+ throw new Error(data.errors[0].message);
28
+ }
29
+ return data.data;
30
+ }
31
+
32
+ async function reviewTasks() {
33
+ console.log('๐Ÿ“‹ LINEAR TASK REVIEW\n' + '='.repeat(50));
34
+
35
+ try {
36
+ // Get viewer info
37
+ const viewerData = await queryLinear(`
38
+ query {
39
+ viewer {
40
+ name
41
+ email
42
+ }
43
+ }
44
+ `);
45
+
46
+ console.log(`๐Ÿ‘ค Logged in as: ${viewerData.viewer.name || viewerData.viewer.email}\n`);
47
+
48
+ // Get all active issues
49
+ const issuesData = await queryLinear(`
50
+ query {
51
+ issues(
52
+ filter: {
53
+ state: { type: { in: ["started", "unstarted"] } }
54
+ }
55
+ orderBy: updatedAt
56
+ first: 100
57
+ ) {
58
+ nodes {
59
+ identifier
60
+ title
61
+ priority
62
+ priorityLabel
63
+ createdAt
64
+ updatedAt
65
+ state {
66
+ name
67
+ type
68
+ }
69
+ assignee {
70
+ name
71
+ email
72
+ }
73
+ labels {
74
+ nodes {
75
+ name
76
+ color
77
+ }
78
+ }
79
+ estimate
80
+ url
81
+ }
82
+ }
83
+ }
84
+ `);
85
+
86
+ const issues = issuesData.issues.nodes;
87
+
88
+ // Group by state
89
+ const byState = {};
90
+ issues.forEach(issue => {
91
+ const stateName = issue.state.name;
92
+ if (!byState[stateName]) byState[stateName] = [];
93
+ byState[stateName].push(issue);
94
+ });
95
+
96
+ // Priority mapping
97
+ const priorityLabels = {
98
+ 0: '๐Ÿ”ด No Priority',
99
+ 1: '๐Ÿ”ด Urgent',
100
+ 2: '๐ŸŸ  High',
101
+ 3: '๐ŸŸก Medium',
102
+ 4: '๐Ÿ”ต Low'
103
+ };
104
+
105
+ // Display by state
106
+ const stateOrder = ['In Progress', 'Todo', 'Triage', 'Backlog'];
107
+
108
+ stateOrder.forEach(state => {
109
+ if (byState[state] && byState[state].length > 0) {
110
+ console.log(`\n๐Ÿ“Š ${state.toUpperCase()} (${byState[state].length} tasks)`);
111
+ console.log('-'.repeat(50));
112
+
113
+ byState[state]
114
+ .sort((a, b) => (a.priority || 5) - (b.priority || 5))
115
+ .slice(0, 10)
116
+ .forEach(issue => {
117
+ const priority = priorityLabels[issue.priority] || 'โšช None';
118
+ const assignee = issue.assignee ? `๐Ÿ‘ค ${issue.assignee.name}` : '๐Ÿ‘ค Unassigned';
119
+ const labels = issue.labels.nodes.map(l => l.name).join(', ');
120
+ const labelStr = labels ? ` [${labels}]` : '';
121
+
122
+ console.log(`\n ${issue.identifier}: ${issue.title}`);
123
+ console.log(` ${priority} | ${assignee}${labelStr}`);
124
+ console.log(` ๐Ÿ“Ž ${issue.url}`);
125
+ });
126
+
127
+ if (byState[state].length > 10) {
128
+ console.log(`\n ... and ${byState[state].length - 10} more tasks`);
129
+ }
130
+ }
131
+ });
132
+
133
+ // Summary statistics
134
+ console.log('\n' + '='.repeat(50));
135
+ console.log('๐Ÿ“ˆ SUMMARY STATISTICS\n');
136
+
137
+ const inProgress = byState['In Progress']?.length || 0;
138
+ const todo = byState['Todo']?.length || 0;
139
+ const triage = byState['Triage']?.length || 0;
140
+ const backlog = byState['Backlog']?.length || 0;
141
+
142
+ console.log(` ๐Ÿƒ In Progress: ${inProgress}`);
143
+ console.log(` ๐Ÿ“ Todo: ${todo}`);
144
+ console.log(` ๐Ÿ” Triage: ${triage}`);
145
+ console.log(` ๐Ÿ“ฆ Backlog: ${backlog}`);
146
+ console.log(` ๐Ÿ“Š Total Active: ${issues.length}`);
147
+
148
+ // High priority items
149
+ const urgent = issues.filter(i => i.priority === 1);
150
+ const high = issues.filter(i => i.priority === 2);
151
+
152
+ if (urgent.length > 0) {
153
+ console.log('\n๐Ÿšจ URGENT PRIORITY TASKS:');
154
+ urgent.forEach(issue => {
155
+ const state = issue.state.name;
156
+ const assignee = issue.assignee?.name || 'Unassigned';
157
+ console.log(` โ€ข ${issue.identifier}: ${issue.title} [${state}] - ${assignee}`);
158
+ });
159
+ }
160
+
161
+ if (high.length > 0) {
162
+ console.log('\n๐Ÿ”ฅ HIGH PRIORITY TASKS:');
163
+ high.slice(0, 5).forEach(issue => {
164
+ const state = issue.state.name;
165
+ const assignee = issue.assignee?.name || 'Unassigned';
166
+ console.log(` โ€ข ${issue.identifier}: ${issue.title} [${state}] - ${assignee}`);
167
+ });
168
+ }
169
+
170
+ // Recommendations
171
+ console.log('\n' + '='.repeat(50));
172
+ console.log('๐Ÿ’ก RECOMMENDED NEXT ACTIONS:\n');
173
+
174
+ // Find tasks to work on
175
+ const recommendations = [];
176
+
177
+ // 1. In-progress tasks that need completion
178
+ const myInProgress = issues.filter(i =>
179
+ i.state.name === 'In Progress' &&
180
+ (!i.assignee || i.assignee.name === viewerData.viewer.name)
181
+ );
182
+
183
+ if (myInProgress.length > 0) {
184
+ recommendations.push({
185
+ reason: '๐Ÿƒ Continue in-progress work',
186
+ tasks: myInProgress.slice(0, 2)
187
+ });
188
+ }
189
+
190
+ // 2. High priority unassigned todos
191
+ const highPriorityTodos = issues.filter(i =>
192
+ i.state.name === 'Todo' &&
193
+ i.priority <= 2 &&
194
+ !i.assignee
195
+ );
196
+
197
+ if (highPriorityTodos.length > 0) {
198
+ recommendations.push({
199
+ reason: '๐Ÿ”ฅ High priority unassigned tasks',
200
+ tasks: highPriorityTodos.slice(0, 2)
201
+ });
202
+ }
203
+
204
+ // 3. Any todo tasks
205
+ const todoTasks = issues.filter(i =>
206
+ i.state.name === 'Todo' &&
207
+ !i.assignee
208
+ );
209
+
210
+ if (todoTasks.length > 0 && recommendations.length < 2) {
211
+ recommendations.push({
212
+ reason: '๐Ÿ“ Available todo tasks',
213
+ tasks: todoTasks.slice(0, 2)
214
+ });
215
+ }
216
+
217
+ if (recommendations.length > 0) {
218
+ recommendations.forEach(rec => {
219
+ console.log(rec.reason);
220
+ rec.tasks.forEach(task => {
221
+ const priority = priorityLabels[task.priority] || 'โšช None';
222
+ console.log(` โ””โ”€ ${task.identifier}: ${task.title}`);
223
+ console.log(` ${priority} | ${task.url}`);
224
+ });
225
+ console.log('');
226
+ });
227
+ } else {
228
+ console.log('โœ… No immediate tasks requiring attention');
229
+ }
230
+
231
+ } catch (error) {
232
+ console.error('โŒ Error:', error.message);
233
+ process.exit(1);
234
+ }
235
+ }
236
+
237
+ reviewTasks();
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env ts-node
2
+
3
+ /**
4
+ * Standalone script to list all Linear tasks grouped by status
5
+ */
6
+
7
+ import { LinearClient } from '../src/integrations/linear/client.js';
8
+ import { LinearAuthManager } from '../src/integrations/linear/auth.js';
9
+ import chalk from 'chalk';
10
+ // Type-safe environment variable access
11
+ function getEnv(key: string, defaultValue?: string): string {
12
+ const value = process.env[key];
13
+ if (value === undefined) {
14
+ if (defaultValue !== undefined) return defaultValue;
15
+ throw new Error(`Environment variable ${key} is required`);
16
+ }
17
+ return value;
18
+ }
19
+
20
+ function getOptionalEnv(key: string): string | undefined {
21
+ return process.env[key];
22
+ }
23
+
24
+ interface TasksByStatus {
25
+ [status: string]: Array<{
26
+ identifier: string;
27
+ title: string;
28
+ priority: number;
29
+ assignee?: string;
30
+ url: string;
31
+ }>;
32
+ }
33
+
34
+ async function main() {
35
+ try {
36
+ console.log(chalk.cyan('๐Ÿ” Fetching Linear tasks...\n'));
37
+
38
+ // Try to get authentication
39
+ const authManager = new LinearAuthManager(process.cwd());
40
+ const tokens = authManager.loadTokens();
41
+ const apiKey = process.env['LINEAR_API_KEY'];
42
+
43
+ if (!tokens && !apiKey) {
44
+ console.log(chalk.red('โŒ Not authenticated with Linear'));
45
+ console.log('Run: node dist/src/cli/index.js linear setup');
46
+ process.exit(1);
47
+ }
48
+
49
+ // Create client
50
+ const client = apiKey
51
+ ? new LinearClient({ apiKey })
52
+ : new LinearClient({
53
+ apiKey: tokens?.accessToken ?? '',
54
+ useBearer: true,
55
+ });
56
+
57
+ // Get all issues (increase limit to get more tasks)
58
+ console.log(chalk.gray('Fetching issues...'));
59
+ const issues = await client.getIssues({ limit: 200 });
60
+
61
+ if (!issues || issues.length === 0) {
62
+ console.log(chalk.gray('No issues found'));
63
+ return;
64
+ }
65
+
66
+ console.log(chalk.green(`โœ“ Found ${issues.length} tasks`));
67
+
68
+ // Group tasks by status
69
+ const tasksByStatus: TasksByStatus = {};
70
+
71
+ issues.forEach((issue) => {
72
+ const statusType = issue.state.type;
73
+ const statusName = issue.state.name;
74
+ const key = `${statusType} (${statusName})`;
75
+
76
+ if (!tasksByStatus[key]) {
77
+ tasksByStatus[key] = [];
78
+ }
79
+
80
+ tasksByStatus[key].push({
81
+ identifier: issue.identifier,
82
+ title: issue.title,
83
+ priority: issue.priority,
84
+ assignee: issue.assignee?.name,
85
+ url: issue.url,
86
+ });
87
+ });
88
+
89
+ // Define status order for display
90
+ const statusOrder = [
91
+ 'backlog',
92
+ 'unstarted',
93
+ 'started',
94
+ 'completed',
95
+ 'cancelled',
96
+ ];
97
+
98
+ // Display results grouped by status
99
+ console.log(chalk.cyan('\n๐Ÿ“‹ Linear Tasks by Status:\n'));
100
+
101
+ statusOrder.forEach((statusType) => {
102
+ // Find all status keys that match this type
103
+ const matchingKeys = Object.keys(tasksByStatus).filter((key) =>
104
+ key.startsWith(statusType)
105
+ );
106
+
107
+ matchingKeys.forEach((statusKey) => {
108
+ const tasks = tasksByStatus[statusKey];
109
+ if (tasks.length === 0) return;
110
+
111
+ // Status header with count
112
+ console.log(
113
+ chalk.bold.white(
114
+ `\n${getStatusEmoji(statusType)} ${statusKey} (${tasks.length} tasks)`
115
+ )
116
+ );
117
+ console.log(chalk.gray(''.padEnd(60, 'โ”€')));
118
+
119
+ // List tasks
120
+ tasks.forEach((task) => {
121
+ const priorityStr =
122
+ task.priority > 0
123
+ ? chalk.yellow(`P${task.priority}`)
124
+ : chalk.gray('--');
125
+ const assigneeStr = task.assignee
126
+ ? chalk.blue(task.assignee)
127
+ : chalk.gray('Unassigned');
128
+ const titleStr =
129
+ task.title.length > 50
130
+ ? task.title.substring(0, 47) + '...'
131
+ : task.title;
132
+
133
+ console.log(
134
+ ` ${chalk.cyan(task.identifier.padEnd(8))} ${titleStr.padEnd(50)} ${priorityStr.padEnd(8)} ${assigneeStr}`
135
+ );
136
+ });
137
+ });
138
+ });
139
+
140
+ // Summary
141
+ const totalTasks = issues.length;
142
+ const statusCounts = Object.entries(tasksByStatus).map(
143
+ ([status, tasks]) => ({
144
+ status,
145
+ count: tasks.length,
146
+ })
147
+ );
148
+
149
+ console.log(chalk.cyan('\n๐Ÿ“Š Summary:'));
150
+ statusCounts.forEach(({ status, count }) => {
151
+ console.log(chalk.gray(` ${status}: ${count} tasks`));
152
+ });
153
+ console.log(chalk.bold(` Total: ${totalTasks} tasks`));
154
+ } catch (error: unknown) {
155
+ console.error(chalk.red('โŒ Error:'), (error as Error).message);
156
+ process.exit(1);
157
+ }
158
+ }
159
+
160
+ function getStatusEmoji(statusType: string): string {
161
+ switch (statusType) {
162
+ case 'backlog':
163
+ return '๐Ÿ“‹';
164
+ case 'unstarted':
165
+ return '๐Ÿ“';
166
+ case 'started':
167
+ return 'โณ';
168
+ case 'completed':
169
+ return 'โœ…';
170
+ case 'cancelled':
171
+ return 'โŒ';
172
+ default:
173
+ return '๐Ÿ“„';
174
+ }
175
+ }
176
+
177
+ // Direct execution
178
+ main();
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Proxy for Railway-hosted StackMemory
4
+ * Bridges Claude Desktop to Railway API
5
+ */
6
+
7
+ import https from 'https';
8
+
9
+ const RAILWAY_URL = process.env.RAILWAY_URL || 'https://stackmemory-production.up.railway.app';
10
+ const API_KEY = process.env.API_KEY;
11
+
12
+ if (!API_KEY) {
13
+ console.error('ERROR: API_KEY environment variable is required');
14
+ process.exit(1);
15
+ }
16
+
17
+ // Simple proxy that forwards MCP requests to Railway
18
+ process.stdin.on('data', async (data) => {
19
+ try {
20
+ const request = JSON.parse(data.toString());
21
+
22
+ // Forward to Railway API
23
+ const response = await makeRequest('/api/tools/execute', {
24
+ tool: request.method,
25
+ params: request.params
26
+ });
27
+
28
+ // Send response back to Claude
29
+ process.stdout.write(JSON.stringify(response) + '\n');
30
+ } catch (error) {
31
+ process.stderr.write(`Error: ${error.message}\n`);
32
+ }
33
+ });
34
+
35
+ async function makeRequest(path, body) {
36
+ return new Promise((resolve, reject) => {
37
+ const url = new URL(path, RAILWAY_URL);
38
+
39
+ const options = {
40
+ method: 'POST',
41
+ headers: {
42
+ 'Authorization': `Bearer ${API_KEY}`,
43
+ 'Content-Type': 'application/json'
44
+ }
45
+ };
46
+
47
+ const req = https.request(url, options, (res) => {
48
+ let data = '';
49
+ res.on('data', chunk => data += chunk);
50
+ res.on('end', () => {
51
+ try {
52
+ resolve(JSON.parse(data));
53
+ } catch (e) {
54
+ resolve({ error: data });
55
+ }
56
+ });
57
+ });
58
+
59
+ req.on('error', reject);
60
+ req.write(JSON.stringify(body));
61
+ req.end();
62
+ });
63
+ }
64
+
65
+ console.error('StackMemory Railway MCP Proxy started');
66
+ console.error(`Connected to: ${RAILWAY_URL}`);
@@ -0,0 +1,85 @@
1
+ #!/bin/bash
2
+
3
+ # OpenCode wrapper with StackMemory integration
4
+ # Usage: Add alias to ~/.zshrc: alias opencode-sm='~/Dev/stackmemory/scripts/opencode-wrapper.sh'
5
+
6
+ # Check for auto-sync flag
7
+ AUTO_SYNC=false
8
+ SYNC_INTERVAL=5
9
+ for arg in "$@"; do
10
+ case $arg in
11
+ --auto-sync)
12
+ AUTO_SYNC=true
13
+ shift
14
+ ;;
15
+ --sync-interval=*)
16
+ SYNC_INTERVAL="${arg#*=}"
17
+ shift
18
+ ;;
19
+ esac
20
+ done
21
+
22
+ # Auto-initialize StackMemory if in git repo without it
23
+ if [ -d ".git" ] && [ ! -d ".stackmemory" ]; then
24
+ echo "๐Ÿ“ฆ Initializing StackMemory for this project..."
25
+ stackmemory init --silent 2>/dev/null || true
26
+ fi
27
+
28
+ # Load existing context if available
29
+ if [ -d ".stackmemory" ]; then
30
+ echo "๐Ÿง  Loading StackMemory context..."
31
+ stackmemory status --brief 2>/dev/null || true
32
+ fi
33
+
34
+ # Start Linear auto-sync in background if requested
35
+ SYNC_PID=""
36
+ if [ "$AUTO_SYNC" = true ] && [ -n "$LINEAR_API_KEY" ]; then
37
+ echo "๐Ÿ”„ Starting Linear auto-sync (${SYNC_INTERVAL}min intervals)..."
38
+ (
39
+ while true; do
40
+ sleep $((SYNC_INTERVAL * 60))
41
+ if [ -d ".stackmemory" ]; then
42
+ stackmemory linear sync --quiet 2>/dev/null || true
43
+ fi
44
+ done
45
+ ) &
46
+ SYNC_PID=$!
47
+ fi
48
+
49
+ cleanup() {
50
+ echo ""
51
+ echo "๐Ÿ“ Saving StackMemory context..."
52
+
53
+ # Kill auto-sync if running
54
+ if [ -n "$SYNC_PID" ] && kill -0 $SYNC_PID 2>/dev/null; then
55
+ echo "๐Ÿ›‘ Stopping auto-sync..."
56
+ kill $SYNC_PID 2>/dev/null || true
57
+ fi
58
+
59
+ # Check if in a git repo with stackmemory
60
+ if [ -d ".stackmemory" ]; then
61
+ # Save current context
62
+ stackmemory status 2>/dev/null
63
+
64
+ # If Linear API key is set, final sync
65
+ if [ -n "$LINEAR_API_KEY" ]; then
66
+ echo "๐Ÿ”„ Final Linear sync..."
67
+ stackmemory linear sync 2>/dev/null
68
+ fi
69
+
70
+ echo "โœ… StackMemory context saved"
71
+ fi
72
+ }
73
+
74
+ # Set trap for exit signals
75
+ trap cleanup EXIT INT TERM
76
+
77
+ # Run OpenCode
78
+ if command -v opencode &> /dev/null; then
79
+ opencode "$@"
80
+ else
81
+ echo "โŒ OpenCode not found. Please install it first."
82
+ echo " Run: curl -fsSL https://opencode.ai/install | bash"
83
+ echo " Or: npm install -g opencode-ai"
84
+ exit 1
85
+ fi
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Local NPM Publishing Script with Token
4
+ * Usage: node scripts/publish-local.js
5
+ *
6
+ * Requires NPM_TOKEN in environment or .env file
7
+ */
8
+
9
+ import { execSync } from 'child_process';
10
+ import { existsSync, readFileSync } from 'fs';
11
+ import { join } from 'path';
12
+ import chalk from 'chalk';
13
+
14
+ // Load .env file if it exists
15
+ const envPath = join(process.cwd(), '.env');
16
+ if (existsSync(envPath)) {
17
+ const envContent = readFileSync(envPath, 'utf-8');
18
+ envContent.split('\n').forEach(line => {
19
+ const [key, value] = line.split('=');
20
+ if (key && value && !process.env[key]) {
21
+ process.env[key.trim()] = value.trim();
22
+ }
23
+ });
24
+ }
25
+
26
+ // Check for NPM token
27
+ const npmToken = process.env.NPM_TOKEN;
28
+ if (!npmToken) {
29
+ console.error(chalk.red('โŒ NPM_TOKEN not found'));
30
+ console.log(chalk.yellow('Please set NPM_TOKEN environment variable:'));
31
+ console.log(chalk.gray(' export NPM_TOKEN=npm_xxx...'));
32
+ console.log(chalk.gray(' Or create a .env file with NPM_TOKEN=npm_xxx...'));
33
+ console.log();
34
+ console.log(chalk.yellow('Get your token from:'));
35
+ console.log(chalk.blue(' https://www.npmjs.com/settings/YOUR_USERNAME/tokens'));
36
+ process.exit(1);
37
+ }
38
+
39
+ // Create .npmrc with token
40
+ const npmrcContent = `//registry.npmjs.org/:_authToken=${npmToken}
41
+ registry=https://registry.npmjs.org/
42
+ access=public
43
+ `;
44
+
45
+ console.log(chalk.green('๐Ÿ“ Setting up NPM authentication...'));
46
+ execSync(`echo "${npmrcContent}" > ~/.npmrc`);
47
+
48
+ try {
49
+ // Check current version
50
+ console.log(chalk.yellow('๐Ÿ“ฆ Current package info:'));
51
+ execSync('npm view @stackmemoryai/stackmemory version', { stdio: 'inherit' });
52
+
53
+ // Build
54
+ console.log(chalk.yellow('\n๐Ÿ”จ Building package...'));
55
+ execSync('npm run build', { stdio: 'inherit' });
56
+
57
+ // Publish
58
+ console.log(chalk.yellow('\n๐Ÿš€ Publishing to NPM...'));
59
+ execSync('npm publish --access public', { stdio: 'inherit' });
60
+
61
+ console.log(chalk.green('\nโœ… Successfully published to NPM!'));
62
+
63
+ // Show new version
64
+ console.log(chalk.yellow('\n๐Ÿ“ฆ New package info:'));
65
+ execSync('npm view @stackmemoryai/stackmemory version', { stdio: 'inherit' });
66
+
67
+ } catch (error) {
68
+ console.error(chalk.red('\nโŒ Publishing failed:'), error.message);
69
+ process.exit(1);
70
+ } finally {
71
+ // Clean up .npmrc (optional, for security)
72
+ console.log(chalk.gray('\n๐Ÿงน Cleaning up credentials...'));
73
+ execSync('rm ~/.npmrc 2>/dev/null || true');
74
+ }