squish-memory 0.8.2 → 0.9.1

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 (266) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/.env.mcp +30 -0
  4. package/.mcp.json +2 -5
  5. package/CHANGELOG.md +111 -0
  6. package/QUICK-START.md +65 -0
  7. package/README.md +188 -530
  8. package/commands/managed-sync.ts +69 -0
  9. package/commands/mcp-server.ts +519 -0
  10. package/config/mcp-cli-fallback-policy.json +22 -0
  11. package/config/mcp-migration-map.json +22 -0
  12. package/config/mcp-mode-semantics.json +21 -0
  13. package/config/mcp-remote-auth.json +36 -0
  14. package/config/mcp-universal.schema.json +48 -0
  15. package/config/mcp.json +38 -0
  16. package/config/remote-memory-policy.json +32 -0
  17. package/dist/algorithms/merge/detection/hash-filters.js +2 -2
  18. package/dist/algorithms/merge/detection/hash-filters.js.map +1 -1
  19. package/dist/algorithms/merge/detection/two-stage-detector.d.ts +5 -2
  20. package/dist/algorithms/merge/detection/two-stage-detector.d.ts.map +1 -1
  21. package/dist/algorithms/merge/detection/two-stage-detector.js +139 -22
  22. package/dist/algorithms/merge/detection/two-stage-detector.js.map +1 -1
  23. package/dist/commands/managed-sync.d.ts +10 -0
  24. package/dist/commands/managed-sync.d.ts.map +1 -0
  25. package/dist/commands/managed-sync.js +64 -0
  26. package/dist/commands/managed-sync.js.map +1 -0
  27. package/dist/commands/mcp-server.d.ts +3 -0
  28. package/dist/commands/mcp-server.d.ts.map +1 -0
  29. package/dist/commands/mcp-server.js +389 -0
  30. package/dist/commands/mcp-server.js.map +1 -0
  31. package/dist/config.d.ts +24 -1
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/config.js +32 -1
  34. package/dist/config.js.map +1 -1
  35. package/dist/core/associations.d.ts +1 -1
  36. package/dist/core/associations.d.ts.map +1 -1
  37. package/dist/core/consolidation.d.ts +31 -0
  38. package/dist/core/consolidation.d.ts.map +1 -1
  39. package/dist/core/consolidation.js +237 -29
  40. package/dist/core/consolidation.js.map +1 -1
  41. package/dist/core/embeddings/google-multimodal.d.ts +14 -0
  42. package/dist/core/embeddings/google-multimodal.d.ts.map +1 -0
  43. package/dist/core/embeddings/google-multimodal.js +142 -0
  44. package/dist/core/embeddings/google-multimodal.js.map +1 -0
  45. package/dist/core/embeddings.d.ts +3 -2
  46. package/dist/core/embeddings.d.ts.map +1 -1
  47. package/dist/core/embeddings.js +61 -39
  48. package/dist/core/embeddings.js.map +1 -1
  49. package/dist/core/mcp/client.d.ts +17 -0
  50. package/dist/core/mcp/client.d.ts.map +1 -0
  51. package/dist/core/mcp/client.js +101 -0
  52. package/dist/core/mcp/client.js.map +1 -0
  53. package/dist/core/mcp/index.d.ts +6 -0
  54. package/dist/core/mcp/index.d.ts.map +1 -0
  55. package/dist/core/mcp/index.js +6 -0
  56. package/dist/core/mcp/index.js.map +1 -0
  57. package/dist/core/mcp/server.d.ts +18 -0
  58. package/dist/core/mcp/server.d.ts.map +1 -0
  59. package/dist/core/mcp/server.js +131 -0
  60. package/dist/core/mcp/server.js.map +1 -0
  61. package/dist/core/mcp/standalone-server.d.ts +13 -0
  62. package/dist/core/mcp/standalone-server.d.ts.map +1 -0
  63. package/dist/core/mcp/standalone-server.js +46 -0
  64. package/dist/core/mcp/standalone-server.js.map +1 -0
  65. package/dist/core/mcp/tools.d.ts +9 -0
  66. package/dist/core/mcp/tools.d.ts.map +1 -0
  67. package/dist/core/mcp/tools.js +262 -0
  68. package/dist/core/mcp/tools.js.map +1 -0
  69. package/dist/core/mcp/types.d.ts +315 -0
  70. package/dist/core/mcp/types.d.ts.map +1 -0
  71. package/dist/core/mcp/types.js +48 -0
  72. package/dist/core/mcp/types.js.map +1 -0
  73. package/dist/core/memory/categorizer.d.ts +27 -0
  74. package/dist/core/memory/categorizer.d.ts.map +1 -0
  75. package/dist/core/memory/categorizer.js +304 -0
  76. package/dist/core/memory/categorizer.js.map +1 -0
  77. package/dist/core/memory/conflict-detector.d.ts +7 -0
  78. package/dist/core/memory/conflict-detector.d.ts.map +1 -0
  79. package/dist/core/memory/conflict-detector.js +43 -0
  80. package/dist/core/memory/conflict-detector.js.map +1 -0
  81. package/dist/core/memory/context-collector.d.ts +10 -0
  82. package/dist/core/memory/context-collector.d.ts.map +1 -0
  83. package/dist/core/memory/context-collector.js +55 -0
  84. package/dist/core/memory/context-collector.js.map +1 -0
  85. package/dist/core/memory/contradiction-resolver.d.ts +40 -0
  86. package/dist/core/memory/contradiction-resolver.d.ts.map +1 -0
  87. package/dist/core/memory/contradiction-resolver.js +368 -0
  88. package/dist/core/memory/contradiction-resolver.js.map +1 -0
  89. package/dist/core/memory/edit-workflow.d.ts +19 -0
  90. package/dist/core/memory/edit-workflow.d.ts.map +1 -0
  91. package/dist/core/memory/edit-workflow.js +120 -0
  92. package/dist/core/memory/edit-workflow.js.map +1 -0
  93. package/dist/core/memory/feedback-tracker.d.ts +12 -0
  94. package/dist/core/memory/feedback-tracker.d.ts.map +1 -0
  95. package/dist/core/memory/feedback-tracker.js +151 -0
  96. package/dist/core/memory/feedback-tracker.js.map +1 -0
  97. package/dist/core/memory/hybrid-retrieval.d.ts +11 -12
  98. package/dist/core/memory/hybrid-retrieval.d.ts.map +1 -1
  99. package/dist/core/memory/hybrid-retrieval.js +56 -28
  100. package/dist/core/memory/hybrid-retrieval.js.map +1 -1
  101. package/dist/core/memory/hybrid-scorer.d.ts +5 -16
  102. package/dist/core/memory/hybrid-scorer.d.ts.map +1 -1
  103. package/dist/core/memory/hybrid-scorer.js +161 -125
  104. package/dist/core/memory/hybrid-scorer.js.map +1 -1
  105. package/dist/core/memory/hybrid-search.js +53 -19
  106. package/dist/core/memory/hybrid-search.js.map +1 -1
  107. package/dist/core/memory/memories.d.ts +4 -0
  108. package/dist/core/memory/memories.d.ts.map +1 -1
  109. package/dist/core/memory/memories.js +133 -60
  110. package/dist/core/memory/memories.js.map +1 -1
  111. package/dist/core/memory/progressive-disclosure.d.ts +43 -0
  112. package/dist/core/memory/progressive-disclosure.d.ts.map +1 -0
  113. package/dist/core/memory/progressive-disclosure.js +280 -0
  114. package/dist/core/memory/progressive-disclosure.js.map +1 -0
  115. package/dist/core/memory/query-rewriter.d.ts +13 -0
  116. package/dist/core/memory/query-rewriter.d.ts.map +1 -0
  117. package/dist/core/memory/query-rewriter.js +118 -0
  118. package/dist/core/memory/query-rewriter.js.map +1 -0
  119. package/dist/core/memory/response-analyzer.d.ts +9 -0
  120. package/dist/core/memory/response-analyzer.d.ts.map +1 -0
  121. package/dist/core/memory/response-analyzer.js +61 -0
  122. package/dist/core/memory/response-analyzer.js.map +1 -0
  123. package/dist/core/memory/stats.d.ts +17 -0
  124. package/dist/core/memory/stats.d.ts.map +1 -0
  125. package/dist/core/memory/stats.js +87 -0
  126. package/dist/core/memory/stats.js.map +1 -0
  127. package/dist/core/memory/telemetry.d.ts +69 -0
  128. package/dist/core/memory/telemetry.d.ts.map +1 -0
  129. package/dist/core/memory/telemetry.js +313 -0
  130. package/dist/core/memory/telemetry.js.map +1 -0
  131. package/dist/core/memory/temporal-facts.d.ts +41 -0
  132. package/dist/core/memory/temporal-facts.d.ts.map +1 -0
  133. package/dist/core/memory/temporal-facts.js +262 -0
  134. package/dist/core/memory/temporal-facts.js.map +1 -0
  135. package/dist/core/memory/trigger-detector.d.ts +14 -0
  136. package/dist/core/memory/trigger-detector.d.ts.map +1 -0
  137. package/dist/core/memory/trigger-detector.js +42 -0
  138. package/dist/core/memory/trigger-detector.js.map +1 -0
  139. package/dist/core/memory/write-gate.d.ts +54 -0
  140. package/dist/core/memory/write-gate.d.ts.map +1 -0
  141. package/dist/core/memory/write-gate.js +210 -0
  142. package/dist/core/memory/write-gate.js.map +1 -0
  143. package/dist/core/projects.d.ts +2 -0
  144. package/dist/core/projects.d.ts.map +1 -1
  145. package/dist/core/projects.js +33 -0
  146. package/dist/core/projects.js.map +1 -1
  147. package/dist/core/scheduler/cron-scheduler.d.ts +32 -0
  148. package/dist/core/scheduler/cron-scheduler.d.ts.map +1 -0
  149. package/dist/core/scheduler/cron-scheduler.js +238 -0
  150. package/dist/core/scheduler/cron-scheduler.js.map +1 -0
  151. package/dist/core/scheduler/heartbeat.d.ts +11 -0
  152. package/dist/core/scheduler/heartbeat.d.ts.map +1 -0
  153. package/dist/core/scheduler/heartbeat.js +73 -0
  154. package/dist/core/scheduler/heartbeat.js.map +1 -0
  155. package/dist/core/scheduler/index.d.ts +8 -0
  156. package/dist/core/scheduler/index.d.ts.map +1 -0
  157. package/dist/core/scheduler/index.js +8 -0
  158. package/dist/core/scheduler/index.js.map +1 -0
  159. package/dist/core/scheduler/job-runner.d.ts +11 -0
  160. package/dist/core/scheduler/job-runner.d.ts.map +1 -0
  161. package/dist/core/scheduler/job-runner.js +161 -0
  162. package/dist/core/scheduler/job-runner.js.map +1 -0
  163. package/dist/core/session/auto-load.d.ts +6 -0
  164. package/dist/core/session/auto-load.d.ts.map +1 -0
  165. package/dist/core/session/auto-load.js +119 -0
  166. package/dist/core/session/auto-load.js.map +1 -0
  167. package/dist/core/session/index.d.ts +7 -0
  168. package/dist/core/session/index.d.ts.map +1 -0
  169. package/dist/core/session/index.js +7 -0
  170. package/dist/core/session/index.js.map +1 -0
  171. package/dist/core/session/types.d.ts +26 -0
  172. package/dist/core/session/types.d.ts.map +1 -0
  173. package/dist/core/session/types.js +10 -0
  174. package/dist/core/session/types.js.map +1 -0
  175. package/dist/core/snapshots/comparison.d.ts.map +1 -1
  176. package/dist/core/snapshots/comparison.js +8 -2
  177. package/dist/core/snapshots/comparison.js.map +1 -1
  178. package/dist/core/utils/content-extraction.d.ts.map +1 -1
  179. package/dist/core/utils/content-extraction.js +11 -1
  180. package/dist/core/utils/content-extraction.js.map +1 -1
  181. package/dist/core/utils/summarization-helpers.d.ts.map +1 -1
  182. package/dist/core/utils/summarization-helpers.js +4 -1
  183. package/dist/core/utils/summarization-helpers.js.map +1 -1
  184. package/dist/core/utils.d.ts.map +1 -1
  185. package/dist/core/utils.js +26 -3
  186. package/dist/core/utils.js.map +1 -1
  187. package/dist/core/worker.d.ts +20 -0
  188. package/dist/core/worker.d.ts.map +1 -1
  189. package/dist/core/worker.js +86 -0
  190. package/dist/core/worker.js.map +1 -1
  191. package/dist/db/adapter.d.ts +1 -5
  192. package/dist/db/adapter.d.ts.map +1 -1
  193. package/dist/db/adapter.js +125 -12
  194. package/dist/db/adapter.js.map +1 -1
  195. package/dist/db/bootstrap.d.ts.map +1 -1
  196. package/dist/db/bootstrap.js +178 -3
  197. package/dist/db/bootstrap.js.map +1 -1
  198. package/dist/db/index.d.ts +1 -5
  199. package/dist/db/index.d.ts.map +1 -1
  200. package/dist/db/index.js +7 -4
  201. package/dist/db/index.js.map +1 -1
  202. package/dist/drizzle/schema-sqlite.d.ts +1953 -612
  203. package/dist/drizzle/schema-sqlite.d.ts.map +1 -1
  204. package/dist/drizzle/schema-sqlite.js +134 -0
  205. package/dist/drizzle/schema-sqlite.js.map +1 -1
  206. package/dist/drizzle/schema.d.ts +684 -3
  207. package/dist/drizzle/schema.d.ts.map +1 -1
  208. package/dist/drizzle/schema.js +81 -1
  209. package/dist/drizzle/schema.js.map +1 -1
  210. package/dist/index.d.ts +3 -3
  211. package/dist/index.js +152 -13
  212. package/dist/index.js.map +1 -1
  213. package/package.json +125 -103
  214. package/scripts/build-release.sh +33 -0
  215. package/scripts/db/check-db.mjs +88 -0
  216. package/scripts/db/fix-all-columns.mjs +52 -0
  217. package/scripts/db/fix-schema-all.mjs +55 -0
  218. package/scripts/db/fix-schema-full.mjs +46 -0
  219. package/scripts/db/fix-schema.mjs +38 -0
  220. package/scripts/db/init-db.mjs +13 -0
  221. package/scripts/db/recreate-db.mjs +14 -0
  222. package/scripts/generate-mcp.mjs +264 -0
  223. package/scripts/github-release.sh +61 -0
  224. package/scripts/init-dirs.mjs +13 -0
  225. package/scripts/init-dirs.ts +15 -0
  226. package/scripts/install-mcp.mjs +116 -0
  227. package/scripts/install-web.sh +120 -0
  228. package/scripts/install.mjs +340 -0
  229. package/scripts/openclaw-bootstrap.mjs +127 -0
  230. package/scripts/package-release.sh +71 -0
  231. package/scripts/remote-preflight.mjs +62 -0
  232. package/scripts/squish-fallback.mjs +132 -0
  233. package/scripts/test/test-all-systems.mjs +139 -0
  234. package/scripts/test/test-memory-system.mjs +139 -0
  235. package/scripts/test/test-v0.5.0.mjs +210 -0
  236. package/scripts/verify-mcp.mjs +214 -0
  237. package/skills/memory-guide/SKILL.md +181 -123
  238. package/skills/squish-cli/SKILL.md +200 -0
  239. package/skills/squish-mcp/SKILL.md +311 -0
  240. package/skills/squish-memory/SKILL.md +100 -62
  241. package/skills/squish-memory/claude-desktop.json +12 -0
  242. package/skills/squish-memory/install.mjs +335 -0
  243. package/skills/squish-memory/install.sh +94 -62
  244. package/skills/squish-memory/openclaw.json +13 -0
  245. package/skills/squish-memory/opencode.json +14 -0
  246. package/skills/squish-memory/skill.json +32 -0
  247. package/dist/adapters/claude-code/capture.d.ts +0 -11
  248. package/dist/adapters/claude-code/capture.d.ts.map +0 -1
  249. package/dist/adapters/claude-code/capture.js +0 -100
  250. package/dist/adapters/claude-code/capture.js.map +0 -1
  251. package/dist/adapters/claude-code/index.d.ts +0 -5
  252. package/dist/adapters/claude-code/index.d.ts.map +0 -1
  253. package/dist/adapters/claude-code/index.js +0 -6
  254. package/dist/adapters/claude-code/index.js.map +0 -1
  255. package/dist/adapters/claude-code/injection.d.ts +0 -34
  256. package/dist/adapters/claude-code/injection.d.ts.map +0 -1
  257. package/dist/adapters/claude-code/injection.js +0 -127
  258. package/dist/adapters/claude-code/injection.js.map +0 -1
  259. package/dist/adapters/claude-code/plugin-wrapper.d.ts +0 -21
  260. package/dist/adapters/claude-code/plugin-wrapper.d.ts.map +0 -1
  261. package/dist/adapters/claude-code/plugin-wrapper.js +0 -239
  262. package/dist/adapters/claude-code/plugin-wrapper.js.map +0 -1
  263. package/dist/adapters/claude-code/types.d.ts +0 -46
  264. package/dist/adapters/claude-code/types.d.ts.map +0 -1
  265. package/dist/adapters/claude-code/types.js +0 -6
  266. package/dist/adapters/claude-code/types.js.map +0 -1
@@ -0,0 +1,38 @@
1
+ import Database from 'better-sqlite3';
2
+ import { getDataDir } from './dist/config.js';
3
+
4
+ const dbPath = `${getDataDir()}/squish.db`;
5
+ console.log(`Fixing schema for: ${dbPath}`);
6
+
7
+ const db = new Database(dbPath);
8
+
9
+ // Check if embedding column exists
10
+ const tableInfo = db.prepare("PRAGMA table_info(memories)").all();
11
+ const hasEmbedding = tableInfo.some(col => col.name === 'embedding');
12
+
13
+ if (!hasEmbedding) {
14
+ console.log('Adding missing embedding column...');
15
+ db.exec(`ALTER TABLE memories ADD COLUMN embedding BLOB;`);
16
+ console.log('✅ Added embedding column');
17
+ } else {
18
+ console.log('✅ embedding column already exists');
19
+ }
20
+
21
+ // Check other tables that might need the embedding column
22
+ const tables = ['observations', 'messages', 'entities'];
23
+ for (const table of tables) {
24
+ const info = db.prepare(`PRAGMA table_info(${table})`).all();
25
+ const hasCol = info.some(col => col.name === 'embedding');
26
+ if (!hasCol) {
27
+ console.log(`Adding embedding column to ${table}...`);
28
+ try {
29
+ db.exec(`ALTER TABLE ${table} ADD COLUMN embedding BLOB;`);
30
+ console.log(`✅ Added embedding column to ${table}`);
31
+ } catch (e) {
32
+ console.log(`⚠️ Could not add to ${table}: ${e.message}`);
33
+ }
34
+ }
35
+ }
36
+
37
+ db.close();
38
+ console.log('✅ Schema fix complete');
@@ -0,0 +1,13 @@
1
+ import { createDb } from './dist/db/adapter.js';
2
+
3
+ async function main() {
4
+ try {
5
+ await createDb();
6
+ console.log('✅ Database initialized successfully');
7
+ } catch (error) {
8
+ console.error('❌ Failed to initialize database:', error.message);
9
+ process.exit(1);
10
+ }
11
+ }
12
+
13
+ main();
@@ -0,0 +1,14 @@
1
+ import { createDb } from './dist/db/adapter.js';
2
+
3
+ async function main() {
4
+ try {
5
+ console.log('Creating database with proper schema...');
6
+ await createDb();
7
+ console.log('✅ Database recreated successfully');
8
+ } catch (error) {
9
+ console.error('❌ Failed:', error.message);
10
+ process.exit(1);
11
+ }
12
+ }
13
+
14
+ main();
@@ -0,0 +1,264 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import crypto from "node:crypto";
6
+
7
+ const root = process.cwd();
8
+ const defaultSourcePath = path.join(root, "config", "mcp.json");
9
+ const defaultOutDir = path.join(root, "generated", "mcp");
10
+ const defaultImports = [
11
+ "cursor",
12
+ "claude-code",
13
+ "claude-desktop",
14
+ "codex",
15
+ "windsurf",
16
+ "opencode",
17
+ "vscode"
18
+ ];
19
+
20
+ function parseArgs(argv) {
21
+ const args = {
22
+ configPath: defaultSourcePath,
23
+ outDir: defaultOutDir,
24
+ strictEnv: false
25
+ };
26
+
27
+ for (let i = 2; i < argv.length; i += 1) {
28
+ const token = argv[i];
29
+ if (token === "--strict-env") {
30
+ args.strictEnv = true;
31
+ continue;
32
+ }
33
+ if (token === "--config") {
34
+ args.configPath = path.resolve(argv[i + 1]);
35
+ i += 1;
36
+ continue;
37
+ }
38
+ if (token === "--out") {
39
+ args.outDir = path.resolve(argv[i + 1]);
40
+ i += 1;
41
+ continue;
42
+ }
43
+ throw new Error(`Unknown argument: ${token}`);
44
+ }
45
+
46
+ return args;
47
+ }
48
+
49
+ function readJson(filePath) {
50
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
51
+ }
52
+
53
+ function ensureDir(dirPath) {
54
+ fs.mkdirSync(dirPath, { recursive: true });
55
+ }
56
+
57
+ function writeJson(filePath, data) {
58
+ fs.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
59
+ }
60
+
61
+ function sha256File(filePath) {
62
+ const hash = crypto.createHash("sha256");
63
+ hash.update(fs.readFileSync(filePath));
64
+ return hash.digest("hex");
65
+ }
66
+
67
+ function sortObjectKeys(input) {
68
+ if (Array.isArray(input)) {
69
+ return input.map(sortObjectKeys);
70
+ }
71
+ if (input && typeof input === "object") {
72
+ const sorted = {};
73
+ for (const key of Object.keys(input).sort()) {
74
+ sorted[key] = sortObjectKeys(input[key]);
75
+ }
76
+ return sorted;
77
+ }
78
+ return input;
79
+ }
80
+
81
+ function extractEnvPlaceholders(servers) {
82
+ const placeholders = [];
83
+ for (const [serverName, server] of Object.entries(servers)) {
84
+ const env = server?.env || {};
85
+ for (const [envKey, value] of Object.entries(env)) {
86
+ if (typeof value !== "string") continue;
87
+ const match = value.match(/^\$\{([A-Z0-9_]+)\}$/);
88
+ if (match) {
89
+ placeholders.push({ serverName, envKey, variable: match[1] });
90
+ }
91
+ }
92
+ }
93
+ return placeholders;
94
+ }
95
+
96
+ function validateConfig(config, strictEnv) {
97
+ if (!config || typeof config !== "object") {
98
+ throw new Error("Invalid config: expected object");
99
+ }
100
+
101
+ if (!config.defaults || typeof config.defaults !== "object") {
102
+ throw new Error("Invalid config: defaults must be an object");
103
+ }
104
+
105
+ if (!config.servers || typeof config.servers !== "object") {
106
+ throw new Error("Invalid config: servers must be an object");
107
+ }
108
+
109
+ const serverNames = Object.keys(config.servers);
110
+ if (serverNames.length === 0) {
111
+ throw new Error("Invalid config: at least one server is required");
112
+ }
113
+
114
+ for (const [serverName, server] of Object.entries(config.servers)) {
115
+ if (!server || typeof server !== "object") {
116
+ throw new Error(`Invalid server ${serverName}: expected object`);
117
+ }
118
+ if (!server.command || typeof server.command !== "string") {
119
+ throw new Error(`Invalid server ${serverName}: command is required`);
120
+ }
121
+ if (!Array.isArray(server.args)) {
122
+ throw new Error(`Invalid server ${serverName}: args must be an array`);
123
+ }
124
+ if (!server.transport || typeof server.transport !== "string") {
125
+ throw new Error(`Invalid server ${serverName}: transport is required`);
126
+ }
127
+ if (!server.env || typeof server.env !== "object") {
128
+ throw new Error(`Invalid server ${serverName}: env must be an object`);
129
+ }
130
+ }
131
+
132
+ const includeServers = config.includeServers || [];
133
+ if (includeServers.length > 0) {
134
+ const unique = new Set(includeServers);
135
+ if (unique.size !== includeServers.length) {
136
+ throw new Error("Invalid config: includeServers contains duplicates");
137
+ }
138
+ for (const name of includeServers) {
139
+ if (!config.servers[name]) {
140
+ throw new Error(`Invalid config: includeServers references unknown server ${name}`);
141
+ }
142
+ }
143
+ }
144
+
145
+ if (strictEnv) {
146
+ const unresolved = extractEnvPlaceholders(config.servers)
147
+ .filter((entry) => !process.env[entry.variable]);
148
+ if (unresolved.length > 0) {
149
+ const first = unresolved[0];
150
+ throw new Error(
151
+ `Missing required env for strict mode: ${first.variable} (server=${first.serverName}, key=${first.envKey})`
152
+ );
153
+ }
154
+ }
155
+ }
156
+
157
+ function selectServers(config) {
158
+ const include = config.includeServers || [];
159
+ if (include.length === 0) {
160
+ return config.servers;
161
+ }
162
+ const selected = {};
163
+ for (const serverName of include) {
164
+ selected[serverName] = config.servers[serverName];
165
+ }
166
+ return selected;
167
+ }
168
+
169
+ function toOpenClawMemoryConfig(runtime) {
170
+ return {
171
+ memory: {
172
+ backend: "qmd",
173
+ qmd: {
174
+ mcporter: {
175
+ enabled: true,
176
+ serverName: "qmd",
177
+ startDaemon: true
178
+ },
179
+ limits: {
180
+ timeoutMs: runtime.requestTimeoutMs,
181
+ maxSnippetChars: runtime.resultMaxChars,
182
+ maxResults: 12
183
+ }
184
+ }
185
+ }
186
+ };
187
+ }
188
+
189
+ function toMcporterConfig(servers) {
190
+ return {
191
+ mcpServers: servers,
192
+ imports: defaultImports
193
+ };
194
+ }
195
+
196
+ function removeLegacyProfileDirectories(outDir) {
197
+ const removed = [];
198
+ if (!fs.existsSync(outDir)) return;
199
+ const entries = fs.readdirSync(outDir, { withFileTypes: true });
200
+ for (const entry of entries) {
201
+ if (entry.isDirectory()) {
202
+ fs.rmSync(path.join(outDir, entry.name), { recursive: true, force: true });
203
+ removed.push(entry.name);
204
+ }
205
+ }
206
+ return removed;
207
+ }
208
+
209
+ function main() {
210
+ const args = parseArgs(process.argv);
211
+ const config = readJson(args.configPath);
212
+
213
+ validateConfig(config, args.strictEnv);
214
+
215
+ ensureDir(args.outDir);
216
+ const removedLegacyDirs = removeLegacyProfileDirectories(args.outDir) || [];
217
+
218
+ if (config.profiles && typeof config.profiles === "object") {
219
+ console.warn(
220
+ "[mcp-migration] legacy profiles detected in config/mcp.json and ignored by universal generator"
221
+ );
222
+ }
223
+ if (removedLegacyDirs.length > 0) {
224
+ console.warn(
225
+ `[mcp-migration] removed legacy profile output directories: ${removedLegacyDirs.join(", ")}`
226
+ );
227
+ }
228
+
229
+ const runtime = sortObjectKeys(config.defaults);
230
+ const selectedServers = sortObjectKeys(selectServers(config));
231
+
232
+ const fileMap = {
233
+ "runtime.json": runtime,
234
+ "mcp-servers.json": { mcpServers: selectedServers },
235
+ "mcporter.json": toMcporterConfig(selectedServers),
236
+ "openclaw-memory-qmd.json": toOpenClawMemoryConfig(runtime)
237
+ };
238
+
239
+ for (const [fileName, json] of Object.entries(fileMap)) {
240
+ writeJson(path.join(args.outDir, fileName), json);
241
+ }
242
+
243
+ const manifestFiles = Object.keys(fileMap)
244
+ .sort()
245
+ .map((fileName) => {
246
+ const filePath = path.join(args.outDir, fileName);
247
+ return {
248
+ file: fileName,
249
+ sha256: sha256File(filePath)
250
+ };
251
+ });
252
+
253
+ const manifest = {
254
+ mode: "universal",
255
+ generatedAt: new Date().toISOString(),
256
+ source: path.relative(root, args.configPath).replace(/\\/g, "/"),
257
+ files: manifestFiles
258
+ };
259
+
260
+ writeJson(path.join(args.outDir, "manifest.json"), manifest);
261
+ console.log(`Generated universal MCP artifacts in ${args.outDir}`);
262
+ }
263
+
264
+ main();
@@ -0,0 +1,61 @@
1
+ #!/bin/bash
2
+
3
+ # Squish GitHub Release Script
4
+ # Run after npm publish to create GitHub release
5
+
6
+ VERSION="0.3.0"
7
+ REPO="michielhdoteth/squish"
8
+
9
+ echo "🏷️ Creating GitHub release v$VERSION..."
10
+
11
+ # Build binaries for different platforms
12
+ echo "🔨 Building binaries..."
13
+
14
+ # Linux x64
15
+ echo "Building linux-x64..."
16
+ npx pkg dist/index.js --targets node18-linux-x64 --output bin/squish-linux-x64
17
+ tar -czf squish-v${VERSION}-linux-x64.tar.gz bin/ dist/ plugin.json README.md LICENSE
18
+
19
+ # Linux ARM64
20
+ echo "Building linux-arm64..."
21
+ npx pkg dist/index.js --targets node18-linux-arm64 --output bin/squish-linux-arm64
22
+ tar -czf squish-v${VERSION}-linux-arm64.tar.gz bin/ dist/ plugin.json README.md LICENSE
23
+
24
+ # macOS ARM64 (Apple Silicon)
25
+ echo "Building macos-arm64..."
26
+ npx pkg dist/index.js --targets node18-macos-arm64 --output bin/squish-macos-arm64
27
+ tar -czf squish-v${VERSION}-macos-arm64.tar.gz bin/ dist/ plugin.json README.md LICENSE
28
+
29
+ # Windows x64
30
+ echo "Building windows-x64..."
31
+ npx pkg dist/index.js --targets node18-win-x64 --output bin/squish-windows-x64.exe
32
+ zip squish-v${VERSION}-windows-x64.zip bin/ dist/ plugin.json README.md LICENSE
33
+
34
+ echo "📦 Binaries created!"
35
+
36
+ # Create GitHub release (requires gh CLI)
37
+ echo "🚀 Creating GitHub release..."
38
+ gh release create "v${VERSION}" \
39
+ --title "Squish v${VERSION} - Memory Plugin for Claude Code" \
40
+ --notes "Local-first persistent memory for Claude Code with code quality improvements and better maintainability.
41
+
42
+ ## What's New in v0.3.0
43
+
44
+ ### Code Quality Improvements
45
+ - Reduced complexity in core modules (summarization, temporal-facts, requirements)
46
+ - Split long files into focused submodules for better organization
47
+ - Eliminated ~200+ lines of duplicated code
48
+ - Created 9 shared utility modules in core/utils/
49
+
50
+ ### Installation
51
+ \`\`\`bash
52
+ npx squish-install
53
+ \`\`\`
54
+
55
+ Or visit: https://github.com/michielhdoteth/squish" \
56
+ squish-v${VERSION}-linux-x64.tar.gz \
57
+ squish-v${VERSION}-linux-arm64.tar.gz \
58
+ squish-v${VERSION}-macos-arm64.tar.gz \
59
+ squish-v${VERSION}-windows-x64.zip
60
+
61
+ echo "🎉 Release v${VERSION} published!"
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, mkdirSync } from 'node:fs';
4
+ import { homedir } from 'node:os';
5
+ import { join } from 'node:path';
6
+
7
+ const defaultDir = join(homedir(), '.squish');
8
+
9
+ if (!existsSync(defaultDir)) {
10
+ mkdirSync(defaultDir, { recursive: true });
11
+ }
12
+
13
+ console.log(`Squish data directory: ${defaultDir}`);
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Squish Directory Initialization
4
+ * Creates default data directories for npm-installed Squish
5
+ */
6
+ import { mkdirSync, existsSync } from 'fs';
7
+ import { join, homedir } from 'path';
8
+
9
+ // Create ~/.squish (default global data directory)
10
+ const defaultDir = join(homedir(), '.squish');
11
+ if (!existsSync(defaultDir)) {
12
+ mkdirSync(defaultDir, { recursive: true });
13
+ }
14
+
15
+ console.log(`Squish data directory: ${defaultDir}`);
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+
7
+ const root = process.cwd();
8
+ const defaultSourceDir = path.join(root, "generated", "mcp");
9
+
10
+ const clientDefaultDirs = {
11
+ "claude-code": path.join(os.homedir(), ".claude"),
12
+ opencode: path.join(os.homedir(), ".config", "opencode"),
13
+ codex: path.join(os.homedir(), ".codex"),
14
+ cursor: path.join(os.homedir(), ".cursor"),
15
+ vscode: path.join(os.homedir(), ".vscode", "mcp"),
16
+ windsurf: path.join(os.homedir(), ".windsurf"),
17
+ openclaw: path.join(os.homedir(), ".openclaw")
18
+ };
19
+
20
+ function parseArgs(argv) {
21
+ const args = {
22
+ client: "",
23
+ sourceDir: defaultSourceDir,
24
+ targetDir: "",
25
+ dryRun: false,
26
+ backup: true
27
+ };
28
+
29
+ for (let i = 2; i < argv.length; i += 1) {
30
+ const token = argv[i];
31
+ if (token === "--dry-run") {
32
+ args.dryRun = true;
33
+ continue;
34
+ }
35
+ if (token === "--no-backup") {
36
+ args.backup = false;
37
+ continue;
38
+ }
39
+ if (token === "--client") {
40
+ args.client = argv[i + 1];
41
+ i += 1;
42
+ continue;
43
+ }
44
+ if (token === "--source") {
45
+ args.sourceDir = path.resolve(argv[i + 1]);
46
+ i += 1;
47
+ continue;
48
+ }
49
+ if (token === "--target") {
50
+ args.targetDir = path.resolve(argv[i + 1]);
51
+ i += 1;
52
+ continue;
53
+ }
54
+ throw new Error(`Unknown argument: ${token}`);
55
+ }
56
+
57
+ if (!args.client) {
58
+ throw new Error("Missing required argument: --client");
59
+ }
60
+ if (!clientDefaultDirs[args.client]) {
61
+ throw new Error(`Unsupported client: ${args.client}`);
62
+ }
63
+ if (!args.targetDir) {
64
+ args.targetDir = clientDefaultDirs[args.client];
65
+ }
66
+
67
+ return args;
68
+ }
69
+
70
+ function ensureDir(dirPath) {
71
+ fs.mkdirSync(dirPath, { recursive: true });
72
+ }
73
+
74
+ function backupFile(targetPath) {
75
+ if (!fs.existsSync(targetPath)) return;
76
+ fs.copyFileSync(targetPath, `${targetPath}.bak`);
77
+ }
78
+
79
+ function copyFile(sourcePath, targetPath, options) {
80
+ if (!fs.existsSync(sourcePath)) {
81
+ throw new Error(`Missing source file: ${sourcePath}`);
82
+ }
83
+ if (options.backup) {
84
+ backupFile(targetPath);
85
+ }
86
+ if (!options.dryRun) {
87
+ fs.copyFileSync(sourcePath, targetPath);
88
+ }
89
+ }
90
+
91
+ function filePlanForClient(client) {
92
+ if (client === "openclaw") {
93
+ return [
94
+ { from: "mcporter.json", to: "mcporter.json" },
95
+ { from: "openclaw-memory-qmd.json", to: "openclaw-memory-qmd.json" }
96
+ ];
97
+ }
98
+ return [{ from: "mcp-servers.json", to: "mcp-servers.json" }];
99
+ }
100
+
101
+ function main() {
102
+ const args = parseArgs(process.argv);
103
+ const plan = filePlanForClient(args.client);
104
+
105
+ ensureDir(args.targetDir);
106
+
107
+ for (const item of plan) {
108
+ const sourcePath = path.join(args.sourceDir, item.from);
109
+ const targetPath = path.join(args.targetDir, item.to);
110
+ copyFile(sourcePath, targetPath, args);
111
+ const modeTag = args.dryRun ? "DRY_RUN" : "INSTALLED";
112
+ console.log(`${modeTag} ${item.from} -> ${targetPath}`);
113
+ }
114
+ }
115
+
116
+ main();
@@ -0,0 +1,120 @@
1
+ #!/bin/bash
2
+
3
+ # Simple web server to host Squish install script
4
+ # This would be deployed to make https://get.squish.dev work
5
+
6
+ echo "Content-Type: application/x-shellscript"
7
+ echo ""
8
+ cat << 'EOF'
9
+ #!/bin/bash
10
+
11
+ # Squish v0.2.6 - One-line installer for Claude Code Plugin
12
+ # Usage: curl -fsSL https://get.squish.dev | bash
13
+
14
+ set -e
15
+
16
+ # Colors for output
17
+ RED='\033[0;31m'
18
+ GREEN='\033[0;32m'
19
+ YELLOW='\033[1;33m'
20
+ BLUE='\033[0;34m'
21
+ NC='\033[0m' # No Color
22
+
23
+ echo -e "${BLUE}🐙 Installing Squish Memory v0.2.6...${NC}"
24
+
25
+ # Detect platform and architecture
26
+ detect_platform() {
27
+ case "$(uname -s)" in
28
+ Linux*) PLATFORM="linux" ;;
29
+ Darwin*) PLATFORM="macos" ;;
30
+ CYGWIN*|MINGW*|MSYS*) PLATFORM="windows" ;;
31
+ *) echo -e "${RED}Unsupported platform: $(uname -s)${NC}"; exit 1 ;;
32
+ esac
33
+
34
+ case "$(uname -m)" in
35
+ x86_64|amd64) ARCH="x64" ;;
36
+ arm64|aarch64) ARCH="arm64" ;;
37
+ *) echo -e "${RED}Unsupported architecture: $(uname -m)${NC}"; exit 1 ;;
38
+ esac
39
+ }
40
+
41
+ # Download and extract Squish
42
+ install_squish() {
43
+ echo -e "${BLUE}Downloading Squish for ${PLATFORM}-${ARCH}...${NC}"
44
+
45
+ TMP_DIR=$(mktemp -d)
46
+ cd "$TMP_DIR"
47
+
48
+ DOWNLOAD_URL="https://github.com/michielhdoteth/squish-memory/releases/download/v0.2.6"
49
+
50
+ if [ "$PLATFORM" = "windows" ]; then
51
+ FILENAME="squish-v0.2.6-windows-${ARCH}.zip"
52
+ curl -L -o "$FILENAME" "${DOWNLOAD_URL}/${FILENAME}"
53
+ unzip -q "$FILENAME"
54
+ else
55
+ FILENAME="squish-v0.2.6-${PLATFORM}-${ARCH}.tar.gz"
56
+ curl -L -o "$FILENAME" "${DOWNLOAD_URL}/${FILENAME}"
57
+ tar -xzf "$FILENAME"
58
+ fi
59
+
60
+ # Install to ~/.squish
61
+ INSTALL_DIR="$HOME/.squish"
62
+ mkdir -p "$INSTALL_DIR"
63
+ cp -r squish/* "$INSTALL_DIR/"
64
+ chmod +x "$INSTALL_DIR/bin/squish"
65
+
66
+ cd - > /dev/null
67
+ rm -rf "$TMP_DIR"
68
+
69
+ echo -e "${GREEN}✓ Installed to: ${INSTALL_DIR}${NC}"
70
+ }
71
+
72
+ # Setup Claude Code configuration
73
+ setup_claude() {
74
+ echo -e "${BLUE}Configuring Claude Code...${NC}"
75
+
76
+ CLAUDE_CONFIG="$HOME/.claude/settings.json"
77
+ mkdir -p "$HOME/.claude"
78
+
79
+ # Backup existing config
80
+ if [ -f "$CLAUDE_CONFIG" ]; then
81
+ cp "$CLAUDE_CONFIG" "${CLAUDE_CONFIG}.backup.$(date +%s)"
82
+ fi
83
+
84
+ # Create or update config
85
+ if [ -f "$CLAUDE_CONFIG" ] && command -v jq &> /dev/null; then
86
+ jq --arg bin_path "$HOME/.squish/bin/squish" '.mcpServers.squish = {"command": "node", "args": [$bin_path]}' "$CLAUDE_CONFIG" > "${CLAUDE_CONFIG}.tmp" && mv "${CLAUDE_CONFIG}.tmp" "$CLAUDE_CONFIG"
87
+ else
88
+ cat > "$CLAUDE_CONFIG" << EOF
89
+ {
90
+ "mcpServers": {
91
+ "squish": {
92
+ "command": "node",
93
+ "args": ["$HOME/.squish/bin/squish"]
94
+ }
95
+ }
96
+ }
97
+ EOF
98
+ fi
99
+
100
+ echo -e "${GREEN}✓ Claude Code configured${NC}"
101
+ }
102
+
103
+ # Main installation
104
+ main() {
105
+ detect_platform
106
+ install_squish
107
+ setup_claude
108
+
109
+ echo ""
110
+ echo -e "${GREEN}🎉 Squish v0.2.6 installed successfully!${NC}"
111
+ echo ""
112
+ echo -e "${BLUE}Next steps:${NC}"
113
+ echo -e " 1. Restart Claude Code"
114
+ echo -e " 2. Visit http://localhost:37777 for web UI"
115
+ echo ""
116
+ echo -e "${BLUE}Documentation: https://github.com/michielhdoteth/squish-memory${NC}"
117
+ }
118
+
119
+ main "$@"
120
+ EOF