claude-crap 0.3.3 → 0.3.4
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/CHANGELOG.md +20 -0
- package/README.md +1 -1
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +52 -3
- package/dist/dashboard/server.js.map +1 -1
- package/package.json +6 -2
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.mcp.json +1 -1
- package/plugin/bundle/launcher.mjs +112 -0
- package/plugin/bundle/mcp-server.mjs +40 -3
- package/plugin/bundle/mcp-server.mjs.map +2 -2
- package/plugin/eslint.config.mjs +15 -0
- package/plugin/launcher.mjs +112 -0
- package/plugin/package-lock.json +2714 -0
- package/plugin/package.json +5 -1
- package/scripts/bundle-plugin.mjs +30 -0
- package/src/dashboard/server.ts +68 -3
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-check
|
|
3
|
+
/**
|
|
4
|
+
* claude-crap :: MCP server launcher — zero-dependency bootstrap wrapper.
|
|
5
|
+
*
|
|
6
|
+
* This file is the actual entry point declared in `.mcp.json`. It
|
|
7
|
+
* ensures the MCP server's runtime dependencies (fastify, pino,
|
|
8
|
+
* tree-sitter, etc.) are installed before the server's static ESM
|
|
9
|
+
* `import` statements fire. Without this guard, a clean install from
|
|
10
|
+
* git would fail with ERR_MODULE_NOT_FOUND because `node_modules/`
|
|
11
|
+
* is not committed to the repository.
|
|
12
|
+
*
|
|
13
|
+
* Design constraints:
|
|
14
|
+
*
|
|
15
|
+
* - ZERO external dependencies — only Node.js builtins.
|
|
16
|
+
* - Synchronous check + install so the control flow is linear.
|
|
17
|
+
* - All output goes to stderr (fd 2) to preserve the MCP JSON-RPC
|
|
18
|
+
* channel on stdout.
|
|
19
|
+
* - Must work on macOS, Linux, and Windows.
|
|
20
|
+
*
|
|
21
|
+
* After dependencies are guaranteed to exist, this module dynamically
|
|
22
|
+
* imports `./mcp-server.mjs` which handles the rest of the startup.
|
|
23
|
+
*
|
|
24
|
+
* @module launcher
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
28
|
+
import { execFileSync } from "node:child_process";
|
|
29
|
+
import { dirname, join, resolve } from "node:path";
|
|
30
|
+
import { fileURLToPath } from "node:url";
|
|
31
|
+
|
|
32
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The plugin root is one level above `bundle/`. This is where
|
|
36
|
+
* `package.json` lives and where `npm install` must run.
|
|
37
|
+
*
|
|
38
|
+
* In the deployed layout:
|
|
39
|
+
* ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/
|
|
40
|
+
* ├── package.json ← PLUGIN_ROOT
|
|
41
|
+
* ├── node_modules/ ← created by ensureDependencies()
|
|
42
|
+
* └── bundle/
|
|
43
|
+
* ├── launcher.mjs ← this file
|
|
44
|
+
* └── mcp-server.mjs ← the real entry point
|
|
45
|
+
*/
|
|
46
|
+
const PLUGIN_ROOT = resolve(__dirname, "..");
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check whether all runtime dependencies are installed. When they are
|
|
50
|
+
* not, run `npm install --omit=dev` synchronously and verify success.
|
|
51
|
+
*
|
|
52
|
+
* The check is deliberately simple: if the `node_modules/` directory
|
|
53
|
+
* exists we assume all packages are present. A more thorough check
|
|
54
|
+
* would resolve every external, but the cost of a false-positive skip
|
|
55
|
+
* is a cryptic ERR_MODULE_NOT_FOUND — vs. a ~5s npm install on first
|
|
56
|
+
* run. Speed wins.
|
|
57
|
+
*/
|
|
58
|
+
function ensureDependencies() {
|
|
59
|
+
const nodeModulesPath = join(PLUGIN_ROOT, "node_modules");
|
|
60
|
+
if (existsSync(nodeModulesPath)) return; // fast path — already installed
|
|
61
|
+
|
|
62
|
+
// ── Report what we're about to install ────────────────────────────
|
|
63
|
+
let depsSummary = "(unable to read package.json)";
|
|
64
|
+
try {
|
|
65
|
+
const pkgPath = join(PLUGIN_ROOT, "package.json");
|
|
66
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
67
|
+
const deps = Object.entries(pkg.dependencies || {});
|
|
68
|
+
depsSummary = deps.map(([n, v]) => `${n}@${v}`).join(", ");
|
|
69
|
+
} catch {
|
|
70
|
+
/* proceed anyway — the install itself will surface any real error */
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
process.stderr.write(
|
|
74
|
+
`[claude-crap] node_modules/ not found — installing runtime dependencies...\n` +
|
|
75
|
+
`[claude-crap] deps: ${depsSummary}\n`,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// ── Run npm install synchronously ─────────────────────────────────
|
|
79
|
+
try {
|
|
80
|
+
execFileSync("npm", [
|
|
81
|
+
"install",
|
|
82
|
+
"--omit=dev",
|
|
83
|
+
"--no-audit",
|
|
84
|
+
"--no-fund",
|
|
85
|
+
"--no-progress",
|
|
86
|
+
"--loglevel=error",
|
|
87
|
+
], {
|
|
88
|
+
cwd: PLUGIN_ROOT,
|
|
89
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
90
|
+
timeout: 120_000, // 2 minutes — generous for slow networks
|
|
91
|
+
env: { ...process.env, NODE_ENV: "production" },
|
|
92
|
+
});
|
|
93
|
+
process.stderr.write("[claude-crap] dependencies installed successfully.\n");
|
|
94
|
+
} catch (err) {
|
|
95
|
+
const stderr = /** @type {any} */ (err).stderr?.toString?.() ?? "";
|
|
96
|
+
const lastLines = stderr.split("\n").filter(Boolean).slice(-20).join("\n");
|
|
97
|
+
process.stderr.write(
|
|
98
|
+
`[claude-crap] FATAL: npm install failed (exit ${/** @type {any} */ (err).status ?? "unknown"}).\n` +
|
|
99
|
+
(lastLines ? `${lastLines}\n` : "") +
|
|
100
|
+
`[claude-crap] Try manually: cd "${PLUGIN_ROOT}" && npm install --omit=dev\n`,
|
|
101
|
+
);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ── Bootstrap ─────────────────────────────────────────────────────────
|
|
107
|
+
ensureDependencies();
|
|
108
|
+
|
|
109
|
+
// Now that node_modules/ exists, the static ESM imports inside
|
|
110
|
+
// mcp-server.mjs can resolve. Dynamic import avoids top-level
|
|
111
|
+
// resolution failures.
|
|
112
|
+
await import("./mcp-server.mjs");
|