patchcord 0.3.40 → 0.3.42
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/bin/patchcord.mjs +69 -27
- package/package.json +1 -1
package/bin/patchcord.mjs
CHANGED
|
@@ -4,6 +4,9 @@ import { existsSync, mkdirSync, cpSync } from "fs";
|
|
|
4
4
|
import { join, dirname } from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import { execSync } from "child_process";
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
|
|
9
|
+
const HOME = homedir();
|
|
7
10
|
|
|
8
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
12
|
const pluginRoot = join(__dirname, "..");
|
|
@@ -71,7 +74,7 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
71
74
|
globalChanges.push("Claude Code plugin installed");
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
const claudeSettings = join(
|
|
77
|
+
const claudeSettings = join(HOME, ".claude", "settings.json");
|
|
75
78
|
if (existsSync(claudeSettings)) {
|
|
76
79
|
try {
|
|
77
80
|
const settings = JSON.parse(readFileSync(claudeSettings, "utf-8"));
|
|
@@ -109,7 +112,7 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
109
112
|
}
|
|
110
113
|
|
|
111
114
|
// Cursor
|
|
112
|
-
const cursorSkillsRoot = join(
|
|
115
|
+
const cursorSkillsRoot = join(HOME, ".cursor", "skills-cursor");
|
|
113
116
|
if (existsSync(cursorSkillsRoot)) {
|
|
114
117
|
const cursorSkillDir = join(cursorSkillsRoot, "patchcord");
|
|
115
118
|
const cursorWaitDir = join(cursorSkillsRoot, "patchcord-wait");
|
|
@@ -128,9 +131,9 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
// Windsurf
|
|
131
|
-
if (existsSync(join(
|
|
132
|
-
const windsurfSkillDir = join(
|
|
133
|
-
const windsurfWaitDir = join(
|
|
134
|
+
if (existsSync(join(HOME, ".codeium", "windsurf"))) {
|
|
135
|
+
const windsurfSkillDir = join(HOME, ".codeium", "windsurf", "skills", "patchcord");
|
|
136
|
+
const windsurfWaitDir = join(HOME, ".codeium", "windsurf", "skills", "patchcord-wait");
|
|
134
137
|
let windsurfChanged = false;
|
|
135
138
|
if (!existsSync(windsurfSkillDir)) {
|
|
136
139
|
mkdirSync(windsurfSkillDir, { recursive: true });
|
|
@@ -146,10 +149,10 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
146
149
|
}
|
|
147
150
|
|
|
148
151
|
// Gemini CLI
|
|
149
|
-
if (existsSync(join(
|
|
150
|
-
const geminiSkillDir = join(
|
|
151
|
-
const geminiWaitDir = join(
|
|
152
|
-
const geminiCmdDir = join(
|
|
152
|
+
if (existsSync(join(HOME, ".gemini"))) {
|
|
153
|
+
const geminiSkillDir = join(HOME, ".gemini", "skills", "patchcord");
|
|
154
|
+
const geminiWaitDir = join(HOME, ".gemini", "skills", "patchcord-wait");
|
|
155
|
+
const geminiCmdDir = join(HOME, ".gemini", "commands");
|
|
153
156
|
let geminiChanged = false;
|
|
154
157
|
if (!existsSync(geminiSkillDir)) {
|
|
155
158
|
mkdirSync(geminiSkillDir, { recursive: true });
|
|
@@ -171,7 +174,7 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
171
174
|
}
|
|
172
175
|
|
|
173
176
|
// Codex CLI
|
|
174
|
-
const codexConfig = join(
|
|
177
|
+
const codexConfig = join(HOME, ".codex", "config.toml");
|
|
175
178
|
if (existsSync(codexConfig)) {
|
|
176
179
|
const content = readFileSync(codexConfig, "utf-8");
|
|
177
180
|
if (!content.includes("[apps.patchcord]")) {
|
|
@@ -207,17 +210,19 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
207
210
|
console.log(` ${cyan}4.${r} Windsurf`);
|
|
208
211
|
console.log(` ${cyan}5.${r} Gemini CLI`);
|
|
209
212
|
console.log(` ${cyan}6.${r} VS Code (Copilot)`);
|
|
210
|
-
console.log(` ${cyan}7.${r} Zed
|
|
213
|
+
console.log(` ${cyan}7.${r} Zed`);
|
|
214
|
+
console.log(` ${cyan}8.${r} OpenCode\n`);
|
|
211
215
|
|
|
212
|
-
const choice = (await ask(`${dim}Choose (1-
|
|
216
|
+
const choice = (await ask(`${dim}Choose (1-8):${r} `)).trim();
|
|
213
217
|
const isCodex = choice === "2";
|
|
214
218
|
const isCursor = choice === "3";
|
|
215
219
|
const isWindsurf = choice === "4";
|
|
216
220
|
const isGemini = choice === "5";
|
|
217
221
|
const isVSCode = choice === "6";
|
|
218
222
|
const isZed = choice === "7";
|
|
223
|
+
const isOpenCode = choice === "8";
|
|
219
224
|
|
|
220
|
-
if (!["1", "2", "3", "4", "5", "6", "7"].includes(choice)) {
|
|
225
|
+
if (!["1", "2", "3", "4", "5", "6", "7", "8"].includes(choice)) {
|
|
221
226
|
console.error("Invalid choice.");
|
|
222
227
|
rl.close();
|
|
223
228
|
process.exit(1);
|
|
@@ -273,7 +278,7 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
273
278
|
} catch {}
|
|
274
279
|
}
|
|
275
280
|
// Warn about global config conflict
|
|
276
|
-
const globalCursor = join(
|
|
281
|
+
const globalCursor = join(HOME, ".cursor", "mcp.json");
|
|
277
282
|
if (existsSync(globalCursor)) {
|
|
278
283
|
try {
|
|
279
284
|
const global = JSON.parse(readFileSync(globalCursor, "utf-8"));
|
|
@@ -286,7 +291,7 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
286
291
|
} catch {}
|
|
287
292
|
}
|
|
288
293
|
} else if (isWindsurf) {
|
|
289
|
-
const wsPath = join(
|
|
294
|
+
const wsPath = join(HOME, ".codeium", "windsurf", "mcp_config.json");
|
|
290
295
|
if (existsSync(wsPath)) {
|
|
291
296
|
try {
|
|
292
297
|
const content = readFileSync(wsPath, "utf-8").trim();
|
|
@@ -304,7 +309,7 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
304
309
|
} catch {}
|
|
305
310
|
}
|
|
306
311
|
} else if (isGemini) {
|
|
307
|
-
const geminiPath = join(
|
|
312
|
+
const geminiPath = join(HOME, ".gemini", "settings.json");
|
|
308
313
|
if (existsSync(geminiPath)) {
|
|
309
314
|
try {
|
|
310
315
|
const existing = JSON.parse(readFileSync(geminiPath, "utf-8"));
|
|
@@ -339,8 +344,8 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
339
344
|
}
|
|
340
345
|
} else if (isZed) {
|
|
341
346
|
const zedPath = process.platform === "darwin"
|
|
342
|
-
? join(
|
|
343
|
-
: join(
|
|
347
|
+
? join(HOME, "Library", "Application Support", "Zed", "settings.json")
|
|
348
|
+
: join(HOME, ".config", "zed", "settings.json");
|
|
344
349
|
if (existsSync(zedPath)) {
|
|
345
350
|
try {
|
|
346
351
|
const existing = JSON.parse(readFileSync(zedPath, "utf-8"));
|
|
@@ -356,6 +361,23 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
356
361
|
}
|
|
357
362
|
} catch {}
|
|
358
363
|
}
|
|
364
|
+
} else if (isOpenCode) {
|
|
365
|
+
const ocPath = join(cwd, "opencode.json");
|
|
366
|
+
if (existsSync(ocPath)) {
|
|
367
|
+
try {
|
|
368
|
+
const existing = JSON.parse(readFileSync(ocPath, "utf-8"));
|
|
369
|
+
if (existing.mcp?.patchcord) {
|
|
370
|
+
console.log(`\n ${yellow}⚠ OpenCode already configured in this project${r}`);
|
|
371
|
+
console.log(` ${dim}${ocPath}${r}`);
|
|
372
|
+
const replace = (await ask(` ${dim}Replace? (y/N):${r} `)).trim().toLowerCase();
|
|
373
|
+
if (replace !== "y" && replace !== "yes") {
|
|
374
|
+
console.log("Keeping existing config.");
|
|
375
|
+
rl.close();
|
|
376
|
+
process.exit(0);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
} catch {}
|
|
380
|
+
}
|
|
359
381
|
} else if (isCodex) {
|
|
360
382
|
const configPath = join(cwd, ".codex", "config.toml");
|
|
361
383
|
if (existsSync(configPath)) {
|
|
@@ -468,7 +490,7 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
468
490
|
console.log(` ${dim}Per-project only — other projects won't see this agent.${r}`);
|
|
469
491
|
} else if (isWindsurf) {
|
|
470
492
|
// Windsurf: global only (~/.codeium/windsurf/mcp_config.json)
|
|
471
|
-
const wsPath = join(
|
|
493
|
+
const wsPath = join(HOME, ".codeium", "windsurf", "mcp_config.json");
|
|
472
494
|
const wsConfig = {
|
|
473
495
|
mcpServers: {
|
|
474
496
|
patchcord: {
|
|
@@ -496,7 +518,7 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
496
518
|
writeFileSync(wsPath, JSON.stringify(wsConfig, null, 2) + "\n");
|
|
497
519
|
}
|
|
498
520
|
} else {
|
|
499
|
-
mkdirSync(join(
|
|
521
|
+
mkdirSync(join(HOME, ".codeium", "windsurf"), { recursive: true });
|
|
500
522
|
writeFileSync(wsPath, JSON.stringify(wsConfig, null, 2) + "\n");
|
|
501
523
|
}
|
|
502
524
|
// Install workflows as slash commands (.windsurf/workflows/) — per-project
|
|
@@ -509,7 +531,7 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
509
531
|
console.log(` ${yellow}MCP config is global — all Windsurf projects share this agent.${r}`);
|
|
510
532
|
} else if (isGemini) {
|
|
511
533
|
// Gemini CLI: global only (~/.gemini/settings.json)
|
|
512
|
-
const geminiPath = join(
|
|
534
|
+
const geminiPath = join(HOME, ".gemini", "settings.json");
|
|
513
535
|
let geminiSettings = {};
|
|
514
536
|
if (existsSync(geminiPath)) {
|
|
515
537
|
try {
|
|
@@ -529,15 +551,15 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
529
551
|
geminiSettings.tools.allowed = geminiSettings.tools.allowed.filter(t => !t.startsWith("mcp_patchcord_"));
|
|
530
552
|
if (geminiSettings.tools.allowed.length === 0) delete geminiSettings.tools;
|
|
531
553
|
}
|
|
532
|
-
mkdirSync(join(
|
|
554
|
+
mkdirSync(join(HOME, ".gemini"), { recursive: true });
|
|
533
555
|
writeFileSync(geminiPath, JSON.stringify(geminiSettings, null, 2) + "\n");
|
|
534
556
|
console.log(`\n ${green}✓${r} Gemini CLI configured: ${dim}${geminiPath}${r}`);
|
|
535
557
|
console.log(` ${yellow}Global config — all Gemini CLI projects share this agent.${r}`);
|
|
536
558
|
} else if (isZed) {
|
|
537
559
|
// Zed: global settings.json → context_servers
|
|
538
560
|
const zedPath = process.platform === "darwin"
|
|
539
|
-
? join(
|
|
540
|
-
: join(
|
|
561
|
+
? join(HOME, "Library", "Application Support", "Zed", "settings.json")
|
|
562
|
+
: join(HOME, ".config", "zed", "settings.json");
|
|
541
563
|
let zedSettings = {};
|
|
542
564
|
if (existsSync(zedPath)) {
|
|
543
565
|
try {
|
|
@@ -553,12 +575,32 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
553
575
|
},
|
|
554
576
|
};
|
|
555
577
|
const zedDir = process.platform === "darwin"
|
|
556
|
-
? join(
|
|
557
|
-
: join(
|
|
578
|
+
? join(HOME, "Library", "Application Support", "Zed")
|
|
579
|
+
: join(HOME, ".config", "zed");
|
|
558
580
|
mkdirSync(zedDir, { recursive: true });
|
|
559
581
|
writeFileSync(zedPath, JSON.stringify(zedSettings, null, 2) + "\n");
|
|
560
582
|
console.log(`\n ${green}✓${r} Zed configured: ${dim}${zedPath}${r}`);
|
|
561
583
|
console.log(` ${yellow}Global config — all Zed projects share this agent.${r}`);
|
|
584
|
+
} else if (isOpenCode) {
|
|
585
|
+
// OpenCode: per-project opencode.json → mcp
|
|
586
|
+
const ocPath = join(cwd, "opencode.json");
|
|
587
|
+
let ocConfig = {};
|
|
588
|
+
if (existsSync(ocPath)) {
|
|
589
|
+
try {
|
|
590
|
+
ocConfig = JSON.parse(readFileSync(ocPath, "utf-8"));
|
|
591
|
+
} catch {}
|
|
592
|
+
}
|
|
593
|
+
if (!ocConfig.mcp) ocConfig.mcp = {};
|
|
594
|
+
ocConfig.mcp.patchcord = {
|
|
595
|
+
type: "remote",
|
|
596
|
+
url: `${serverUrl}/mcp`,
|
|
597
|
+
headers: {
|
|
598
|
+
Authorization: `Bearer ${token}`,
|
|
599
|
+
"X-Patchcord-Machine": hostname,
|
|
600
|
+
},
|
|
601
|
+
};
|
|
602
|
+
writeFileSync(ocPath, JSON.stringify(ocConfig, null, 2) + "\n");
|
|
603
|
+
console.log(`\n ${green}✓${r} OpenCode configured: ${dim}${ocPath}${r}`);
|
|
562
604
|
} else if (isVSCode) {
|
|
563
605
|
// VS Code: write .vscode/mcp.json (per-project)
|
|
564
606
|
const vscodeDir = join(cwd, ".vscode");
|
|
@@ -654,7 +696,7 @@ if (!cmd || cmd === "install" || cmd === "agent") {
|
|
|
654
696
|
console.log(`\n ${green}✓${r} Claude Code configured: ${dim}${mcpPath}${r}`);
|
|
655
697
|
}
|
|
656
698
|
|
|
657
|
-
const toolName = isZed ? "Zed" : isVSCode ? "VS Code" : isGemini ? "Gemini CLI" : isWindsurf ? "Windsurf" : isCursor ? "Cursor" : isCodex ? "Codex" : "Claude Code";
|
|
699
|
+
const toolName = isOpenCode ? "OpenCode" : isZed ? "Zed" : isVSCode ? "VS Code" : isGemini ? "Gemini CLI" : isWindsurf ? "Windsurf" : isCursor ? "Cursor" : isCodex ? "Codex" : "Claude Code";
|
|
658
700
|
console.log(`\n${dim}Restart your ${toolName} session, then run:${r} ${bold}inbox()${r}`);
|
|
659
701
|
process.exit(0);
|
|
660
702
|
}
|