set-prompt 0.2.1 → 0.4.0
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 +40 -0
- package/README.md +81 -49
- package/dist/index.js +712 -199
- package/package.json +5 -6
- package/dist/bin/set-prompt.js +0 -2
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Command } from "commander";
|
|
|
5
5
|
import chalk8 from "chalk";
|
|
6
6
|
import figlet from "figlet";
|
|
7
7
|
import fs6 from "fs";
|
|
8
|
-
import
|
|
8
|
+
import path5 from "path";
|
|
9
9
|
import { fileURLToPath } from "url";
|
|
10
10
|
|
|
11
11
|
// src/commands/install-command.ts
|
|
@@ -27,20 +27,28 @@ var ROO_DIR = path.join(os.homedir(), ".roo");
|
|
|
27
27
|
var ROO_BACKUP_DIR = path.join(ROO_DIR, "SET_PROMPT_BACKUP");
|
|
28
28
|
var OPENCLAW_DIR = path.join(os.homedir(), ".openclaw", "workspace");
|
|
29
29
|
var OPENCLAW_BACKUP_DIR = path.join(OPENCLAW_DIR, "SET_PROMPT_BACKUP");
|
|
30
|
+
var ANTIGRAVITY_DIR = path.join(os.homedir(), ".gemini", "antigravity");
|
|
31
|
+
var ANTIGRAVITY_BACKUP_DIR = path.join(ANTIGRAVITY_DIR, "SET_PROMPT_BACKUP");
|
|
32
|
+
var CODEX_DIR = path.join(os.homedir(), ".codex");
|
|
33
|
+
var CODEX_BACKUP_DIR = path.join(CODEX_DIR, "SET_PROMPT_BACKUP");
|
|
34
|
+
var CURSOR_DIR = path.join(HOME_DIR, "cursor");
|
|
35
|
+
var CURSOR_PLUGIN_DIR = path.join(os.homedir(), ".cursor", "plugins", "local", "set-prompt");
|
|
30
36
|
var PROMPT_DIR_NAMES = ["skills", "commands", "hooks", "agents"];
|
|
31
37
|
var AGENT_PROMPT_DIRS = {
|
|
32
38
|
["claudecode" /* CLAUDECODE */]: ["skills", "commands", "hooks", "agents"],
|
|
33
39
|
["roocode" /* ROOCODE */]: ["skills", "commands"],
|
|
34
40
|
["openclaw" /* OPENCLAW */]: ["skills"],
|
|
35
41
|
["codex" /* CODEX */]: ["skills", "commands"],
|
|
36
|
-
["antigravity" /* ANTIGRAVITY */]: ["skills",
|
|
42
|
+
["antigravity" /* ANTIGRAVITY */]: ["skills"],
|
|
43
|
+
["cursor" /* CURSOR */]: ["skills", "agents", "rules"]
|
|
37
44
|
};
|
|
38
45
|
var ALL_AGENTS = [
|
|
39
46
|
{ name: "Claude Code", value: "claudecode" /* CLAUDECODE */ },
|
|
40
47
|
{ name: "RooCode", value: "roocode" /* ROOCODE */ },
|
|
41
48
|
{ name: "OpenClaw", value: "openclaw" /* OPENCLAW */ },
|
|
42
49
|
{ name: "Codex", value: "codex" /* CODEX */ },
|
|
43
|
-
{ name: "Antigravity", value: "antigravity" /* ANTIGRAVITY */ }
|
|
50
|
+
{ name: "Antigravity", value: "antigravity" /* ANTIGRAVITY */ },
|
|
51
|
+
{ name: "Cursor", value: "cursor" /* CURSOR */ }
|
|
44
52
|
];
|
|
45
53
|
|
|
46
54
|
// src/_libs/config.ts
|
|
@@ -63,10 +71,18 @@ var OpenclawConfigSchema = z.object({
|
|
|
63
71
|
backup_path: z.string().nullish().optional()
|
|
64
72
|
});
|
|
65
73
|
var CodexConfigSchema = z.object({
|
|
66
|
-
path: z.string().nullable()
|
|
74
|
+
path: z.string().nullable(),
|
|
75
|
+
backup_path: z.string().nullish().optional()
|
|
67
76
|
});
|
|
68
77
|
var AntigravityConfigSchema = z.object({
|
|
69
|
-
path: z.string().nullable()
|
|
78
|
+
path: z.string().nullable(),
|
|
79
|
+
backup_path: z.string().nullish().optional()
|
|
80
|
+
});
|
|
81
|
+
var CursorConfigSchema = z.object({
|
|
82
|
+
path: z.string().nullable(),
|
|
83
|
+
// ~/.set-prompt/cursor (플러그인 파일 구조)
|
|
84
|
+
plugin_dir: z.string().nullable()
|
|
85
|
+
// ~/.cursor/plugins/set-prompt (설치 symlink)
|
|
70
86
|
});
|
|
71
87
|
var GlobalConfigSchema = z.object({
|
|
72
88
|
repo_path: z.string(),
|
|
@@ -75,7 +91,8 @@ var GlobalConfigSchema = z.object({
|
|
|
75
91
|
roocode: RoocodeConfigSchema.nullable(),
|
|
76
92
|
openclaw: OpenclawConfigSchema.nullable(),
|
|
77
93
|
codex: CodexConfigSchema.nullish().optional(),
|
|
78
|
-
antigravity: AntigravityConfigSchema.nullish().optional()
|
|
94
|
+
antigravity: AntigravityConfigSchema.nullish().optional(),
|
|
95
|
+
cursor: CursorConfigSchema.nullish().optional()
|
|
79
96
|
});
|
|
80
97
|
|
|
81
98
|
// src/_libs/config.ts
|
|
@@ -88,6 +105,7 @@ var ConfigManager = class {
|
|
|
88
105
|
this._openclaw = null;
|
|
89
106
|
this._codex = null;
|
|
90
107
|
this._antigravity = null;
|
|
108
|
+
this._cursor = null;
|
|
91
109
|
}
|
|
92
110
|
get repo_path() {
|
|
93
111
|
return this._repo_path;
|
|
@@ -110,6 +128,9 @@ var ConfigManager = class {
|
|
|
110
128
|
get antigravity() {
|
|
111
129
|
return this._antigravity;
|
|
112
130
|
}
|
|
131
|
+
get cursor() {
|
|
132
|
+
return this._cursor;
|
|
133
|
+
}
|
|
113
134
|
set repo_path(v) {
|
|
114
135
|
this._repo_path = v;
|
|
115
136
|
}
|
|
@@ -131,10 +152,13 @@ var ConfigManager = class {
|
|
|
131
152
|
set antigravity(v) {
|
|
132
153
|
this._antigravity = v;
|
|
133
154
|
}
|
|
155
|
+
set cursor(v) {
|
|
156
|
+
this._cursor = v;
|
|
157
|
+
}
|
|
134
158
|
init() {
|
|
135
159
|
this._loadFromDisk();
|
|
136
160
|
if (this._repo_path != null) {
|
|
137
|
-
console.log(chalk.
|
|
161
|
+
console.log(chalk.green(`Config loaded`) + chalk.dim(` from ${CONFIG_PATH}`));
|
|
138
162
|
}
|
|
139
163
|
}
|
|
140
164
|
save() {
|
|
@@ -151,7 +175,8 @@ var ConfigManager = class {
|
|
|
151
175
|
roocode: this._roocode,
|
|
152
176
|
openclaw: this._openclaw,
|
|
153
177
|
codex: this._codex,
|
|
154
|
-
antigravity: this._antigravity
|
|
178
|
+
antigravity: this._antigravity,
|
|
179
|
+
cursor: this._cursor
|
|
155
180
|
}, null, 4);
|
|
156
181
|
fs.writeFileSync(CONFIG_PATH, configStr, "utf-8");
|
|
157
182
|
console.log(chalk.green(`Config saved`) + chalk.dim(` \u2192 ${CONFIG_PATH}`));
|
|
@@ -185,6 +210,9 @@ var ConfigManager = class {
|
|
|
185
210
|
isAntigravityEnabled() {
|
|
186
211
|
return this._antigravity != null;
|
|
187
212
|
}
|
|
213
|
+
isCursorEnabled() {
|
|
214
|
+
return this._cursor != null;
|
|
215
|
+
}
|
|
188
216
|
_assign(config) {
|
|
189
217
|
this._repo_path = config.repo_path;
|
|
190
218
|
this._remote_url = config.remote_url;
|
|
@@ -193,6 +221,7 @@ var ConfigManager = class {
|
|
|
193
221
|
this._openclaw = config.openclaw;
|
|
194
222
|
this._codex = config.codex ?? null;
|
|
195
223
|
this._antigravity = config.antigravity ?? null;
|
|
224
|
+
this._cursor = config.cursor ?? null;
|
|
196
225
|
}
|
|
197
226
|
_loadFromDisk() {
|
|
198
227
|
if (fs.existsSync(CONFIG_PATH) === false) {
|
|
@@ -282,15 +311,20 @@ customInstructions: "Additional behavior guidelines..."
|
|
|
282
311
|
|
|
283
312
|
# OpenClaw
|
|
284
313
|
homepage: "https://github.com/you/my-skill"
|
|
285
|
-
|
|
314
|
+
user-invocable: true
|
|
315
|
+
disable-model-invocation: false
|
|
316
|
+
metadata: {"os":["darwin","linux"],"requires":{"bins":["git"],"env":["MY_API_KEY"]}}
|
|
317
|
+
|
|
318
|
+
# Antigravity
|
|
319
|
+
name: my-skill
|
|
320
|
+
description: "What this skill does and when to use it"
|
|
286
321
|
---
|
|
287
322
|
\`\`\`
|
|
288
323
|
|
|
289
324
|
| Field | Required | Platform | Description |
|
|
290
325
|
|-------|----------|----------|-------------|
|
|
291
|
-
| \`name\` | Yes | All | Display name. Claude Code: lowercase, numbers, hyphens only (max 64 chars). RooCode: emoji allowed. |
|
|
326
|
+
| \`name\` | Yes | All | Display name. Claude Code: lowercase, numbers, hyphens only (max 64 chars). RooCode: emoji allowed. Antigravity: optional, defaults to folder name. |
|
|
292
327
|
| \`description\` | Yes | All | What it does and when to use it. Claude uses this to decide auto-loading. |
|
|
293
|
-
| \`disable-model-invocation\` | No | CC, OpenClaw | \`true\` = prevent auto-loading, manual \`/name\` only. (default: \`false\`) |
|
|
294
328
|
| \`allowed-tools\` | No | Claude Code | Tools Claude can use without asking. e.g. \`Read\` \`Write\` \`Edit\` \`Bash\` \`Grep\` \`Glob\` |
|
|
295
329
|
| \`model\` | No | Claude Code | Model to use when active. \`sonnet\` or \`haiku\` |
|
|
296
330
|
| \`context\` | No | Claude Code | \`fork\` = run in a forked subagent context |
|
|
@@ -301,15 +335,14 @@ metadata: {"openclaw":{"emoji":"\u{1F527}","os":["darwin","linux"]}}
|
|
|
301
335
|
| \`groups\` | Yes | RooCode | Tool permissions: \`read\` \`edit\` \`command\` \`mcp\` \`browser\` |
|
|
302
336
|
| \`whenToUse\` | No | RooCode | Guide for auto mode selection |
|
|
303
337
|
| \`customInstructions\` | No | RooCode | Additional behavior guidelines |
|
|
304
|
-
| \`
|
|
305
|
-
| \`metadata\` | No | OpenClaw | Single-line JSON for platform gating
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
\`\`\`
|
|
338
|
+
| \`groups\` (restricted) | No | RooCode | Restrict edit to file patterns: \`[edit, {fileRegex: '\\.(md|ts)$', description: "..."}]\` |
|
|
339
|
+
| \`metadata\` | No | OpenClaw | Single-line JSON for platform gating: \`os\` (platform filter), \`requires.bins\` (required binaries), \`requires.env\` (required env vars) |
|
|
340
|
+
| \`homepage\` | No | OpenClaw | URL shown as "Website" in the macOS Skills UI. Also settable via \`metadata.openclaw.homepage\`. |
|
|
341
|
+
| \`user-invocable\` | No | OpenClaw | \`false\` = hidden from \`/\` menu. (default: \`true\`) |
|
|
342
|
+
| \`disable-model-invocation\` | No | CC, OpenClaw | \`true\` = skill excluded from model prompt, still available via user invocation. (default: \`false\`) |
|
|
343
|
+
| \`command-dispatch\` | No | OpenClaw | \`"tool"\` = bypass model, dispatch directly to a tool |
|
|
344
|
+
| \`command-tool\` | No | OpenClaw | Tool to invoke when \`command-dispatch: "tool"\` |
|
|
345
|
+
| \`command-arg-mode\` | No | OpenClaw | How arguments are forwarded to the tool. (default: \`"raw"\`) |
|
|
313
346
|
|
|
314
347
|
---
|
|
315
348
|
|
|
@@ -360,9 +393,6 @@ command-tool: "Bash"
|
|
|
360
393
|
| \`context\` | No | Claude Code | \`fork\` = run in a forked subagent context |
|
|
361
394
|
| \`agent\` | No | Claude Code | Subagent type when \`context: fork\`. e.g. \`general-purpose\` \`Explore\` \`Plan\` |
|
|
362
395
|
| \`hooks\` | No | Claude Code | Lifecycle hooks for pre/post processing. |
|
|
363
|
-
| \`command-dispatch\` | No | OpenClaw | \`"tool"\` = bypass model, dispatch directly to a tool |
|
|
364
|
-
| \`command-tool\` | No | OpenClaw | Tool to invoke when \`command-dispatch: "tool"\` |
|
|
365
|
-
| \`command-arg-mode\` | No | OpenClaw | How arguments are forwarded to the tool. (default: \`"raw"\`) |
|
|
366
396
|
|
|
367
397
|
---
|
|
368
398
|
|
|
@@ -527,18 +557,23 @@ var scaffoldCommand = async (localPath, options = {}) => {
|
|
|
527
557
|
}
|
|
528
558
|
const created = [];
|
|
529
559
|
const guideMdPath = path2.join(targetPath, "SET_PROMPT_GUIDE.md");
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
created.push(" SET_PROMPT_GUIDE.md");
|
|
533
|
-
}
|
|
560
|
+
fs2.writeFileSync(guideMdPath, SET_PROMPT_GUIDE, { encoding: "utf-8", flag: "w" });
|
|
561
|
+
created.push(" SET_PROMPT_GUIDE.md");
|
|
534
562
|
for (const dirName of PROMPT_DIR_NAMES) {
|
|
535
563
|
const dirPath = path2.join(targetPath, dirName);
|
|
536
564
|
if (fs2.existsSync(dirPath)) {
|
|
537
565
|
console.warn(chalk2.yellow(`Directory already exists: '${dirName}' (skipping)`));
|
|
538
|
-
|
|
566
|
+
} else {
|
|
567
|
+
fs2.mkdirSync(dirPath, { recursive: true });
|
|
568
|
+
created.push(` ${dirName}/`);
|
|
569
|
+
}
|
|
570
|
+
const gitkeepPath = path2.join(dirPath, ".gitkeep");
|
|
571
|
+
if (!fs2.existsSync(gitkeepPath)) {
|
|
572
|
+
fs2.writeFileSync(gitkeepPath, "", { encoding: "utf-8" });
|
|
573
|
+
if (!created.includes(` ${dirName}/`)) {
|
|
574
|
+
created.push(` ${dirName}/.gitkeep`);
|
|
575
|
+
}
|
|
539
576
|
}
|
|
540
|
-
fs2.mkdirSync(dirPath, { recursive: true });
|
|
541
|
-
created.push(` ${dirName}/`);
|
|
542
577
|
}
|
|
543
578
|
if (created.length > 0) {
|
|
544
579
|
console.log(chalk2.green("Created:"));
|
|
@@ -554,21 +589,23 @@ var scaffoldCommand = async (localPath, options = {}) => {
|
|
|
554
589
|
|
|
555
590
|
// src/commands/install-command.ts
|
|
556
591
|
var cloneRepo = async (remoteUrl) => {
|
|
557
|
-
const proceed = await confirm2({
|
|
558
|
-
message: `Clone and register "${remoteUrl}"?`,
|
|
559
|
-
default: true
|
|
560
|
-
});
|
|
561
|
-
if (proceed == false) {
|
|
562
|
-
console.log(chalk3.yellow("Cancelled."));
|
|
563
|
-
return false;
|
|
564
|
-
}
|
|
565
592
|
const localPath = path3.join(HOME_DIR, "repo");
|
|
593
|
+
let backupPath = null;
|
|
566
594
|
if (fs3.existsSync(localPath) == true) {
|
|
567
|
-
console.warn(chalk3.yellow(`Existing repo found. Backing up before proceeding.`));
|
|
568
595
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
596
|
+
backupPath = path3.join(HOME_DIR, `repo.bak.${timestamp}`);
|
|
597
|
+
try {
|
|
598
|
+
fs3.renameSync(localPath, backupPath);
|
|
599
|
+
console.log(chalk3.yellow(" backed up") + chalk3.dim(` existing repo \u2192 ${backupPath}`));
|
|
600
|
+
} catch (ex) {
|
|
601
|
+
if (ex.code === "EPERM") {
|
|
602
|
+
console.error(chalk3.red("\u274C Cannot rename existing repo \u2014 it may be open in another process."));
|
|
603
|
+
console.log(chalk3.dim(` Close any editors or terminals using: ${localPath}`));
|
|
604
|
+
} else {
|
|
605
|
+
console.error(chalk3.red(`\u274C Failed to backup existing repo: ${ex.message}`));
|
|
606
|
+
}
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
572
609
|
}
|
|
573
610
|
fs3.mkdirSync(path3.dirname(localPath), { recursive: true });
|
|
574
611
|
console.log(`Cloning ${remoteUrl}...`);
|
|
@@ -578,6 +615,10 @@ var cloneRepo = async (remoteUrl) => {
|
|
|
578
615
|
process.exit(1);
|
|
579
616
|
}
|
|
580
617
|
console.log("\u2705 Cloned successfully.");
|
|
618
|
+
if (backupPath != null) {
|
|
619
|
+
fs3.rmSync(backupPath, { recursive: true, force: true });
|
|
620
|
+
console.log(chalk3.red(" removed") + chalk3.dim(` backup \u2192 ${backupPath}`));
|
|
621
|
+
}
|
|
581
622
|
await scaffoldCommand(localPath, { force: true });
|
|
582
623
|
configManager.repo_path = localPath;
|
|
583
624
|
configManager.remote_url = remoteUrl;
|
|
@@ -594,6 +635,26 @@ var installCommand = async (target) => {
|
|
|
594
635
|
console.log(chalk3.dim(" Example: set-prompt install https://github.com/you/my-prompts"));
|
|
595
636
|
process.exit(1);
|
|
596
637
|
}
|
|
638
|
+
const normalizeUrl = (url) => url.replace(/\.git$/, "").toLowerCase();
|
|
639
|
+
if (configManager.repo_path != null) {
|
|
640
|
+
if (normalizeUrl(configManager.remote_url ?? "") === normalizeUrl(target)) {
|
|
641
|
+
console.error(chalk3.red(`\u274C Already installed from the same URL: ${target}`));
|
|
642
|
+
console.log(chalk3.dim(" Use `set-prompt update` to pull the latest changes."));
|
|
643
|
+
return false;
|
|
644
|
+
}
|
|
645
|
+
console.warn(chalk3.yellow(`\u26A0 Switching repo: ${configManager.remote_url} \u2192 ${target}`));
|
|
646
|
+
const proceed = await confirm2({ message: "Replace existing installation?", default: false });
|
|
647
|
+
if (!proceed) {
|
|
648
|
+
console.log(chalk3.yellow("Cancelled."));
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
} else {
|
|
652
|
+
const proceed = await confirm2({ message: `Clone and register "${target}"?`, default: true });
|
|
653
|
+
if (!proceed) {
|
|
654
|
+
console.log(chalk3.yellow("Cancelled."));
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
597
658
|
return await cloneRepo(target);
|
|
598
659
|
} catch (ex) {
|
|
599
660
|
console.error(chalk3.red(`Unexpected error: ${ex.message}`), ex);
|
|
@@ -606,7 +667,7 @@ import path4 from "path";
|
|
|
606
667
|
import fs4 from "fs";
|
|
607
668
|
import os2 from "os";
|
|
608
669
|
import chalk4 from "chalk";
|
|
609
|
-
import { checkbox } from "@inquirer/prompts";
|
|
670
|
+
import { confirm as confirm3, checkbox } from "@inquirer/prompts";
|
|
610
671
|
import { pathExists } from "fs-extra";
|
|
611
672
|
var resolveRepoPath = () => {
|
|
612
673
|
if (configManager.repo_path == null) {
|
|
@@ -616,7 +677,8 @@ var resolveRepoPath = () => {
|
|
|
616
677
|
}
|
|
617
678
|
return configManager.repo_path;
|
|
618
679
|
};
|
|
619
|
-
var
|
|
680
|
+
var MARKET_NAME = "set-prompt";
|
|
681
|
+
var PLUGIN_NAME = "sppt";
|
|
620
682
|
var linkClaudeCode = async () => {
|
|
621
683
|
const repoPath = resolveRepoPath();
|
|
622
684
|
if (repoPath == null) {
|
|
@@ -628,7 +690,7 @@ var linkClaudeCode = async () => {
|
|
|
628
690
|
const marketplaceMetaDir = path4.join(CLAUDE_CODE_DIR, ".claude-plugin");
|
|
629
691
|
fs4.mkdirSync(marketplaceMetaDir, { recursive: true });
|
|
630
692
|
const marketplaceJson = {
|
|
631
|
-
name:
|
|
693
|
+
name: MARKET_NAME,
|
|
632
694
|
owner: { name: os2.userInfo().username },
|
|
633
695
|
metadata: { description: "Managed by set-prompt", version: "1.0.0" },
|
|
634
696
|
plugins: [{ name: PLUGIN_NAME, source: `./plugins/${PLUGIN_NAME}`, description: "Managed by set-prompt" }]
|
|
@@ -705,11 +767,11 @@ var linkClaudeCode = async () => {
|
|
|
705
767
|
}
|
|
706
768
|
settings.extraKnownMarketplaces = {
|
|
707
769
|
...settings.extraKnownMarketplaces,
|
|
708
|
-
[
|
|
770
|
+
[MARKET_NAME]: { source: { source: "directory", path: CLAUDE_CODE_DIR } }
|
|
709
771
|
};
|
|
710
772
|
settings.enabledPlugins = {
|
|
711
773
|
...settings.enabledPlugins,
|
|
712
|
-
[`${PLUGIN_NAME}@${
|
|
774
|
+
[`${PLUGIN_NAME}@${MARKET_NAME}`]: true
|
|
713
775
|
};
|
|
714
776
|
let backupPath = null;
|
|
715
777
|
if (fs4.existsSync(claudeSettingsPath)) {
|
|
@@ -752,6 +814,38 @@ var linkClaudeCode = async () => {
|
|
|
752
814
|
return false;
|
|
753
815
|
}
|
|
754
816
|
};
|
|
817
|
+
const patchInstalledPlugins = () => {
|
|
818
|
+
const installPath = path4.join(CLAUDE_CODE_DIR, "plugins", PLUGIN_NAME);
|
|
819
|
+
const installedPluginsPath = path4.join(os2.homedir(), ".claude", "plugins", "installed_plugins.json");
|
|
820
|
+
const pluginKey = `${PLUGIN_NAME}@${MARKET_NAME}`;
|
|
821
|
+
try {
|
|
822
|
+
let data = { version: 2, plugins: {} };
|
|
823
|
+
if (fs4.existsSync(installedPluginsPath)) {
|
|
824
|
+
try {
|
|
825
|
+
data = JSON.parse(fs4.readFileSync(installedPluginsPath, "utf-8"));
|
|
826
|
+
} catch {
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
if (data.plugins == null) {
|
|
830
|
+
data.plugins = {};
|
|
831
|
+
}
|
|
832
|
+
data.plugins[pluginKey] = [
|
|
833
|
+
{
|
|
834
|
+
scope: "user",
|
|
835
|
+
installPath,
|
|
836
|
+
version: "1.0.0",
|
|
837
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
838
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
839
|
+
}
|
|
840
|
+
];
|
|
841
|
+
fs4.mkdirSync(path4.dirname(installedPluginsPath), { recursive: true });
|
|
842
|
+
fs4.writeFileSync(installedPluginsPath, JSON.stringify(data, null, 2), "utf-8");
|
|
843
|
+
console.log(`\u2705 Patched installed_plugins.json \u2192 installPath points to source.`);
|
|
844
|
+
console.log(chalk4.dim(` ${installPath}`));
|
|
845
|
+
} catch (ex) {
|
|
846
|
+
console.warn(chalk4.yellow(` \u26A0 Could not patch installed_plugins.json: ${ex.message}`));
|
|
847
|
+
}
|
|
848
|
+
};
|
|
755
849
|
console.log(chalk4.green(`
|
|
756
850
|
Setting up Claude Code plugin...`));
|
|
757
851
|
console.log(chalk4.dim(CLAUDE_CODE_DIR));
|
|
@@ -763,6 +857,7 @@ Setting up Claude Code plugin...`));
|
|
|
763
857
|
if (settingsOk === false) {
|
|
764
858
|
return;
|
|
765
859
|
}
|
|
860
|
+
patchInstalledPlugins();
|
|
766
861
|
configManager.claude_code = { path: CLAUDE_CODE_DIR };
|
|
767
862
|
configManager.save();
|
|
768
863
|
};
|
|
@@ -781,19 +876,30 @@ Setting up RooCode integration...`));
|
|
|
781
876
|
const dirsToBackup = [];
|
|
782
877
|
for (const dir of roocodeDirs) {
|
|
783
878
|
const target = path4.join(ROO_DIR, dir);
|
|
784
|
-
if (fs4.existsSync(target) && fs4.lstatSync(target).isSymbolicLink() === false) {
|
|
879
|
+
if (fs4.existsSync(target) && fs4.lstatSync(target).isSymbolicLink() === false && fs4.readdirSync(target).length > 0) {
|
|
785
880
|
dirsToBackup.push(dir);
|
|
786
881
|
}
|
|
787
882
|
}
|
|
788
883
|
if (dirsToBackup.length === 0) {
|
|
789
884
|
return true;
|
|
790
885
|
}
|
|
886
|
+
console.log(chalk4.yellow(`
|
|
887
|
+
\u26A0 The following existing directories will be replaced by symlinks:`));
|
|
888
|
+
for (const dir of dirsToBackup) {
|
|
889
|
+
console.log(chalk4.dim(` - ${path4.join(ROO_DIR, dir)}`));
|
|
890
|
+
}
|
|
891
|
+
console.log(chalk4.yellow(` They will be backed up to: `) + chalk4.dim(ROO_BACKUP_DIR));
|
|
892
|
+
const ok = await confirm3({ message: "Back up existing directories?", default: true });
|
|
893
|
+
if (!ok) {
|
|
894
|
+
console.log(chalk4.yellow("Skipped RooCode linking."));
|
|
895
|
+
return false;
|
|
896
|
+
}
|
|
791
897
|
fs4.mkdirSync(ROO_BACKUP_DIR, { recursive: true });
|
|
792
898
|
for (const dir of dirsToBackup) {
|
|
793
899
|
const src = path4.join(ROO_DIR, dir);
|
|
794
900
|
const dest = path4.join(ROO_BACKUP_DIR, dir);
|
|
795
901
|
fs4.renameSync(src, dest);
|
|
796
|
-
console.log(chalk4.
|
|
902
|
+
console.log(chalk4.yellow(" backed up") + chalk4.dim(`: ${dir}/ \u2192 ${dest}`));
|
|
797
903
|
}
|
|
798
904
|
return true;
|
|
799
905
|
} catch (ex) {
|
|
@@ -854,19 +960,30 @@ Setting up OpenClaw integration...`));
|
|
|
854
960
|
const dirsToBackup = [];
|
|
855
961
|
for (const dir of openclawDirs) {
|
|
856
962
|
const target = path4.join(OPENCLAW_DIR, dir);
|
|
857
|
-
if (fs4.existsSync(target) && fs4.lstatSync(target).isSymbolicLink() === false) {
|
|
963
|
+
if (fs4.existsSync(target) && fs4.lstatSync(target).isSymbolicLink() === false && fs4.readdirSync(target).length > 0) {
|
|
858
964
|
dirsToBackup.push(dir);
|
|
859
965
|
}
|
|
860
966
|
}
|
|
861
967
|
if (dirsToBackup.length === 0) {
|
|
862
968
|
return true;
|
|
863
969
|
}
|
|
970
|
+
console.log(chalk4.yellow(`
|
|
971
|
+
\u26A0 The following existing directories will be replaced by symlinks:`));
|
|
972
|
+
for (const dir of dirsToBackup) {
|
|
973
|
+
console.log(chalk4.dim(` - ${path4.join(OPENCLAW_DIR, dir)}`));
|
|
974
|
+
}
|
|
975
|
+
console.log(chalk4.yellow(` They will be backed up to: `) + chalk4.dim(OPENCLAW_BACKUP_DIR));
|
|
976
|
+
const ok = await confirm3({ message: "Back up existing directories?", default: true });
|
|
977
|
+
if (!ok) {
|
|
978
|
+
console.log(chalk4.yellow("Skipped OpenClaw linking."));
|
|
979
|
+
return false;
|
|
980
|
+
}
|
|
864
981
|
fs4.mkdirSync(OPENCLAW_BACKUP_DIR, { recursive: true });
|
|
865
982
|
for (const dir of dirsToBackup) {
|
|
866
983
|
const src = path4.join(OPENCLAW_DIR, dir);
|
|
867
984
|
const dest = path4.join(OPENCLAW_BACKUP_DIR, dir);
|
|
868
985
|
fs4.renameSync(src, dest);
|
|
869
|
-
console.log(chalk4.
|
|
986
|
+
console.log(chalk4.yellow(" backed up") + chalk4.dim(`: ${dir}/ \u2192 ${dest}`));
|
|
870
987
|
}
|
|
871
988
|
return true;
|
|
872
989
|
} catch (ex) {
|
|
@@ -912,219 +1029,615 @@ Setting up OpenClaw integration...`));
|
|
|
912
1029
|
configManager.openclaw = { path: OPENCLAW_DIR, backup_path: OPENCLAW_BACKUP_DIR };
|
|
913
1030
|
configManager.save();
|
|
914
1031
|
};
|
|
915
|
-
var linkCodex = async () => {
|
|
916
|
-
if (resolveRepoPath() == null) {
|
|
917
|
-
return;
|
|
918
|
-
}
|
|
919
|
-
console.log(chalk4.yellow("Codex integration is not yet implemented."));
|
|
920
|
-
};
|
|
921
1032
|
var linkAntigravity = async () => {
|
|
922
|
-
|
|
1033
|
+
const repoPath = resolveRepoPath();
|
|
1034
|
+
if (repoPath == null) {
|
|
923
1035
|
return;
|
|
924
1036
|
}
|
|
925
|
-
console.log(chalk4.
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1037
|
+
console.log(chalk4.green(`
|
|
1038
|
+
Setting up Antigravity integration...`));
|
|
1039
|
+
console.log(chalk4.dim(ANTIGRAVITY_DIR));
|
|
1040
|
+
const antigravityDirs = AGENT_PROMPT_DIRS["antigravity" /* ANTIGRAVITY */];
|
|
1041
|
+
const backupExistingAntigravityFiles = async () => {
|
|
1042
|
+
try {
|
|
1043
|
+
fs4.mkdirSync(ANTIGRAVITY_DIR, { recursive: true });
|
|
1044
|
+
const dirsToBackup = [];
|
|
1045
|
+
for (const dir of antigravityDirs) {
|
|
1046
|
+
const target = path4.join(ANTIGRAVITY_DIR, dir);
|
|
1047
|
+
if (fs4.existsSync(target) && fs4.lstatSync(target).isSymbolicLink() === false && fs4.readdirSync(target).length > 0) {
|
|
1048
|
+
dirsToBackup.push(dir);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
if (dirsToBackup.length === 0) {
|
|
1052
|
+
return true;
|
|
1053
|
+
}
|
|
1054
|
+
console.log(chalk4.yellow(`
|
|
1055
|
+
\u26A0 The following existing directories will be replaced by symlinks:`));
|
|
1056
|
+
for (const dir of dirsToBackup) {
|
|
1057
|
+
console.log(chalk4.dim(` - ${path4.join(ANTIGRAVITY_DIR, dir)}`));
|
|
1058
|
+
}
|
|
1059
|
+
console.log(chalk4.yellow(` They will be backed up to: `) + chalk4.dim(ANTIGRAVITY_BACKUP_DIR));
|
|
1060
|
+
const ok = await confirm3({ message: "Back up existing directories?", default: true });
|
|
1061
|
+
if (!ok) {
|
|
1062
|
+
console.log(chalk4.yellow("Skipped Antigravity linking."));
|
|
1063
|
+
return false;
|
|
1064
|
+
}
|
|
1065
|
+
fs4.mkdirSync(ANTIGRAVITY_BACKUP_DIR, { recursive: true });
|
|
1066
|
+
for (const dir of antigravityDirs) {
|
|
1067
|
+
const src = path4.join(ANTIGRAVITY_DIR, dir);
|
|
1068
|
+
const dest = path4.join(ANTIGRAVITY_BACKUP_DIR, dir);
|
|
1069
|
+
fs4.renameSync(src, dest);
|
|
1070
|
+
console.log(chalk4.yellow(" backed up") + chalk4.dim(`: ${dir}/ \u2192 ${dest}`));
|
|
1071
|
+
}
|
|
1072
|
+
return true;
|
|
1073
|
+
} catch (ex) {
|
|
1074
|
+
console.error(chalk4.red(`\u274C Failed to backup existing directories: ${ex.message}`));
|
|
1075
|
+
return false;
|
|
933
1076
|
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1077
|
+
};
|
|
1078
|
+
const setAntigravityAssets = async () => {
|
|
1079
|
+
try {
|
|
1080
|
+
const linked = [];
|
|
1081
|
+
for (const dir of antigravityDirs) {
|
|
1082
|
+
const src = path4.join(repoPath, dir);
|
|
1083
|
+
const dest = path4.join(ANTIGRAVITY_DIR, dir);
|
|
1084
|
+
if (await pathExists(src) === false) {
|
|
1085
|
+
continue;
|
|
1086
|
+
}
|
|
1087
|
+
if (fs4.existsSync(dest)) {
|
|
1088
|
+
fs4.rmSync(dest, { recursive: true, force: true });
|
|
1089
|
+
}
|
|
1090
|
+
const symlinkType = process.platform === "win32" ? "junction" : "dir";
|
|
1091
|
+
fs4.symlinkSync(src, dest, symlinkType);
|
|
1092
|
+
linked.push({ dir, src });
|
|
1093
|
+
}
|
|
1094
|
+
for (const { dir, src } of linked) {
|
|
1095
|
+
const isLast = linked[linked.length - 1].dir === dir;
|
|
1096
|
+
const branch = isLast ? "\u2514\u2500\u2500" : "\u251C\u2500\u2500";
|
|
1097
|
+
console.log(chalk4.dim(` ${branch} `) + chalk4.bold(`${dir}/`) + chalk4.dim(` \u2192 ${src}`) + chalk4.green(" \u2713"));
|
|
1098
|
+
}
|
|
1099
|
+
return true;
|
|
1100
|
+
} catch (ex) {
|
|
1101
|
+
console.error(chalk4.red(`\u274C Failed to create symlinks: ${ex.message}`));
|
|
1102
|
+
return false;
|
|
944
1103
|
}
|
|
1104
|
+
};
|
|
1105
|
+
const backupOk = await backupExistingAntigravityFiles();
|
|
1106
|
+
if (backupOk === false) {
|
|
945
1107
|
return;
|
|
946
1108
|
}
|
|
947
|
-
const
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
const applied = a.value === "claudecode" /* CLAUDECODE */ ? configManager.isClaudeCodeEnabled() : a.value === "roocode" /* ROOCODE */ ? configManager.isRooCodeEnabled() : a.value === "openclaw" /* OPENCLAW */ ? configManager.isOpenclawEnabled() : a.value === "codex" /* CODEX */ ? configManager.isCodexEnabled() : a.value === "antigravity" /* ANTIGRAVITY */ ? configManager.isAntigravityEnabled() : false;
|
|
951
|
-
return {
|
|
952
|
-
name: applied ? `${a.name} ${chalk4.dim("(applied)")}` : a.name,
|
|
953
|
-
value: a.value,
|
|
954
|
-
checked: applied
|
|
955
|
-
};
|
|
956
|
-
})
|
|
957
|
-
});
|
|
958
|
-
for (const a of selected) {
|
|
959
|
-
if (a === "claudecode" /* CLAUDECODE */) {
|
|
960
|
-
await linkClaudeCode();
|
|
961
|
-
} else if (a === "roocode" /* ROOCODE */) {
|
|
962
|
-
await linkRooCode();
|
|
963
|
-
} else if (a === "openclaw" /* OPENCLAW */) {
|
|
964
|
-
await linkOpenclaw();
|
|
965
|
-
} else if (a === "codex" /* CODEX */) {
|
|
966
|
-
await linkCodex();
|
|
967
|
-
} else if (a === "antigravity" /* ANTIGRAVITY */) {
|
|
968
|
-
await linkAntigravity();
|
|
969
|
-
}
|
|
1109
|
+
const linkOk = await setAntigravityAssets();
|
|
1110
|
+
if (linkOk === false) {
|
|
1111
|
+
return;
|
|
970
1112
|
}
|
|
1113
|
+
configManager.antigravity = { path: ANTIGRAVITY_DIR, backup_path: ANTIGRAVITY_BACKUP_DIR };
|
|
1114
|
+
configManager.save();
|
|
971
1115
|
};
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
var PLUGIN_NAME2 = "set-prompt";
|
|
980
|
-
var rollbackClaudeCode = () => {
|
|
981
|
-
const claudeSettingsPath = path5.join(os3.homedir(), ".claude", "settings.json");
|
|
982
|
-
if (fs5.existsSync(claudeSettingsPath) === false) {
|
|
1116
|
+
var linkCodex = async () => {
|
|
1117
|
+
console.error(chalk4.red("\u274C Codex integration is not available in this version."));
|
|
1118
|
+
return;
|
|
1119
|
+
};
|
|
1120
|
+
var linkCursor = async () => {
|
|
1121
|
+
const repoPath = resolveRepoPath();
|
|
1122
|
+
if (repoPath == null) {
|
|
983
1123
|
return;
|
|
984
1124
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1125
|
+
const CURSOR_LOCAL_DIR = "local";
|
|
1126
|
+
const CURSOR_PLUGIN_NAME = "set-prompt";
|
|
1127
|
+
const setCursorAssets = async () => {
|
|
988
1128
|
try {
|
|
989
|
-
|
|
1129
|
+
const marketplaceMetaDir = path4.join(CURSOR_DIR, ".cursor-plugin");
|
|
1130
|
+
fs4.mkdirSync(marketplaceMetaDir, { recursive: true });
|
|
1131
|
+
const marketplaceJson = {
|
|
1132
|
+
name: CURSOR_PLUGIN_NAME,
|
|
1133
|
+
owner: { name: os2.userInfo().username },
|
|
1134
|
+
metadata: { description: "Managed by set-prompt" },
|
|
1135
|
+
plugins: [{ name: CURSOR_PLUGIN_NAME, source: `./plugins/${CURSOR_LOCAL_DIR}/${CURSOR_PLUGIN_NAME}`, description: "Managed by set-prompt" }]
|
|
1136
|
+
};
|
|
1137
|
+
fs4.writeFileSync(
|
|
1138
|
+
path4.join(marketplaceMetaDir, "marketplace.json"),
|
|
1139
|
+
JSON.stringify(marketplaceJson, null, 2),
|
|
1140
|
+
"utf-8"
|
|
1141
|
+
);
|
|
1142
|
+
console.log(chalk4.dim(" \u251C\u2500\u2500 .cursor-plugin/"));
|
|
1143
|
+
console.log(chalk4.dim(" \u2502 \u2514\u2500\u2500 marketplace.json") + chalk4.green(" \u2713"));
|
|
1144
|
+
const pluginDir = path4.join(CURSOR_DIR, "plugins", CURSOR_LOCAL_DIR, CURSOR_PLUGIN_NAME);
|
|
1145
|
+
const pluginMetaDir = path4.join(pluginDir, ".cursor-plugin");
|
|
1146
|
+
fs4.mkdirSync(pluginMetaDir, { recursive: true });
|
|
1147
|
+
const cursorDirs = AGENT_PROMPT_DIRS["cursor" /* CURSOR */];
|
|
1148
|
+
const pluginJson = {
|
|
1149
|
+
name: CURSOR_PLUGIN_NAME,
|
|
1150
|
+
displayName: "set-prompt",
|
|
1151
|
+
version: "1.0.0",
|
|
1152
|
+
description: "Managed by set-prompt"
|
|
1153
|
+
};
|
|
1154
|
+
for (const dir of cursorDirs) {
|
|
1155
|
+
pluginJson[dir] = `./${dir}/`;
|
|
1156
|
+
}
|
|
1157
|
+
fs4.writeFileSync(
|
|
1158
|
+
path4.join(pluginMetaDir, "plugin.json"),
|
|
1159
|
+
JSON.stringify(pluginJson, null, 2),
|
|
1160
|
+
"utf-8"
|
|
1161
|
+
);
|
|
1162
|
+
console.log(chalk4.dim(" \u2514\u2500\u2500 plugins/"));
|
|
1163
|
+
console.log(chalk4.dim(` \u2514\u2500\u2500 ${CURSOR_PLUGIN_NAME}/`));
|
|
1164
|
+
console.log(chalk4.dim(" \u251C\u2500\u2500 .cursor-plugin/"));
|
|
1165
|
+
console.log(chalk4.dim(" \u2502 \u2514\u2500\u2500 plugin.json") + chalk4.green(" \u2713"));
|
|
1166
|
+
const linked = [];
|
|
1167
|
+
for (const dir of cursorDirs) {
|
|
1168
|
+
const src = path4.join(repoPath, dir);
|
|
1169
|
+
const dest = path4.join(pluginDir, dir);
|
|
1170
|
+
if (await pathExists(src) === false) {
|
|
1171
|
+
continue;
|
|
1172
|
+
}
|
|
1173
|
+
if (fs4.existsSync(dest)) {
|
|
1174
|
+
fs4.rmSync(dest, { recursive: true, force: true });
|
|
1175
|
+
}
|
|
1176
|
+
const symlinkType2 = process.platform === "win32" ? "junction" : "dir";
|
|
1177
|
+
fs4.symlinkSync(src, dest, symlinkType2);
|
|
1178
|
+
linked.push({ dir, src });
|
|
1179
|
+
}
|
|
1180
|
+
for (const { dir, src } of linked) {
|
|
1181
|
+
const isLast = linked[linked.length - 1].dir === dir;
|
|
1182
|
+
const branch = isLast ? "\u2514\u2500\u2500" : "\u251C\u2500\u2500";
|
|
1183
|
+
console.log(chalk4.dim(` ${branch} `) + chalk4.bold(`${dir}/`) + chalk4.dim(` \u2192 ${src}`) + chalk4.green(" \u2713"));
|
|
1184
|
+
}
|
|
1185
|
+
fs4.rmSync(CURSOR_PLUGIN_DIR, { recursive: true, force: true });
|
|
1186
|
+
fs4.mkdirSync(path4.dirname(CURSOR_PLUGIN_DIR), { recursive: true });
|
|
1187
|
+
const symlinkType = process.platform === "win32" ? "junction" : "dir";
|
|
1188
|
+
fs4.symlinkSync(pluginDir, CURSOR_PLUGIN_DIR, symlinkType);
|
|
1189
|
+
console.log(chalk4.green(`
|
|
1190
|
+
\u2705 Installed to Cursor plugins.`));
|
|
1191
|
+
console.log(chalk4.dim(` ${CURSOR_PLUGIN_DIR}`));
|
|
1192
|
+
return true;
|
|
990
1193
|
} catch (ex) {
|
|
991
|
-
console.
|
|
1194
|
+
console.error(chalk4.red(`\u274C Failed to build Cursor plugin structure: ${ex.message}`));
|
|
1195
|
+
return false;
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
console.log(chalk4.green(`
|
|
1199
|
+
Setting up Cursor plugin...`));
|
|
1200
|
+
console.log(chalk4.dim(CURSOR_DIR));
|
|
1201
|
+
const structureOk = await setCursorAssets();
|
|
1202
|
+
if (structureOk === false) {
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
configManager.cursor = { path: CURSOR_DIR, plugin_dir: CURSOR_PLUGIN_DIR };
|
|
1206
|
+
configManager.save();
|
|
1207
|
+
};
|
|
1208
|
+
var unlinkClaudeCode = async (force = false) => {
|
|
1209
|
+
if (!force) {
|
|
1210
|
+
const ok = await confirm3({
|
|
1211
|
+
message: `Remove Claude Code plugin dir (${CLAUDE_CODE_DIR}) and settings entries?`,
|
|
1212
|
+
default: false
|
|
1213
|
+
});
|
|
1214
|
+
if (!ok) {
|
|
1215
|
+
console.log(chalk4.yellow("Cancelled."));
|
|
992
1216
|
return;
|
|
993
1217
|
}
|
|
994
|
-
|
|
995
|
-
|
|
1218
|
+
}
|
|
1219
|
+
console.log(chalk4.red(`
|
|
1220
|
+
Removing Claude Code plugin...`));
|
|
1221
|
+
console.log(chalk4.dim(CLAUDE_CODE_DIR));
|
|
1222
|
+
const claudeSettingsPath = path4.join(os2.homedir(), ".claude", "settings.json");
|
|
1223
|
+
if (fs4.existsSync(claudeSettingsPath)) {
|
|
996
1224
|
try {
|
|
997
|
-
const
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1225
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1226
|
+
const backupPath = `${claudeSettingsPath}.bak.${timestamp}`;
|
|
1227
|
+
fs4.copyFileSync(claudeSettingsPath, backupPath);
|
|
1228
|
+
const settings = JSON.parse(fs4.readFileSync(claudeSettingsPath, "utf-8"));
|
|
1229
|
+
if (settings?.extraKnownMarketplaces?.[MARKET_NAME] !== void 0) {
|
|
1230
|
+
delete settings.extraKnownMarketplaces[MARKET_NAME];
|
|
1002
1231
|
}
|
|
1003
|
-
settings
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1232
|
+
if (settings?.enabledPlugins?.[`${PLUGIN_NAME}@${MARKET_NAME}`] !== void 0) {
|
|
1233
|
+
delete settings.enabledPlugins[`${PLUGIN_NAME}@${MARKET_NAME}`];
|
|
1234
|
+
}
|
|
1235
|
+
try {
|
|
1236
|
+
fs4.writeFileSync(claudeSettingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
1237
|
+
fs4.unlinkSync(backupPath);
|
|
1238
|
+
console.log(chalk4.red(" removed") + chalk4.dim(` set-prompt entries from: ${claudeSettingsPath}`));
|
|
1239
|
+
} catch (ex) {
|
|
1240
|
+
fs4.copyFileSync(backupPath, claudeSettingsPath);
|
|
1241
|
+
fs4.unlinkSync(backupPath);
|
|
1242
|
+
console.warn(chalk4.yellow(" \u26A0 Write failed \u2014 rolled back to original."));
|
|
1243
|
+
}
|
|
1244
|
+
} catch (ex) {
|
|
1245
|
+
console.error(chalk4.red(` \u274C Failed to clean up settings.json: ${ex.message}`));
|
|
1014
1246
|
}
|
|
1247
|
+
}
|
|
1248
|
+
const claudePluginsDir = path4.join(os2.homedir(), ".claude", "plugins");
|
|
1249
|
+
const installedPluginsPath = path4.join(claudePluginsDir, "installed_plugins.json");
|
|
1250
|
+
if (fs4.existsSync(installedPluginsPath)) {
|
|
1015
1251
|
try {
|
|
1016
|
-
|
|
1017
|
-
|
|
1252
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1253
|
+
const backupPath = `${installedPluginsPath}.bak.${timestamp}`;
|
|
1254
|
+
fs4.copyFileSync(installedPluginsPath, backupPath);
|
|
1255
|
+
const installed = JSON.parse(fs4.readFileSync(installedPluginsPath, "utf-8"));
|
|
1256
|
+
if (installed?.plugins && typeof installed.plugins === "object") {
|
|
1257
|
+
for (const key of Object.keys(installed.plugins)) {
|
|
1258
|
+
if (key.endsWith(`@${MARKET_NAME}`)) {
|
|
1259
|
+
delete installed.plugins[key];
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1018
1263
|
try {
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
console.
|
|
1022
|
-
} catch {
|
|
1023
|
-
|
|
1264
|
+
fs4.writeFileSync(installedPluginsPath, JSON.stringify(installed, null, 2), "utf-8");
|
|
1265
|
+
fs4.unlinkSync(backupPath);
|
|
1266
|
+
console.log(chalk4.red(" removed") + chalk4.dim(` set-prompt entries from: ${installedPluginsPath}`));
|
|
1267
|
+
} catch (ex) {
|
|
1268
|
+
fs4.copyFileSync(backupPath, installedPluginsPath);
|
|
1269
|
+
fs4.unlinkSync(backupPath);
|
|
1270
|
+
console.warn(chalk4.yellow(" \u26A0 Write failed \u2014 rolled back installed_plugins.json."));
|
|
1024
1271
|
}
|
|
1025
|
-
|
|
1272
|
+
} catch (ex) {
|
|
1273
|
+
console.error(chalk4.red(` \u274C Failed to clean up installed_plugins.json: ${ex.message}`));
|
|
1026
1274
|
}
|
|
1275
|
+
}
|
|
1276
|
+
const knownMarketplacesPath = path4.join(claudePluginsDir, "known_marketplaces.json");
|
|
1277
|
+
if (fs4.existsSync(knownMarketplacesPath)) {
|
|
1027
1278
|
try {
|
|
1028
|
-
|
|
1029
|
-
|
|
1279
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1280
|
+
const backupPath = `${knownMarketplacesPath}.bak.${timestamp}`;
|
|
1281
|
+
fs4.copyFileSync(knownMarketplacesPath, backupPath);
|
|
1282
|
+
const marketplaces = JSON.parse(fs4.readFileSync(knownMarketplacesPath, "utf-8"));
|
|
1283
|
+
if (marketplaces?.[MARKET_NAME] !== void 0) {
|
|
1284
|
+
delete marketplaces[MARKET_NAME];
|
|
1285
|
+
}
|
|
1286
|
+
try {
|
|
1287
|
+
fs4.writeFileSync(knownMarketplacesPath, JSON.stringify(marketplaces, null, 2), "utf-8");
|
|
1288
|
+
fs4.unlinkSync(backupPath);
|
|
1289
|
+
console.log(chalk4.red(" removed") + chalk4.dim(` set-prompt entry from: ${knownMarketplacesPath}`));
|
|
1290
|
+
} catch (ex) {
|
|
1291
|
+
fs4.copyFileSync(backupPath, knownMarketplacesPath);
|
|
1292
|
+
fs4.unlinkSync(backupPath);
|
|
1293
|
+
console.warn(chalk4.yellow(" \u26A0 Write failed \u2014 rolled back known_marketplaces.json."));
|
|
1294
|
+
}
|
|
1295
|
+
} catch (ex) {
|
|
1296
|
+
console.error(chalk4.red(` \u274C Failed to clean up known_marketplaces.json: ${ex.message}`));
|
|
1030
1297
|
}
|
|
1031
|
-
console.log(chalk5.dim(` removed set-prompt entries from: ${claudeSettingsPath}`));
|
|
1032
|
-
} catch (ex) {
|
|
1033
|
-
console.error(chalk5.red(` \u274C Failed to clean up settings.json: ${ex.message}`));
|
|
1034
1298
|
}
|
|
1299
|
+
if (fs4.existsSync(CLAUDE_CODE_DIR)) {
|
|
1300
|
+
fs4.rmSync(CLAUDE_CODE_DIR, { recursive: true, force: true });
|
|
1301
|
+
console.log(chalk4.red(" removed") + chalk4.dim(`: ${CLAUDE_CODE_DIR}`));
|
|
1302
|
+
}
|
|
1303
|
+
configManager.claude_code = null;
|
|
1304
|
+
configManager.save();
|
|
1035
1305
|
};
|
|
1036
|
-
var
|
|
1306
|
+
var unlinkRooCode = async (force = false) => {
|
|
1307
|
+
if (!force) {
|
|
1308
|
+
const ok = await confirm3({
|
|
1309
|
+
message: `Remove RooCode symlinks from ${ROO_DIR}?`,
|
|
1310
|
+
default: false
|
|
1311
|
+
});
|
|
1312
|
+
if (!ok) {
|
|
1313
|
+
console.log(chalk4.yellow("Cancelled."));
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
console.log(chalk4.red(`
|
|
1318
|
+
Removing RooCode integration...`));
|
|
1319
|
+
console.log(chalk4.dim(ROO_DIR));
|
|
1037
1320
|
const backupPath = configManager.roocode?.backup_path ?? ROO_BACKUP_DIR;
|
|
1038
1321
|
for (const dir of AGENT_PROMPT_DIRS["roocode" /* ROOCODE */]) {
|
|
1039
|
-
const target =
|
|
1040
|
-
if (
|
|
1041
|
-
|
|
1042
|
-
console.log(
|
|
1322
|
+
const target = path4.join(ROO_DIR, dir);
|
|
1323
|
+
if (fs4.existsSync(target) && fs4.lstatSync(target).isSymbolicLink()) {
|
|
1324
|
+
fs4.unlinkSync(target);
|
|
1325
|
+
console.log(chalk4.red(" removed symlink") + chalk4.dim(`: ${target}`));
|
|
1043
1326
|
}
|
|
1044
1327
|
}
|
|
1045
|
-
if (
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1328
|
+
if (fs4.existsSync(backupPath)) {
|
|
1329
|
+
try {
|
|
1330
|
+
for (const dir of AGENT_PROMPT_DIRS["roocode" /* ROOCODE */]) {
|
|
1331
|
+
const src = path4.join(backupPath, dir);
|
|
1332
|
+
const dest = path4.join(ROO_DIR, dir);
|
|
1333
|
+
if (!fs4.existsSync(src)) {
|
|
1334
|
+
continue;
|
|
1335
|
+
}
|
|
1336
|
+
fs4.renameSync(src, dest);
|
|
1337
|
+
console.log(chalk4.green(" restored") + chalk4.dim(`: ${dir}/`));
|
|
1054
1338
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1339
|
+
fs4.rmdirSync(backupPath);
|
|
1340
|
+
} catch (ex) {
|
|
1341
|
+
console.error(chalk4.red(` \u274C Failed to restore RooCode backup: ${ex.message}`));
|
|
1057
1342
|
}
|
|
1058
|
-
fs5.rmdirSync(backupPath);
|
|
1059
|
-
} catch (ex) {
|
|
1060
|
-
console.error(chalk5.red(` \u274C Failed to restore RooCode backup: ${ex.message}`));
|
|
1061
1343
|
}
|
|
1344
|
+
configManager.roocode = null;
|
|
1345
|
+
configManager.save();
|
|
1062
1346
|
};
|
|
1063
|
-
var
|
|
1347
|
+
var unlinkOpenclaw = async (force = false) => {
|
|
1348
|
+
if (!force) {
|
|
1349
|
+
const ok = await confirm3({
|
|
1350
|
+
message: `Remove OpenClaw symlinks from ${OPENCLAW_DIR}?`,
|
|
1351
|
+
default: false
|
|
1352
|
+
});
|
|
1353
|
+
if (!ok) {
|
|
1354
|
+
console.log(chalk4.yellow("Cancelled."));
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
console.log(chalk4.red(`
|
|
1359
|
+
Removing OpenClaw integration...`));
|
|
1360
|
+
console.log(chalk4.dim(OPENCLAW_DIR));
|
|
1064
1361
|
const backupPath = configManager.openclaw?.backup_path ?? OPENCLAW_BACKUP_DIR;
|
|
1065
1362
|
for (const dir of AGENT_PROMPT_DIRS["openclaw" /* OPENCLAW */]) {
|
|
1066
|
-
const target =
|
|
1067
|
-
if (
|
|
1068
|
-
|
|
1069
|
-
console.log(
|
|
1363
|
+
const target = path4.join(OPENCLAW_DIR, dir);
|
|
1364
|
+
if (fs4.existsSync(target) && fs4.lstatSync(target).isSymbolicLink()) {
|
|
1365
|
+
fs4.unlinkSync(target);
|
|
1366
|
+
console.log(chalk4.red(" removed symlink") + chalk4.dim(`: ${target}`));
|
|
1070
1367
|
}
|
|
1071
1368
|
}
|
|
1072
|
-
if (
|
|
1369
|
+
if (fs4.existsSync(backupPath)) {
|
|
1370
|
+
try {
|
|
1371
|
+
for (const dir of AGENT_PROMPT_DIRS["openclaw" /* OPENCLAW */]) {
|
|
1372
|
+
const src = path4.join(backupPath, dir);
|
|
1373
|
+
const dest = path4.join(OPENCLAW_DIR, dir);
|
|
1374
|
+
if (!fs4.existsSync(src)) {
|
|
1375
|
+
continue;
|
|
1376
|
+
}
|
|
1377
|
+
fs4.renameSync(src, dest);
|
|
1378
|
+
console.log(chalk4.green(" restored") + chalk4.dim(`: ${dir}/`));
|
|
1379
|
+
}
|
|
1380
|
+
fs4.rmdirSync(backupPath);
|
|
1381
|
+
} catch (ex) {
|
|
1382
|
+
console.error(chalk4.red(` \u274C Failed to restore OpenClaw backup: ${ex.message}`));
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
configManager.openclaw = null;
|
|
1386
|
+
configManager.save();
|
|
1387
|
+
};
|
|
1388
|
+
var unlinkAntigravity = async (force = false) => {
|
|
1389
|
+
if (!force) {
|
|
1390
|
+
const ok = await confirm3({
|
|
1391
|
+
message: `Remove Antigravity symlinks from ${ANTIGRAVITY_DIR}?`,
|
|
1392
|
+
default: false
|
|
1393
|
+
});
|
|
1394
|
+
if (!ok) {
|
|
1395
|
+
console.log(chalk4.yellow("Cancelled."));
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
console.log(chalk4.red(`
|
|
1400
|
+
Removing Antigravity integration...`));
|
|
1401
|
+
console.log(chalk4.dim(ANTIGRAVITY_DIR));
|
|
1402
|
+
const backupPath = configManager.antigravity?.backup_path ?? ANTIGRAVITY_BACKUP_DIR;
|
|
1403
|
+
for (const dir of AGENT_PROMPT_DIRS["antigravity" /* ANTIGRAVITY */]) {
|
|
1404
|
+
const target = path4.join(ANTIGRAVITY_DIR, dir);
|
|
1405
|
+
if (fs4.existsSync(target) && fs4.lstatSync(target).isSymbolicLink()) {
|
|
1406
|
+
fs4.unlinkSync(target);
|
|
1407
|
+
console.log(chalk4.red(" removed symlink") + chalk4.dim(`: ${target}`));
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
if (fs4.existsSync(backupPath)) {
|
|
1411
|
+
try {
|
|
1412
|
+
for (const dir of AGENT_PROMPT_DIRS["antigravity" /* ANTIGRAVITY */]) {
|
|
1413
|
+
const src = path4.join(backupPath, dir);
|
|
1414
|
+
const dest = path4.join(ANTIGRAVITY_DIR, dir);
|
|
1415
|
+
if (!fs4.existsSync(src)) {
|
|
1416
|
+
continue;
|
|
1417
|
+
}
|
|
1418
|
+
fs4.renameSync(src, dest);
|
|
1419
|
+
console.log(chalk4.green(" restored") + chalk4.dim(`: ${dir}/`));
|
|
1420
|
+
}
|
|
1421
|
+
fs4.rmdirSync(backupPath);
|
|
1422
|
+
} catch (ex) {
|
|
1423
|
+
console.error(chalk4.red(` \u274C Failed to restore Antigravity backup: ${ex.message}`));
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
configManager.antigravity = null;
|
|
1427
|
+
configManager.save();
|
|
1428
|
+
};
|
|
1429
|
+
var unlinkCodex = async (force = false) => {
|
|
1430
|
+
if (!force) {
|
|
1431
|
+
const ok = await confirm3({
|
|
1432
|
+
message: `Remove Codex symlinks from ${CODEX_DIR}?`,
|
|
1433
|
+
default: false
|
|
1434
|
+
});
|
|
1435
|
+
if (!ok) {
|
|
1436
|
+
console.log(chalk4.yellow("Cancelled."));
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
console.log(chalk4.red(`
|
|
1441
|
+
Removing Codex integration...`));
|
|
1442
|
+
console.log(chalk4.dim(CODEX_DIR));
|
|
1443
|
+
const backupPath = configManager.codex?.backup_path ?? CODEX_BACKUP_DIR;
|
|
1444
|
+
for (const dir of AGENT_PROMPT_DIRS["codex" /* CODEX */]) {
|
|
1445
|
+
const target = path4.join(CODEX_DIR, dir);
|
|
1446
|
+
if (fs4.existsSync(target) && fs4.lstatSync(target).isSymbolicLink()) {
|
|
1447
|
+
fs4.unlinkSync(target);
|
|
1448
|
+
console.log(chalk4.red(" removed symlink") + chalk4.dim(`: ${target}`));
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
if (fs4.existsSync(backupPath)) {
|
|
1452
|
+
try {
|
|
1453
|
+
for (const dir of AGENT_PROMPT_DIRS["codex" /* CODEX */]) {
|
|
1454
|
+
const src = path4.join(backupPath, dir);
|
|
1455
|
+
const dest = path4.join(CODEX_DIR, dir);
|
|
1456
|
+
if (!fs4.existsSync(src)) {
|
|
1457
|
+
continue;
|
|
1458
|
+
}
|
|
1459
|
+
fs4.renameSync(src, dest);
|
|
1460
|
+
console.log(chalk4.green(" restored") + chalk4.dim(`: ${dir}/`));
|
|
1461
|
+
}
|
|
1462
|
+
fs4.rmdirSync(backupPath);
|
|
1463
|
+
} catch (ex) {
|
|
1464
|
+
console.error(chalk4.red(` \u274C Failed to restore Codex backup: ${ex.message}`));
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
configManager.codex = null;
|
|
1468
|
+
configManager.save();
|
|
1469
|
+
};
|
|
1470
|
+
var unlinkCursor = async (force = false) => {
|
|
1471
|
+
if (!force) {
|
|
1472
|
+
const ok = await confirm3({
|
|
1473
|
+
message: `Remove Cursor plugin dir (${CURSOR_PLUGIN_DIR}) and plugin structure?`,
|
|
1474
|
+
default: false
|
|
1475
|
+
});
|
|
1476
|
+
if (!ok) {
|
|
1477
|
+
console.log(chalk4.yellow("Cancelled."));
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
console.log(chalk4.red(`
|
|
1482
|
+
Removing Cursor plugin...`));
|
|
1483
|
+
console.log(chalk4.dim(CURSOR_PLUGIN_DIR));
|
|
1484
|
+
fs4.rmSync(CURSOR_PLUGIN_DIR, { recursive: true, force: true });
|
|
1485
|
+
console.log(chalk4.red(" removed") + chalk4.dim(`: ${CURSOR_PLUGIN_DIR}`));
|
|
1486
|
+
if (fs4.existsSync(CURSOR_DIR)) {
|
|
1487
|
+
fs4.rmSync(CURSOR_DIR, { recursive: true, force: true });
|
|
1488
|
+
console.log(chalk4.red(" removed") + chalk4.dim(`: ${CURSOR_DIR}`));
|
|
1489
|
+
}
|
|
1490
|
+
configManager.cursor = null;
|
|
1491
|
+
configManager.save();
|
|
1492
|
+
};
|
|
1493
|
+
var linkCommand = async (tool) => {
|
|
1494
|
+
if (tool != null) {
|
|
1495
|
+
const known = ALL_AGENTS.some((a) => a.value === tool);
|
|
1496
|
+
if (!known) {
|
|
1497
|
+
console.log(chalk4.red(`Unknown vendor: ${tool}`));
|
|
1498
|
+
process.exit(1);
|
|
1499
|
+
}
|
|
1500
|
+
if (tool === "claudecode" /* CLAUDECODE */) {
|
|
1501
|
+
await linkClaudeCode();
|
|
1502
|
+
} else if (tool === "roocode" /* ROOCODE */) {
|
|
1503
|
+
await linkRooCode();
|
|
1504
|
+
} else if (tool === "openclaw" /* OPENCLAW */) {
|
|
1505
|
+
await linkOpenclaw();
|
|
1506
|
+
} else if (tool === "codex" /* CODEX */) {
|
|
1507
|
+
await linkCodex();
|
|
1508
|
+
} else if (tool === "antigravity" /* ANTIGRAVITY */) {
|
|
1509
|
+
await linkAntigravity();
|
|
1510
|
+
} else if (tool === "cursor" /* CURSOR */) {
|
|
1511
|
+
await linkCursor();
|
|
1512
|
+
}
|
|
1073
1513
|
return;
|
|
1074
1514
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1515
|
+
const prevLinked = {
|
|
1516
|
+
["claudecode" /* CLAUDECODE */]: configManager.isClaudeCodeEnabled(),
|
|
1517
|
+
["roocode" /* ROOCODE */]: configManager.isRooCodeEnabled(),
|
|
1518
|
+
["openclaw" /* OPENCLAW */]: configManager.isOpenclawEnabled(),
|
|
1519
|
+
["codex" /* CODEX */]: configManager.isCodexEnabled(),
|
|
1520
|
+
["antigravity" /* ANTIGRAVITY */]: configManager.isAntigravityEnabled(),
|
|
1521
|
+
["cursor" /* CURSOR */]: configManager.isCursorEnabled()
|
|
1522
|
+
};
|
|
1523
|
+
const selected = await checkbox({
|
|
1524
|
+
message: "Which AI agent do you want to integrate?",
|
|
1525
|
+
choices: ALL_AGENTS.map((a) => ({
|
|
1526
|
+
name: prevLinked[a.value] ? `${a.name} ${chalk4.dim("(applied)")}` : a.name,
|
|
1527
|
+
value: a.value,
|
|
1528
|
+
checked: prevLinked[a.value]
|
|
1529
|
+
}))
|
|
1530
|
+
});
|
|
1531
|
+
const toLink = ALL_AGENTS.filter((a) => !prevLinked[a.value] && selected.includes(a.value));
|
|
1532
|
+
const toUnlink = ALL_AGENTS.filter((a) => prevLinked[a.value] && !selected.includes(a.value));
|
|
1533
|
+
console.log();
|
|
1534
|
+
if (toLink.length > 0) {
|
|
1535
|
+
console.log(chalk4.green(" Link ") + chalk4.dim("\u2192 ") + toLink.map((a) => chalk4.bold(a.name)).join(chalk4.dim(", ")));
|
|
1536
|
+
}
|
|
1537
|
+
if (toUnlink.length > 0) {
|
|
1538
|
+
console.log(chalk4.red(" Unlink ") + chalk4.dim("\u2192 ") + toUnlink.map((a) => chalk4.bold(a.name)).join(chalk4.dim(", ")));
|
|
1539
|
+
}
|
|
1540
|
+
console.log();
|
|
1541
|
+
if (toLink.length === 0 && toUnlink.length === 0) {
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
for (const a of ALL_AGENTS) {
|
|
1545
|
+
const was = prevLinked[a.value];
|
|
1546
|
+
const now = selected.includes(a.value);
|
|
1547
|
+
if (!was && now) {
|
|
1548
|
+
if (a.value === "claudecode" /* CLAUDECODE */) {
|
|
1549
|
+
await linkClaudeCode();
|
|
1550
|
+
} else if (a.value === "roocode" /* ROOCODE */) {
|
|
1551
|
+
await linkRooCode();
|
|
1552
|
+
} else if (a.value === "openclaw" /* OPENCLAW */) {
|
|
1553
|
+
await linkOpenclaw();
|
|
1554
|
+
} else if (a.value === "codex" /* CODEX */) {
|
|
1555
|
+
await linkCodex();
|
|
1556
|
+
} else if (a.value === "antigravity" /* ANTIGRAVITY */) {
|
|
1557
|
+
await linkAntigravity();
|
|
1558
|
+
} else if (a.value === "cursor" /* CURSOR */) {
|
|
1559
|
+
await linkCursor();
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
if (was && !now) {
|
|
1563
|
+
if (a.value === "claudecode" /* CLAUDECODE */) {
|
|
1564
|
+
await unlinkClaudeCode(true);
|
|
1565
|
+
} else if (a.value === "roocode" /* ROOCODE */) {
|
|
1566
|
+
await unlinkRooCode(true);
|
|
1567
|
+
} else if (a.value === "openclaw" /* OPENCLAW */) {
|
|
1568
|
+
await unlinkOpenclaw(true);
|
|
1569
|
+
} else if (a.value === "codex" /* CODEX */) {
|
|
1570
|
+
await unlinkCodex(true);
|
|
1571
|
+
} else if (a.value === "antigravity" /* ANTIGRAVITY */) {
|
|
1572
|
+
await unlinkAntigravity(true);
|
|
1573
|
+
} else if (a.value === "cursor" /* CURSOR */) {
|
|
1574
|
+
await unlinkCursor(true);
|
|
1081
1575
|
}
|
|
1082
|
-
fs5.renameSync(src, dest);
|
|
1083
|
-
console.log(chalk5.dim(` restored: ${dir}/`));
|
|
1084
1576
|
}
|
|
1085
|
-
fs5.rmdirSync(backupPath);
|
|
1086
|
-
} catch (ex) {
|
|
1087
|
-
console.error(chalk5.red(` \u274C Failed to restore OpenClaw backup: ${ex.message}`));
|
|
1088
1577
|
}
|
|
1089
1578
|
};
|
|
1579
|
+
|
|
1580
|
+
// src/commands/uninstall-command.ts
|
|
1581
|
+
import fs5 from "fs";
|
|
1582
|
+
import chalk5 from "chalk";
|
|
1583
|
+
import { confirm as confirm4 } from "@inquirer/prompts";
|
|
1090
1584
|
var uninstallCommand = async () => {
|
|
1091
1585
|
const targets = [
|
|
1092
|
-
{ label: `
|
|
1093
|
-
{ label: `
|
|
1094
|
-
{ label: `Home dir ${chalk5.dim(HOME_DIR)}`, path: HOME_DIR }
|
|
1586
|
+
{ label: `Config file ${chalk5.dim(CONFIG_PATH)}`, path: CONFIG_PATH },
|
|
1587
|
+
{ label: `Home dir ${chalk5.dim(HOME_DIR)}`, path: HOME_DIR }
|
|
1095
1588
|
].filter((t) => fs5.existsSync(t.path));
|
|
1096
|
-
const
|
|
1589
|
+
const hasClaudeCode = configManager.isClaudeCodeEnabled();
|
|
1097
1590
|
const hasRooCode = configManager.isRooCodeEnabled();
|
|
1098
1591
|
const hasOpenclaw = configManager.isOpenclawEnabled();
|
|
1099
|
-
|
|
1592
|
+
const hasAntigravity = configManager.isAntigravityEnabled();
|
|
1593
|
+
const hasCodex = configManager.isCodexEnabled();
|
|
1594
|
+
const hasCursor = configManager.isCursorEnabled();
|
|
1595
|
+
if (targets.length === 0 && !hasClaudeCode && !hasRooCode && !hasOpenclaw && !hasAntigravity && !hasCodex && !hasCursor) {
|
|
1100
1596
|
console.log(chalk5.yellow("Nothing to remove."));
|
|
1101
1597
|
return;
|
|
1102
1598
|
}
|
|
1103
1599
|
console.log(chalk5.red("\nThe following will be removed:"));
|
|
1104
1600
|
targets.forEach((t) => console.log(` ${t.label}`));
|
|
1105
|
-
if (
|
|
1106
|
-
|
|
1107
|
-
console.log(` set-prompt entries in ${chalk5.dim(claudeSettingsPath)}`);
|
|
1601
|
+
if (hasClaudeCode) {
|
|
1602
|
+
console.log(` Claude Code plugin dir ${chalk5.dim(CLAUDE_CODE_DIR)}`);
|
|
1108
1603
|
}
|
|
1109
1604
|
if (hasRooCode) {
|
|
1110
|
-
console.log(` RooCode symlinks
|
|
1605
|
+
console.log(` RooCode symlinks ${chalk5.dim("(backup will be restored)")}`);
|
|
1111
1606
|
}
|
|
1112
1607
|
if (hasOpenclaw) {
|
|
1113
|
-
console.log(` OpenClaw symlinks
|
|
1608
|
+
console.log(` OpenClaw symlinks ${chalk5.dim("(backup will be restored)")}`);
|
|
1609
|
+
}
|
|
1610
|
+
if (hasAntigravity) {
|
|
1611
|
+
console.log(` Antigravity symlinks ${chalk5.dim("(backup will be restored)")}`);
|
|
1612
|
+
}
|
|
1613
|
+
if (hasCodex) {
|
|
1614
|
+
console.log(` Codex symlinks ${chalk5.dim("(backup will be restored)")}`);
|
|
1615
|
+
}
|
|
1616
|
+
if (hasCursor) {
|
|
1617
|
+
console.log(` Cursor plugin dir ${chalk5.dim("(symlink will be removed)")}`);
|
|
1114
1618
|
}
|
|
1115
1619
|
const ok = await confirm4({ message: "Proceed?", default: false });
|
|
1116
|
-
if (ok
|
|
1620
|
+
if (!ok) {
|
|
1117
1621
|
console.log(chalk5.yellow("Cancelled."));
|
|
1118
1622
|
return;
|
|
1119
1623
|
}
|
|
1120
|
-
if (
|
|
1121
|
-
|
|
1624
|
+
if (hasClaudeCode) {
|
|
1625
|
+
await unlinkClaudeCode(true);
|
|
1122
1626
|
}
|
|
1123
1627
|
if (hasRooCode) {
|
|
1124
|
-
|
|
1628
|
+
await unlinkRooCode(true);
|
|
1125
1629
|
}
|
|
1126
1630
|
if (hasOpenclaw) {
|
|
1127
|
-
|
|
1631
|
+
await unlinkOpenclaw(true);
|
|
1632
|
+
}
|
|
1633
|
+
if (hasAntigravity) {
|
|
1634
|
+
await unlinkAntigravity(true);
|
|
1635
|
+
}
|
|
1636
|
+
if (hasCodex) {
|
|
1637
|
+
await unlinkCodex(true);
|
|
1638
|
+
}
|
|
1639
|
+
if (hasCursor) {
|
|
1640
|
+
await unlinkCursor(true);
|
|
1128
1641
|
}
|
|
1129
1642
|
for (const t of targets) {
|
|
1130
1643
|
fs5.rmSync(t.path, { recursive: true, force: true });
|
|
@@ -1214,8 +1727,8 @@ process.on("unhandledRejection", (reason) => {
|
|
|
1214
1727
|
}
|
|
1215
1728
|
throw reason;
|
|
1216
1729
|
});
|
|
1217
|
-
var __dirname =
|
|
1218
|
-
var pkg = JSON.parse(fs6.readFileSync(
|
|
1730
|
+
var __dirname = path5.dirname(fileURLToPath(import.meta.url));
|
|
1731
|
+
var pkg = JSON.parse(fs6.readFileSync(path5.join(__dirname, "../package.json"), "utf-8"));
|
|
1219
1732
|
configManager.init();
|
|
1220
1733
|
var program = new Command();
|
|
1221
1734
|
var banner = chalk8.cyan(figlet.textSync("Set-Prompt", { horizontalLayout: "full" }));
|