patchcord 0.5.10 → 0.5.12
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/plugin.json +1 -1
- package/bin/patchcord.mjs +41 -50
- package/package.json +1 -1
package/bin/patchcord.mjs
CHANGED
|
@@ -122,45 +122,10 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
|
|
|
122
122
|
try { rmSync(npmCachePatchcord, { recursive: true, force: true }); } catch {}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
// Stable plugin location: copy plugin files out of the bunx/npx temp
|
|
126
|
-
// dir into a path under HOME that won't get reused across npx
|
|
127
|
-
// invocations. Without this, `claude plugin marketplace add` points at
|
|
128
|
-
// /tmp/bunx-1000-patchcord@latest/... which bunx aggressively caches
|
|
129
|
-
// and may not re-download for "@latest" — so the marketplace can stay
|
|
130
|
-
// pinned to a stale tarball, and `claude plugin update` resolves the
|
|
131
|
-
// wrong (sometimes very old) version.
|
|
132
|
-
let marketplaceSource = pluginRoot;
|
|
133
|
-
try {
|
|
134
|
-
const stableDir = join(HOME, ".patchcord", "plugin");
|
|
135
|
-
if (existsSync(stableDir)) {
|
|
136
|
-
rmSync(stableDir, { recursive: true, force: true });
|
|
137
|
-
}
|
|
138
|
-
mkdirSync(stableDir, { recursive: true });
|
|
139
|
-
cpSync(pluginRoot, stableDir, { recursive: true });
|
|
140
|
-
marketplaceSource = stableDir;
|
|
141
|
-
|
|
142
|
-
// Some Claude Code versions silently keep the existing source path
|
|
143
|
-
// on re-add for a marketplace name that's already registered. Wipe
|
|
144
|
-
// any old patchcord-marketplace entry so the next `marketplace add`
|
|
145
|
-
// is forced to write the new stable path.
|
|
146
|
-
const kmpPath = join(HOME, ".claude", "plugins", "known_marketplaces.json");
|
|
147
|
-
if (existsSync(kmpPath)) {
|
|
148
|
-
try {
|
|
149
|
-
const kmp = JSON.parse(readFileSync(kmpPath, "utf-8"));
|
|
150
|
-
if (kmp["patchcord-marketplace"]) {
|
|
151
|
-
delete kmp["patchcord-marketplace"];
|
|
152
|
-
writeFileSync(kmpPath, JSON.stringify(kmp, null, 2) + "\n");
|
|
153
|
-
}
|
|
154
|
-
} catch {}
|
|
155
|
-
}
|
|
156
|
-
} catch (e) {
|
|
157
|
-
globalChanges.push(`✗ Stable plugin path setup failed (${e.message}), falling back to bunx temp dir`);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
125
|
// Always re-add marketplace (copies fresh files from this npx package)
|
|
161
126
|
// and install/update plugin. Claude Code's built-in plugin update
|
|
162
127
|
// doesn't detect new versions from local sources (#37252).
|
|
163
|
-
run(`claude plugin marketplace add "${
|
|
128
|
+
run(`claude plugin marketplace add "${pluginRoot}"`);
|
|
164
129
|
const installed = run(`claude plugin list`)?.includes("patchcord");
|
|
165
130
|
wasPluginInstalled = !!installed;
|
|
166
131
|
if (installed) {
|
|
@@ -335,23 +300,45 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
|
|
|
335
300
|
apiUrl = serverUrl;
|
|
336
301
|
}
|
|
337
302
|
|
|
303
|
+
// --tool=<slug> — pre-select client type. The dashboard's
|
|
304
|
+
// /console/connect/<platform> tile pages emit `--tool=<slug>` in the
|
|
305
|
+
// displayed npx command so the user picks the agent type ONCE on the
|
|
306
|
+
// web UI; the installer skips its terminal picker, and the
|
|
307
|
+
// `&tool=<slug>` query param appended to the browser connectUrl below
|
|
308
|
+
// makes the web /connect page skip its picker too.
|
|
309
|
+
// Unknown slugs (incl. `replit`, `unknown`) silently fall through —
|
|
310
|
+
// the existing interactive flow takes over.
|
|
311
|
+
const toolFlag = flags.find(f => f.startsWith("--tool="))?.split("=")[1]
|
|
312
|
+
|| (flags.includes("--tool") ? flags[flags.indexOf("--tool") + 1] : "");
|
|
313
|
+
let toolSlug = "";
|
|
314
|
+
if (toolFlag) {
|
|
315
|
+
const normalized = toolFlag.replace(/-/g, "_");
|
|
316
|
+
if (CLIENT_TYPE_MAP[normalized]) {
|
|
317
|
+
choice = CLIENT_TYPE_MAP[normalized];
|
|
318
|
+
}
|
|
319
|
+
toolSlug = toolFlag; // preserved as-is for the URL param
|
|
320
|
+
}
|
|
321
|
+
|
|
338
322
|
// --token bypass for power users / CI / self-hosters
|
|
339
323
|
const tokenFlag = flags.find(f => f.startsWith("--token="))?.split("=")[1]
|
|
340
324
|
|| (flags.includes("--token") ? flags[flags.indexOf("--token") + 1] : "");
|
|
341
325
|
|
|
342
326
|
if (tokenFlag) {
|
|
343
|
-
// --token bypass: need tool picker in terminal
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
327
|
+
// --token bypass: need tool picker in terminal — unless --tool=<slug>
|
|
328
|
+
// already pre-selected one for us.
|
|
329
|
+
if (!choice) {
|
|
330
|
+
console.log(`\n${bold}Which tool are you setting up?${r}\n`);
|
|
331
|
+
console.log(` ${cyan}1.${r} Claude Code ${cyan}5.${r} Gemini CLI`);
|
|
332
|
+
console.log(` ${cyan}2.${r} Codex CLI ${cyan}6.${r} VS Code`);
|
|
333
|
+
console.log(` ${cyan}3.${r} Cursor ${cyan}7.${r} Zed`);
|
|
334
|
+
console.log(` ${cyan}4.${r} Windsurf ${cyan}8.${r} OpenCode`);
|
|
335
|
+
console.log(` ${cyan}11.${r} Cline ${cyan}9.${r} OpenClaw\n`);
|
|
336
|
+
choice = (await ask(`${dim}Choose (1-9, 11):${r} `)).trim();
|
|
337
|
+
if (!["1","2","3","4","5","6","7","8","9","11"].includes(choice)) {
|
|
338
|
+
console.error("Invalid choice.");
|
|
339
|
+
rl.close();
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
355
342
|
}
|
|
356
343
|
token = tokenFlag.trim();
|
|
357
344
|
if (!isSafeToken(token)) {
|
|
@@ -516,8 +503,12 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
|
|
|
516
503
|
process.exit(1);
|
|
517
504
|
}
|
|
518
505
|
} else {
|
|
519
|
-
// Open browser or show URL
|
|
520
|
-
|
|
506
|
+
// Open browser or show URL.
|
|
507
|
+
// Append &tool=<slug> when --tool was passed so the web /connect
|
|
508
|
+
// page skips its type picker (the user already chose on the
|
|
509
|
+
// dashboard tile).
|
|
510
|
+
const toolParam = toolSlug ? `&tool=${encodeURIComponent(toolSlug)}` : "";
|
|
511
|
+
const connectUrl = `https://patchcord.dev/connect?session=${sessionId}${toolParam}`;
|
|
521
512
|
|
|
522
513
|
if (canOpenBrowser()) {
|
|
523
514
|
const opened = openBrowser(connectUrl);
|