claudekit-cli 3.22.1 → 3.24.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/dist/index.js +652 -247
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18468,6 +18468,25 @@ class PathResolver {
|
|
|
18468
18468
|
}
|
|
18469
18469
|
return join(homedir(), ".claude");
|
|
18470
18470
|
}
|
|
18471
|
+
static getOpenCodeDir(global2, baseDir) {
|
|
18472
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
18473
|
+
if (testHome) {
|
|
18474
|
+
return global2 ? join(testHome, ".config", "opencode") : join(baseDir || testHome, ".opencode");
|
|
18475
|
+
}
|
|
18476
|
+
if (!global2) {
|
|
18477
|
+
return join(baseDir || process.cwd(), ".opencode");
|
|
18478
|
+
}
|
|
18479
|
+
const os = platform();
|
|
18480
|
+
if (os === "win32") {
|
|
18481
|
+
const appData = process.env.APPDATA || join(homedir(), "AppData", "Roaming");
|
|
18482
|
+
return join(appData, "opencode");
|
|
18483
|
+
}
|
|
18484
|
+
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
18485
|
+
if (xdgConfigHome) {
|
|
18486
|
+
return join(xdgConfigHome, "opencode");
|
|
18487
|
+
}
|
|
18488
|
+
return join(homedir(), ".config", "opencode");
|
|
18489
|
+
}
|
|
18471
18490
|
static getPathPrefix(global2) {
|
|
18472
18491
|
return global2 ? "" : ".claude";
|
|
18473
18492
|
}
|
|
@@ -34271,7 +34290,7 @@ async function handleDownload(ctx) {
|
|
|
34271
34290
|
};
|
|
34272
34291
|
}
|
|
34273
34292
|
// src/commands/init/phases/merge-handler.ts
|
|
34274
|
-
import { join as
|
|
34293
|
+
import { join as join50 } from "node:path";
|
|
34275
34294
|
|
|
34276
34295
|
// src/domains/installation/file-merger.ts
|
|
34277
34296
|
init_logger();
|
|
@@ -36208,9 +36227,6 @@ class InstalledSettingsTracker {
|
|
|
36208
36227
|
}
|
|
36209
36228
|
}
|
|
36210
36229
|
|
|
36211
|
-
// src/domains/config/merger/merge-engine.ts
|
|
36212
|
-
init_logger();
|
|
36213
|
-
|
|
36214
36230
|
// src/domains/config/merger/diff-calculator.ts
|
|
36215
36231
|
function truncateCommand(cmd, maxLen = 50) {
|
|
36216
36232
|
if (cmd.length <= maxLen)
|
|
@@ -36409,12 +36425,61 @@ function mergeHooks(sourceHooks, destHooks, result, options) {
|
|
|
36409
36425
|
const merged = { ...destHooks };
|
|
36410
36426
|
const installedHooks = options?.installedSettings?.hooks ?? [];
|
|
36411
36427
|
const sourceKit = options?.sourceKit;
|
|
36428
|
+
const sourceCommands = new Set;
|
|
36429
|
+
for (const entries of Object.values(sourceHooks)) {
|
|
36430
|
+
extractCommands(entries, sourceCommands);
|
|
36431
|
+
}
|
|
36412
36432
|
for (const [eventName, sourceEntries] of Object.entries(sourceHooks)) {
|
|
36413
36433
|
const destEntries = destHooks[eventName] || [];
|
|
36414
36434
|
merged[eventName] = mergeHookEntries(sourceEntries, destEntries, eventName, result, installedHooks, sourceKit);
|
|
36415
36435
|
}
|
|
36436
|
+
if (installedHooks.length > 0) {
|
|
36437
|
+
const deprecatedHooks = installedHooks.filter((hook) => !sourceCommands.has(normalizeCommand(hook)));
|
|
36438
|
+
if (deprecatedHooks.length > 0) {
|
|
36439
|
+
result.removedHooks = result.removedHooks ?? [];
|
|
36440
|
+
for (const [eventName, entries] of Object.entries(merged)) {
|
|
36441
|
+
const filtered = removeDeprecatedFromEntries(entries, deprecatedHooks, result);
|
|
36442
|
+
if (filtered.length > 0) {
|
|
36443
|
+
merged[eventName] = filtered;
|
|
36444
|
+
} else {
|
|
36445
|
+
delete merged[eventName];
|
|
36446
|
+
}
|
|
36447
|
+
}
|
|
36448
|
+
}
|
|
36449
|
+
}
|
|
36416
36450
|
return merged;
|
|
36417
36451
|
}
|
|
36452
|
+
function removeDeprecatedFromEntries(entries, deprecatedHooks, result) {
|
|
36453
|
+
const deprecatedSet = new Set(deprecatedHooks.map((h2) => normalizeCommand(h2)));
|
|
36454
|
+
const filtered = [];
|
|
36455
|
+
for (const entry of entries) {
|
|
36456
|
+
if ("hooks" in entry && entry.hooks) {
|
|
36457
|
+
const remainingHooks = entry.hooks.filter((h2) => {
|
|
36458
|
+
if (h2.command && deprecatedSet.has(normalizeCommand(h2.command))) {
|
|
36459
|
+
result.hooksRemoved++;
|
|
36460
|
+
result.removedHooks?.push(h2.command);
|
|
36461
|
+
logger.info(`Removed deprecated hook: ${h2.command.slice(0, 60)}...`);
|
|
36462
|
+
return false;
|
|
36463
|
+
}
|
|
36464
|
+
return true;
|
|
36465
|
+
});
|
|
36466
|
+
if (remainingHooks.length > 0) {
|
|
36467
|
+
filtered.push({ ...entry, hooks: remainingHooks });
|
|
36468
|
+
}
|
|
36469
|
+
} else if ("command" in entry) {
|
|
36470
|
+
if (deprecatedSet.has(normalizeCommand(entry.command))) {
|
|
36471
|
+
result.hooksRemoved++;
|
|
36472
|
+
result.removedHooks?.push(entry.command);
|
|
36473
|
+
logger.info(`Removed deprecated hook: ${entry.command.slice(0, 60)}...`);
|
|
36474
|
+
} else {
|
|
36475
|
+
filtered.push(entry);
|
|
36476
|
+
}
|
|
36477
|
+
} else {
|
|
36478
|
+
filtered.push(entry);
|
|
36479
|
+
}
|
|
36480
|
+
}
|
|
36481
|
+
return filtered;
|
|
36482
|
+
}
|
|
36418
36483
|
function mergeMcp(sourceMcp, destMcp, result, options) {
|
|
36419
36484
|
if (!sourceMcp)
|
|
36420
36485
|
return destMcp;
|
|
@@ -36491,6 +36556,24 @@ function mergeMcp(sourceMcp, destMcp, result, options) {
|
|
|
36491
36556
|
}
|
|
36492
36557
|
}
|
|
36493
36558
|
}
|
|
36559
|
+
if (installedServers.length > 0 && merged.servers) {
|
|
36560
|
+
const sourceServerNames = new Set(Object.keys(sourceMcp.servers || {}));
|
|
36561
|
+
const deprecatedServers = installedServers.filter((server) => !sourceServerNames.has(server));
|
|
36562
|
+
if (deprecatedServers.length > 0) {
|
|
36563
|
+
result.removedMcpServers = result.removedMcpServers ?? [];
|
|
36564
|
+
for (const serverName of deprecatedServers) {
|
|
36565
|
+
if (serverName in merged.servers) {
|
|
36566
|
+
delete merged.servers[serverName];
|
|
36567
|
+
result.mcpServersRemoved++;
|
|
36568
|
+
result.removedMcpServers.push(serverName);
|
|
36569
|
+
logger.info(`Removed deprecated MCP server: ${serverName}`);
|
|
36570
|
+
}
|
|
36571
|
+
}
|
|
36572
|
+
if (merged.servers && Object.keys(merged.servers).length === 0) {
|
|
36573
|
+
merged.servers = undefined;
|
|
36574
|
+
}
|
|
36575
|
+
}
|
|
36576
|
+
}
|
|
36494
36577
|
for (const key of Object.keys(sourceMcp)) {
|
|
36495
36578
|
if (key !== "servers" && !(key in merged)) {
|
|
36496
36579
|
merged[key] = sourceMcp[key];
|
|
@@ -36504,8 +36587,10 @@ function mergeSettings(source, destination, options) {
|
|
|
36504
36587
|
hooksAdded: 0,
|
|
36505
36588
|
hooksPreserved: 0,
|
|
36506
36589
|
hooksSkipped: 0,
|
|
36590
|
+
hooksRemoved: 0,
|
|
36507
36591
|
mcpServersPreserved: 0,
|
|
36508
36592
|
mcpServersSkipped: 0,
|
|
36593
|
+
mcpServersRemoved: 0,
|
|
36509
36594
|
conflictsDetected: [],
|
|
36510
36595
|
newlyInstalledHooks: [],
|
|
36511
36596
|
newlyInstalledServers: [],
|
|
@@ -37715,8 +37800,113 @@ class FileScanner2 {
|
|
|
37715
37800
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
37716
37801
|
init_logger();
|
|
37717
37802
|
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
37718
|
-
import { lstat as lstat5, mkdir as mkdir16, readdir as
|
|
37803
|
+
import { lstat as lstat5, mkdir as mkdir16, readdir as readdir12, stat as stat8 } from "node:fs/promises";
|
|
37804
|
+
import { join as join47 } from "node:path";
|
|
37805
|
+
|
|
37806
|
+
// src/services/transformers/commands-prefix/content-transformer.ts
|
|
37807
|
+
init_logger();
|
|
37808
|
+
import { readFile as readFile17, readdir as readdir11, writeFile as writeFile14 } from "node:fs/promises";
|
|
37719
37809
|
import { join as join46 } from "node:path";
|
|
37810
|
+
var TRANSFORMABLE_EXTENSIONS = new Set([
|
|
37811
|
+
".md",
|
|
37812
|
+
".txt",
|
|
37813
|
+
".json",
|
|
37814
|
+
".yaml",
|
|
37815
|
+
".yml",
|
|
37816
|
+
".ts",
|
|
37817
|
+
".js",
|
|
37818
|
+
".mjs",
|
|
37819
|
+
".cjs",
|
|
37820
|
+
".py"
|
|
37821
|
+
]);
|
|
37822
|
+
var COMMAND_ROOTS = [
|
|
37823
|
+
"plan",
|
|
37824
|
+
"fix",
|
|
37825
|
+
"code",
|
|
37826
|
+
"review",
|
|
37827
|
+
"cook",
|
|
37828
|
+
"brainstorm",
|
|
37829
|
+
"integrate",
|
|
37830
|
+
"bootstrap",
|
|
37831
|
+
"worktree",
|
|
37832
|
+
"scout",
|
|
37833
|
+
"test",
|
|
37834
|
+
"debug",
|
|
37835
|
+
"preview",
|
|
37836
|
+
"kanban",
|
|
37837
|
+
"journal",
|
|
37838
|
+
"watzup"
|
|
37839
|
+
];
|
|
37840
|
+
function buildCommandPatterns() {
|
|
37841
|
+
const patterns = [];
|
|
37842
|
+
for (const cmd of COMMAND_ROOTS) {
|
|
37843
|
+
patterns.push({
|
|
37844
|
+
regex: new RegExp(`(?<![\\w:])(\\/)${cmd}(:)`, "g"),
|
|
37845
|
+
replacement: "$1ck:$2".replace("$2", `${cmd}:`)
|
|
37846
|
+
});
|
|
37847
|
+
patterns.push({
|
|
37848
|
+
regex: new RegExp(`(?<![\\w:])(\\/)${cmd}(?=[\\s\`"'\\)\\]}>.,;:!?]|$)`, "g"),
|
|
37849
|
+
replacement: `$1ck:${cmd}`
|
|
37850
|
+
});
|
|
37851
|
+
}
|
|
37852
|
+
return patterns;
|
|
37853
|
+
}
|
|
37854
|
+
function transformCommandContent(content) {
|
|
37855
|
+
let changes = 0;
|
|
37856
|
+
let transformed = content;
|
|
37857
|
+
const patterns = buildCommandPatterns();
|
|
37858
|
+
for (const { regex: regex2, replacement } of patterns) {
|
|
37859
|
+
regex2.lastIndex = 0;
|
|
37860
|
+
const matches = transformed.match(regex2);
|
|
37861
|
+
if (matches) {
|
|
37862
|
+
changes += matches.length;
|
|
37863
|
+
regex2.lastIndex = 0;
|
|
37864
|
+
transformed = transformed.replace(regex2, replacement);
|
|
37865
|
+
}
|
|
37866
|
+
}
|
|
37867
|
+
return { transformed, changes };
|
|
37868
|
+
}
|
|
37869
|
+
function shouldTransformFile(filename) {
|
|
37870
|
+
const ext2 = filename.toLowerCase().slice(filename.lastIndexOf("."));
|
|
37871
|
+
return TRANSFORMABLE_EXTENSIONS.has(ext2);
|
|
37872
|
+
}
|
|
37873
|
+
async function transformCommandReferences(directory, options = {}) {
|
|
37874
|
+
let filesTransformed = 0;
|
|
37875
|
+
let totalReplacements = 0;
|
|
37876
|
+
async function processDirectory(dir) {
|
|
37877
|
+
const entries = await readdir11(dir, { withFileTypes: true });
|
|
37878
|
+
for (const entry of entries) {
|
|
37879
|
+
const fullPath = join46(dir, entry.name);
|
|
37880
|
+
if (entry.isDirectory()) {
|
|
37881
|
+
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
37882
|
+
continue;
|
|
37883
|
+
}
|
|
37884
|
+
await processDirectory(fullPath);
|
|
37885
|
+
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
37886
|
+
try {
|
|
37887
|
+
const content = await readFile17(fullPath, "utf-8");
|
|
37888
|
+
const { transformed, changes } = transformCommandContent(content);
|
|
37889
|
+
if (changes > 0) {
|
|
37890
|
+
if (options.dryRun) {
|
|
37891
|
+
logger.debug(`[dry-run] Would transform ${changes} command ref(s) in ${fullPath}`);
|
|
37892
|
+
} else {
|
|
37893
|
+
await writeFile14(fullPath, transformed, "utf-8");
|
|
37894
|
+
if (options.verbose) {
|
|
37895
|
+
logger.verbose(`Transformed ${changes} command ref(s) in ${fullPath}`);
|
|
37896
|
+
}
|
|
37897
|
+
}
|
|
37898
|
+
filesTransformed++;
|
|
37899
|
+
totalReplacements += changes;
|
|
37900
|
+
}
|
|
37901
|
+
} catch (error) {
|
|
37902
|
+
logger.debug(`Skipped ${fullPath}: ${error instanceof Error ? error.message : "unknown"}`);
|
|
37903
|
+
}
|
|
37904
|
+
}
|
|
37905
|
+
}
|
|
37906
|
+
}
|
|
37907
|
+
await processDirectory(directory);
|
|
37908
|
+
return { filesTransformed, totalReplacements };
|
|
37909
|
+
}
|
|
37720
37910
|
|
|
37721
37911
|
// src/services/transformers/commands-prefix/prefix-utils.ts
|
|
37722
37912
|
init_logger();
|
|
@@ -37761,22 +37951,22 @@ function shouldApplyPrefix(options) {
|
|
|
37761
37951
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
37762
37952
|
async function applyPrefix(extractDir) {
|
|
37763
37953
|
validatePath(extractDir, "extractDir");
|
|
37764
|
-
const commandsDir =
|
|
37954
|
+
const commandsDir = join47(extractDir, ".claude", "commands");
|
|
37765
37955
|
if (!await import_fs_extra13.pathExists(commandsDir)) {
|
|
37766
37956
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
37767
37957
|
return;
|
|
37768
37958
|
}
|
|
37769
37959
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
37770
|
-
const backupDir =
|
|
37771
|
-
const tempDir =
|
|
37960
|
+
const backupDir = join47(extractDir, ".commands-backup");
|
|
37961
|
+
const tempDir = join47(extractDir, ".commands-prefix-temp");
|
|
37772
37962
|
try {
|
|
37773
|
-
const entries = await
|
|
37963
|
+
const entries = await readdir12(commandsDir);
|
|
37774
37964
|
if (entries.length === 0) {
|
|
37775
37965
|
logger.verbose("Commands directory is empty, skipping prefix application");
|
|
37776
37966
|
return;
|
|
37777
37967
|
}
|
|
37778
37968
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
37779
|
-
const ckDir2 =
|
|
37969
|
+
const ckDir2 = join47(commandsDir, "ck");
|
|
37780
37970
|
const ckStat = await stat8(ckDir2);
|
|
37781
37971
|
if (ckStat.isDirectory()) {
|
|
37782
37972
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
@@ -37786,17 +37976,17 @@ async function applyPrefix(extractDir) {
|
|
|
37786
37976
|
await import_fs_extra13.copy(commandsDir, backupDir);
|
|
37787
37977
|
logger.verbose("Created backup of commands directory");
|
|
37788
37978
|
await mkdir16(tempDir, { recursive: true });
|
|
37789
|
-
const ckDir =
|
|
37979
|
+
const ckDir = join47(tempDir, "ck");
|
|
37790
37980
|
await mkdir16(ckDir, { recursive: true });
|
|
37791
37981
|
let processedCount = 0;
|
|
37792
37982
|
for (const entry of entries) {
|
|
37793
|
-
const sourcePath =
|
|
37983
|
+
const sourcePath = join47(commandsDir, entry);
|
|
37794
37984
|
const stats = await lstat5(sourcePath);
|
|
37795
37985
|
if (stats.isSymbolicLink()) {
|
|
37796
37986
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
37797
37987
|
continue;
|
|
37798
37988
|
}
|
|
37799
|
-
const destPath =
|
|
37989
|
+
const destPath = join47(ckDir, entry);
|
|
37800
37990
|
await import_fs_extra13.copy(sourcePath, destPath, {
|
|
37801
37991
|
overwrite: false,
|
|
37802
37992
|
errorOnExist: true
|
|
@@ -37813,7 +38003,17 @@ async function applyPrefix(extractDir) {
|
|
|
37813
38003
|
await import_fs_extra13.remove(commandsDir);
|
|
37814
38004
|
await import_fs_extra13.move(tempDir, commandsDir);
|
|
37815
38005
|
await import_fs_extra13.remove(backupDir);
|
|
37816
|
-
logger.success("Successfully
|
|
38006
|
+
logger.success("Successfully reorganized commands to /ck: prefix");
|
|
38007
|
+
const claudeDir = join47(extractDir, ".claude");
|
|
38008
|
+
logger.info("Transforming command references in file contents...");
|
|
38009
|
+
const transformResult = await transformCommandReferences(claudeDir, {
|
|
38010
|
+
verbose: logger.isVerbose()
|
|
38011
|
+
});
|
|
38012
|
+
if (transformResult.totalReplacements > 0) {
|
|
38013
|
+
logger.success(`Transformed ${transformResult.totalReplacements} command ref(s) in ${transformResult.filesTransformed} file(s)`);
|
|
38014
|
+
} else {
|
|
38015
|
+
logger.verbose("No command references needed transformation");
|
|
38016
|
+
}
|
|
37817
38017
|
} catch (error) {
|
|
37818
38018
|
if (await import_fs_extra13.pathExists(backupDir)) {
|
|
37819
38019
|
try {
|
|
@@ -37840,21 +38040,21 @@ async function applyPrefix(extractDir) {
|
|
|
37840
38040
|
}
|
|
37841
38041
|
|
|
37842
38042
|
// src/services/transformers/commands-prefix/prefix-cleaner.ts
|
|
37843
|
-
import { lstat as lstat7, readdir as
|
|
37844
|
-
import { join as
|
|
38043
|
+
import { lstat as lstat7, readdir as readdir14 } from "node:fs/promises";
|
|
38044
|
+
import { join as join49 } from "node:path";
|
|
37845
38045
|
init_logger();
|
|
37846
38046
|
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
37847
38047
|
|
|
37848
38048
|
// src/services/transformers/commands-prefix/file-processor.ts
|
|
37849
|
-
import { lstat as lstat6, readdir as
|
|
37850
|
-
import { join as
|
|
38049
|
+
import { lstat as lstat6, readdir as readdir13 } from "node:fs/promises";
|
|
38050
|
+
import { join as join48 } from "node:path";
|
|
37851
38051
|
init_logger();
|
|
37852
38052
|
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
37853
38053
|
async function scanDirectoryFiles(dir) {
|
|
37854
38054
|
const files = [];
|
|
37855
|
-
const entries = await
|
|
38055
|
+
const entries = await readdir13(dir);
|
|
37856
38056
|
for (const entry of entries) {
|
|
37857
|
-
const fullPath =
|
|
38057
|
+
const fullPath = join48(dir, entry);
|
|
37858
38058
|
const stats = await lstat6(fullPath);
|
|
37859
38059
|
if (stats.isSymbolicLink()) {
|
|
37860
38060
|
continue;
|
|
@@ -37962,8 +38162,8 @@ function logCleanupSummary(deletedCount, preservedCount, dryRun, results) {
|
|
|
37962
38162
|
async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
37963
38163
|
const { dryRun = false } = options;
|
|
37964
38164
|
validatePath(targetDir, "targetDir");
|
|
37965
|
-
const claudeDir = isGlobal ? targetDir :
|
|
37966
|
-
const commandsDir =
|
|
38165
|
+
const claudeDir = isGlobal ? targetDir : join49(targetDir, ".claude");
|
|
38166
|
+
const commandsDir = join49(claudeDir, "commands");
|
|
37967
38167
|
const accumulator = {
|
|
37968
38168
|
results: [],
|
|
37969
38169
|
deletedCount: 0,
|
|
@@ -37991,13 +38191,13 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
|
37991
38191
|
logger.verbose("All existing files will be preserved as user-owned");
|
|
37992
38192
|
return result;
|
|
37993
38193
|
}
|
|
37994
|
-
const entries = await
|
|
38194
|
+
const entries = await readdir14(commandsDir);
|
|
37995
38195
|
if (entries.length === 0) {
|
|
37996
38196
|
logger.verbose("Commands directory is empty");
|
|
37997
38197
|
return result;
|
|
37998
38198
|
}
|
|
37999
38199
|
for (const entry of entries) {
|
|
38000
|
-
const entryPath =
|
|
38200
|
+
const entryPath = join49(commandsDir, entry);
|
|
38001
38201
|
const stats = await lstat7(entryPath);
|
|
38002
38202
|
if (stats.isSymbolicLink()) {
|
|
38003
38203
|
addSymlinkSkip(entry, accumulator);
|
|
@@ -38049,7 +38249,7 @@ async function handleMerge(ctx) {
|
|
|
38049
38249
|
let customClaudeFiles = [];
|
|
38050
38250
|
if (!ctx.options.fresh) {
|
|
38051
38251
|
logger.info("Scanning for custom .claude files...");
|
|
38052
|
-
const scanSourceDir = ctx.options.global ?
|
|
38252
|
+
const scanSourceDir = ctx.options.global ? join50(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
38053
38253
|
const scanTargetSubdir = ctx.options.global ? "" : ".claude";
|
|
38054
38254
|
customClaudeFiles = await FileScanner2.findCustomFiles(ctx.resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
38055
38255
|
} else {
|
|
@@ -38113,7 +38313,7 @@ async function handleMerge(ctx) {
|
|
|
38113
38313
|
return { ...ctx, cancelled: true };
|
|
38114
38314
|
}
|
|
38115
38315
|
}
|
|
38116
|
-
const sourceDir = ctx.options.global ?
|
|
38316
|
+
const sourceDir = ctx.options.global ? join50(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
38117
38317
|
await merger.merge(sourceDir, ctx.resolvedDir, ctx.isNonInteractive);
|
|
38118
38318
|
const fileConflicts = merger.getFileConflicts();
|
|
38119
38319
|
if (fileConflicts.length > 0 && !ctx.isNonInteractive) {
|
|
@@ -38142,7 +38342,7 @@ async function handleMerge(ctx) {
|
|
|
38142
38342
|
};
|
|
38143
38343
|
}
|
|
38144
38344
|
// src/commands/init/phases/migration-handler.ts
|
|
38145
|
-
import { join as
|
|
38345
|
+
import { join as join58 } from "node:path";
|
|
38146
38346
|
|
|
38147
38347
|
// src/domains/skills/skills-detector.ts
|
|
38148
38348
|
init_logger();
|
|
@@ -38154,8 +38354,8 @@ init_logger();
|
|
|
38154
38354
|
// src/domains/skills/skills-manifest.ts
|
|
38155
38355
|
init_logger();
|
|
38156
38356
|
import { createHash as createHash2 } from "node:crypto";
|
|
38157
|
-
import { readFile as
|
|
38158
|
-
import { join as
|
|
38357
|
+
import { readFile as readFile18, readdir as readdir15, writeFile as writeFile15 } from "node:fs/promises";
|
|
38358
|
+
import { join as join51, relative as relative9 } from "node:path";
|
|
38159
38359
|
init_types2();
|
|
38160
38360
|
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
38161
38361
|
|
|
@@ -38179,18 +38379,18 @@ class SkillsManifestManager {
|
|
|
38179
38379
|
return manifest;
|
|
38180
38380
|
}
|
|
38181
38381
|
static async writeManifest(skillsDir, manifest) {
|
|
38182
|
-
const manifestPath =
|
|
38183
|
-
await
|
|
38382
|
+
const manifestPath = join51(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
38383
|
+
await writeFile15(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
38184
38384
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
38185
38385
|
}
|
|
38186
38386
|
static async readManifest(skillsDir) {
|
|
38187
|
-
const manifestPath =
|
|
38387
|
+
const manifestPath = join51(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
38188
38388
|
if (!await import_fs_extra17.pathExists(manifestPath)) {
|
|
38189
38389
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
38190
38390
|
return null;
|
|
38191
38391
|
}
|
|
38192
38392
|
try {
|
|
38193
|
-
const content = await
|
|
38393
|
+
const content = await readFile18(manifestPath, "utf-8");
|
|
38194
38394
|
const data = JSON.parse(content);
|
|
38195
38395
|
const manifest = SkillsManifestSchema.parse(data);
|
|
38196
38396
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -38201,14 +38401,14 @@ class SkillsManifestManager {
|
|
|
38201
38401
|
}
|
|
38202
38402
|
}
|
|
38203
38403
|
static async detectStructure(skillsDir) {
|
|
38204
|
-
const entries = await
|
|
38404
|
+
const entries = await readdir15(skillsDir, { withFileTypes: true });
|
|
38205
38405
|
const dirs = entries.filter((entry) => entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith("."));
|
|
38206
38406
|
if (dirs.length === 0) {
|
|
38207
38407
|
return "flat";
|
|
38208
38408
|
}
|
|
38209
38409
|
for (const dir of dirs.slice(0, 3)) {
|
|
38210
|
-
const dirPath =
|
|
38211
|
-
const subEntries = await
|
|
38410
|
+
const dirPath = join51(skillsDir, dir.name);
|
|
38411
|
+
const subEntries = await readdir15(dirPath, { withFileTypes: true });
|
|
38212
38412
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
38213
38413
|
if (hasSubdirs) {
|
|
38214
38414
|
return "categorized";
|
|
@@ -38223,10 +38423,10 @@ class SkillsManifestManager {
|
|
|
38223
38423
|
static async scanSkills(skillsDir, structure) {
|
|
38224
38424
|
const skills = [];
|
|
38225
38425
|
if (structure === "flat") {
|
|
38226
|
-
const entries = await
|
|
38426
|
+
const entries = await readdir15(skillsDir, { withFileTypes: true });
|
|
38227
38427
|
for (const entry of entries) {
|
|
38228
38428
|
if (entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith(".")) {
|
|
38229
|
-
const skillPath =
|
|
38429
|
+
const skillPath = join51(skillsDir, entry.name);
|
|
38230
38430
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
38231
38431
|
skills.push({
|
|
38232
38432
|
name: entry.name,
|
|
@@ -38235,14 +38435,14 @@ class SkillsManifestManager {
|
|
|
38235
38435
|
}
|
|
38236
38436
|
}
|
|
38237
38437
|
} else {
|
|
38238
|
-
const categories = await
|
|
38438
|
+
const categories = await readdir15(skillsDir, { withFileTypes: true });
|
|
38239
38439
|
for (const category of categories) {
|
|
38240
38440
|
if (category.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(category.name) && !category.name.startsWith(".")) {
|
|
38241
|
-
const categoryPath =
|
|
38242
|
-
const skillEntries = await
|
|
38441
|
+
const categoryPath = join51(skillsDir, category.name);
|
|
38442
|
+
const skillEntries = await readdir15(categoryPath, { withFileTypes: true });
|
|
38243
38443
|
for (const skillEntry of skillEntries) {
|
|
38244
38444
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
38245
|
-
const skillPath =
|
|
38445
|
+
const skillPath = join51(categoryPath, skillEntry.name);
|
|
38246
38446
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
38247
38447
|
skills.push({
|
|
38248
38448
|
name: skillEntry.name,
|
|
@@ -38262,7 +38462,7 @@ class SkillsManifestManager {
|
|
|
38262
38462
|
files.sort();
|
|
38263
38463
|
for (const file of files) {
|
|
38264
38464
|
const relativePath = relative9(dirPath, file);
|
|
38265
|
-
const content = await
|
|
38465
|
+
const content = await readFile18(file);
|
|
38266
38466
|
hash.update(relativePath);
|
|
38267
38467
|
hash.update(content);
|
|
38268
38468
|
}
|
|
@@ -38270,9 +38470,9 @@ class SkillsManifestManager {
|
|
|
38270
38470
|
}
|
|
38271
38471
|
static async getAllFiles(dirPath) {
|
|
38272
38472
|
const files = [];
|
|
38273
|
-
const entries = await
|
|
38473
|
+
const entries = await readdir15(dirPath, { withFileTypes: true });
|
|
38274
38474
|
for (const entry of entries) {
|
|
38275
|
-
const fullPath =
|
|
38475
|
+
const fullPath = join51(dirPath, entry.name);
|
|
38276
38476
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name)) {
|
|
38277
38477
|
continue;
|
|
38278
38478
|
}
|
|
@@ -38393,13 +38593,13 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
38393
38593
|
|
|
38394
38594
|
// src/domains/skills/detection/script-detector.ts
|
|
38395
38595
|
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
38396
|
-
import { readdir as
|
|
38397
|
-
import { join as
|
|
38596
|
+
import { readdir as readdir16 } from "node:fs/promises";
|
|
38597
|
+
import { join as join52 } from "node:path";
|
|
38398
38598
|
async function scanDirectory(skillsDir) {
|
|
38399
38599
|
if (!await import_fs_extra18.pathExists(skillsDir)) {
|
|
38400
38600
|
return ["flat", []];
|
|
38401
38601
|
}
|
|
38402
|
-
const entries = await
|
|
38602
|
+
const entries = await readdir16(skillsDir, { withFileTypes: true });
|
|
38403
38603
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
38404
38604
|
if (dirs.length === 0) {
|
|
38405
38605
|
return ["flat", []];
|
|
@@ -38407,13 +38607,13 @@ async function scanDirectory(skillsDir) {
|
|
|
38407
38607
|
let totalSkillLikeCount = 0;
|
|
38408
38608
|
const allSkills = [];
|
|
38409
38609
|
for (const dir of dirs) {
|
|
38410
|
-
const dirPath =
|
|
38411
|
-
const subEntries = await
|
|
38610
|
+
const dirPath = join52(skillsDir, dir.name);
|
|
38611
|
+
const subEntries = await readdir16(dirPath, { withFileTypes: true });
|
|
38412
38612
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
38413
38613
|
if (subdirs.length > 0) {
|
|
38414
38614
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
38415
|
-
const subdirPath =
|
|
38416
|
-
const subdirFiles = await
|
|
38615
|
+
const subdirPath = join52(dirPath, subdir.name);
|
|
38616
|
+
const subdirFiles = await readdir16(subdirPath, { withFileTypes: true });
|
|
38417
38617
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
38418
38618
|
if (hasSkillMarker) {
|
|
38419
38619
|
totalSkillLikeCount++;
|
|
@@ -38569,12 +38769,12 @@ class SkillsMigrationDetector {
|
|
|
38569
38769
|
// src/domains/skills/skills-migrator.ts
|
|
38570
38770
|
init_logger();
|
|
38571
38771
|
init_types2();
|
|
38572
|
-
import { join as
|
|
38772
|
+
import { join as join57 } from "node:path";
|
|
38573
38773
|
|
|
38574
38774
|
// src/domains/skills/migrator/migration-executor.ts
|
|
38575
38775
|
init_logger();
|
|
38576
|
-
import { copyFile as copyFile4, mkdir as mkdir17, readdir as
|
|
38577
|
-
import { join as
|
|
38776
|
+
import { copyFile as copyFile4, mkdir as mkdir17, readdir as readdir17, rm as rm3 } from "node:fs/promises";
|
|
38777
|
+
import { join as join53 } from "node:path";
|
|
38578
38778
|
var import_fs_extra20 = __toESM(require_lib(), 1);
|
|
38579
38779
|
|
|
38580
38780
|
// src/domains/skills/skills-migration-prompts.ts
|
|
@@ -38737,10 +38937,10 @@ Detected changes:`;
|
|
|
38737
38937
|
// src/domains/skills/migrator/migration-executor.ts
|
|
38738
38938
|
async function copySkillDirectory(sourceDir, destDir) {
|
|
38739
38939
|
await mkdir17(destDir, { recursive: true });
|
|
38740
|
-
const entries = await
|
|
38940
|
+
const entries = await readdir17(sourceDir, { withFileTypes: true });
|
|
38741
38941
|
for (const entry of entries) {
|
|
38742
|
-
const sourcePath =
|
|
38743
|
-
const destPath =
|
|
38942
|
+
const sourcePath = join53(sourceDir, entry.name);
|
|
38943
|
+
const destPath = join53(destDir, entry.name);
|
|
38744
38944
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
38745
38945
|
continue;
|
|
38746
38946
|
}
|
|
@@ -38755,7 +38955,7 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
38755
38955
|
const migrated = [];
|
|
38756
38956
|
const preserved = [];
|
|
38757
38957
|
const errors2 = [];
|
|
38758
|
-
const tempDir =
|
|
38958
|
+
const tempDir = join53(currentSkillsDir, "..", ".skills-migration-temp");
|
|
38759
38959
|
await mkdir17(tempDir, { recursive: true });
|
|
38760
38960
|
try {
|
|
38761
38961
|
for (const mapping of mappings) {
|
|
@@ -38776,9 +38976,9 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
38776
38976
|
}
|
|
38777
38977
|
}
|
|
38778
38978
|
const category = mapping.category;
|
|
38779
|
-
const targetPath = category ?
|
|
38979
|
+
const targetPath = category ? join53(tempDir, category, skillName) : join53(tempDir, skillName);
|
|
38780
38980
|
if (category) {
|
|
38781
|
-
await mkdir17(
|
|
38981
|
+
await mkdir17(join53(tempDir, category), { recursive: true });
|
|
38782
38982
|
}
|
|
38783
38983
|
await copySkillDirectory(currentSkillPath, targetPath);
|
|
38784
38984
|
migrated.push(skillName);
|
|
@@ -38844,8 +39044,8 @@ function validateMigrationPath(path11, paramName) {
|
|
|
38844
39044
|
init_logger();
|
|
38845
39045
|
init_types2();
|
|
38846
39046
|
var import_fs_extra21 = __toESM(require_lib(), 1);
|
|
38847
|
-
import { copyFile as copyFile5, mkdir as mkdir18, readdir as
|
|
38848
|
-
import { basename as basename2, join as
|
|
39047
|
+
import { copyFile as copyFile5, mkdir as mkdir18, readdir as readdir18, rm as rm4, stat as stat9 } from "node:fs/promises";
|
|
39048
|
+
import { basename as basename2, join as join54, normalize as normalize6 } from "node:path";
|
|
38849
39049
|
function validatePath2(path11, paramName) {
|
|
38850
39050
|
if (!path11 || typeof path11 !== "string") {
|
|
38851
39051
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -38871,7 +39071,7 @@ class SkillsBackupManager {
|
|
|
38871
39071
|
const timestamp = Date.now();
|
|
38872
39072
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
38873
39073
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
38874
|
-
const backupDir = parentDir ?
|
|
39074
|
+
const backupDir = parentDir ? join54(parentDir, backupDirName) : join54(skillsDir, "..", backupDirName);
|
|
38875
39075
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
38876
39076
|
try {
|
|
38877
39077
|
await mkdir18(backupDir, { recursive: true });
|
|
@@ -38921,8 +39121,8 @@ class SkillsBackupManager {
|
|
|
38921
39121
|
return [];
|
|
38922
39122
|
}
|
|
38923
39123
|
try {
|
|
38924
|
-
const entries = await
|
|
38925
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
39124
|
+
const entries = await readdir18(parentDir, { withFileTypes: true });
|
|
39125
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join54(parentDir, entry.name));
|
|
38926
39126
|
backups.sort().reverse();
|
|
38927
39127
|
return backups;
|
|
38928
39128
|
} catch (error) {
|
|
@@ -38948,10 +39148,10 @@ class SkillsBackupManager {
|
|
|
38948
39148
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
38949
39149
|
}
|
|
38950
39150
|
static async copyDirectory(sourceDir, destDir) {
|
|
38951
|
-
const entries = await
|
|
39151
|
+
const entries = await readdir18(sourceDir, { withFileTypes: true });
|
|
38952
39152
|
for (const entry of entries) {
|
|
38953
|
-
const sourcePath =
|
|
38954
|
-
const destPath =
|
|
39153
|
+
const sourcePath = join54(sourceDir, entry.name);
|
|
39154
|
+
const destPath = join54(destDir, entry.name);
|
|
38955
39155
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
38956
39156
|
continue;
|
|
38957
39157
|
}
|
|
@@ -38965,9 +39165,9 @@ class SkillsBackupManager {
|
|
|
38965
39165
|
}
|
|
38966
39166
|
static async getDirectorySize(dirPath) {
|
|
38967
39167
|
let size = 0;
|
|
38968
|
-
const entries = await
|
|
39168
|
+
const entries = await readdir18(dirPath, { withFileTypes: true });
|
|
38969
39169
|
for (const entry of entries) {
|
|
38970
|
-
const fullPath =
|
|
39170
|
+
const fullPath = join54(dirPath, entry.name);
|
|
38971
39171
|
if (entry.isSymbolicLink()) {
|
|
38972
39172
|
continue;
|
|
38973
39173
|
}
|
|
@@ -39001,13 +39201,13 @@ import { relative as relative11 } from "node:path";
|
|
|
39001
39201
|
// src/domains/skills/customization/hash-calculator.ts
|
|
39002
39202
|
import { createHash as createHash3 } from "node:crypto";
|
|
39003
39203
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
39004
|
-
import { readFile as
|
|
39005
|
-
import { join as
|
|
39204
|
+
import { readFile as readFile19, readdir as readdir19 } from "node:fs/promises";
|
|
39205
|
+
import { join as join55, relative as relative10 } from "node:path";
|
|
39006
39206
|
async function getAllFiles(dirPath) {
|
|
39007
39207
|
const files = [];
|
|
39008
|
-
const entries = await
|
|
39208
|
+
const entries = await readdir19(dirPath, { withFileTypes: true });
|
|
39009
39209
|
for (const entry of entries) {
|
|
39010
|
-
const fullPath =
|
|
39210
|
+
const fullPath = join55(dirPath, entry.name);
|
|
39011
39211
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name) || entry.isSymbolicLink()) {
|
|
39012
39212
|
continue;
|
|
39013
39213
|
}
|
|
@@ -39040,7 +39240,7 @@ async function hashDirectory(dirPath) {
|
|
|
39040
39240
|
files.sort();
|
|
39041
39241
|
for (const file of files) {
|
|
39042
39242
|
const relativePath = relative10(dirPath, file);
|
|
39043
|
-
const content = await
|
|
39243
|
+
const content = await readFile19(file);
|
|
39044
39244
|
hash.update(relativePath);
|
|
39045
39245
|
hash.update(content);
|
|
39046
39246
|
}
|
|
@@ -39133,8 +39333,8 @@ async function detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
|
39133
39333
|
// src/domains/skills/customization/scan-reporter.ts
|
|
39134
39334
|
init_types2();
|
|
39135
39335
|
var import_fs_extra23 = __toESM(require_lib(), 1);
|
|
39136
|
-
import { readdir as
|
|
39137
|
-
import { join as
|
|
39336
|
+
import { readdir as readdir20 } from "node:fs/promises";
|
|
39337
|
+
import { join as join56, normalize as normalize7 } from "node:path";
|
|
39138
39338
|
function validatePath3(path11, paramName) {
|
|
39139
39339
|
if (!path11 || typeof path11 !== "string") {
|
|
39140
39340
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -39150,19 +39350,19 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
39150
39350
|
if (!await import_fs_extra23.pathExists(skillsDir)) {
|
|
39151
39351
|
return ["flat", []];
|
|
39152
39352
|
}
|
|
39153
|
-
const entries = await
|
|
39353
|
+
const entries = await readdir20(skillsDir, { withFileTypes: true });
|
|
39154
39354
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
39155
39355
|
if (dirs.length === 0) {
|
|
39156
39356
|
return ["flat", []];
|
|
39157
39357
|
}
|
|
39158
|
-
const firstDirPath =
|
|
39159
|
-
const subEntries = await
|
|
39358
|
+
const firstDirPath = join56(skillsDir, dirs[0].name);
|
|
39359
|
+
const subEntries = await readdir20(firstDirPath, { withFileTypes: true });
|
|
39160
39360
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
39161
39361
|
if (subdirs.length > 0) {
|
|
39162
39362
|
let skillLikeCount = 0;
|
|
39163
39363
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
39164
|
-
const subdirPath =
|
|
39165
|
-
const subdirFiles = await
|
|
39364
|
+
const subdirPath = join56(firstDirPath, subdir.name);
|
|
39365
|
+
const subdirFiles = await readdir20(subdirPath, { withFileTypes: true });
|
|
39166
39366
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
39167
39367
|
if (hasSkillMarker) {
|
|
39168
39368
|
skillLikeCount++;
|
|
@@ -39171,8 +39371,8 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
39171
39371
|
if (skillLikeCount > 0) {
|
|
39172
39372
|
const skills = [];
|
|
39173
39373
|
for (const dir of dirs) {
|
|
39174
|
-
const categoryPath =
|
|
39175
|
-
const skillDirs = await
|
|
39374
|
+
const categoryPath = join56(skillsDir, dir.name);
|
|
39375
|
+
const skillDirs = await readdir20(categoryPath, { withFileTypes: true });
|
|
39176
39376
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
39177
39377
|
}
|
|
39178
39378
|
return ["categorized", skills];
|
|
@@ -39181,17 +39381,17 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
39181
39381
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
39182
39382
|
}
|
|
39183
39383
|
async function findSkillPath(skillsDir, skillName) {
|
|
39184
|
-
const flatPath =
|
|
39384
|
+
const flatPath = join56(skillsDir, skillName);
|
|
39185
39385
|
if (await import_fs_extra23.pathExists(flatPath)) {
|
|
39186
39386
|
return { path: flatPath, category: undefined };
|
|
39187
39387
|
}
|
|
39188
|
-
const entries = await
|
|
39388
|
+
const entries = await readdir20(skillsDir, { withFileTypes: true });
|
|
39189
39389
|
for (const entry of entries) {
|
|
39190
39390
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
39191
39391
|
continue;
|
|
39192
39392
|
}
|
|
39193
|
-
const categoryPath =
|
|
39194
|
-
const skillPath =
|
|
39393
|
+
const categoryPath = join56(skillsDir, entry.name);
|
|
39394
|
+
const skillPath = join56(categoryPath, skillName);
|
|
39195
39395
|
if (await import_fs_extra23.pathExists(skillPath)) {
|
|
39196
39396
|
return { path: skillPath, category: entry.name };
|
|
39197
39397
|
}
|
|
@@ -39285,7 +39485,7 @@ class SkillsMigrator {
|
|
|
39285
39485
|
}
|
|
39286
39486
|
}
|
|
39287
39487
|
if (options.backup && !options.dryRun) {
|
|
39288
|
-
const claudeDir =
|
|
39488
|
+
const claudeDir = join57(currentSkillsDir, "..");
|
|
39289
39489
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
39290
39490
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
39291
39491
|
}
|
|
@@ -39345,7 +39545,7 @@ async function handleMigration(ctx) {
|
|
|
39345
39545
|
logger.debug("Skipping skills migration (fresh installation)");
|
|
39346
39546
|
return ctx;
|
|
39347
39547
|
}
|
|
39348
|
-
const newSkillsDir =
|
|
39548
|
+
const newSkillsDir = join58(ctx.extractDir, ".claude", "skills");
|
|
39349
39549
|
const currentSkillsDir = PathResolver.buildSkillsPath(ctx.resolvedDir, ctx.options.global);
|
|
39350
39550
|
if (!await import_fs_extra24.pathExists(newSkillsDir) || !await import_fs_extra24.pathExists(currentSkillsDir)) {
|
|
39351
39551
|
return ctx;
|
|
@@ -39367,13 +39567,156 @@ async function handleMigration(ctx) {
|
|
|
39367
39567
|
}
|
|
39368
39568
|
return ctx;
|
|
39369
39569
|
}
|
|
39570
|
+
// src/commands/init/phases/opencode-handler.ts
|
|
39571
|
+
import { cp, readdir as readdir22, rm as rm5 } from "node:fs/promises";
|
|
39572
|
+
import { join as join60 } from "node:path";
|
|
39573
|
+
|
|
39574
|
+
// src/services/transformers/opencode-path-transformer.ts
|
|
39575
|
+
init_logger();
|
|
39576
|
+
import { readFile as readFile20, readdir as readdir21, writeFile as writeFile16 } from "node:fs/promises";
|
|
39577
|
+
import { platform as platform10 } from "node:os";
|
|
39578
|
+
import { extname as extname2, join as join59 } from "node:path";
|
|
39579
|
+
var IS_WINDOWS3 = platform10() === "win32";
|
|
39580
|
+
function getOpenCodeGlobalPath() {
|
|
39581
|
+
return IS_WINDOWS3 ? "%APPDATA%/opencode/" : "$HOME/.config/opencode/";
|
|
39582
|
+
}
|
|
39583
|
+
var TRANSFORMABLE_EXTENSIONS2 = new Set([
|
|
39584
|
+
".md",
|
|
39585
|
+
".js",
|
|
39586
|
+
".ts",
|
|
39587
|
+
".json",
|
|
39588
|
+
".sh",
|
|
39589
|
+
".ps1",
|
|
39590
|
+
".yaml",
|
|
39591
|
+
".yml",
|
|
39592
|
+
".toml"
|
|
39593
|
+
]);
|
|
39594
|
+
function transformOpenCodeContent(content) {
|
|
39595
|
+
let changes = 0;
|
|
39596
|
+
let transformed = content;
|
|
39597
|
+
const globalPath = getOpenCodeGlobalPath();
|
|
39598
|
+
transformed = transformed.replace(/\.\/\.opencode\//g, () => {
|
|
39599
|
+
changes++;
|
|
39600
|
+
return globalPath;
|
|
39601
|
+
});
|
|
39602
|
+
transformed = transformed.replace(/(["'`])\.opencode\//g, (_match, quote) => {
|
|
39603
|
+
changes++;
|
|
39604
|
+
return `${quote}${globalPath}`;
|
|
39605
|
+
});
|
|
39606
|
+
transformed = transformed.replace(/\(\.opencode\//g, () => {
|
|
39607
|
+
changes++;
|
|
39608
|
+
return `(${globalPath}`;
|
|
39609
|
+
});
|
|
39610
|
+
transformed = transformed.replace(/ \.opencode\//g, () => {
|
|
39611
|
+
changes++;
|
|
39612
|
+
return ` ${globalPath}`;
|
|
39613
|
+
});
|
|
39614
|
+
transformed = transformed.replace(/^\.opencode\//gm, () => {
|
|
39615
|
+
changes++;
|
|
39616
|
+
return globalPath;
|
|
39617
|
+
});
|
|
39618
|
+
transformed = transformed.replace(/: \.opencode\//g, () => {
|
|
39619
|
+
changes++;
|
|
39620
|
+
return `: ${globalPath}`;
|
|
39621
|
+
});
|
|
39622
|
+
transformed = transformed.replace(/:\.opencode\//g, () => {
|
|
39623
|
+
changes++;
|
|
39624
|
+
return `:${globalPath}`;
|
|
39625
|
+
});
|
|
39626
|
+
return { transformed, changes };
|
|
39627
|
+
}
|
|
39628
|
+
function shouldTransformFile2(filename) {
|
|
39629
|
+
const ext2 = extname2(filename).toLowerCase();
|
|
39630
|
+
return TRANSFORMABLE_EXTENSIONS2.has(ext2);
|
|
39631
|
+
}
|
|
39632
|
+
async function transformPathsForGlobalOpenCode(directory, options = {}) {
|
|
39633
|
+
let filesTransformed = 0;
|
|
39634
|
+
let totalChanges = 0;
|
|
39635
|
+
let filesSkipped = 0;
|
|
39636
|
+
async function processDirectory2(dir) {
|
|
39637
|
+
const entries = await readdir21(dir, { withFileTypes: true });
|
|
39638
|
+
for (const entry of entries) {
|
|
39639
|
+
const fullPath = join59(dir, entry.name);
|
|
39640
|
+
if (entry.isDirectory()) {
|
|
39641
|
+
if (entry.name === "node_modules" || entry.name.startsWith(".")) {
|
|
39642
|
+
continue;
|
|
39643
|
+
}
|
|
39644
|
+
await processDirectory2(fullPath);
|
|
39645
|
+
} else if (entry.isFile() && shouldTransformFile2(entry.name)) {
|
|
39646
|
+
try {
|
|
39647
|
+
const content = await readFile20(fullPath, "utf-8");
|
|
39648
|
+
const { transformed, changes } = transformOpenCodeContent(content);
|
|
39649
|
+
if (changes > 0) {
|
|
39650
|
+
await writeFile16(fullPath, transformed, "utf-8");
|
|
39651
|
+
filesTransformed++;
|
|
39652
|
+
totalChanges += changes;
|
|
39653
|
+
if (options.verbose) {
|
|
39654
|
+
logger.verbose(`Transformed ${changes} OpenCode path(s) in ${fullPath}`);
|
|
39655
|
+
}
|
|
39656
|
+
}
|
|
39657
|
+
} catch (error) {
|
|
39658
|
+
filesSkipped++;
|
|
39659
|
+
if (options.verbose) {
|
|
39660
|
+
logger.verbose(`Skipping ${fullPath}: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
39661
|
+
}
|
|
39662
|
+
}
|
|
39663
|
+
}
|
|
39664
|
+
}
|
|
39665
|
+
}
|
|
39666
|
+
await processDirectory2(directory);
|
|
39667
|
+
return { filesTransformed, totalChanges, filesSkipped };
|
|
39668
|
+
}
|
|
39669
|
+
|
|
39670
|
+
// src/commands/init/phases/opencode-handler.ts
|
|
39671
|
+
init_logger();
|
|
39672
|
+
var import_fs_extra25 = __toESM(require_lib(), 1);
|
|
39673
|
+
async function handleOpenCode(ctx) {
|
|
39674
|
+
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir) {
|
|
39675
|
+
return ctx;
|
|
39676
|
+
}
|
|
39677
|
+
const openCodeSource = join60(ctx.extractDir, ".opencode");
|
|
39678
|
+
if (!await import_fs_extra25.pathExists(openCodeSource)) {
|
|
39679
|
+
logger.debug("No .opencode directory in archive, skipping");
|
|
39680
|
+
return ctx;
|
|
39681
|
+
}
|
|
39682
|
+
logger.info("Processing .opencode configuration...");
|
|
39683
|
+
if (ctx.options.global) {
|
|
39684
|
+
const targetDir = PathResolver.getOpenCodeDir(true);
|
|
39685
|
+
logger.verbose(`Relocating .opencode to ${targetDir}`);
|
|
39686
|
+
const transformResult = await transformPathsForGlobalOpenCode(openCodeSource, {
|
|
39687
|
+
verbose: logger.isVerbose()
|
|
39688
|
+
});
|
|
39689
|
+
if (transformResult.totalChanges > 0) {
|
|
39690
|
+
logger.success(`Transformed ${transformResult.totalChanges} OpenCode path(s) in ${transformResult.filesTransformed} file(s)`);
|
|
39691
|
+
}
|
|
39692
|
+
await import_fs_extra25.ensureDir(targetDir);
|
|
39693
|
+
const entries = await readdir22(openCodeSource, { withFileTypes: true });
|
|
39694
|
+
for (const entry of entries) {
|
|
39695
|
+
const sourcePath = join60(openCodeSource, entry.name);
|
|
39696
|
+
const targetPath = join60(targetDir, entry.name);
|
|
39697
|
+
if (await import_fs_extra25.pathExists(targetPath)) {
|
|
39698
|
+
if (!ctx.options.forceOverwrite) {
|
|
39699
|
+
logger.verbose(`Skipping existing: ${entry.name}`);
|
|
39700
|
+
continue;
|
|
39701
|
+
}
|
|
39702
|
+
}
|
|
39703
|
+
await cp(sourcePath, targetPath, { recursive: true });
|
|
39704
|
+
logger.verbose(`Copied: ${entry.name}`);
|
|
39705
|
+
}
|
|
39706
|
+
await rm5(openCodeSource, { recursive: true, force: true });
|
|
39707
|
+
logger.success(`OpenCode config installed to ${targetDir}`);
|
|
39708
|
+
} else {
|
|
39709
|
+
logger.debug("Local mode: .opencode will be placed at project root");
|
|
39710
|
+
}
|
|
39711
|
+
return ctx;
|
|
39712
|
+
}
|
|
39370
39713
|
// src/domains/config/config-manager.ts
|
|
39371
39714
|
init_logger();
|
|
39372
39715
|
import { existsSync as existsSync18 } from "node:fs";
|
|
39373
|
-
import { mkdir as mkdir19, readFile as
|
|
39716
|
+
import { mkdir as mkdir19, readFile as readFile21, rename as rename2, rm as rm6, writeFile as writeFile17 } from "node:fs/promises";
|
|
39374
39717
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
39375
|
-
import { platform as
|
|
39376
|
-
import { join as
|
|
39718
|
+
import { platform as platform11 } from "node:os";
|
|
39719
|
+
import { join as join61 } from "node:path";
|
|
39377
39720
|
init_types2();
|
|
39378
39721
|
var PROJECT_CONFIG_FILE = ".ck.json";
|
|
39379
39722
|
|
|
@@ -39381,7 +39724,7 @@ class ConfigManager {
|
|
|
39381
39724
|
static config = null;
|
|
39382
39725
|
static globalFlag = false;
|
|
39383
39726
|
static getProjectConfigDir(projectDir, global3) {
|
|
39384
|
-
return global3 ? projectDir :
|
|
39727
|
+
return global3 ? projectDir : join61(projectDir, ".claude");
|
|
39385
39728
|
}
|
|
39386
39729
|
static setGlobalFlag(global3) {
|
|
39387
39730
|
ConfigManager.globalFlag = global3;
|
|
@@ -39397,7 +39740,7 @@ class ConfigManager {
|
|
|
39397
39740
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
39398
39741
|
try {
|
|
39399
39742
|
if (existsSync18(configFile)) {
|
|
39400
|
-
const content = await
|
|
39743
|
+
const content = await readFile21(configFile, "utf-8");
|
|
39401
39744
|
const data = JSON.parse(content);
|
|
39402
39745
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
39403
39746
|
logger.debug(`Config loaded from ${configFile}`);
|
|
@@ -39416,12 +39759,12 @@ class ConfigManager {
|
|
|
39416
39759
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
39417
39760
|
if (!existsSync18(configDir)) {
|
|
39418
39761
|
await mkdir19(configDir, { recursive: true });
|
|
39419
|
-
if (
|
|
39762
|
+
if (platform11() !== "win32") {
|
|
39420
39763
|
await chmod2(configDir, 448);
|
|
39421
39764
|
}
|
|
39422
39765
|
}
|
|
39423
|
-
await
|
|
39424
|
-
if (
|
|
39766
|
+
await writeFile17(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
39767
|
+
if (platform11() !== "win32") {
|
|
39425
39768
|
await chmod2(configFile, 384);
|
|
39426
39769
|
}
|
|
39427
39770
|
ConfigManager.config = validConfig;
|
|
@@ -39448,10 +39791,10 @@ class ConfigManager {
|
|
|
39448
39791
|
}
|
|
39449
39792
|
static async loadProjectConfig(projectDir, global3 = false) {
|
|
39450
39793
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
39451
|
-
const configPath =
|
|
39794
|
+
const configPath = join61(configDir, PROJECT_CONFIG_FILE);
|
|
39452
39795
|
try {
|
|
39453
39796
|
if (existsSync18(configPath)) {
|
|
39454
|
-
const content = await
|
|
39797
|
+
const content = await readFile21(configPath, "utf-8");
|
|
39455
39798
|
const data = JSON.parse(content);
|
|
39456
39799
|
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
39457
39800
|
logger.debug(`Project config loaded from ${configPath}`);
|
|
@@ -39464,7 +39807,7 @@ class ConfigManager {
|
|
|
39464
39807
|
}
|
|
39465
39808
|
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
39466
39809
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
39467
|
-
const configPath =
|
|
39810
|
+
const configPath = join61(configDir, PROJECT_CONFIG_FILE);
|
|
39468
39811
|
try {
|
|
39469
39812
|
if (!existsSync18(configDir)) {
|
|
39470
39813
|
await mkdir19(configDir, { recursive: true });
|
|
@@ -39472,7 +39815,7 @@ class ConfigManager {
|
|
|
39472
39815
|
let existingConfig = {};
|
|
39473
39816
|
if (existsSync18(configPath)) {
|
|
39474
39817
|
try {
|
|
39475
|
-
const content = await
|
|
39818
|
+
const content = await readFile21(configPath, "utf-8");
|
|
39476
39819
|
existingConfig = JSON.parse(content);
|
|
39477
39820
|
} catch (error) {
|
|
39478
39821
|
logger.debug(`Could not parse existing config, starting fresh: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -39487,7 +39830,7 @@ class ConfigManager {
|
|
|
39487
39830
|
...validFolders
|
|
39488
39831
|
}
|
|
39489
39832
|
};
|
|
39490
|
-
await
|
|
39833
|
+
await writeFile17(configPath, JSON.stringify(mergedConfig, null, 2), "utf-8");
|
|
39491
39834
|
logger.debug(`Project config saved to ${configPath}`);
|
|
39492
39835
|
} catch (error) {
|
|
39493
39836
|
throw new Error(`Failed to save project config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -39513,11 +39856,11 @@ class ConfigManager {
|
|
|
39513
39856
|
}
|
|
39514
39857
|
static projectConfigExists(projectDir, global3 = false) {
|
|
39515
39858
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
39516
|
-
return existsSync18(
|
|
39859
|
+
return existsSync18(join61(configDir, PROJECT_CONFIG_FILE));
|
|
39517
39860
|
}
|
|
39518
39861
|
static async migrateNestedConfig(globalDir) {
|
|
39519
|
-
const correctPath =
|
|
39520
|
-
const incorrectPath =
|
|
39862
|
+
const correctPath = join61(globalDir, PROJECT_CONFIG_FILE);
|
|
39863
|
+
const incorrectPath = join61(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
39521
39864
|
if (existsSync18(correctPath)) {
|
|
39522
39865
|
logger.debug("Config already exists at correct location, skipping migration");
|
|
39523
39866
|
return false;
|
|
@@ -39527,9 +39870,9 @@ class ConfigManager {
|
|
|
39527
39870
|
logger.info("Migrating .ck.json from nested location to correct location...");
|
|
39528
39871
|
await rename2(incorrectPath, correctPath);
|
|
39529
39872
|
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
39530
|
-
const nestedClaudeDir =
|
|
39873
|
+
const nestedClaudeDir = join61(globalDir, ".claude");
|
|
39531
39874
|
try {
|
|
39532
|
-
await
|
|
39875
|
+
await rm6(nestedClaudeDir, { recursive: false });
|
|
39533
39876
|
logger.debug("Removed empty nested .claude directory");
|
|
39534
39877
|
} catch (rmError) {
|
|
39535
39878
|
logger.debug(`Could not remove nested .claude dir (may contain other files): ${rmError instanceof Error ? rmError.message : "Unknown"}`);
|
|
@@ -39618,14 +39961,14 @@ Please use only one download method.`);
|
|
|
39618
39961
|
};
|
|
39619
39962
|
}
|
|
39620
39963
|
// src/commands/init/phases/post-install-handler.ts
|
|
39621
|
-
import { join as
|
|
39964
|
+
import { join as join64 } from "node:path";
|
|
39622
39965
|
|
|
39623
39966
|
// src/domains/installation/setup-wizard.ts
|
|
39624
|
-
import { join as
|
|
39967
|
+
import { join as join63 } from "node:path";
|
|
39625
39968
|
|
|
39626
39969
|
// src/domains/config/config-generator.ts
|
|
39627
|
-
var
|
|
39628
|
-
import { join as
|
|
39970
|
+
var import_fs_extra26 = __toESM(require_lib(), 1);
|
|
39971
|
+
import { join as join62 } from "node:path";
|
|
39629
39972
|
async function generateEnvFile(targetDir, values) {
|
|
39630
39973
|
const lines = [
|
|
39631
39974
|
"# Generated by ClaudeKit CLI setup wizard",
|
|
@@ -39667,8 +40010,8 @@ async function generateEnvFile(targetDir, values) {
|
|
|
39667
40010
|
for (const [key, value] of otherValues) {
|
|
39668
40011
|
lines.push(`${key}=${value}`);
|
|
39669
40012
|
}
|
|
39670
|
-
const envPath =
|
|
39671
|
-
await
|
|
40013
|
+
const envPath = join62(targetDir, ".env");
|
|
40014
|
+
await import_fs_extra26.writeFile(envPath, `${lines.join(`
|
|
39672
40015
|
`)}
|
|
39673
40016
|
`, { mode: 384 });
|
|
39674
40017
|
}
|
|
@@ -39686,7 +40029,7 @@ function validateApiKey(value, pattern) {
|
|
|
39686
40029
|
// src/domains/installation/setup-wizard.ts
|
|
39687
40030
|
init_logger();
|
|
39688
40031
|
init_dist2();
|
|
39689
|
-
var
|
|
40032
|
+
var import_fs_extra27 = __toESM(require_lib(), 1);
|
|
39690
40033
|
var ESSENTIAL_CONFIGS = [
|
|
39691
40034
|
{
|
|
39692
40035
|
key: "GEMINI_API_KEY",
|
|
@@ -39715,7 +40058,7 @@ var ESSENTIAL_CONFIGS = [
|
|
|
39715
40058
|
];
|
|
39716
40059
|
async function parseEnvFile(path11) {
|
|
39717
40060
|
try {
|
|
39718
|
-
const content = await
|
|
40061
|
+
const content = await import_fs_extra27.readFile(path11, "utf-8");
|
|
39719
40062
|
const env2 = {};
|
|
39720
40063
|
for (const line of content.split(`
|
|
39721
40064
|
`)) {
|
|
@@ -39741,8 +40084,8 @@ async function parseEnvFile(path11) {
|
|
|
39741
40084
|
}
|
|
39742
40085
|
}
|
|
39743
40086
|
async function checkGlobalConfig() {
|
|
39744
|
-
const globalEnvPath =
|
|
39745
|
-
if (!await
|
|
40087
|
+
const globalEnvPath = join63(PathResolver.getGlobalKitDir(), ".env");
|
|
40088
|
+
if (!await import_fs_extra27.pathExists(globalEnvPath))
|
|
39746
40089
|
return false;
|
|
39747
40090
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
39748
40091
|
return Object.keys(env2).length > 0;
|
|
@@ -39757,8 +40100,8 @@ async function runSetupWizard(options) {
|
|
|
39757
40100
|
let globalEnv = {};
|
|
39758
40101
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
39759
40102
|
if (!isGlobal) {
|
|
39760
|
-
const globalEnvPath =
|
|
39761
|
-
if (await
|
|
40103
|
+
const globalEnvPath = join63(PathResolver.getGlobalKitDir(), ".env");
|
|
40104
|
+
if (await import_fs_extra27.pathExists(globalEnvPath)) {
|
|
39762
40105
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
39763
40106
|
}
|
|
39764
40107
|
}
|
|
@@ -39820,7 +40163,7 @@ async function runSetupWizard(options) {
|
|
|
39820
40163
|
}
|
|
39821
40164
|
}
|
|
39822
40165
|
await generateEnvFile(targetDir, values);
|
|
39823
|
-
f2.success(`Configuration saved to ${
|
|
40166
|
+
f2.success(`Configuration saved to ${join63(targetDir, ".env")}`);
|
|
39824
40167
|
return true;
|
|
39825
40168
|
}
|
|
39826
40169
|
async function promptForAdditionalGeminiKeys(primaryKey) {
|
|
@@ -39870,17 +40213,17 @@ async function promptForAdditionalGeminiKeys(primaryKey) {
|
|
|
39870
40213
|
|
|
39871
40214
|
// src/commands/init/phases/post-install-handler.ts
|
|
39872
40215
|
init_logger();
|
|
39873
|
-
var
|
|
40216
|
+
var import_fs_extra28 = __toESM(require_lib(), 1);
|
|
39874
40217
|
async function handlePostInstall(ctx) {
|
|
39875
40218
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir || !ctx.claudeDir) {
|
|
39876
40219
|
return ctx;
|
|
39877
40220
|
}
|
|
39878
40221
|
if (ctx.options.global) {
|
|
39879
|
-
const claudeMdSource =
|
|
39880
|
-
const claudeMdDest =
|
|
39881
|
-
if (await
|
|
39882
|
-
if (!await
|
|
39883
|
-
await
|
|
40222
|
+
const claudeMdSource = join64(ctx.extractDir, "CLAUDE.md");
|
|
40223
|
+
const claudeMdDest = join64(ctx.resolvedDir, "CLAUDE.md");
|
|
40224
|
+
if (await import_fs_extra28.pathExists(claudeMdSource)) {
|
|
40225
|
+
if (!await import_fs_extra28.pathExists(claudeMdDest)) {
|
|
40226
|
+
await import_fs_extra28.copy(claudeMdSource, claudeMdDest);
|
|
39884
40227
|
logger.success("Copied CLAUDE.md to global directory");
|
|
39885
40228
|
} else {
|
|
39886
40229
|
logger.debug("CLAUDE.md already exists in global directory (preserved)");
|
|
@@ -39924,8 +40267,8 @@ async function handlePostInstall(ctx) {
|
|
|
39924
40267
|
}
|
|
39925
40268
|
}
|
|
39926
40269
|
if (!ctx.options.skipSetup && !ctx.isNonInteractive) {
|
|
39927
|
-
const envPath =
|
|
39928
|
-
if (!await
|
|
40270
|
+
const envPath = join64(ctx.claudeDir, ".env");
|
|
40271
|
+
if (!await import_fs_extra28.pathExists(envPath)) {
|
|
39929
40272
|
const shouldSetup = await ctx.prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
39930
40273
|
if (shouldSetup) {
|
|
39931
40274
|
await runSetupWizard({
|
|
@@ -39946,7 +40289,7 @@ Optional: DISCORD_WEBHOOK_URL, TELEGRAM_BOT_TOKEN`, "Configuration skipped");
|
|
|
39946
40289
|
}
|
|
39947
40290
|
// src/commands/init/phases/selection-handler.ts
|
|
39948
40291
|
import { mkdir as mkdir20 } from "node:fs/promises";
|
|
39949
|
-
import { join as
|
|
40292
|
+
import { join as join66, resolve as resolve7 } from "node:path";
|
|
39950
40293
|
|
|
39951
40294
|
// src/domains/github/kit-access-checker.ts
|
|
39952
40295
|
init_logger();
|
|
@@ -39975,11 +40318,11 @@ async function detectAccessibleKits() {
|
|
|
39975
40318
|
|
|
39976
40319
|
// src/domains/installation/fresh-installer.ts
|
|
39977
40320
|
init_logger();
|
|
39978
|
-
import { join as
|
|
39979
|
-
var
|
|
40321
|
+
import { join as join65 } from "node:path";
|
|
40322
|
+
var import_fs_extra29 = __toESM(require_lib(), 1);
|
|
39980
40323
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
|
|
39981
40324
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
39982
|
-
if (!await
|
|
40325
|
+
if (!await import_fs_extra29.pathExists(claudeDir)) {
|
|
39983
40326
|
logger.info(".claude directory does not exist, proceeding with fresh installation");
|
|
39984
40327
|
return true;
|
|
39985
40328
|
}
|
|
@@ -39994,8 +40337,8 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
39994
40337
|
const { rmSync } = await import("node:fs");
|
|
39995
40338
|
let removedCount = 0;
|
|
39996
40339
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
39997
|
-
const subdirPath =
|
|
39998
|
-
if (await
|
|
40340
|
+
const subdirPath = join65(claudeDir, subdir);
|
|
40341
|
+
if (await import_fs_extra29.pathExists(subdirPath)) {
|
|
39999
40342
|
rmSync(subdirPath, { recursive: true, force: true });
|
|
40000
40343
|
removedCount++;
|
|
40001
40344
|
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
@@ -40012,7 +40355,7 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
40012
40355
|
// src/commands/init/phases/selection-handler.ts
|
|
40013
40356
|
init_logger();
|
|
40014
40357
|
init_types2();
|
|
40015
|
-
var
|
|
40358
|
+
var import_fs_extra30 = __toESM(require_lib(), 1);
|
|
40016
40359
|
|
|
40017
40360
|
// src/commands/init/types.ts
|
|
40018
40361
|
function isSyncContext(ctx) {
|
|
@@ -40176,7 +40519,7 @@ async function handleSelection(ctx) {
|
|
|
40176
40519
|
return { ...ctx, cancelled: true };
|
|
40177
40520
|
}
|
|
40178
40521
|
}
|
|
40179
|
-
if (!await
|
|
40522
|
+
if (!await import_fs_extra30.pathExists(resolvedDir)) {
|
|
40180
40523
|
if (ctx.options.global) {
|
|
40181
40524
|
await mkdir20(resolvedDir, { recursive: true });
|
|
40182
40525
|
logger.info(`Created global directory: ${resolvedDir}`);
|
|
@@ -40188,7 +40531,7 @@ async function handleSelection(ctx) {
|
|
|
40188
40531
|
}
|
|
40189
40532
|
if (!ctx.options.fresh) {
|
|
40190
40533
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
40191
|
-
const claudeDir = prefix ?
|
|
40534
|
+
const claudeDir = prefix ? join66(resolvedDir, prefix) : resolvedDir;
|
|
40192
40535
|
try {
|
|
40193
40536
|
const existingMetadata = await readManifest(claudeDir);
|
|
40194
40537
|
if (existingMetadata?.kits) {
|
|
@@ -40220,7 +40563,7 @@ async function handleSelection(ctx) {
|
|
|
40220
40563
|
}
|
|
40221
40564
|
if (ctx.options.fresh) {
|
|
40222
40565
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
40223
|
-
const claudeDir = prefix ?
|
|
40566
|
+
const claudeDir = prefix ? join66(resolvedDir, prefix) : resolvedDir;
|
|
40224
40567
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
40225
40568
|
if (!canProceed) {
|
|
40226
40569
|
return { ...ctx, cancelled: true };
|
|
@@ -40238,7 +40581,7 @@ async function handleSelection(ctx) {
|
|
|
40238
40581
|
logger.info("Fetching available versions...");
|
|
40239
40582
|
let currentVersion = null;
|
|
40240
40583
|
try {
|
|
40241
|
-
const metadataPath = ctx.options.global ?
|
|
40584
|
+
const metadataPath = ctx.options.global ? join66(PathResolver.getGlobalKitDir(), "metadata.json") : join66(resolvedDir, ".claude", "metadata.json");
|
|
40242
40585
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
40243
40586
|
currentVersion = metadata?.version || null;
|
|
40244
40587
|
if (currentVersion) {
|
|
@@ -40306,24 +40649,24 @@ async function handleSelection(ctx) {
|
|
|
40306
40649
|
};
|
|
40307
40650
|
}
|
|
40308
40651
|
// src/commands/init/phases/sync-handler.ts
|
|
40309
|
-
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as
|
|
40310
|
-
import { dirname as dirname9, join as
|
|
40652
|
+
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as writeFile19 } from "node:fs/promises";
|
|
40653
|
+
import { dirname as dirname9, join as join67, resolve as resolve8 } from "node:path";
|
|
40311
40654
|
init_logger();
|
|
40312
|
-
var
|
|
40655
|
+
var import_fs_extra31 = __toESM(require_lib(), 1);
|
|
40313
40656
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
40314
40657
|
async function handleSync(ctx) {
|
|
40315
40658
|
if (!ctx.options.sync) {
|
|
40316
40659
|
return ctx;
|
|
40317
40660
|
}
|
|
40318
40661
|
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve8(ctx.options.dir || ".");
|
|
40319
|
-
const claudeDir = ctx.options.global ? resolvedDir :
|
|
40320
|
-
if (!await
|
|
40662
|
+
const claudeDir = ctx.options.global ? resolvedDir : join67(resolvedDir, ".claude");
|
|
40663
|
+
if (!await import_fs_extra31.pathExists(claudeDir)) {
|
|
40321
40664
|
logger.error("Cannot sync: no .claude directory found");
|
|
40322
40665
|
ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
|
|
40323
40666
|
return { ...ctx, cancelled: true };
|
|
40324
40667
|
}
|
|
40325
|
-
const metadataPath =
|
|
40326
|
-
if (!await
|
|
40668
|
+
const metadataPath = join67(claudeDir, "metadata.json");
|
|
40669
|
+
if (!await import_fs_extra31.pathExists(metadataPath)) {
|
|
40327
40670
|
logger.error("Cannot sync: no metadata.json found");
|
|
40328
40671
|
ctx.prompts.note(`Your installation may be from an older version.
|
|
40329
40672
|
Run 'ck init' to update.`, "Legacy Installation");
|
|
@@ -40422,7 +40765,7 @@ function getLockTimeout() {
|
|
|
40422
40765
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
40423
40766
|
async function acquireSyncLock(global3) {
|
|
40424
40767
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
40425
|
-
const lockPath =
|
|
40768
|
+
const lockPath = join67(cacheDir, ".sync-lock");
|
|
40426
40769
|
const startTime = Date.now();
|
|
40427
40770
|
const lockTimeout = getLockTimeout();
|
|
40428
40771
|
await mkdir21(dirname9(lockPath), { recursive: true });
|
|
@@ -40468,7 +40811,7 @@ async function executeSyncMerge(ctx) {
|
|
|
40468
40811
|
const releaseLock = await acquireSyncLock(ctx.options.global);
|
|
40469
40812
|
try {
|
|
40470
40813
|
const trackedFiles = ctx.syncTrackedFiles;
|
|
40471
|
-
const upstreamDir = ctx.options.global ?
|
|
40814
|
+
const upstreamDir = ctx.options.global ? join67(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
40472
40815
|
logger.info("Analyzing file changes...");
|
|
40473
40816
|
const plan = await SyncEngine.createSyncPlan(trackedFiles, ctx.claudeDir, upstreamDir);
|
|
40474
40817
|
displaySyncPlan(plan);
|
|
@@ -40487,7 +40830,7 @@ async function executeSyncMerge(ctx) {
|
|
|
40487
40830
|
try {
|
|
40488
40831
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
40489
40832
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
40490
|
-
const targetDir =
|
|
40833
|
+
const targetDir = join67(targetPath, "..");
|
|
40491
40834
|
try {
|
|
40492
40835
|
await mkdir21(targetDir, { recursive: true });
|
|
40493
40836
|
} catch (mkdirError) {
|
|
@@ -40568,7 +40911,7 @@ async function executeSyncMerge(ctx) {
|
|
|
40568
40911
|
try {
|
|
40569
40912
|
const tempPath = `${currentPath}.tmp.${Date.now()}`;
|
|
40570
40913
|
try {
|
|
40571
|
-
await
|
|
40914
|
+
await writeFile19(tempPath, result.result, "utf-8");
|
|
40572
40915
|
await rename3(tempPath, currentPath);
|
|
40573
40916
|
} catch (atomicError) {
|
|
40574
40917
|
await unlink7(tempPath).catch(() => {});
|
|
@@ -40656,9 +40999,9 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
40656
40999
|
for (const file of files) {
|
|
40657
41000
|
try {
|
|
40658
41001
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
40659
|
-
if (await
|
|
41002
|
+
if (await import_fs_extra31.pathExists(sourcePath)) {
|
|
40660
41003
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
40661
|
-
const targetDir =
|
|
41004
|
+
const targetDir = join67(targetPath, "..");
|
|
40662
41005
|
await mkdir21(targetDir, { recursive: true });
|
|
40663
41006
|
await copyFile6(sourcePath, targetPath);
|
|
40664
41007
|
}
|
|
@@ -40672,7 +41015,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
40672
41015
|
}
|
|
40673
41016
|
}
|
|
40674
41017
|
// src/commands/init/phases/transform-handler.ts
|
|
40675
|
-
import { join as
|
|
41018
|
+
import { join as join71 } from "node:path";
|
|
40676
41019
|
|
|
40677
41020
|
// src/services/transformers/folder-path-transformer.ts
|
|
40678
41021
|
init_logger();
|
|
@@ -40681,40 +41024,40 @@ init_types2();
|
|
|
40681
41024
|
// src/services/transformers/folder-transform/folder-renamer.ts
|
|
40682
41025
|
init_logger();
|
|
40683
41026
|
init_types2();
|
|
40684
|
-
var
|
|
40685
|
-
import { rename as rename4, rm as
|
|
40686
|
-
import { join as
|
|
41027
|
+
var import_fs_extra32 = __toESM(require_lib(), 1);
|
|
41028
|
+
import { rename as rename4, rm as rm7 } from "node:fs/promises";
|
|
41029
|
+
import { join as join68, relative as relative12 } from "node:path";
|
|
40687
41030
|
async function collectDirsToRename(extractDir, folders) {
|
|
40688
41031
|
const dirsToRename = [];
|
|
40689
41032
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
40690
|
-
const docsPath =
|
|
40691
|
-
if (await
|
|
41033
|
+
const docsPath = join68(extractDir, DEFAULT_FOLDERS.docs);
|
|
41034
|
+
if (await import_fs_extra32.pathExists(docsPath)) {
|
|
40692
41035
|
dirsToRename.push({
|
|
40693
41036
|
from: docsPath,
|
|
40694
|
-
to:
|
|
41037
|
+
to: join68(extractDir, folders.docs)
|
|
40695
41038
|
});
|
|
40696
41039
|
}
|
|
40697
|
-
const claudeDocsPath =
|
|
40698
|
-
if (await
|
|
41040
|
+
const claudeDocsPath = join68(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
41041
|
+
if (await import_fs_extra32.pathExists(claudeDocsPath)) {
|
|
40699
41042
|
dirsToRename.push({
|
|
40700
41043
|
from: claudeDocsPath,
|
|
40701
|
-
to:
|
|
41044
|
+
to: join68(extractDir, ".claude", folders.docs)
|
|
40702
41045
|
});
|
|
40703
41046
|
}
|
|
40704
41047
|
}
|
|
40705
41048
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
40706
|
-
const plansPath =
|
|
40707
|
-
if (await
|
|
41049
|
+
const plansPath = join68(extractDir, DEFAULT_FOLDERS.plans);
|
|
41050
|
+
if (await import_fs_extra32.pathExists(plansPath)) {
|
|
40708
41051
|
dirsToRename.push({
|
|
40709
41052
|
from: plansPath,
|
|
40710
|
-
to:
|
|
41053
|
+
to: join68(extractDir, folders.plans)
|
|
40711
41054
|
});
|
|
40712
41055
|
}
|
|
40713
|
-
const claudePlansPath =
|
|
40714
|
-
if (await
|
|
41056
|
+
const claudePlansPath = join68(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
41057
|
+
if (await import_fs_extra32.pathExists(claudePlansPath)) {
|
|
40715
41058
|
dirsToRename.push({
|
|
40716
41059
|
from: claudePlansPath,
|
|
40717
|
-
to:
|
|
41060
|
+
to: join68(extractDir, ".claude", folders.plans)
|
|
40718
41061
|
});
|
|
40719
41062
|
}
|
|
40720
41063
|
}
|
|
@@ -40726,8 +41069,8 @@ async function moveAcrossDevices(src, dest) {
|
|
|
40726
41069
|
} catch (e2) {
|
|
40727
41070
|
if (e2.code === "EXDEV") {
|
|
40728
41071
|
logger.debug(`Cross-device move detected, using copy+delete: ${src} -> ${dest}`);
|
|
40729
|
-
await
|
|
40730
|
-
await
|
|
41072
|
+
await import_fs_extra32.copy(src, dest, { overwrite: true });
|
|
41073
|
+
await rm7(src, { recursive: true, force: true });
|
|
40731
41074
|
} else {
|
|
40732
41075
|
throw e2;
|
|
40733
41076
|
}
|
|
@@ -40754,8 +41097,8 @@ async function renameFolders(dirsToRename, extractDir, options) {
|
|
|
40754
41097
|
// src/services/transformers/folder-transform/path-replacer.ts
|
|
40755
41098
|
init_logger();
|
|
40756
41099
|
init_types2();
|
|
40757
|
-
import { readFile as
|
|
40758
|
-
import { join as
|
|
41100
|
+
import { readFile as readFile23, readdir as readdir23, writeFile as writeFile20 } from "node:fs/promises";
|
|
41101
|
+
import { join as join69, relative as relative13 } from "node:path";
|
|
40759
41102
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
40760
41103
|
".md",
|
|
40761
41104
|
".txt",
|
|
@@ -40806,9 +41149,9 @@ function compileReplacements(replacements) {
|
|
|
40806
41149
|
async function transformFileContents(dir, compiledReplacements, options) {
|
|
40807
41150
|
let filesChanged = 0;
|
|
40808
41151
|
let replacementsCount = 0;
|
|
40809
|
-
const entries = await
|
|
41152
|
+
const entries = await readdir23(dir, { withFileTypes: true });
|
|
40810
41153
|
for (const entry of entries) {
|
|
40811
|
-
const fullPath =
|
|
41154
|
+
const fullPath = join69(dir, entry.name);
|
|
40812
41155
|
if (entry.isDirectory()) {
|
|
40813
41156
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
40814
41157
|
continue;
|
|
@@ -40821,7 +41164,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
40821
41164
|
if (!shouldTransform)
|
|
40822
41165
|
continue;
|
|
40823
41166
|
try {
|
|
40824
|
-
const content = await
|
|
41167
|
+
const content = await readFile23(fullPath, "utf-8");
|
|
40825
41168
|
let newContent = content;
|
|
40826
41169
|
let changeCount = 0;
|
|
40827
41170
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -40837,7 +41180,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
40837
41180
|
if (options.dryRun) {
|
|
40838
41181
|
logger.debug(`[dry-run] Would update ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
40839
41182
|
} else {
|
|
40840
|
-
await
|
|
41183
|
+
await writeFile20(fullPath, newContent, "utf-8");
|
|
40841
41184
|
logger.debug(`Updated ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
40842
41185
|
}
|
|
40843
41186
|
filesChanged++;
|
|
@@ -40943,15 +41286,15 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
40943
41286
|
|
|
40944
41287
|
// src/services/transformers/global-path-transformer.ts
|
|
40945
41288
|
init_logger();
|
|
40946
|
-
import { readFile as
|
|
40947
|
-
import { platform as
|
|
40948
|
-
import { extname as
|
|
40949
|
-
var
|
|
40950
|
-
var HOME_PREFIX =
|
|
41289
|
+
import { readFile as readFile24, readdir as readdir24, writeFile as writeFile21 } from "node:fs/promises";
|
|
41290
|
+
import { platform as platform12 } from "node:os";
|
|
41291
|
+
import { extname as extname3, join as join70 } from "node:path";
|
|
41292
|
+
var IS_WINDOWS4 = platform12() === "win32";
|
|
41293
|
+
var HOME_PREFIX = IS_WINDOWS4 ? "%USERPROFILE%" : "$HOME";
|
|
40951
41294
|
function getHomeDirPrefix() {
|
|
40952
41295
|
return HOME_PREFIX;
|
|
40953
41296
|
}
|
|
40954
|
-
var
|
|
41297
|
+
var TRANSFORMABLE_EXTENSIONS3 = new Set([
|
|
40955
41298
|
".md",
|
|
40956
41299
|
".js",
|
|
40957
41300
|
".ts",
|
|
@@ -40968,7 +41311,7 @@ function transformContent(content) {
|
|
|
40968
41311
|
let transformed = content;
|
|
40969
41312
|
const homePrefix = getHomeDirPrefix();
|
|
40970
41313
|
const claudePath = `${homePrefix}/.claude/`;
|
|
40971
|
-
if (
|
|
41314
|
+
if (IS_WINDOWS4) {
|
|
40972
41315
|
transformed = transformed.replace(/\$HOME\/\.claude\//g, () => {
|
|
40973
41316
|
changes++;
|
|
40974
41317
|
return claudePath;
|
|
@@ -40998,7 +41341,7 @@ function transformContent(content) {
|
|
|
40998
41341
|
changes++;
|
|
40999
41342
|
return claudePath;
|
|
41000
41343
|
});
|
|
41001
|
-
if (
|
|
41344
|
+
if (IS_WINDOWS4) {
|
|
41002
41345
|
transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%\/\.claude\//g, () => {
|
|
41003
41346
|
changes++;
|
|
41004
41347
|
return claudePath;
|
|
@@ -41042,10 +41385,10 @@ function transformContent(content) {
|
|
|
41042
41385
|
});
|
|
41043
41386
|
return { transformed, changes };
|
|
41044
41387
|
}
|
|
41045
|
-
function
|
|
41046
|
-
const ext2 =
|
|
41388
|
+
function shouldTransformFile3(filename) {
|
|
41389
|
+
const ext2 = extname3(filename).toLowerCase();
|
|
41047
41390
|
const basename3 = filename.split("/").pop() || filename;
|
|
41048
|
-
return
|
|
41391
|
+
return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename3);
|
|
41049
41392
|
}
|
|
41050
41393
|
async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
41051
41394
|
let filesTransformed = 0;
|
|
@@ -41053,20 +41396,20 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
41053
41396
|
let filesSkipped = 0;
|
|
41054
41397
|
const skippedFiles = [];
|
|
41055
41398
|
async function processDirectory2(dir) {
|
|
41056
|
-
const entries = await
|
|
41399
|
+
const entries = await readdir24(dir, { withFileTypes: true });
|
|
41057
41400
|
for (const entry of entries) {
|
|
41058
|
-
const fullPath =
|
|
41401
|
+
const fullPath = join70(dir, entry.name);
|
|
41059
41402
|
if (entry.isDirectory()) {
|
|
41060
41403
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
41061
41404
|
continue;
|
|
41062
41405
|
}
|
|
41063
41406
|
await processDirectory2(fullPath);
|
|
41064
|
-
} else if (entry.isFile() &&
|
|
41407
|
+
} else if (entry.isFile() && shouldTransformFile3(entry.name)) {
|
|
41065
41408
|
try {
|
|
41066
|
-
const content = await
|
|
41409
|
+
const content = await readFile24(fullPath, "utf-8");
|
|
41067
41410
|
const { transformed, changes } = transformContent(content);
|
|
41068
41411
|
if (changes > 0) {
|
|
41069
|
-
await
|
|
41412
|
+
await writeFile21(fullPath, transformed, "utf-8");
|
|
41070
41413
|
filesTransformed++;
|
|
41071
41414
|
totalChanges += changes;
|
|
41072
41415
|
if (options.verbose) {
|
|
@@ -41131,7 +41474,7 @@ async function handleTransforms(ctx) {
|
|
|
41131
41474
|
logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
|
|
41132
41475
|
}
|
|
41133
41476
|
}
|
|
41134
|
-
const claudeDir = ctx.options.global ? ctx.resolvedDir :
|
|
41477
|
+
const claudeDir = ctx.options.global ? ctx.resolvedDir : join71(ctx.resolvedDir, ".claude");
|
|
41135
41478
|
return {
|
|
41136
41479
|
...ctx,
|
|
41137
41480
|
foldersConfig,
|
|
@@ -41169,6 +41512,9 @@ Installing additional kit: ${kit.name}`);
|
|
|
41169
41512
|
extractDir: undefined
|
|
41170
41513
|
};
|
|
41171
41514
|
ctx = await handleDownload(ctx);
|
|
41515
|
+
if (ctx.cancelled)
|
|
41516
|
+
return ctx;
|
|
41517
|
+
ctx = await handleOpenCode(ctx);
|
|
41172
41518
|
if (ctx.cancelled)
|
|
41173
41519
|
return ctx;
|
|
41174
41520
|
ctx = await handleTransforms(ctx);
|
|
@@ -41235,6 +41581,11 @@ async function executeInit(options, prompts) {
|
|
|
41235
41581
|
ctx = await handleDownload(ctx);
|
|
41236
41582
|
if (ctx.cancelled)
|
|
41237
41583
|
return;
|
|
41584
|
+
if (!isSyncMode) {
|
|
41585
|
+
ctx = await handleOpenCode(ctx);
|
|
41586
|
+
if (ctx.cancelled)
|
|
41587
|
+
return;
|
|
41588
|
+
}
|
|
41238
41589
|
if (!isSyncMode) {
|
|
41239
41590
|
ctx = await handleTransforms(ctx);
|
|
41240
41591
|
if (ctx.cancelled)
|
|
@@ -41316,7 +41667,7 @@ var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
|
41316
41667
|
import { resolve as resolve9 } from "node:path";
|
|
41317
41668
|
init_logger();
|
|
41318
41669
|
init_types2();
|
|
41319
|
-
var
|
|
41670
|
+
var import_fs_extra33 = __toESM(require_lib(), 1);
|
|
41320
41671
|
async function directorySetup(validOptions, prompts) {
|
|
41321
41672
|
const isNonInteractive2 = !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
|
|
41322
41673
|
const config = await ConfigManager.get();
|
|
@@ -41415,8 +41766,8 @@ async function directorySetup(validOptions, prompts) {
|
|
|
41415
41766
|
return null;
|
|
41416
41767
|
}
|
|
41417
41768
|
}
|
|
41418
|
-
if (await
|
|
41419
|
-
const files = await
|
|
41769
|
+
if (await import_fs_extra33.pathExists(resolvedDir)) {
|
|
41770
|
+
const files = await import_fs_extra33.readdir(resolvedDir);
|
|
41420
41771
|
const isEmpty = files.length === 0;
|
|
41421
41772
|
if (!isEmpty) {
|
|
41422
41773
|
if (isNonInteractive2) {
|
|
@@ -41452,7 +41803,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
41452
41803
|
};
|
|
41453
41804
|
}
|
|
41454
41805
|
// src/commands/new/phases/project-creation.ts
|
|
41455
|
-
import { join as
|
|
41806
|
+
import { join as join72 } from "node:path";
|
|
41456
41807
|
init_logger();
|
|
41457
41808
|
init_output_manager();
|
|
41458
41809
|
init_types2();
|
|
@@ -41562,7 +41913,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
41562
41913
|
output.section("Installing");
|
|
41563
41914
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
41564
41915
|
const merger = new FileMerger;
|
|
41565
|
-
const claudeDir =
|
|
41916
|
+
const claudeDir = join72(resolvedDir, ".claude");
|
|
41566
41917
|
merger.setMultiKitContext(claudeDir, kit);
|
|
41567
41918
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
41568
41919
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -41699,7 +42050,7 @@ init_types2();
|
|
|
41699
42050
|
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
41700
42051
|
|
|
41701
42052
|
// src/commands/uninstall/installation-detector.ts
|
|
41702
|
-
var
|
|
42053
|
+
var import_fs_extra34 = __toESM(require_lib(), 1);
|
|
41703
42054
|
async function detectInstallations() {
|
|
41704
42055
|
const installations = [];
|
|
41705
42056
|
const setup = await getClaudeKitSetup(process.cwd());
|
|
@@ -41708,14 +42059,14 @@ async function detectInstallations() {
|
|
|
41708
42059
|
installations.push({
|
|
41709
42060
|
type: "local",
|
|
41710
42061
|
path: setup.project.path,
|
|
41711
|
-
exists: await
|
|
42062
|
+
exists: await import_fs_extra34.pathExists(setup.project.path)
|
|
41712
42063
|
});
|
|
41713
42064
|
}
|
|
41714
42065
|
if (setup.global.path && setup.global.metadata) {
|
|
41715
42066
|
installations.push({
|
|
41716
42067
|
type: "global",
|
|
41717
42068
|
path: setup.global.path,
|
|
41718
|
-
exists: await
|
|
42069
|
+
exists: await import_fs_extra34.pathExists(setup.global.path)
|
|
41719
42070
|
});
|
|
41720
42071
|
}
|
|
41721
42072
|
return installations.filter((i) => i.exists);
|
|
@@ -41723,13 +42074,13 @@ async function detectInstallations() {
|
|
|
41723
42074
|
|
|
41724
42075
|
// src/commands/uninstall/removal-handler.ts
|
|
41725
42076
|
import { readdirSync as readdirSync2, rmSync as rmSync2 } from "node:fs";
|
|
41726
|
-
import { join as
|
|
42077
|
+
import { join as join74 } from "node:path";
|
|
41727
42078
|
init_logger();
|
|
41728
|
-
var
|
|
42079
|
+
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
41729
42080
|
|
|
41730
42081
|
// src/commands/uninstall/analysis-handler.ts
|
|
41731
42082
|
import { readdirSync, rmSync } from "node:fs";
|
|
41732
|
-
import { dirname as dirname10, join as
|
|
42083
|
+
import { dirname as dirname10, join as join73 } from "node:path";
|
|
41733
42084
|
init_logger();
|
|
41734
42085
|
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
41735
42086
|
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
@@ -41776,7 +42127,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
41776
42127
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
41777
42128
|
const kitFiles = metadata.kits[kit].files || [];
|
|
41778
42129
|
for (const trackedFile of kitFiles) {
|
|
41779
|
-
const filePath =
|
|
42130
|
+
const filePath = join73(installation.path, trackedFile.path);
|
|
41780
42131
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
41781
42132
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
41782
42133
|
continue;
|
|
@@ -41806,7 +42157,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
41806
42157
|
return result;
|
|
41807
42158
|
}
|
|
41808
42159
|
for (const trackedFile of allTrackedFiles) {
|
|
41809
|
-
const filePath =
|
|
42160
|
+
const filePath = join73(installation.path, trackedFile.path);
|
|
41810
42161
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
41811
42162
|
if (!ownershipResult.exists)
|
|
41812
42163
|
continue;
|
|
@@ -41866,9 +42217,9 @@ async function removeInstallations(installations, options) {
|
|
|
41866
42217
|
let removedCount = 0;
|
|
41867
42218
|
let cleanedDirs = 0;
|
|
41868
42219
|
for (const item of analysis.toDelete) {
|
|
41869
|
-
const filePath =
|
|
41870
|
-
if (await
|
|
41871
|
-
await
|
|
42220
|
+
const filePath = join74(installation.path, item.path);
|
|
42221
|
+
if (await import_fs_extra35.pathExists(filePath)) {
|
|
42222
|
+
await import_fs_extra35.remove(filePath);
|
|
41872
42223
|
removedCount++;
|
|
41873
42224
|
logger.debug(`Removed: ${item.path}`);
|
|
41874
42225
|
cleanedDirs += await cleanupEmptyDirectories(filePath, installation.path);
|
|
@@ -42037,6 +42388,7 @@ ${import_picocolors22.default.yellow("User modifications will be permanently del
|
|
|
42037
42388
|
}
|
|
42038
42389
|
// src/commands/update-cli.ts
|
|
42039
42390
|
import { exec as exec7 } from "node:child_process";
|
|
42391
|
+
import { join as join76 } from "node:path";
|
|
42040
42392
|
import { promisify as promisify7 } from "node:util";
|
|
42041
42393
|
|
|
42042
42394
|
// src/domains/github/npm-registry.ts
|
|
@@ -42198,14 +42550,14 @@ init_types2();
|
|
|
42198
42550
|
// src/domains/versioning/version-cache.ts
|
|
42199
42551
|
init_logger();
|
|
42200
42552
|
import { existsSync as existsSync19 } from "node:fs";
|
|
42201
|
-
import { mkdir as mkdir22, readFile as
|
|
42202
|
-
import { join as
|
|
42553
|
+
import { mkdir as mkdir22, readFile as readFile25, writeFile as writeFile22 } from "node:fs/promises";
|
|
42554
|
+
import { join as join75 } from "node:path";
|
|
42203
42555
|
class VersionCacheManager {
|
|
42204
42556
|
static CACHE_FILENAME = "version-check.json";
|
|
42205
42557
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
42206
42558
|
static getCacheFile() {
|
|
42207
42559
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
42208
|
-
return
|
|
42560
|
+
return join75(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
42209
42561
|
}
|
|
42210
42562
|
static async load() {
|
|
42211
42563
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -42214,7 +42566,7 @@ class VersionCacheManager {
|
|
|
42214
42566
|
logger.debug("Version check cache not found");
|
|
42215
42567
|
return null;
|
|
42216
42568
|
}
|
|
42217
|
-
const content = await
|
|
42569
|
+
const content = await readFile25(cacheFile, "utf-8");
|
|
42218
42570
|
const cache2 = JSON.parse(content);
|
|
42219
42571
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
42220
42572
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -42234,7 +42586,7 @@ class VersionCacheManager {
|
|
|
42234
42586
|
if (!existsSync19(cacheDir)) {
|
|
42235
42587
|
await mkdir22(cacheDir, { recursive: true, mode: 448 });
|
|
42236
42588
|
}
|
|
42237
|
-
await
|
|
42589
|
+
await writeFile22(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
42238
42590
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
42239
42591
|
} catch (error) {
|
|
42240
42592
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -42443,11 +42795,12 @@ init_logger();
|
|
|
42443
42795
|
init_types2();
|
|
42444
42796
|
init_types2();
|
|
42445
42797
|
var import_compare_versions5 = __toESM(require_umd(), 1);
|
|
42798
|
+
var import_fs_extra36 = __toESM(require_lib(), 1);
|
|
42446
42799
|
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
42447
42800
|
// package.json
|
|
42448
42801
|
var package_default = {
|
|
42449
42802
|
name: "claudekit-cli",
|
|
42450
|
-
version: "3.
|
|
42803
|
+
version: "3.24.0",
|
|
42451
42804
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
42452
42805
|
type: "module",
|
|
42453
42806
|
repository: {
|
|
@@ -42548,18 +42901,51 @@ class CliUpdateError extends ClaudeKitError {
|
|
|
42548
42901
|
}
|
|
42549
42902
|
var PACKAGE_NAME2 = "claudekit-cli";
|
|
42550
42903
|
var KIT_UPDATE_REMINDER_HEADER = "Note: 'ck update' only updates the CLI tool itself.";
|
|
42904
|
+
function buildInitCommand(isGlobal, kit) {
|
|
42905
|
+
const parts = ["ck init"];
|
|
42906
|
+
if (isGlobal)
|
|
42907
|
+
parts.push("-g");
|
|
42908
|
+
if (kit)
|
|
42909
|
+
parts.push(`--kit ${kit}`);
|
|
42910
|
+
parts.push("--yes --install-skills");
|
|
42911
|
+
return parts.join(" ");
|
|
42912
|
+
}
|
|
42913
|
+
async function readMetadataFile(claudeDir) {
|
|
42914
|
+
const metadataPath = join76(claudeDir, "metadata.json");
|
|
42915
|
+
try {
|
|
42916
|
+
if (!await import_fs_extra36.pathExists(metadataPath)) {
|
|
42917
|
+
return null;
|
|
42918
|
+
}
|
|
42919
|
+
const content = await import_fs_extra36.readFile(metadataPath, "utf-8");
|
|
42920
|
+
return JSON.parse(content);
|
|
42921
|
+
} catch {
|
|
42922
|
+
return null;
|
|
42923
|
+
}
|
|
42924
|
+
}
|
|
42551
42925
|
async function displayKitUpdateReminder() {
|
|
42552
42926
|
try {
|
|
42553
42927
|
const setup = await getClaudeKitSetup();
|
|
42554
42928
|
const hasLocal = !!setup.project.metadata;
|
|
42555
42929
|
const hasGlobal = !!setup.global.metadata;
|
|
42556
|
-
const
|
|
42557
|
-
const
|
|
42930
|
+
const localMetadata = hasLocal ? await readMetadataFile(setup.project.path) : null;
|
|
42931
|
+
const globalMetadata = hasGlobal ? await readMetadataFile(setup.global.path) : null;
|
|
42932
|
+
const localKits = localMetadata ? getInstalledKits(localMetadata) : [];
|
|
42933
|
+
const globalKits = globalMetadata ? getInstalledKits(globalMetadata) : [];
|
|
42558
42934
|
const versionsToCheck = new Set;
|
|
42559
|
-
if (
|
|
42560
|
-
|
|
42561
|
-
|
|
42562
|
-
|
|
42935
|
+
if (localMetadata) {
|
|
42936
|
+
for (const kit of localKits) {
|
|
42937
|
+
const version = localMetadata.kits?.[kit]?.version || localMetadata.version;
|
|
42938
|
+
if (version)
|
|
42939
|
+
versionsToCheck.add(version);
|
|
42940
|
+
}
|
|
42941
|
+
}
|
|
42942
|
+
if (globalMetadata) {
|
|
42943
|
+
for (const kit of globalKits) {
|
|
42944
|
+
const version = globalMetadata.kits?.[kit]?.version || globalMetadata.version;
|
|
42945
|
+
if (version)
|
|
42946
|
+
versionsToCheck.add(version);
|
|
42947
|
+
}
|
|
42948
|
+
}
|
|
42563
42949
|
const versionCheckResults = new Map;
|
|
42564
42950
|
if (versionsToCheck.size > 0) {
|
|
42565
42951
|
const checkPromises = [...versionsToCheck].map(async (version) => {
|
|
@@ -42571,33 +42957,52 @@ async function displayKitUpdateReminder() {
|
|
|
42571
42957
|
versionCheckResults.set(version, result);
|
|
42572
42958
|
}
|
|
42573
42959
|
}
|
|
42574
|
-
const
|
|
42575
|
-
|
|
42576
|
-
|
|
42960
|
+
const commands = [];
|
|
42961
|
+
if (localKits.length > 0) {
|
|
42962
|
+
for (const kit of localKits) {
|
|
42963
|
+
const cmd = buildInitCommand(false, kit);
|
|
42964
|
+
const version = localMetadata?.kits?.[kit]?.version || localMetadata?.version;
|
|
42965
|
+
commands.push({
|
|
42966
|
+
cmd,
|
|
42967
|
+
desc: `Update local project (${kit}${version ? `@${version}` : ""})`,
|
|
42968
|
+
version
|
|
42969
|
+
});
|
|
42970
|
+
}
|
|
42971
|
+
} else if (hasLocal) {
|
|
42972
|
+
commands.push({ cmd: "ck init", desc: "Update local project" });
|
|
42973
|
+
} else {
|
|
42974
|
+
commands.push({ cmd: "ck init", desc: "Initialize in current project" });
|
|
42975
|
+
}
|
|
42976
|
+
if (globalKits.length > 0) {
|
|
42977
|
+
for (const kit of globalKits) {
|
|
42978
|
+
const cmd = buildInitCommand(true, kit);
|
|
42979
|
+
const version = globalMetadata?.kits?.[kit]?.version || globalMetadata?.version;
|
|
42980
|
+
commands.push({
|
|
42981
|
+
cmd,
|
|
42982
|
+
desc: `Update global ~/.claude (${kit}${version ? `@${version}` : ""})`,
|
|
42983
|
+
version
|
|
42984
|
+
});
|
|
42985
|
+
}
|
|
42986
|
+
} else if (hasGlobal) {
|
|
42987
|
+
commands.push({ cmd: "ck init -g", desc: "Update global ~/.claude" });
|
|
42988
|
+
} else {
|
|
42989
|
+
commands.push({ cmd: "ck init -g", desc: "Initialize global ~/.claude" });
|
|
42990
|
+
}
|
|
42991
|
+
const maxCmdLen = Math.max(...commands.map((c2) => c2.cmd.length));
|
|
42577
42992
|
const pad = (cmd) => cmd.padEnd(maxCmdLen);
|
|
42578
42993
|
const lines = [];
|
|
42579
42994
|
lines.push(import_picocolors24.default.yellow(KIT_UPDATE_REMINDER_HEADER));
|
|
42580
42995
|
lines.push("");
|
|
42581
42996
|
lines.push("To update your ClaudeKit content (skills, commands, workflows):");
|
|
42582
|
-
|
|
42583
|
-
lines.push(` ${import_picocolors24.default.cyan(pad(
|
|
42584
|
-
|
|
42585
|
-
|
|
42586
|
-
|
|
42587
|
-
|
|
42588
|
-
|
|
42589
|
-
|
|
42590
|
-
lines.push(` ${import_picocolors24.default.cyan(pad(cmdLocal))} Initialize in current project`);
|
|
42591
|
-
}
|
|
42592
|
-
if (hasGlobal && globalVersion) {
|
|
42593
|
-
lines.push(` ${import_picocolors24.default.cyan(pad(cmdGlobal))} Update global ~/.claude (${globalVersion})`);
|
|
42594
|
-
const globalCheck = versionCheckResults.get(globalVersion);
|
|
42595
|
-
if (globalCheck?.updateAvailable) {
|
|
42596
|
-
const indent = " ".repeat(maxCmdLen + 4);
|
|
42597
|
-
lines.push(`${indent}${import_picocolors24.default.green(`→ ${globalCheck.latestVersion} available!`)}`);
|
|
42997
|
+
for (const { cmd, desc: desc2, version } of commands) {
|
|
42998
|
+
lines.push(` ${import_picocolors24.default.cyan(pad(cmd))} ${desc2}`);
|
|
42999
|
+
if (version) {
|
|
43000
|
+
const versionCheck = versionCheckResults.get(version);
|
|
43001
|
+
if (versionCheck?.updateAvailable) {
|
|
43002
|
+
const indent = " ".repeat(maxCmdLen + 4);
|
|
43003
|
+
lines.push(`${indent}${import_picocolors24.default.green(`→ ${versionCheck.latestVersion} available!`)}`);
|
|
43004
|
+
}
|
|
42598
43005
|
}
|
|
42599
|
-
} else {
|
|
42600
|
-
lines.push(` ${import_picocolors24.default.cyan(pad(cmdGlobal))} Initialize global ~/.claude`);
|
|
42601
43006
|
}
|
|
42602
43007
|
logger.info("");
|
|
42603
43008
|
log.info(lines.join(`
|
|
@@ -42872,7 +43277,7 @@ function registerCommands(cli) {
|
|
|
42872
43277
|
|
|
42873
43278
|
// src/cli/version-display.ts
|
|
42874
43279
|
import { existsSync as existsSync20, readFileSync as readFileSync6 } from "node:fs";
|
|
42875
|
-
import { join as
|
|
43280
|
+
import { join as join77 } from "node:path";
|
|
42876
43281
|
init_logger();
|
|
42877
43282
|
init_types2();
|
|
42878
43283
|
var packageVersion = package_default.version;
|
|
@@ -42906,9 +43311,9 @@ async function displayVersion() {
|
|
|
42906
43311
|
let localKitVersion = null;
|
|
42907
43312
|
let isGlobalOnlyKit = false;
|
|
42908
43313
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
42909
|
-
const globalMetadataPath =
|
|
43314
|
+
const globalMetadataPath = join77(globalKitDir, "metadata.json");
|
|
42910
43315
|
const prefix = PathResolver.getPathPrefix(false);
|
|
42911
|
-
const localMetadataPath = prefix ?
|
|
43316
|
+
const localMetadataPath = prefix ? join77(process.cwd(), prefix, "metadata.json") : join77(process.cwd(), "metadata.json");
|
|
42912
43317
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
42913
43318
|
if (!isLocalSameAsGlobal && existsSync20(localMetadataPath)) {
|
|
42914
43319
|
try {
|