crukx-mcp 0.1.3 → 0.1.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/README.md CHANGED
@@ -21,9 +21,19 @@ crukx login
21
21
  # Opens crukx.dev in your browser — sign in and return to terminal
22
22
  ```
23
23
 
24
+ ## Add to your editor
25
+
26
+ ```bash
27
+ crukx install
28
+ # Auto-detects VS Code, Cursor, Claude Desktop, Kiro, opencode
29
+ # and configures them all in one step
30
+ ```
31
+
32
+ Restart your editor. Done — your AI agent can now use Crukx tools.
33
+
24
34
  ---
25
35
 
26
- ## Setup by client
36
+ ## Manual setup (if needed)
27
37
 
28
38
  ### VS Code + GitHub Copilot
29
39
 
package/dist/bin/cli.js CHANGED
@@ -59,7 +59,7 @@ import { fileURLToPath } from "url";
59
59
  import { join as join2, dirname as pathDirname } from "path";
60
60
  var __dirname = pathDirname(fileURLToPath(import.meta.url));
61
61
  var program = new Command();
62
- program.name("crukx").description("Crukx CLI \u2014 reliability control plane for autonomous software engineering").version("0.1.3");
62
+ program.name("crukx").description("Crukx CLI \u2014 reliability control plane for autonomous software engineering").version("0.1.4");
63
63
  program.command("login").description("Authenticate with Crukx via browser").option("--api-url <url>", "Crukx gateway URL", getConfig().CRUKX_API_URL).action(async (opts) => {
64
64
  process.stderr.write("Opening browser to complete login\u2026\n");
65
65
  let startData;
@@ -137,6 +137,103 @@ Expires: ${auth.expires_at}
137
137
  API: ${auth.api_url}
138
138
  `);
139
139
  });
140
+ program.command("install").description("Auto-install Crukx into all detected MCP-compatible clients").option("--dry-run", "Show what would be changed without writing").action(async (opts) => {
141
+ const { existsSync: existsSync3, readFileSync: readFileSync3, writeFileSync: writeFileSync2 } = await import("fs");
142
+ const { homedir: homedir2 } = await import("os");
143
+ const home = homedir2();
144
+ const SERVER_ENTRY = { command: "crukx", args: ["mcp"] };
145
+ function injectMcpServers(raw, key) {
146
+ const cfg = raw ? JSON.parse(raw) : {};
147
+ cfg.mcpServers = { ...cfg.mcpServers ?? {}, [key]: SERVER_ENTRY };
148
+ return JSON.stringify(cfg, null, 2);
149
+ }
150
+ const clients = [
151
+ {
152
+ name: "VS Code (GitHub Copilot)",
153
+ configPath: join2(home, ".vscode", "mcp.json"),
154
+ detect: () => existsSync3(join2(home, ".vscode")) || existsSync3("/usr/share/code") || existsSync3("/Applications/Visual Studio Code.app"),
155
+ inject: (raw) => {
156
+ const cfg = raw ? JSON.parse(raw) : {};
157
+ cfg.servers = { ...cfg.servers ?? {}, crukx: { type: "stdio", ...SERVER_ENTRY } };
158
+ return JSON.stringify(cfg, null, 2);
159
+ }
160
+ },
161
+ {
162
+ name: "Cursor",
163
+ configPath: join2(home, ".cursor", "mcp.json"),
164
+ detect: () => existsSync3(join2(home, ".cursor")) || existsSync3("/Applications/Cursor.app"),
165
+ inject: (raw) => injectMcpServers(raw, "crukx")
166
+ },
167
+ {
168
+ name: "Claude Desktop",
169
+ configPath: process.platform === "darwin" ? join2(home, "Library", "Application Support", "Claude", "claude_desktop_config.json") : join2(home, "AppData", "Roaming", "Claude", "claude_desktop_config.json"),
170
+ detect: () => existsSync3("/Applications/Claude.app") || existsSync3(join2(home, "Library", "Application Support", "Claude")) || existsSync3(join2(home, "AppData", "Local", "AnthropicClaude")),
171
+ inject: (raw) => injectMcpServers(raw, "crukx")
172
+ },
173
+ {
174
+ name: "Kiro",
175
+ configPath: join2(home, ".kiro", "settings", "mcp.json"),
176
+ detect: () => existsSync3(join2(home, ".kiro")),
177
+ inject: (raw) => injectMcpServers(raw, "crukx")
178
+ },
179
+ {
180
+ name: "opencode",
181
+ configPath: join2(home, ".config", "opencode", "config.json"),
182
+ detect: () => existsSync3(join2(home, ".config", "opencode")),
183
+ inject: (raw) => {
184
+ const cfg = raw ? JSON.parse(raw) : {};
185
+ cfg.mcp = { ...cfg.mcp ?? {}, crukx: { ...SERVER_ENTRY, type: "local" } };
186
+ return JSON.stringify(cfg, null, 2);
187
+ }
188
+ }
189
+ ];
190
+ const detected = clients.filter((c) => c.detect());
191
+ if (detected.length === 0) {
192
+ process.stdout.write(
193
+ "No supported MCP clients detected.\n\nSupported: VS Code, Cursor, Claude Desktop, Kiro, opencode\n\nManual setup: https://crukx.dev/docs/mcp\n"
194
+ );
195
+ return;
196
+ }
197
+ process.stdout.write(`Found ${detected.length} client${detected.length > 1 ? "s" : ""}:
198
+
199
+ `);
200
+ let installed = 0;
201
+ for (const client of detected) {
202
+ const raw = existsSync3(client.configPath) ? readFileSync3(client.configPath, "utf-8") : null;
203
+ try {
204
+ const parsed = raw ? JSON.parse(raw) : {};
205
+ if (parsed?.mcpServers?.crukx || parsed?.servers?.crukx || parsed?.mcp?.crukx) {
206
+ process.stdout.write(` \u2705 ${client.name} \u2014 already configured
207
+ `);
208
+ continue;
209
+ }
210
+ } catch {
211
+ }
212
+ const newContent = client.inject(raw);
213
+ if (opts.dryRun) {
214
+ process.stdout.write(` \u{1F4DD} ${client.name} \u2014 would write: ${client.configPath}
215
+ `);
216
+ } else {
217
+ mkdirSync2(dirname2(client.configPath), { recursive: true });
218
+ writeFileSync2(client.configPath, newContent, "utf-8");
219
+ process.stdout.write(` \u2705 ${client.name} \u2014 configured
220
+ `);
221
+ installed++;
222
+ }
223
+ }
224
+ process.stdout.write("\n");
225
+ if (opts.dryRun) {
226
+ process.stdout.write("Dry run complete. Remove --dry-run to apply.\n");
227
+ } else if (installed > 0) {
228
+ process.stdout.write(
229
+ `Installed in ${installed} client${installed > 1 ? "s" : ""}. Restart your editor, then ask:
230
+ "Run a Crukx audit on this file"
231
+ `
232
+ );
233
+ } else {
234
+ process.stdout.write("All clients already configured.\n");
235
+ }
236
+ });
140
237
  program.command("mcp").description("Start the Crukx MCP server (stdio transport)").action(() => {
141
238
  const serverPath = join2(__dirname, "server.js");
142
239
  const child = spawn(process.execPath, [serverPath], {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crukx-mcp",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Crukx MCP server — reliability control plane for autonomous software engineering",
5
5
  "type": "module",
6
6
  "main": "./dist/server.js",