ccjk 11.1.2 → 12.0.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.
Files changed (99) hide show
  1. package/dist/chunks/agent-teams.mjs +1 -1
  2. package/dist/chunks/agent.mjs +1 -1
  3. package/dist/chunks/api-cli.mjs +118 -0
  4. package/dist/chunks/api-providers.mjs +1 -1
  5. package/dist/chunks/api.mjs +8 -759
  6. package/dist/chunks/auto-bootstrap.mjs +1 -1
  7. package/dist/chunks/auto-init.mjs +1 -1
  8. package/dist/chunks/auto-updater.mjs +1 -1
  9. package/dist/chunks/banner.mjs +1 -1
  10. package/dist/chunks/boost.mjs +1 -1
  11. package/dist/chunks/ccjk-agents.mjs +1 -1
  12. package/dist/chunks/ccjk-all.mjs +1 -1
  13. package/dist/chunks/ccjk-config.mjs +1 -1
  14. package/dist/chunks/ccjk-hooks.mjs +1 -1
  15. package/dist/chunks/ccjk-mcp.mjs +1 -1
  16. package/dist/chunks/ccjk-setup.mjs +1 -1
  17. package/dist/chunks/ccjk-skills.mjs +1 -1
  18. package/dist/chunks/ccr.mjs +6 -6
  19. package/dist/chunks/ccu.mjs +1 -1
  20. package/dist/chunks/check-updates.mjs +2 -2
  21. package/dist/chunks/claude-code-config-manager.mjs +2 -2
  22. package/dist/chunks/claude-code-incremental-manager.mjs +2 -2
  23. package/dist/chunks/claude-config.mjs +1 -1
  24. package/dist/chunks/claude-wrapper.mjs +1 -1
  25. package/dist/chunks/codex-config-switch.mjs +1 -1
  26. package/dist/chunks/codex-provider-manager.mjs +1 -1
  27. package/dist/chunks/codex-uninstaller.mjs +1 -1
  28. package/dist/chunks/codex.mjs +1 -1
  29. package/dist/chunks/commands.mjs +1 -1
  30. package/dist/chunks/completion.mjs +1 -1
  31. package/dist/chunks/config-consolidator.mjs +1 -1
  32. package/dist/chunks/config-switch.mjs +2 -2
  33. package/dist/chunks/config.mjs +1 -1
  34. package/dist/chunks/config2.mjs +1 -1
  35. package/dist/chunks/config3.mjs +1 -1
  36. package/dist/chunks/constants.mjs +1 -1
  37. package/dist/chunks/dashboard.mjs +1 -1
  38. package/dist/chunks/doctor.mjs +31 -7
  39. package/dist/chunks/evolution.mjs +1 -1
  40. package/dist/chunks/features.mjs +5 -5
  41. package/dist/chunks/index.mjs +7 -7
  42. package/dist/chunks/index2.mjs +10 -177
  43. package/dist/chunks/index3.mjs +168 -1162
  44. package/dist/chunks/index4.mjs +1076 -910
  45. package/dist/chunks/index5.mjs +947 -137
  46. package/dist/chunks/index6.mjs +167 -635
  47. package/dist/chunks/index7.mjs +663 -0
  48. package/dist/chunks/init.mjs +17 -17
  49. package/dist/chunks/installer.mjs +1 -1
  50. package/dist/chunks/interview.mjs +2 -2
  51. package/dist/chunks/marketplace.mjs +1 -1
  52. package/dist/chunks/mcp-cli.mjs +191 -0
  53. package/dist/chunks/mcp.mjs +2 -2
  54. package/dist/chunks/menu.mjs +3 -3
  55. package/dist/chunks/migrator.mjs +1 -1
  56. package/dist/chunks/monitor.mjs +1 -1
  57. package/dist/chunks/notification.mjs +1 -1
  58. package/dist/chunks/onboarding.mjs +1 -1
  59. package/dist/chunks/package.mjs +1 -1
  60. package/dist/chunks/permission-manager.mjs +1 -1
  61. package/dist/chunks/permissions.mjs +1 -1
  62. package/dist/chunks/persistence-manager.mjs +1 -1
  63. package/dist/chunks/plugin.mjs +1 -1
  64. package/dist/chunks/prompts.mjs +1 -1
  65. package/dist/chunks/providers.mjs +1 -1
  66. package/dist/chunks/quick-actions.mjs +1 -1
  67. package/dist/chunks/quick-setup.mjs +5 -5
  68. package/dist/chunks/remote.mjs +2 -2
  69. package/dist/chunks/silent-updater.mjs +1 -1
  70. package/dist/chunks/simple-config.mjs +1 -1
  71. package/dist/chunks/skill.mjs +1 -1
  72. package/dist/chunks/skills-sync.mjs +1 -1
  73. package/dist/chunks/skills.mjs +1 -1
  74. package/dist/chunks/slash-commands.mjs +2 -2
  75. package/dist/chunks/startup.mjs +1 -1
  76. package/dist/chunks/stats.mjs +1 -1
  77. package/dist/chunks/status.mjs +1 -1
  78. package/dist/chunks/team.mjs +1 -1
  79. package/dist/chunks/thinking.mjs +2 -2
  80. package/dist/chunks/uninstall.mjs +3 -3
  81. package/dist/chunks/update.mjs +4 -4
  82. package/dist/chunks/upgrade-manager.mjs +1 -1
  83. package/dist/chunks/version-checker.mjs +1 -1
  84. package/dist/chunks/vim.mjs +1 -1
  85. package/dist/chunks/zero-config.mjs +1 -1
  86. package/dist/cli.mjs +76 -16
  87. package/dist/index.d.mts +37 -10
  88. package/dist/index.d.ts +37 -10
  89. package/dist/index.mjs +2 -2
  90. package/dist/shared/{ccjk.DB2UYcq0.mjs → ccjk.BOIUTf5z.mjs} +2 -2
  91. package/dist/shared/ccjk.CL4Yat0G.mjs +303 -0
  92. package/dist/shared/{ccjk.CxtuJxaS.mjs → ccjk.CN0edl87.mjs} +1 -1
  93. package/dist/shared/{ccjk.BKoi8-Hy.mjs → ccjk.CrB6OYHv.mjs} +1 -1
  94. package/dist/shared/{ccjk.DVBW2wxp.mjs → ccjk.Dk1HDseQ.mjs} +1 -1
  95. package/dist/shared/ccjk.bhFAMRyc.mjs +460 -0
  96. package/dist/shared/ccjk.cChAaGgT.mjs +88 -0
  97. package/dist/shared/{ccjk.DrMygfCF.mjs → ccjk.j4uut26D.mjs} +1 -1
  98. package/package.json +2 -3
  99. package/dist/shared/ccjk.Cu_R2MbQ.mjs +0 -75
@@ -1,195 +1,1005 @@
1
- import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
- import { homedir } from 'node:os';
3
- import process__default from 'node:process';
4
- import { join } from 'pathe';
5
- import { i as installSuperpowers } from '../shared/ccjk.BKoi8-Hy.mjs';
6
- import 'node:child_process';
7
- import 'node:fs/promises';
8
- import 'node:util';
9
- import './index2.mjs';
10
- import 'node:url';
11
- import 'i18next';
12
- import 'i18next-fs-backend';
1
+ import ansis from 'ansis';
2
+ import ora from 'ora';
3
+ import fs from 'node:fs/promises';
4
+ import os__default from 'node:os';
5
+ import path__default from 'node:path';
6
+ import { exec } from 'node:child_process';
7
+ import { promisify } from 'node:util';
13
8
 
14
- const CORE_SKILLS = [
15
- "agent-browser",
16
- "tdd",
17
- "debugging",
18
- "code-review",
19
- "git-worktrees"
20
- ];
21
-
22
- function getSuperpowersDir$1() {
23
- return join(homedir(), ".claude", "plugins", "superpowers");
9
+ function getCcjkConfigDir() {
10
+ if (process.env.CCJK_CONFIG_DIR) {
11
+ return process.env.CCJK_CONFIG_DIR;
12
+ }
13
+ return path__default.join(os__default.homedir(), ".ccjk");
24
14
  }
25
- function isSuperpowersInstalled() {
26
- const superpowersDir = getSuperpowersDir$1();
27
- return existsSync(superpowersDir) && existsSync(join(superpowersDir, "skills"));
15
+ function getInstallPath(pluginType, name) {
16
+ const configDir = getCcjkConfigDir();
17
+ const typeDir = {
18
+ skill: "skills",
19
+ mcp: "mcp-servers",
20
+ agent: "agents",
21
+ hook: "hooks"
22
+ }[pluginType];
23
+ return path__default.join(configDir, typeDir, name);
28
24
  }
29
- function areCoreSkillsInstalled() {
30
- const skillsDir = join(getSuperpowersDir$1(), "skills");
31
- if (!existsSync(skillsDir)) {
32
- return false;
33
- }
34
- for (const skill of CORE_SKILLS) {
35
- const skillPath = join(skillsDir, skill);
36
- if (!existsSync(skillPath) || !existsSync(join(skillPath, "skill.json"))) {
37
- return false;
25
+ async function copyDirectory(src, dest) {
26
+ await fs.mkdir(dest, { recursive: true });
27
+ const entries = await fs.readdir(src, { withFileTypes: true });
28
+ for (const entry of entries) {
29
+ const srcPath = path__default.join(src, entry.name);
30
+ const destPath = path__default.join(dest, entry.name);
31
+ if (entry.isDirectory()) {
32
+ await copyDirectory(srcPath, destPath);
33
+ } else {
34
+ await fs.copyFile(srcPath, destPath);
38
35
  }
39
36
  }
40
- return true;
41
37
  }
42
- async function autoInstallSuperpowers(lang = "zh-CN") {
38
+ async function downloadFile(url, destPath) {
39
+ const response = await fetch(url, {
40
+ headers: {
41
+ "User-Agent": "ccjk-cli"
42
+ },
43
+ redirect: "follow"
44
+ });
45
+ if (!response.ok) {
46
+ throw new Error(`Failed to download: ${response.statusText}`);
47
+ }
48
+ const buffer = Buffer.from(await response.arrayBuffer());
49
+ await fs.writeFile(destPath, buffer);
50
+ }
51
+
52
+ async function installFromGitHub(sourceInfo, pluginType, options = {}) {
53
+ const { force = false, dryRun = false } = options;
54
+ const { owner, repo, ref = "main", subpath } = sourceInfo;
43
55
  try {
44
- if (isSuperpowersInstalled() && areCoreSkillsInstalled()) {
45
- return true;
46
- }
47
- const result = await installSuperpowers({
48
- lang,
49
- skipPrompt: true
50
- // Skip user prompts for silent installation
51
- });
52
- if (!result.success) {
53
- if (process__default.env.DEBUG) {
54
- console.error("[CCJK Zero-Config] Installation failed:", result.error || result.message);
56
+ const repoInfo = await fetchRepoInfo(owner, repo);
57
+ const defaultBranch = repoInfo.default_branch || "main";
58
+ const actualRef = ref || defaultBranch;
59
+ const installPath = getInstallPath(pluginType, repo);
60
+ if (!force) {
61
+ try {
62
+ await fs.access(installPath);
63
+ return {
64
+ success: false,
65
+ source: sourceInfo.originalUrl,
66
+ sourceType: "github",
67
+ pluginType,
68
+ error: `Plugin already exists at ${installPath}. Use --force to overwrite.`
69
+ };
70
+ } catch {
55
71
  }
56
- return false;
57
72
  }
58
- return isSuperpowersInstalled() && areCoreSkillsInstalled();
73
+ if (dryRun) {
74
+ const files = await listRepoFiles(owner, repo, actualRef, subpath);
75
+ return {
76
+ success: true,
77
+ source: sourceInfo.originalUrl,
78
+ sourceType: "github",
79
+ pluginType,
80
+ installedPath: installPath,
81
+ details: {
82
+ name: repo,
83
+ version: actualRef,
84
+ description: repoInfo.description || void 0,
85
+ files: files.slice(0, 20)
86
+ }
87
+ };
88
+ }
89
+ const tempDir = await downloadRepo(owner, repo, actualRef);
90
+ const sourcePath = subpath ? path__default.join(tempDir, subpath) : tempDir;
91
+ await fs.mkdir(path__default.dirname(installPath), { recursive: true });
92
+ await copyDirectory(sourcePath, installPath);
93
+ await fs.rm(tempDir, { recursive: true, force: true });
94
+ const installedFiles = await listInstalledFiles$1(installPath);
95
+ return {
96
+ success: true,
97
+ source: sourceInfo.originalUrl,
98
+ sourceType: "github",
99
+ pluginType,
100
+ installedPath: installPath,
101
+ details: {
102
+ name: repo,
103
+ version: actualRef,
104
+ description: repoInfo.description || void 0,
105
+ files: installedFiles
106
+ }
107
+ };
59
108
  } catch (error) {
60
- if (process__default.env.DEBUG) {
61
- console.error("[CCJK Zero-Config] Auto-install failed:", error);
109
+ return {
110
+ success: false,
111
+ source: sourceInfo.originalUrl,
112
+ sourceType: "github",
113
+ pluginType,
114
+ error: error instanceof Error ? error.message : String(error)
115
+ };
116
+ }
117
+ }
118
+ async function fetchRepoInfo(owner, repo) {
119
+ const url = `https://api.github.com/repos/${owner}/${repo}`;
120
+ const response = await fetch(url, {
121
+ headers: {
122
+ "Accept": "application/vnd.github.v3+json",
123
+ "User-Agent": "ccjk-cli"
124
+ }
125
+ });
126
+ if (!response.ok) {
127
+ if (response.status === 404) {
128
+ throw new Error(`Repository not found: ${owner}/${repo}`);
62
129
  }
63
- return false;
130
+ throw new Error(`Failed to fetch repository info: ${response.statusText}`);
64
131
  }
132
+ return response.json();
65
133
  }
66
-
67
- function getSkillsDir() {
68
- return join(homedir(), ".claude", "plugins", "superpowers", "skills");
134
+ async function listRepoFiles(owner, repo, ref, subpath) {
135
+ const treePath = subpath || "";
136
+ const url = `https://api.github.com/repos/${owner}/${repo}/git/trees/${ref}?recursive=1`;
137
+ const response = await fetch(url, {
138
+ headers: {
139
+ "Accept": "application/vnd.github.v3+json",
140
+ "User-Agent": "ccjk-cli"
141
+ }
142
+ });
143
+ if (!response.ok) {
144
+ return [];
145
+ }
146
+ const data = await response.json();
147
+ const files = (data.tree || []).filter((item) => item.type === "blob").map((item) => item.path).filter((filePath) => !treePath || filePath.startsWith(treePath));
148
+ return files;
149
+ }
150
+ async function downloadRepo(owner, repo, ref) {
151
+ const zipUrl = `https://github.com/${owner}/${repo}/archive/${ref}.zip`;
152
+ const tempDir = path__default.join(os__default.tmpdir(), `ccjk-${repo}-${Date.now()}`);
153
+ const zipPath = path__default.join(tempDir, "repo.zip");
154
+ await fs.mkdir(tempDir, { recursive: true });
155
+ await downloadFile(zipUrl, zipPath);
156
+ const extractedDir = await extractZip(zipPath, tempDir);
157
+ await fs.unlink(zipPath);
158
+ return extractedDir;
69
159
  }
70
- function isSkillInstalled(skillName) {
71
- const skillPath = join(getSkillsDir(), skillName);
72
- return existsSync(skillPath) && existsSync(join(skillPath, "skill.json"));
160
+ async function extractZip(zipPath, destDir) {
161
+ const { exec } = await import('node:child_process');
162
+ const { promisify } = await import('node:util');
163
+ const execAsync = promisify(exec);
164
+ try {
165
+ await execAsync(`unzip -q "${zipPath}" -d "${destDir}"`);
166
+ } catch {
167
+ try {
168
+ await execAsync(`tar -xf "${zipPath}" -C "${destDir}"`);
169
+ } catch {
170
+ throw new Error("Failed to extract archive. Please ensure unzip or tar is installed.");
171
+ }
172
+ }
173
+ const entries = await fs.readdir(destDir);
174
+ const extractedDir = entries.find((entry) => !entry.endsWith(".zip"));
175
+ if (!extractedDir) {
176
+ throw new Error("Failed to find extracted directory");
177
+ }
178
+ return path__default.join(destDir, extractedDir);
179
+ }
180
+ async function listInstalledFiles$1(dir) {
181
+ const files = [];
182
+ async function walk(currentDir, prefix = "") {
183
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
184
+ for (const entry of entries) {
185
+ const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
186
+ if (entry.isDirectory()) {
187
+ await walk(path__default.join(currentDir, entry.name), relativePath);
188
+ } else {
189
+ files.push(relativePath);
190
+ }
191
+ }
192
+ }
193
+ await walk(dir);
194
+ return files;
73
195
  }
74
- async function loadSkill(skillName) {
196
+
197
+ async function installFromLocal(sourceInfo, pluginType, options = {}) {
198
+ const { force = false, dryRun = false } = options;
199
+ const { absolutePath, originalPath } = sourceInfo;
75
200
  try {
76
- if (!isSkillInstalled(skillName)) {
201
+ const stat = await fs.stat(absolutePath);
202
+ const isFile = stat.isFile();
203
+ const isDirectory = stat.isDirectory();
204
+ if (!isFile && !isDirectory) {
77
205
  return {
78
- skill: skillName,
79
206
  success: false,
80
- error: "Skill not installed"
207
+ source: originalPath,
208
+ sourceType: "local",
209
+ pluginType,
210
+ error: `Source path is neither a file nor a directory: ${absolutePath}`
81
211
  };
82
212
  }
83
- const skillJsonPath = join(getSkillsDir(), skillName, "skill.json");
84
- const skillJson = JSON.parse(readFileSync(skillJsonPath, "utf-8"));
85
- if (!skillJson.name || !skillJson.version) {
213
+ const pluginName = path__default.basename(absolutePath, path__default.extname(absolutePath));
214
+ const installPath = getInstallPath(pluginType, pluginName);
215
+ if (!force) {
216
+ try {
217
+ await fs.access(installPath);
218
+ return {
219
+ success: false,
220
+ source: originalPath,
221
+ sourceType: "local",
222
+ pluginType,
223
+ error: `Plugin already exists at ${installPath}. Use --force to overwrite.`
224
+ };
225
+ } catch {
226
+ }
227
+ }
228
+ const files = isFile ? [path__default.basename(absolutePath)] : await listFiles(absolutePath);
229
+ const pluginInfo = await readPluginInfo(absolutePath, isFile);
230
+ if (dryRun) {
86
231
  return {
87
- skill: skillName,
88
- success: false,
89
- error: "Invalid skill.json format"
232
+ success: true,
233
+ source: originalPath,
234
+ sourceType: "local",
235
+ pluginType,
236
+ installedPath: installPath,
237
+ details: {
238
+ name: pluginInfo.name || pluginName,
239
+ version: pluginInfo.version,
240
+ description: pluginInfo.description,
241
+ files
242
+ }
90
243
  };
91
244
  }
245
+ if (isFile) {
246
+ await fs.mkdir(path__default.dirname(installPath), { recursive: true });
247
+ if (absolutePath.endsWith(".md")) {
248
+ await fs.copyFile(absolutePath, installPath);
249
+ } else {
250
+ await fs.mkdir(installPath, { recursive: true });
251
+ await fs.copyFile(
252
+ absolutePath,
253
+ path__default.join(installPath, path__default.basename(absolutePath))
254
+ );
255
+ }
256
+ } else {
257
+ await fs.mkdir(path__default.dirname(installPath), { recursive: true });
258
+ await copyDirectory(absolutePath, installPath);
259
+ }
260
+ const installedFiles = isFile ? [path__default.basename(absolutePath)] : await listFiles(installPath);
92
261
  return {
93
- skill: skillName,
94
- success: true
262
+ success: true,
263
+ source: originalPath,
264
+ sourceType: "local",
265
+ pluginType,
266
+ installedPath: installPath,
267
+ details: {
268
+ name: pluginInfo.name || pluginName,
269
+ version: pluginInfo.version,
270
+ description: pluginInfo.description,
271
+ files: installedFiles
272
+ }
95
273
  };
96
274
  } catch (error) {
97
275
  return {
98
- skill: skillName,
99
276
  success: false,
100
- error: error instanceof Error ? error.message : "Unknown error"
277
+ source: originalPath,
278
+ sourceType: "local",
279
+ pluginType,
280
+ error: error instanceof Error ? error.message : String(error)
101
281
  };
102
282
  }
103
283
  }
104
- async function loadCoreSkills(_lang = "zh-CN") {
105
- const results = await Promise.all(
106
- CORE_SKILLS.map((skill) => loadSkill(skill))
107
- );
108
- if (process__default.env.DEBUG) {
109
- const successful = results.filter((r) => r.success);
110
- const failed = results.filter((r) => !r.success);
111
- console.log(`[Zero-Config] Loaded ${successful.length}/${CORE_SKILLS.length} core skills`);
112
- if (failed.length > 0) {
113
- console.log(`[Zero-Config] Failed skills: ${failed.map((r) => r.skill).join(", ")}`);
284
+ async function listFiles(dir) {
285
+ const files = [];
286
+ async function walk(currentDir, prefix = "") {
287
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
288
+ for (const entry of entries) {
289
+ if (entry.name.startsWith(".") || entry.name === "node_modules") {
290
+ continue;
291
+ }
292
+ const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
293
+ if (entry.isDirectory()) {
294
+ await walk(path__default.join(currentDir, entry.name), relativePath);
295
+ } else {
296
+ files.push(relativePath);
297
+ }
114
298
  }
115
299
  }
116
- return results;
300
+ await walk(dir);
301
+ return files;
117
302
  }
118
-
119
- function getActivationStatePath() {
120
- return join(homedir(), ".claude", "plugins", "superpowers", ".activation-state.json");
121
- }
122
- function getSuperpowersDir() {
123
- return join(homedir(), ".claude", "plugins", "superpowers");
303
+ async function readPluginInfo(sourcePath, isFile) {
304
+ if (isFile) {
305
+ const name = path__default.basename(sourcePath, path__default.extname(sourcePath));
306
+ return { name };
307
+ }
308
+ try {
309
+ const packageJsonPath = path__default.join(sourcePath, "package.json");
310
+ const content = await fs.readFile(packageJsonPath, "utf-8");
311
+ const packageJson = JSON.parse(content);
312
+ return {
313
+ name: packageJson.name,
314
+ version: packageJson.version,
315
+ description: packageJson.description
316
+ };
317
+ } catch {
318
+ }
319
+ const metaFiles = ["SKILL.md", "skill.md", "README.md", "readme.md"];
320
+ for (const metaFile of metaFiles) {
321
+ try {
322
+ const metaPath = path__default.join(sourcePath, metaFile);
323
+ const content = await fs.readFile(metaPath, "utf-8");
324
+ const titleMatch = content.match(/^#\s+(.+)$/m);
325
+ if (titleMatch) {
326
+ return { name: titleMatch[1].trim() };
327
+ }
328
+ } catch {
329
+ }
330
+ }
331
+ return {};
124
332
  }
125
- function loadActivationState() {
333
+
334
+ const execAsync = promisify(exec);
335
+ async function installFromNpm(sourceInfo, pluginType, options = {}) {
336
+ const { force = false, dryRun = false } = options;
337
+ const { packageName, version } = sourceInfo;
126
338
  try {
127
- const statePath = getActivationStatePath();
128
- if (!existsSync(statePath)) {
129
- return null;
339
+ const packageInfo = await fetchPackageInfo(packageName, version);
340
+ const packageVersion = version || packageInfo.version;
341
+ const shortName = getShortName(packageName);
342
+ const installPath = getInstallPath(pluginType, shortName);
343
+ if (!force) {
344
+ try {
345
+ await fs.access(installPath);
346
+ return {
347
+ success: false,
348
+ source: packageName,
349
+ sourceType: "npm",
350
+ pluginType,
351
+ error: `Plugin already exists at ${installPath}. Use --force to overwrite.`
352
+ };
353
+ } catch {
354
+ }
130
355
  }
131
- const stateJson = readFileSync(statePath, "utf-8");
132
- return JSON.parse(stateJson);
356
+ if (dryRun) {
357
+ const files = packageInfo.files || ["(package files)"];
358
+ return {
359
+ success: true,
360
+ source: packageName,
361
+ sourceType: "npm",
362
+ pluginType,
363
+ installedPath: installPath,
364
+ details: {
365
+ name: packageName,
366
+ version: packageVersion,
367
+ description: packageInfo.description,
368
+ files
369
+ }
370
+ };
371
+ }
372
+ if (pluginType === "mcp") {
373
+ await installMcpPackage(packageName, packageVersion, installPath);
374
+ } else {
375
+ await installGenericPackage(packageName, packageVersion, installPath);
376
+ }
377
+ const installedFiles = await listInstalledFiles(installPath);
378
+ return {
379
+ success: true,
380
+ source: packageName,
381
+ sourceType: "npm",
382
+ pluginType,
383
+ installedPath: installPath,
384
+ details: {
385
+ name: packageName,
386
+ version: packageVersion,
387
+ description: packageInfo.description,
388
+ files: installedFiles
389
+ }
390
+ };
133
391
  } catch (error) {
134
- if (process__default.env.DEBUG) {
135
- console.error("[Zero-Config] Failed to load activation state:", error);
392
+ return {
393
+ success: false,
394
+ source: packageName,
395
+ sourceType: "npm",
396
+ pluginType,
397
+ error: error instanceof Error ? error.message : String(error)
398
+ };
399
+ }
400
+ }
401
+ async function fetchPackageInfo(packageName, version) {
402
+ const url = version ? `https://registry.npmjs.org/${packageName}/${version}` : `https://registry.npmjs.org/${packageName}/latest`;
403
+ const response = await fetch(url);
404
+ if (!response.ok) {
405
+ if (response.status === 404) {
406
+ throw new Error(`Package not found: ${packageName}`);
136
407
  }
137
- return null;
408
+ throw new Error(`Failed to fetch package info: ${response.statusText}`);
138
409
  }
410
+ const data = await response.json();
411
+ return {
412
+ version: data.version,
413
+ description: data.description,
414
+ files: data.files
415
+ };
416
+ }
417
+ function getShortName(packageName) {
418
+ if (packageName.startsWith("@")) {
419
+ const parts = packageName.split("/");
420
+ return parts[1] || packageName;
421
+ }
422
+ return packageName;
139
423
  }
140
- function saveActivationState(status) {
424
+ async function installMcpPackage(packageName, version, installPath) {
425
+ await fs.mkdir(installPath, { recursive: true });
426
+ const packageJson = {
427
+ name: `ccjk-mcp-${getShortName(packageName)}`,
428
+ version: "1.0.0",
429
+ private: true,
430
+ dependencies: {
431
+ [packageName]: version
432
+ }
433
+ };
434
+ await fs.writeFile(
435
+ path__default.join(installPath, "package.json"),
436
+ JSON.stringify(packageJson, null, 2)
437
+ );
141
438
  try {
142
- const statePath = getActivationStatePath();
143
- writeFileSync(statePath, JSON.stringify(status, null, 2), "utf-8");
439
+ await execAsync("npm install", { cwd: installPath });
144
440
  } catch (error) {
145
- if (process__default.env.DEBUG) {
146
- console.error("[Zero-Config] Failed to save activation state:", error);
441
+ try {
442
+ await execAsync("pnpm install", { cwd: installPath });
443
+ } catch {
444
+ throw new Error(
445
+ `Failed to install package. Original error: ${error instanceof Error ? error.message : String(error)}`
446
+ );
147
447
  }
148
448
  }
149
449
  }
150
- function checkActivationStatus() {
151
- const superpowersInstalled = existsSync(getSuperpowersDir());
152
- const savedState = loadActivationState();
153
- if (savedState) {
154
- return savedState;
450
+ async function installGenericPackage(packageName, version, installPath) {
451
+ const registryUrl = `https://registry.npmjs.org/${packageName}/${version}`;
452
+ const response = await fetch(registryUrl);
453
+ if (!response.ok) {
454
+ throw new Error(`Failed to fetch package info: ${response.statusText}`);
455
+ }
456
+ const data = await response.json();
457
+ const tarballUrl = data.dist?.tarball;
458
+ if (!tarballUrl) {
459
+ throw new Error("Failed to get tarball URL");
460
+ }
461
+ const tarballResponse = await fetch(tarballUrl);
462
+ if (!tarballResponse.ok) {
463
+ throw new Error(`Failed to download tarball: ${tarballResponse.statusText}`);
464
+ }
465
+ await fs.mkdir(installPath, { recursive: true });
466
+ const tarballBuffer = Buffer.from(await tarballResponse.arrayBuffer());
467
+ const tarballPath = path__default.join(installPath, "package.tgz");
468
+ await fs.writeFile(tarballPath, tarballBuffer);
469
+ try {
470
+ await execAsync(`tar -xzf package.tgz --strip-components=1`, { cwd: installPath });
471
+ } finally {
472
+ await fs.unlink(tarballPath).catch(() => {
473
+ });
474
+ }
475
+ }
476
+ async function listInstalledFiles(dir) {
477
+ const files = [];
478
+ async function walk(currentDir, prefix = "") {
479
+ try {
480
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
481
+ for (const entry of entries) {
482
+ if (entry.name === "node_modules")
483
+ continue;
484
+ const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
485
+ if (entry.isDirectory()) {
486
+ await walk(path__default.join(currentDir, entry.name), relativePath);
487
+ } else {
488
+ files.push(relativePath);
489
+ }
490
+ }
491
+ } catch {
492
+ }
493
+ }
494
+ await walk(dir);
495
+ return files;
496
+ }
497
+
498
+ function parseSource(source) {
499
+ const trimmed = source.trim();
500
+ const githubInfo = parseGitHubSource(trimmed);
501
+ if (githubInfo) {
502
+ return githubInfo;
503
+ }
504
+ const localInfo = parseLocalSource(trimmed);
505
+ if (localInfo) {
506
+ return localInfo;
507
+ }
508
+ return parseNpmSource(trimmed);
509
+ }
510
+ function parseGitHubSource(source) {
511
+ const prefixMatch = source.match(/^(?:github|gh):([^/]+)\/([^#@/]+)(?:#(.+))?$/);
512
+ if (prefixMatch) {
513
+ return {
514
+ type: "github",
515
+ owner: prefixMatch[1],
516
+ repo: prefixMatch[2],
517
+ ref: prefixMatch[3],
518
+ originalUrl: source
519
+ };
520
+ }
521
+ const urlMatch = source.match(
522
+ /^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/tree\/([^/]+))?(?:\/(.+))?$/
523
+ );
524
+ if (urlMatch) {
525
+ return {
526
+ type: "github",
527
+ owner: urlMatch[1],
528
+ repo: urlMatch[2],
529
+ ref: urlMatch[3],
530
+ subpath: urlMatch[4],
531
+ originalUrl: source
532
+ };
533
+ }
534
+ const shortMatch = source.match(/^([\w-]+)\/([\w.-]+)(?:#(.+))?$/);
535
+ if (shortMatch && !source.startsWith(".") && !source.startsWith("/") && !source.startsWith("~")) {
536
+ return {
537
+ type: "github",
538
+ owner: shortMatch[1],
539
+ repo: shortMatch[2],
540
+ ref: shortMatch[3],
541
+ originalUrl: source
542
+ };
543
+ }
544
+ return null;
545
+ }
546
+ function parseLocalSource(source) {
547
+ if (source.startsWith("./") || source.startsWith("../") || source.startsWith("/") || source.startsWith("~/")) {
548
+ let absolutePath;
549
+ if (source.startsWith("~/")) {
550
+ absolutePath = path__default.join(os__default.homedir(), source.slice(2));
551
+ } else if (path__default.isAbsolute(source)) {
552
+ absolutePath = source;
553
+ } else {
554
+ absolutePath = path__default.resolve(process.cwd(), source);
555
+ }
556
+ return {
557
+ type: "local",
558
+ absolutePath,
559
+ originalPath: source
560
+ };
561
+ }
562
+ if (/^[a-z]:[\\/]/i.test(source)) {
563
+ return {
564
+ type: "local",
565
+ absolutePath: path__default.resolve(source),
566
+ originalPath: source
567
+ };
568
+ }
569
+ return null;
570
+ }
571
+ function parseNpmSource(source) {
572
+ const npmPrefixMatch = source.match(/^npm:(.+)$/);
573
+ const packageStr = npmPrefixMatch ? npmPrefixMatch[1] : source;
574
+ const scopedMatch = packageStr.match(/^(@[^/]+)\/([^@]+)(?:@(.+))?$/);
575
+ if (scopedMatch) {
576
+ return {
577
+ type: "npm",
578
+ scope: scopedMatch[1],
579
+ packageName: `${scopedMatch[1]}/${scopedMatch[2]}`,
580
+ version: scopedMatch[3]
581
+ };
582
+ }
583
+ const versionMatch = packageStr.match(/^([^@]+)@(.+)$/);
584
+ if (versionMatch) {
585
+ return {
586
+ type: "npm",
587
+ packageName: versionMatch[1],
588
+ version: versionMatch[2]
589
+ };
155
590
  }
156
591
  return {
157
- isInstalled: superpowersInstalled,
158
- coreSkillsLoaded: false,
159
- loadedSkills: [],
160
- needsActivation: true,
161
- lastActivation: void 0
592
+ type: "npm",
593
+ packageName: packageStr
162
594
  };
163
595
  }
164
- async function activateSuperpowers(lang = "zh-CN") {
165
- const currentStatus = checkActivationStatus();
166
- if (!currentStatus.needsActivation) {
167
- return currentStatus;
596
+ function buildGitHubRawUrl(info, filePath) {
597
+ const ref = info.ref || "main";
598
+ return `https://raw.githubusercontent.com/${info.owner}/${info.repo}/${ref}/${filePath}`;
599
+ }
600
+
601
+ async function detectPluginType(sourceInfo) {
602
+ const result = await detectPluginTypeWithConfidence(sourceInfo);
603
+ return result.type;
604
+ }
605
+ async function detectPluginTypeWithConfidence(sourceInfo) {
606
+ switch (sourceInfo.type) {
607
+ case "github":
608
+ return detectFromGitHub(sourceInfo);
609
+ case "npm":
610
+ return detectFromNpm(sourceInfo);
611
+ case "local":
612
+ return detectFromLocal(sourceInfo);
613
+ default:
614
+ return { type: "skill", confidence: "low", reason: "Unknown source type" };
615
+ }
616
+ }
617
+ async function detectFromGitHub(info) {
618
+ const repoNameResult = detectFromRepoName(info.repo);
619
+ if (repoNameResult.confidence === "high") {
620
+ return repoNameResult;
168
621
  }
169
- if (!currentStatus.isInstalled) {
170
- const installSuccess = await autoInstallSuperpowers(lang);
171
- if (!installSuccess) {
622
+ try {
623
+ const packageJsonUrl = buildGitHubRawUrl(info, "package.json");
624
+ const response = await fetch(packageJsonUrl);
625
+ if (response.ok) {
626
+ const packageJson = await response.json();
627
+ const pkgResult = detectFromPackageJson(packageJson);
628
+ if (pkgResult.confidence !== "low") {
629
+ return pkgResult;
630
+ }
631
+ }
632
+ } catch {
633
+ }
634
+ const filePatterns = [
635
+ { file: "SKILL.md", type: "skill" },
636
+ { file: "skill.md", type: "skill" },
637
+ { file: "AGENT.md", type: "agent" },
638
+ { file: "agent.md", type: "agent" },
639
+ { file: "mcp.json", type: "mcp" },
640
+ { file: "hook.json", type: "hook" }
641
+ ];
642
+ for (const pattern of filePatterns) {
643
+ try {
644
+ const fileUrl = buildGitHubRawUrl(info, pattern.file);
645
+ const response = await fetch(fileUrl, { method: "HEAD" });
646
+ if (response.ok) {
647
+ return {
648
+ type: pattern.type,
649
+ confidence: "high",
650
+ reason: `Found ${pattern.file}`
651
+ };
652
+ }
653
+ } catch {
654
+ }
655
+ }
656
+ return repoNameResult.confidence !== "low" ? repoNameResult : { type: "skill", confidence: "low", reason: "Default type" };
657
+ }
658
+ async function detectFromNpm(info) {
659
+ const nameResult = detectFromPackageName(info.packageName);
660
+ if (nameResult.confidence === "high") {
661
+ return nameResult;
662
+ }
663
+ try {
664
+ const registryUrl = `https://registry.npmjs.org/${info.packageName}`;
665
+ const response = await fetch(registryUrl);
666
+ if (response.ok) {
667
+ const data = await response.json();
668
+ const latestVersion = data["dist-tags"]?.latest;
669
+ if (latestVersion && data.versions?.[latestVersion]) {
670
+ const packageJson = data.versions[latestVersion];
671
+ const pkgResult = detectFromPackageJson(packageJson);
672
+ if (pkgResult.confidence !== "low") {
673
+ return pkgResult;
674
+ }
675
+ }
676
+ }
677
+ } catch {
678
+ }
679
+ return nameResult.confidence !== "low" ? nameResult : { type: "skill", confidence: "low", reason: "Default type" };
680
+ }
681
+ async function detectFromLocal(info) {
682
+ const { absolutePath } = info;
683
+ const dirName = path__default.basename(absolutePath);
684
+ const dirResult = detectFromRepoName(dirName);
685
+ if (dirResult.confidence === "high") {
686
+ return dirResult;
687
+ }
688
+ try {
689
+ const packageJsonPath = path__default.join(absolutePath, "package.json");
690
+ const content = await fs.readFile(packageJsonPath, "utf-8");
691
+ const packageJson = JSON.parse(content);
692
+ const pkgResult = detectFromPackageJson(packageJson);
693
+ if (pkgResult.confidence !== "low") {
694
+ return pkgResult;
695
+ }
696
+ } catch {
697
+ }
698
+ const filePatterns = [
699
+ { file: "SKILL.md", type: "skill" },
700
+ { file: "skill.md", type: "skill" },
701
+ { file: "AGENT.md", type: "agent" },
702
+ { file: "agent.md", type: "agent" },
703
+ { file: "mcp.json", type: "mcp" },
704
+ { file: "hook.json", type: "hook" }
705
+ ];
706
+ for (const pattern of filePatterns) {
707
+ try {
708
+ const filePath = path__default.join(absolutePath, pattern.file);
709
+ await fs.access(filePath);
172
710
  return {
173
- isInstalled: false,
174
- coreSkillsLoaded: false,
175
- loadedSkills: [],
176
- needsActivation: true,
177
- lastActivation: void 0
711
+ type: pattern.type,
712
+ confidence: "high",
713
+ reason: `Found ${pattern.file}`
178
714
  };
715
+ } catch {
716
+ }
717
+ }
718
+ try {
719
+ const stat = await fs.stat(absolutePath);
720
+ if (stat.isFile() && absolutePath.endsWith(".md")) {
721
+ return {
722
+ type: "skill",
723
+ confidence: "high",
724
+ reason: "Single markdown file"
725
+ };
726
+ }
727
+ } catch {
728
+ }
729
+ return dirResult.confidence !== "low" ? dirResult : { type: "skill", confidence: "low", reason: "Default type" };
730
+ }
731
+ function detectFromRepoName(name) {
732
+ const lowerName = name.toLowerCase();
733
+ if (lowerName.includes("mcp-server") || lowerName.includes("mcp_server") || lowerName.startsWith("mcp-") || lowerName.endsWith("-mcp")) {
734
+ return { type: "mcp", confidence: "high", reason: `Name contains MCP pattern: ${name}` };
735
+ }
736
+ if (lowerName.includes("agent") || lowerName.includes("-agent") || lowerName.endsWith("-agent")) {
737
+ return { type: "agent", confidence: "medium", reason: `Name contains agent pattern: ${name}` };
738
+ }
739
+ if (lowerName.includes("hook") || lowerName.includes("-hook") || lowerName.endsWith("-hook")) {
740
+ return { type: "hook", confidence: "medium", reason: `Name contains hook pattern: ${name}` };
741
+ }
742
+ if (lowerName.includes("skill") || lowerName.includes("-skill") || lowerName.endsWith("-skill")) {
743
+ return { type: "skill", confidence: "medium", reason: `Name contains skill pattern: ${name}` };
744
+ }
745
+ return { type: "skill", confidence: "low", reason: "No pattern matched" };
746
+ }
747
+ function detectFromPackageName(packageName) {
748
+ const lowerName = packageName.toLowerCase();
749
+ if (lowerName.startsWith("@modelcontextprotocol/")) {
750
+ return { type: "mcp", confidence: "high", reason: "MCP official scope" };
751
+ }
752
+ if (lowerName.includes("mcp-server") || lowerName.includes("mcp_server")) {
753
+ return { type: "mcp", confidence: "high", reason: "MCP server pattern in name" };
754
+ }
755
+ return detectFromRepoName(packageName);
756
+ }
757
+ function detectFromPackageJson(packageJson) {
758
+ if (packageJson.ccjk && typeof packageJson.ccjk === "object") {
759
+ const ccjk = packageJson.ccjk;
760
+ if (ccjk.type && typeof ccjk.type === "string") {
761
+ const type = ccjk.type;
762
+ if (["skill", "mcp", "agent", "hook"].includes(type)) {
763
+ return { type, confidence: "high", reason: "Explicit ccjk.type field" };
764
+ }
765
+ }
766
+ }
767
+ if (Array.isArray(packageJson.keywords)) {
768
+ const keywords = packageJson.keywords;
769
+ const keywordMap = {
770
+ "mcp-server": "mcp",
771
+ "mcp": "mcp",
772
+ "model-context-protocol": "mcp",
773
+ "ccjk-skill": "skill",
774
+ "claude-skill": "skill",
775
+ "ccjk-agent": "agent",
776
+ "ccjk-hook": "hook"
777
+ };
778
+ for (const keyword of keywords) {
779
+ const type = keywordMap[keyword.toLowerCase()];
780
+ if (type) {
781
+ return { type, confidence: "high", reason: `Keyword: ${keyword}` };
782
+ }
783
+ }
784
+ }
785
+ if (packageJson.bin) {
786
+ const binKeys = Object.keys(packageJson.bin);
787
+ for (const key of binKeys) {
788
+ if (key.includes("mcp") || key.includes("server")) {
789
+ return { type: "mcp", confidence: "medium", reason: `Binary name: ${key}` };
790
+ }
791
+ }
792
+ }
793
+ if (typeof packageJson.main === "string") {
794
+ const main = packageJson.main.toLowerCase();
795
+ if (main.includes("server") || main.includes("mcp")) {
796
+ return { type: "mcp", confidence: "low", reason: `Main file: ${packageJson.main}` };
179
797
  }
180
798
  }
181
- const loadResults = await loadCoreSkills(lang);
182
- const successfulLoads = loadResults.filter((r) => r.success);
183
- const allCoreSkillsLoaded = successfulLoads.length === loadResults.length;
184
- const newStatus = {
185
- isInstalled: true,
186
- coreSkillsLoaded: allCoreSkillsLoaded,
187
- loadedSkills: successfulLoads.map((r) => r.skill),
188
- needsActivation: false,
189
- lastActivation: (/* @__PURE__ */ new Date()).toISOString()
799
+ return { type: "skill", confidence: "low", reason: "No specific indicators" };
800
+ }
801
+
802
+ async function addCommand(source, options = {}) {
803
+ const { force = false, dryRun = false, json = false, lang = "en" } = options;
804
+ const i18n = getI18n(lang);
805
+ const spinner = json ? null : ora(i18n.parsing).start();
806
+ let sourceInfo;
807
+ try {
808
+ sourceInfo = parseSource(source);
809
+ spinner?.succeed(i18n.parsed(sourceInfo.type));
810
+ } catch (error) {
811
+ spinner?.fail(i18n.parseFailed);
812
+ const result = {
813
+ success: false,
814
+ source,
815
+ sourceType: "local",
816
+ pluginType: "skill",
817
+ error: error instanceof Error ? error.message : String(error)
818
+ };
819
+ if (json) {
820
+ console.log(JSON.stringify(result, null, 2));
821
+ } else {
822
+ console.error(ansis.red(`
823
+ ${i18n.error}: ${result.error}
824
+ `));
825
+ }
826
+ return result;
827
+ }
828
+ let pluginType = options.type;
829
+ if (!pluginType) {
830
+ spinner?.start(i18n.detectingType);
831
+ try {
832
+ pluginType = await detectPluginType(sourceInfo);
833
+ spinner?.succeed(i18n.detectedType(pluginType));
834
+ } catch {
835
+ spinner?.info(i18n.defaultType);
836
+ pluginType = "skill";
837
+ }
838
+ }
839
+ spinner?.start(dryRun ? i18n.previewInstall : i18n.installing);
840
+ try {
841
+ let result;
842
+ switch (sourceInfo.type) {
843
+ case "github":
844
+ result = await installFromGitHub(sourceInfo, pluginType, { force, dryRun });
845
+ break;
846
+ case "npm":
847
+ result = await installFromNpm(sourceInfo, pluginType, { force, dryRun });
848
+ break;
849
+ case "local":
850
+ result = await installFromLocal(sourceInfo, pluginType, { force, dryRun });
851
+ break;
852
+ default:
853
+ throw new Error(`Unsupported source type: ${sourceInfo.type}`);
854
+ }
855
+ if (result.success) {
856
+ spinner?.succeed(dryRun ? i18n.previewSuccess : i18n.installSuccess);
857
+ } else {
858
+ spinner?.fail(i18n.installFailed);
859
+ }
860
+ if (json) {
861
+ console.log(JSON.stringify(result, null, 2));
862
+ } else if (result.success && !dryRun) {
863
+ printSuccessMessage(result, i18n);
864
+ } else if (result.success && dryRun) {
865
+ printPreviewMessage(result, i18n);
866
+ } else {
867
+ console.error(ansis.red(`
868
+ ${i18n.error}: ${result.error}
869
+ `));
870
+ }
871
+ return result;
872
+ } catch (error) {
873
+ spinner?.fail(i18n.installFailed);
874
+ const result = {
875
+ success: false,
876
+ source,
877
+ sourceType: sourceInfo.type,
878
+ pluginType,
879
+ error: error instanceof Error ? error.message : String(error)
880
+ };
881
+ if (json) {
882
+ console.log(JSON.stringify(result, null, 2));
883
+ } else {
884
+ console.error(ansis.red(`
885
+ ${i18n.error}: ${result.error}
886
+ `));
887
+ }
888
+ return result;
889
+ }
890
+ }
891
+ function printSuccessMessage(result, i18n) {
892
+ console.log();
893
+ console.log(ansis.green.bold(`\u2713 ${i18n.installed}`));
894
+ console.log();
895
+ console.log(` ${ansis.gray(i18n.name)}: ${result.details?.name || result.source}`);
896
+ if (result.details?.version) {
897
+ console.log(` ${ansis.gray(i18n.version)}: ${result.details.version}`);
898
+ }
899
+ console.log(` ${ansis.gray(i18n.type)}: ${result.pluginType}`);
900
+ console.log(` ${ansis.gray(i18n.path)}: ${result.installedPath}`);
901
+ console.log();
902
+ console.log(ansis.cyan(i18n.nextSteps));
903
+ switch (result.pluginType) {
904
+ case "skill":
905
+ console.log(` ${ansis.gray("\u2022")} ${i18n.skillHint}`);
906
+ break;
907
+ case "mcp":
908
+ console.log(` ${ansis.gray("\u2022")} ${i18n.mcpHint}`);
909
+ break;
910
+ case "agent":
911
+ console.log(` ${ansis.gray("\u2022")} ${i18n.agentHint}`);
912
+ break;
913
+ case "hook":
914
+ console.log(` ${ansis.gray("\u2022")} ${i18n.hookHint}`);
915
+ break;
916
+ }
917
+ console.log();
918
+ }
919
+ function printPreviewMessage(result, i18n) {
920
+ console.log();
921
+ console.log(ansis.yellow.bold(`\u26A1 ${i18n.preview}`));
922
+ console.log();
923
+ console.log(` ${ansis.gray(i18n.source)}: ${result.source}`);
924
+ console.log(` ${ansis.gray(i18n.type)}: ${result.pluginType}`);
925
+ console.log(` ${ansis.gray(i18n.target)}: ${result.installedPath}`);
926
+ if (result.details?.files?.length) {
927
+ console.log(` ${ansis.gray(i18n.files)}:`);
928
+ for (const file of result.details.files.slice(0, 5)) {
929
+ console.log(` ${ansis.gray("\u2022")} ${file}`);
930
+ }
931
+ if (result.details.files.length > 5) {
932
+ console.log(` ${ansis.gray("...")} ${i18n.andMore(result.details.files.length - 5)}`);
933
+ }
934
+ }
935
+ console.log();
936
+ console.log(ansis.gray(i18n.dryRunNote));
937
+ console.log();
938
+ }
939
+ function getI18n(lang) {
940
+ const texts = {
941
+ "zh-CN": {
942
+ parsing: "\u89E3\u6790\u6765\u6E90...",
943
+ parsed: (type) => `\u6765\u6E90\u7C7B\u578B: ${type}`,
944
+ parseFailed: "\u89E3\u6790\u6765\u6E90\u5931\u8D25",
945
+ detectingType: "\u68C0\u6D4B\u63D2\u4EF6\u7C7B\u578B...",
946
+ detectedType: (type) => `\u68C0\u6D4B\u5230\u7C7B\u578B: ${type}`,
947
+ defaultType: "\u4F7F\u7528\u9ED8\u8BA4\u7C7B\u578B: skill",
948
+ installing: "\u5B89\u88C5\u4E2D...",
949
+ previewInstall: "\u9884\u89C8\u5B89\u88C5...",
950
+ installSuccess: "\u5B89\u88C5\u6210\u529F",
951
+ previewSuccess: "\u9884\u89C8\u5B8C\u6210",
952
+ installFailed: "\u5B89\u88C5\u5931\u8D25",
953
+ error: "\u9519\u8BEF",
954
+ installed: "\u63D2\u4EF6\u5DF2\u5B89\u88C5",
955
+ preview: "\u5B89\u88C5\u9884\u89C8 (dry-run)",
956
+ name: "\u540D\u79F0",
957
+ version: "\u7248\u672C",
958
+ type: "\u7C7B\u578B",
959
+ path: "\u8DEF\u5F84",
960
+ source: "\u6765\u6E90",
961
+ target: "\u76EE\u6807",
962
+ files: "\u6587\u4EF6",
963
+ nextSteps: "\u4E0B\u4E00\u6B65:",
964
+ skillHint: "\u4F7F\u7528 /skill-name \u5728 Claude Code \u4E2D\u8C03\u7528",
965
+ mcpHint: "\u8FD0\u884C ccjk mcp status \u67E5\u770B\u72B6\u6001",
966
+ agentHint: "\u4F7F\u7528 ccjk agent list \u67E5\u770B\u5DF2\u5B89\u88C5\u7684 agent",
967
+ hookHint: "\u8FD0\u884C ccjk hooks list \u67E5\u770B\u5DF2\u5B89\u88C5\u7684 hook",
968
+ dryRunNote: "\u8FD9\u662F\u9884\u89C8\u6A21\u5F0F\uFF0C\u672A\u5B9E\u9645\u5B89\u88C5\u3002\u79FB\u9664 --dry-run \u6267\u884C\u5B89\u88C5\u3002",
969
+ andMore: (n) => `\u8FD8\u6709 ${n} \u4E2A\u6587\u4EF6`
970
+ },
971
+ "en": {
972
+ parsing: "Parsing source...",
973
+ parsed: (type) => `Source type: ${type}`,
974
+ parseFailed: "Failed to parse source",
975
+ detectingType: "Detecting plugin type...",
976
+ detectedType: (type) => `Detected type: ${type}`,
977
+ defaultType: "Using default type: skill",
978
+ installing: "Installing...",
979
+ previewInstall: "Previewing installation...",
980
+ installSuccess: "Installation successful",
981
+ previewSuccess: "Preview complete",
982
+ installFailed: "Installation failed",
983
+ error: "Error",
984
+ installed: "Plugin installed",
985
+ preview: "Installation preview (dry-run)",
986
+ name: "Name",
987
+ version: "Version",
988
+ type: "Type",
989
+ path: "Path",
990
+ source: "Source",
991
+ target: "Target",
992
+ files: "Files",
993
+ nextSteps: "Next steps:",
994
+ skillHint: "Use /skill-name in Claude Code to invoke",
995
+ mcpHint: "Run ccjk mcp status to check status",
996
+ agentHint: "Use ccjk agent list to see installed agents",
997
+ hookHint: "Run ccjk hooks list to see installed hooks",
998
+ dryRunNote: "This is preview mode, nothing was installed. Remove --dry-run to install.",
999
+ andMore: (n) => `and ${n} more files`
1000
+ }
190
1001
  };
191
- saveActivationState(newStatus);
192
- return newStatus;
1002
+ return texts[lang];
193
1003
  }
194
1004
 
195
- export { activateSuperpowers, autoInstallSuperpowers, checkActivationStatus, loadCoreSkills, loadSkill };
1005
+ export { addCommand, parseSource };