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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +2 -2
- package/.env.mcp +30 -0
- package/.mcp.json +2 -5
- package/CHANGELOG.md +111 -0
- package/QUICK-START.md +65 -0
- package/README.md +188 -530
- package/commands/managed-sync.ts +69 -0
- package/commands/mcp-server.ts +519 -0
- package/config/mcp-cli-fallback-policy.json +22 -0
- package/config/mcp-migration-map.json +22 -0
- package/config/mcp-mode-semantics.json +21 -0
- package/config/mcp-remote-auth.json +36 -0
- package/config/mcp-universal.schema.json +48 -0
- package/config/mcp.json +38 -0
- package/config/remote-memory-policy.json +32 -0
- package/dist/algorithms/merge/detection/hash-filters.js +2 -2
- package/dist/algorithms/merge/detection/hash-filters.js.map +1 -1
- package/dist/algorithms/merge/detection/two-stage-detector.d.ts +5 -2
- package/dist/algorithms/merge/detection/two-stage-detector.d.ts.map +1 -1
- package/dist/algorithms/merge/detection/two-stage-detector.js +139 -22
- package/dist/algorithms/merge/detection/two-stage-detector.js.map +1 -1
- package/dist/commands/managed-sync.d.ts +10 -0
- package/dist/commands/managed-sync.d.ts.map +1 -0
- package/dist/commands/managed-sync.js +64 -0
- package/dist/commands/managed-sync.js.map +1 -0
- package/dist/commands/mcp-server.d.ts +3 -0
- package/dist/commands/mcp-server.d.ts.map +1 -0
- package/dist/commands/mcp-server.js +389 -0
- package/dist/commands/mcp-server.js.map +1 -0
- package/dist/config.d.ts +24 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +32 -1
- package/dist/config.js.map +1 -1
- package/dist/core/associations.d.ts +1 -1
- package/dist/core/associations.d.ts.map +1 -1
- package/dist/core/consolidation.d.ts +31 -0
- package/dist/core/consolidation.d.ts.map +1 -1
- package/dist/core/consolidation.js +237 -29
- package/dist/core/consolidation.js.map +1 -1
- package/dist/core/embeddings/google-multimodal.d.ts +14 -0
- package/dist/core/embeddings/google-multimodal.d.ts.map +1 -0
- package/dist/core/embeddings/google-multimodal.js +142 -0
- package/dist/core/embeddings/google-multimodal.js.map +1 -0
- package/dist/core/embeddings.d.ts +3 -2
- package/dist/core/embeddings.d.ts.map +1 -1
- package/dist/core/embeddings.js +61 -39
- package/dist/core/embeddings.js.map +1 -1
- package/dist/core/mcp/client.d.ts +17 -0
- package/dist/core/mcp/client.d.ts.map +1 -0
- package/dist/core/mcp/client.js +101 -0
- package/dist/core/mcp/client.js.map +1 -0
- package/dist/core/mcp/index.d.ts +6 -0
- package/dist/core/mcp/index.d.ts.map +1 -0
- package/dist/core/mcp/index.js +6 -0
- package/dist/core/mcp/index.js.map +1 -0
- package/dist/core/mcp/server.d.ts +18 -0
- package/dist/core/mcp/server.d.ts.map +1 -0
- package/dist/core/mcp/server.js +131 -0
- package/dist/core/mcp/server.js.map +1 -0
- package/dist/core/mcp/standalone-server.d.ts +13 -0
- package/dist/core/mcp/standalone-server.d.ts.map +1 -0
- package/dist/core/mcp/standalone-server.js +46 -0
- package/dist/core/mcp/standalone-server.js.map +1 -0
- package/dist/core/mcp/tools.d.ts +9 -0
- package/dist/core/mcp/tools.d.ts.map +1 -0
- package/dist/core/mcp/tools.js +262 -0
- package/dist/core/mcp/tools.js.map +1 -0
- package/dist/core/mcp/types.d.ts +315 -0
- package/dist/core/mcp/types.d.ts.map +1 -0
- package/dist/core/mcp/types.js +48 -0
- package/dist/core/mcp/types.js.map +1 -0
- package/dist/core/memory/categorizer.d.ts +27 -0
- package/dist/core/memory/categorizer.d.ts.map +1 -0
- package/dist/core/memory/categorizer.js +304 -0
- package/dist/core/memory/categorizer.js.map +1 -0
- package/dist/core/memory/conflict-detector.d.ts +7 -0
- package/dist/core/memory/conflict-detector.d.ts.map +1 -0
- package/dist/core/memory/conflict-detector.js +43 -0
- package/dist/core/memory/conflict-detector.js.map +1 -0
- package/dist/core/memory/context-collector.d.ts +10 -0
- package/dist/core/memory/context-collector.d.ts.map +1 -0
- package/dist/core/memory/context-collector.js +55 -0
- package/dist/core/memory/context-collector.js.map +1 -0
- package/dist/core/memory/contradiction-resolver.d.ts +40 -0
- package/dist/core/memory/contradiction-resolver.d.ts.map +1 -0
- package/dist/core/memory/contradiction-resolver.js +368 -0
- package/dist/core/memory/contradiction-resolver.js.map +1 -0
- package/dist/core/memory/edit-workflow.d.ts +19 -0
- package/dist/core/memory/edit-workflow.d.ts.map +1 -0
- package/dist/core/memory/edit-workflow.js +120 -0
- package/dist/core/memory/edit-workflow.js.map +1 -0
- package/dist/core/memory/feedback-tracker.d.ts +12 -0
- package/dist/core/memory/feedback-tracker.d.ts.map +1 -0
- package/dist/core/memory/feedback-tracker.js +151 -0
- package/dist/core/memory/feedback-tracker.js.map +1 -0
- package/dist/core/memory/hybrid-retrieval.d.ts +11 -12
- package/dist/core/memory/hybrid-retrieval.d.ts.map +1 -1
- package/dist/core/memory/hybrid-retrieval.js +56 -28
- package/dist/core/memory/hybrid-retrieval.js.map +1 -1
- package/dist/core/memory/hybrid-scorer.d.ts +5 -16
- package/dist/core/memory/hybrid-scorer.d.ts.map +1 -1
- package/dist/core/memory/hybrid-scorer.js +161 -125
- package/dist/core/memory/hybrid-scorer.js.map +1 -1
- package/dist/core/memory/hybrid-search.js +53 -19
- package/dist/core/memory/hybrid-search.js.map +1 -1
- package/dist/core/memory/memories.d.ts +4 -0
- package/dist/core/memory/memories.d.ts.map +1 -1
- package/dist/core/memory/memories.js +133 -60
- package/dist/core/memory/memories.js.map +1 -1
- package/dist/core/memory/progressive-disclosure.d.ts +43 -0
- package/dist/core/memory/progressive-disclosure.d.ts.map +1 -0
- package/dist/core/memory/progressive-disclosure.js +280 -0
- package/dist/core/memory/progressive-disclosure.js.map +1 -0
- package/dist/core/memory/query-rewriter.d.ts +13 -0
- package/dist/core/memory/query-rewriter.d.ts.map +1 -0
- package/dist/core/memory/query-rewriter.js +118 -0
- package/dist/core/memory/query-rewriter.js.map +1 -0
- package/dist/core/memory/response-analyzer.d.ts +9 -0
- package/dist/core/memory/response-analyzer.d.ts.map +1 -0
- package/dist/core/memory/response-analyzer.js +61 -0
- package/dist/core/memory/response-analyzer.js.map +1 -0
- package/dist/core/memory/stats.d.ts +17 -0
- package/dist/core/memory/stats.d.ts.map +1 -0
- package/dist/core/memory/stats.js +87 -0
- package/dist/core/memory/stats.js.map +1 -0
- package/dist/core/memory/telemetry.d.ts +69 -0
- package/dist/core/memory/telemetry.d.ts.map +1 -0
- package/dist/core/memory/telemetry.js +313 -0
- package/dist/core/memory/telemetry.js.map +1 -0
- package/dist/core/memory/temporal-facts.d.ts +41 -0
- package/dist/core/memory/temporal-facts.d.ts.map +1 -0
- package/dist/core/memory/temporal-facts.js +262 -0
- package/dist/core/memory/temporal-facts.js.map +1 -0
- package/dist/core/memory/trigger-detector.d.ts +14 -0
- package/dist/core/memory/trigger-detector.d.ts.map +1 -0
- package/dist/core/memory/trigger-detector.js +42 -0
- package/dist/core/memory/trigger-detector.js.map +1 -0
- package/dist/core/memory/write-gate.d.ts +54 -0
- package/dist/core/memory/write-gate.d.ts.map +1 -0
- package/dist/core/memory/write-gate.js +210 -0
- package/dist/core/memory/write-gate.js.map +1 -0
- package/dist/core/projects.d.ts +2 -0
- package/dist/core/projects.d.ts.map +1 -1
- package/dist/core/projects.js +33 -0
- package/dist/core/projects.js.map +1 -1
- package/dist/core/scheduler/cron-scheduler.d.ts +32 -0
- package/dist/core/scheduler/cron-scheduler.d.ts.map +1 -0
- package/dist/core/scheduler/cron-scheduler.js +238 -0
- package/dist/core/scheduler/cron-scheduler.js.map +1 -0
- package/dist/core/scheduler/heartbeat.d.ts +11 -0
- package/dist/core/scheduler/heartbeat.d.ts.map +1 -0
- package/dist/core/scheduler/heartbeat.js +73 -0
- package/dist/core/scheduler/heartbeat.js.map +1 -0
- package/dist/core/scheduler/index.d.ts +8 -0
- package/dist/core/scheduler/index.d.ts.map +1 -0
- package/dist/core/scheduler/index.js +8 -0
- package/dist/core/scheduler/index.js.map +1 -0
- package/dist/core/scheduler/job-runner.d.ts +11 -0
- package/dist/core/scheduler/job-runner.d.ts.map +1 -0
- package/dist/core/scheduler/job-runner.js +161 -0
- package/dist/core/scheduler/job-runner.js.map +1 -0
- package/dist/core/session/auto-load.d.ts +6 -0
- package/dist/core/session/auto-load.d.ts.map +1 -0
- package/dist/core/session/auto-load.js +119 -0
- package/dist/core/session/auto-load.js.map +1 -0
- package/dist/core/session/index.d.ts +7 -0
- package/dist/core/session/index.d.ts.map +1 -0
- package/dist/core/session/index.js +7 -0
- package/dist/core/session/index.js.map +1 -0
- package/dist/core/session/types.d.ts +26 -0
- package/dist/core/session/types.d.ts.map +1 -0
- package/dist/core/session/types.js +10 -0
- package/dist/core/session/types.js.map +1 -0
- package/dist/core/snapshots/comparison.d.ts.map +1 -1
- package/dist/core/snapshots/comparison.js +8 -2
- package/dist/core/snapshots/comparison.js.map +1 -1
- package/dist/core/utils/content-extraction.d.ts.map +1 -1
- package/dist/core/utils/content-extraction.js +11 -1
- package/dist/core/utils/content-extraction.js.map +1 -1
- package/dist/core/utils/summarization-helpers.d.ts.map +1 -1
- package/dist/core/utils/summarization-helpers.js +4 -1
- package/dist/core/utils/summarization-helpers.js.map +1 -1
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +26 -3
- package/dist/core/utils.js.map +1 -1
- package/dist/core/worker.d.ts +20 -0
- package/dist/core/worker.d.ts.map +1 -1
- package/dist/core/worker.js +86 -0
- package/dist/core/worker.js.map +1 -1
- package/dist/db/adapter.d.ts +1 -5
- package/dist/db/adapter.d.ts.map +1 -1
- package/dist/db/adapter.js +125 -12
- package/dist/db/adapter.js.map +1 -1
- package/dist/db/bootstrap.d.ts.map +1 -1
- package/dist/db/bootstrap.js +178 -3
- package/dist/db/bootstrap.js.map +1 -1
- package/dist/db/index.d.ts +1 -5
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +7 -4
- package/dist/db/index.js.map +1 -1
- package/dist/drizzle/schema-sqlite.d.ts +1953 -612
- package/dist/drizzle/schema-sqlite.d.ts.map +1 -1
- package/dist/drizzle/schema-sqlite.js +134 -0
- package/dist/drizzle/schema-sqlite.js.map +1 -1
- package/dist/drizzle/schema.d.ts +684 -3
- package/dist/drizzle/schema.d.ts.map +1 -1
- package/dist/drizzle/schema.js +81 -1
- package/dist/drizzle/schema.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +152 -13
- package/dist/index.js.map +1 -1
- package/package.json +125 -103
- package/scripts/build-release.sh +33 -0
- package/scripts/db/check-db.mjs +88 -0
- package/scripts/db/fix-all-columns.mjs +52 -0
- package/scripts/db/fix-schema-all.mjs +55 -0
- package/scripts/db/fix-schema-full.mjs +46 -0
- package/scripts/db/fix-schema.mjs +38 -0
- package/scripts/db/init-db.mjs +13 -0
- package/scripts/db/recreate-db.mjs +14 -0
- package/scripts/generate-mcp.mjs +264 -0
- package/scripts/github-release.sh +61 -0
- package/scripts/init-dirs.mjs +13 -0
- package/scripts/init-dirs.ts +15 -0
- package/scripts/install-mcp.mjs +116 -0
- package/scripts/install-web.sh +120 -0
- package/scripts/install.mjs +340 -0
- package/scripts/openclaw-bootstrap.mjs +127 -0
- package/scripts/package-release.sh +71 -0
- package/scripts/remote-preflight.mjs +62 -0
- package/scripts/squish-fallback.mjs +132 -0
- package/scripts/test/test-all-systems.mjs +139 -0
- package/scripts/test/test-memory-system.mjs +139 -0
- package/scripts/test/test-v0.5.0.mjs +210 -0
- package/scripts/verify-mcp.mjs +214 -0
- package/skills/memory-guide/SKILL.md +181 -123
- package/skills/squish-cli/SKILL.md +200 -0
- package/skills/squish-mcp/SKILL.md +311 -0
- package/skills/squish-memory/SKILL.md +100 -62
- package/skills/squish-memory/claude-desktop.json +12 -0
- package/skills/squish-memory/install.mjs +335 -0
- package/skills/squish-memory/install.sh +94 -62
- package/skills/squish-memory/openclaw.json +13 -0
- package/skills/squish-memory/opencode.json +14 -0
- package/skills/squish-memory/skill.json +32 -0
- package/dist/adapters/claude-code/capture.d.ts +0 -11
- package/dist/adapters/claude-code/capture.d.ts.map +0 -1
- package/dist/adapters/claude-code/capture.js +0 -100
- package/dist/adapters/claude-code/capture.js.map +0 -1
- package/dist/adapters/claude-code/index.d.ts +0 -5
- package/dist/adapters/claude-code/index.d.ts.map +0 -1
- package/dist/adapters/claude-code/index.js +0 -6
- package/dist/adapters/claude-code/index.js.map +0 -1
- package/dist/adapters/claude-code/injection.d.ts +0 -34
- package/dist/adapters/claude-code/injection.d.ts.map +0 -1
- package/dist/adapters/claude-code/injection.js +0 -127
- package/dist/adapters/claude-code/injection.js.map +0 -1
- package/dist/adapters/claude-code/plugin-wrapper.d.ts +0 -21
- package/dist/adapters/claude-code/plugin-wrapper.d.ts.map +0 -1
- package/dist/adapters/claude-code/plugin-wrapper.js +0 -239
- package/dist/adapters/claude-code/plugin-wrapper.js.map +0 -1
- package/dist/adapters/claude-code/types.d.ts +0 -46
- package/dist/adapters/claude-code/types.d.ts.map +0 -1
- package/dist/adapters/claude-code/types.js +0 -6
- 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
|