claudekit-cli 3.22.1 → 3.23.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 +354 -173
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -34271,7 +34271,7 @@ async function handleDownload(ctx) {
|
|
|
34271
34271
|
};
|
|
34272
34272
|
}
|
|
34273
34273
|
// src/commands/init/phases/merge-handler.ts
|
|
34274
|
-
import { join as
|
|
34274
|
+
import { join as join50 } from "node:path";
|
|
34275
34275
|
|
|
34276
34276
|
// src/domains/installation/file-merger.ts
|
|
34277
34277
|
init_logger();
|
|
@@ -36208,9 +36208,6 @@ class InstalledSettingsTracker {
|
|
|
36208
36208
|
}
|
|
36209
36209
|
}
|
|
36210
36210
|
|
|
36211
|
-
// src/domains/config/merger/merge-engine.ts
|
|
36212
|
-
init_logger();
|
|
36213
|
-
|
|
36214
36211
|
// src/domains/config/merger/diff-calculator.ts
|
|
36215
36212
|
function truncateCommand(cmd, maxLen = 50) {
|
|
36216
36213
|
if (cmd.length <= maxLen)
|
|
@@ -36409,12 +36406,61 @@ function mergeHooks(sourceHooks, destHooks, result, options) {
|
|
|
36409
36406
|
const merged = { ...destHooks };
|
|
36410
36407
|
const installedHooks = options?.installedSettings?.hooks ?? [];
|
|
36411
36408
|
const sourceKit = options?.sourceKit;
|
|
36409
|
+
const sourceCommands = new Set;
|
|
36410
|
+
for (const entries of Object.values(sourceHooks)) {
|
|
36411
|
+
extractCommands(entries, sourceCommands);
|
|
36412
|
+
}
|
|
36412
36413
|
for (const [eventName, sourceEntries] of Object.entries(sourceHooks)) {
|
|
36413
36414
|
const destEntries = destHooks[eventName] || [];
|
|
36414
36415
|
merged[eventName] = mergeHookEntries(sourceEntries, destEntries, eventName, result, installedHooks, sourceKit);
|
|
36415
36416
|
}
|
|
36417
|
+
if (installedHooks.length > 0) {
|
|
36418
|
+
const deprecatedHooks = installedHooks.filter((hook) => !sourceCommands.has(normalizeCommand(hook)));
|
|
36419
|
+
if (deprecatedHooks.length > 0) {
|
|
36420
|
+
result.removedHooks = result.removedHooks ?? [];
|
|
36421
|
+
for (const [eventName, entries] of Object.entries(merged)) {
|
|
36422
|
+
const filtered = removeDeprecatedFromEntries(entries, deprecatedHooks, result);
|
|
36423
|
+
if (filtered.length > 0) {
|
|
36424
|
+
merged[eventName] = filtered;
|
|
36425
|
+
} else {
|
|
36426
|
+
delete merged[eventName];
|
|
36427
|
+
}
|
|
36428
|
+
}
|
|
36429
|
+
}
|
|
36430
|
+
}
|
|
36416
36431
|
return merged;
|
|
36417
36432
|
}
|
|
36433
|
+
function removeDeprecatedFromEntries(entries, deprecatedHooks, result) {
|
|
36434
|
+
const deprecatedSet = new Set(deprecatedHooks.map((h2) => normalizeCommand(h2)));
|
|
36435
|
+
const filtered = [];
|
|
36436
|
+
for (const entry of entries) {
|
|
36437
|
+
if ("hooks" in entry && entry.hooks) {
|
|
36438
|
+
const remainingHooks = entry.hooks.filter((h2) => {
|
|
36439
|
+
if (h2.command && deprecatedSet.has(normalizeCommand(h2.command))) {
|
|
36440
|
+
result.hooksRemoved++;
|
|
36441
|
+
result.removedHooks?.push(h2.command);
|
|
36442
|
+
logger.info(`Removed deprecated hook: ${h2.command.slice(0, 60)}...`);
|
|
36443
|
+
return false;
|
|
36444
|
+
}
|
|
36445
|
+
return true;
|
|
36446
|
+
});
|
|
36447
|
+
if (remainingHooks.length > 0) {
|
|
36448
|
+
filtered.push({ ...entry, hooks: remainingHooks });
|
|
36449
|
+
}
|
|
36450
|
+
} else if ("command" in entry) {
|
|
36451
|
+
if (deprecatedSet.has(normalizeCommand(entry.command))) {
|
|
36452
|
+
result.hooksRemoved++;
|
|
36453
|
+
result.removedHooks?.push(entry.command);
|
|
36454
|
+
logger.info(`Removed deprecated hook: ${entry.command.slice(0, 60)}...`);
|
|
36455
|
+
} else {
|
|
36456
|
+
filtered.push(entry);
|
|
36457
|
+
}
|
|
36458
|
+
} else {
|
|
36459
|
+
filtered.push(entry);
|
|
36460
|
+
}
|
|
36461
|
+
}
|
|
36462
|
+
return filtered;
|
|
36463
|
+
}
|
|
36418
36464
|
function mergeMcp(sourceMcp, destMcp, result, options) {
|
|
36419
36465
|
if (!sourceMcp)
|
|
36420
36466
|
return destMcp;
|
|
@@ -36491,6 +36537,24 @@ function mergeMcp(sourceMcp, destMcp, result, options) {
|
|
|
36491
36537
|
}
|
|
36492
36538
|
}
|
|
36493
36539
|
}
|
|
36540
|
+
if (installedServers.length > 0 && merged.servers) {
|
|
36541
|
+
const sourceServerNames = new Set(Object.keys(sourceMcp.servers || {}));
|
|
36542
|
+
const deprecatedServers = installedServers.filter((server) => !sourceServerNames.has(server));
|
|
36543
|
+
if (deprecatedServers.length > 0) {
|
|
36544
|
+
result.removedMcpServers = result.removedMcpServers ?? [];
|
|
36545
|
+
for (const serverName of deprecatedServers) {
|
|
36546
|
+
if (serverName in merged.servers) {
|
|
36547
|
+
delete merged.servers[serverName];
|
|
36548
|
+
result.mcpServersRemoved++;
|
|
36549
|
+
result.removedMcpServers.push(serverName);
|
|
36550
|
+
logger.info(`Removed deprecated MCP server: ${serverName}`);
|
|
36551
|
+
}
|
|
36552
|
+
}
|
|
36553
|
+
if (merged.servers && Object.keys(merged.servers).length === 0) {
|
|
36554
|
+
merged.servers = undefined;
|
|
36555
|
+
}
|
|
36556
|
+
}
|
|
36557
|
+
}
|
|
36494
36558
|
for (const key of Object.keys(sourceMcp)) {
|
|
36495
36559
|
if (key !== "servers" && !(key in merged)) {
|
|
36496
36560
|
merged[key] = sourceMcp[key];
|
|
@@ -36504,8 +36568,10 @@ function mergeSettings(source, destination, options) {
|
|
|
36504
36568
|
hooksAdded: 0,
|
|
36505
36569
|
hooksPreserved: 0,
|
|
36506
36570
|
hooksSkipped: 0,
|
|
36571
|
+
hooksRemoved: 0,
|
|
36507
36572
|
mcpServersPreserved: 0,
|
|
36508
36573
|
mcpServersSkipped: 0,
|
|
36574
|
+
mcpServersRemoved: 0,
|
|
36509
36575
|
conflictsDetected: [],
|
|
36510
36576
|
newlyInstalledHooks: [],
|
|
36511
36577
|
newlyInstalledServers: [],
|
|
@@ -37715,8 +37781,113 @@ class FileScanner2 {
|
|
|
37715
37781
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
37716
37782
|
init_logger();
|
|
37717
37783
|
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
37718
|
-
import { lstat as lstat5, mkdir as mkdir16, readdir as
|
|
37784
|
+
import { lstat as lstat5, mkdir as mkdir16, readdir as readdir12, stat as stat8 } from "node:fs/promises";
|
|
37785
|
+
import { join as join47 } from "node:path";
|
|
37786
|
+
|
|
37787
|
+
// src/services/transformers/commands-prefix/content-transformer.ts
|
|
37788
|
+
init_logger();
|
|
37789
|
+
import { readFile as readFile17, readdir as readdir11, writeFile as writeFile14 } from "node:fs/promises";
|
|
37719
37790
|
import { join as join46 } from "node:path";
|
|
37791
|
+
var TRANSFORMABLE_EXTENSIONS = new Set([
|
|
37792
|
+
".md",
|
|
37793
|
+
".txt",
|
|
37794
|
+
".json",
|
|
37795
|
+
".yaml",
|
|
37796
|
+
".yml",
|
|
37797
|
+
".ts",
|
|
37798
|
+
".js",
|
|
37799
|
+
".mjs",
|
|
37800
|
+
".cjs",
|
|
37801
|
+
".py"
|
|
37802
|
+
]);
|
|
37803
|
+
var COMMAND_ROOTS = [
|
|
37804
|
+
"plan",
|
|
37805
|
+
"fix",
|
|
37806
|
+
"code",
|
|
37807
|
+
"review",
|
|
37808
|
+
"cook",
|
|
37809
|
+
"brainstorm",
|
|
37810
|
+
"integrate",
|
|
37811
|
+
"bootstrap",
|
|
37812
|
+
"worktree",
|
|
37813
|
+
"scout",
|
|
37814
|
+
"test",
|
|
37815
|
+
"debug",
|
|
37816
|
+
"preview",
|
|
37817
|
+
"kanban",
|
|
37818
|
+
"journal",
|
|
37819
|
+
"watzup"
|
|
37820
|
+
];
|
|
37821
|
+
function buildCommandPatterns() {
|
|
37822
|
+
const patterns = [];
|
|
37823
|
+
for (const cmd of COMMAND_ROOTS) {
|
|
37824
|
+
patterns.push({
|
|
37825
|
+
regex: new RegExp(`(?<![\\w:])(\\/)${cmd}(:)`, "g"),
|
|
37826
|
+
replacement: "$1ck:$2".replace("$2", `${cmd}:`)
|
|
37827
|
+
});
|
|
37828
|
+
patterns.push({
|
|
37829
|
+
regex: new RegExp(`(?<![\\w:])(\\/)${cmd}(?=[\\s\`"'\\)\\]}>.,;:!?]|$)`, "g"),
|
|
37830
|
+
replacement: `$1ck:${cmd}`
|
|
37831
|
+
});
|
|
37832
|
+
}
|
|
37833
|
+
return patterns;
|
|
37834
|
+
}
|
|
37835
|
+
function transformCommandContent(content) {
|
|
37836
|
+
let changes = 0;
|
|
37837
|
+
let transformed = content;
|
|
37838
|
+
const patterns = buildCommandPatterns();
|
|
37839
|
+
for (const { regex: regex2, replacement } of patterns) {
|
|
37840
|
+
regex2.lastIndex = 0;
|
|
37841
|
+
const matches = transformed.match(regex2);
|
|
37842
|
+
if (matches) {
|
|
37843
|
+
changes += matches.length;
|
|
37844
|
+
regex2.lastIndex = 0;
|
|
37845
|
+
transformed = transformed.replace(regex2, replacement);
|
|
37846
|
+
}
|
|
37847
|
+
}
|
|
37848
|
+
return { transformed, changes };
|
|
37849
|
+
}
|
|
37850
|
+
function shouldTransformFile(filename) {
|
|
37851
|
+
const ext2 = filename.toLowerCase().slice(filename.lastIndexOf("."));
|
|
37852
|
+
return TRANSFORMABLE_EXTENSIONS.has(ext2);
|
|
37853
|
+
}
|
|
37854
|
+
async function transformCommandReferences(directory, options = {}) {
|
|
37855
|
+
let filesTransformed = 0;
|
|
37856
|
+
let totalReplacements = 0;
|
|
37857
|
+
async function processDirectory(dir) {
|
|
37858
|
+
const entries = await readdir11(dir, { withFileTypes: true });
|
|
37859
|
+
for (const entry of entries) {
|
|
37860
|
+
const fullPath = join46(dir, entry.name);
|
|
37861
|
+
if (entry.isDirectory()) {
|
|
37862
|
+
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
37863
|
+
continue;
|
|
37864
|
+
}
|
|
37865
|
+
await processDirectory(fullPath);
|
|
37866
|
+
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
37867
|
+
try {
|
|
37868
|
+
const content = await readFile17(fullPath, "utf-8");
|
|
37869
|
+
const { transformed, changes } = transformCommandContent(content);
|
|
37870
|
+
if (changes > 0) {
|
|
37871
|
+
if (options.dryRun) {
|
|
37872
|
+
logger.debug(`[dry-run] Would transform ${changes} command ref(s) in ${fullPath}`);
|
|
37873
|
+
} else {
|
|
37874
|
+
await writeFile14(fullPath, transformed, "utf-8");
|
|
37875
|
+
if (options.verbose) {
|
|
37876
|
+
logger.verbose(`Transformed ${changes} command ref(s) in ${fullPath}`);
|
|
37877
|
+
}
|
|
37878
|
+
}
|
|
37879
|
+
filesTransformed++;
|
|
37880
|
+
totalReplacements += changes;
|
|
37881
|
+
}
|
|
37882
|
+
} catch (error) {
|
|
37883
|
+
logger.debug(`Skipped ${fullPath}: ${error instanceof Error ? error.message : "unknown"}`);
|
|
37884
|
+
}
|
|
37885
|
+
}
|
|
37886
|
+
}
|
|
37887
|
+
}
|
|
37888
|
+
await processDirectory(directory);
|
|
37889
|
+
return { filesTransformed, totalReplacements };
|
|
37890
|
+
}
|
|
37720
37891
|
|
|
37721
37892
|
// src/services/transformers/commands-prefix/prefix-utils.ts
|
|
37722
37893
|
init_logger();
|
|
@@ -37761,22 +37932,22 @@ function shouldApplyPrefix(options) {
|
|
|
37761
37932
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
37762
37933
|
async function applyPrefix(extractDir) {
|
|
37763
37934
|
validatePath(extractDir, "extractDir");
|
|
37764
|
-
const commandsDir =
|
|
37935
|
+
const commandsDir = join47(extractDir, ".claude", "commands");
|
|
37765
37936
|
if (!await import_fs_extra13.pathExists(commandsDir)) {
|
|
37766
37937
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
37767
37938
|
return;
|
|
37768
37939
|
}
|
|
37769
37940
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
37770
|
-
const backupDir =
|
|
37771
|
-
const tempDir =
|
|
37941
|
+
const backupDir = join47(extractDir, ".commands-backup");
|
|
37942
|
+
const tempDir = join47(extractDir, ".commands-prefix-temp");
|
|
37772
37943
|
try {
|
|
37773
|
-
const entries = await
|
|
37944
|
+
const entries = await readdir12(commandsDir);
|
|
37774
37945
|
if (entries.length === 0) {
|
|
37775
37946
|
logger.verbose("Commands directory is empty, skipping prefix application");
|
|
37776
37947
|
return;
|
|
37777
37948
|
}
|
|
37778
37949
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
37779
|
-
const ckDir2 =
|
|
37950
|
+
const ckDir2 = join47(commandsDir, "ck");
|
|
37780
37951
|
const ckStat = await stat8(ckDir2);
|
|
37781
37952
|
if (ckStat.isDirectory()) {
|
|
37782
37953
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
@@ -37786,17 +37957,17 @@ async function applyPrefix(extractDir) {
|
|
|
37786
37957
|
await import_fs_extra13.copy(commandsDir, backupDir);
|
|
37787
37958
|
logger.verbose("Created backup of commands directory");
|
|
37788
37959
|
await mkdir16(tempDir, { recursive: true });
|
|
37789
|
-
const ckDir =
|
|
37960
|
+
const ckDir = join47(tempDir, "ck");
|
|
37790
37961
|
await mkdir16(ckDir, { recursive: true });
|
|
37791
37962
|
let processedCount = 0;
|
|
37792
37963
|
for (const entry of entries) {
|
|
37793
|
-
const sourcePath =
|
|
37964
|
+
const sourcePath = join47(commandsDir, entry);
|
|
37794
37965
|
const stats = await lstat5(sourcePath);
|
|
37795
37966
|
if (stats.isSymbolicLink()) {
|
|
37796
37967
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
37797
37968
|
continue;
|
|
37798
37969
|
}
|
|
37799
|
-
const destPath =
|
|
37970
|
+
const destPath = join47(ckDir, entry);
|
|
37800
37971
|
await import_fs_extra13.copy(sourcePath, destPath, {
|
|
37801
37972
|
overwrite: false,
|
|
37802
37973
|
errorOnExist: true
|
|
@@ -37813,7 +37984,17 @@ async function applyPrefix(extractDir) {
|
|
|
37813
37984
|
await import_fs_extra13.remove(commandsDir);
|
|
37814
37985
|
await import_fs_extra13.move(tempDir, commandsDir);
|
|
37815
37986
|
await import_fs_extra13.remove(backupDir);
|
|
37816
|
-
logger.success("Successfully
|
|
37987
|
+
logger.success("Successfully reorganized commands to /ck: prefix");
|
|
37988
|
+
const claudeDir = join47(extractDir, ".claude");
|
|
37989
|
+
logger.info("Transforming command references in file contents...");
|
|
37990
|
+
const transformResult = await transformCommandReferences(claudeDir, {
|
|
37991
|
+
verbose: logger.isVerbose()
|
|
37992
|
+
});
|
|
37993
|
+
if (transformResult.totalReplacements > 0) {
|
|
37994
|
+
logger.success(`Transformed ${transformResult.totalReplacements} command ref(s) in ${transformResult.filesTransformed} file(s)`);
|
|
37995
|
+
} else {
|
|
37996
|
+
logger.verbose("No command references needed transformation");
|
|
37997
|
+
}
|
|
37817
37998
|
} catch (error) {
|
|
37818
37999
|
if (await import_fs_extra13.pathExists(backupDir)) {
|
|
37819
38000
|
try {
|
|
@@ -37840,21 +38021,21 @@ async function applyPrefix(extractDir) {
|
|
|
37840
38021
|
}
|
|
37841
38022
|
|
|
37842
38023
|
// src/services/transformers/commands-prefix/prefix-cleaner.ts
|
|
37843
|
-
import { lstat as lstat7, readdir as
|
|
37844
|
-
import { join as
|
|
38024
|
+
import { lstat as lstat7, readdir as readdir14 } from "node:fs/promises";
|
|
38025
|
+
import { join as join49 } from "node:path";
|
|
37845
38026
|
init_logger();
|
|
37846
38027
|
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
37847
38028
|
|
|
37848
38029
|
// src/services/transformers/commands-prefix/file-processor.ts
|
|
37849
|
-
import { lstat as lstat6, readdir as
|
|
37850
|
-
import { join as
|
|
38030
|
+
import { lstat as lstat6, readdir as readdir13 } from "node:fs/promises";
|
|
38031
|
+
import { join as join48 } from "node:path";
|
|
37851
38032
|
init_logger();
|
|
37852
38033
|
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
37853
38034
|
async function scanDirectoryFiles(dir) {
|
|
37854
38035
|
const files = [];
|
|
37855
|
-
const entries = await
|
|
38036
|
+
const entries = await readdir13(dir);
|
|
37856
38037
|
for (const entry of entries) {
|
|
37857
|
-
const fullPath =
|
|
38038
|
+
const fullPath = join48(dir, entry);
|
|
37858
38039
|
const stats = await lstat6(fullPath);
|
|
37859
38040
|
if (stats.isSymbolicLink()) {
|
|
37860
38041
|
continue;
|
|
@@ -37962,8 +38143,8 @@ function logCleanupSummary(deletedCount, preservedCount, dryRun, results) {
|
|
|
37962
38143
|
async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
37963
38144
|
const { dryRun = false } = options;
|
|
37964
38145
|
validatePath(targetDir, "targetDir");
|
|
37965
|
-
const claudeDir = isGlobal ? targetDir :
|
|
37966
|
-
const commandsDir =
|
|
38146
|
+
const claudeDir = isGlobal ? targetDir : join49(targetDir, ".claude");
|
|
38147
|
+
const commandsDir = join49(claudeDir, "commands");
|
|
37967
38148
|
const accumulator = {
|
|
37968
38149
|
results: [],
|
|
37969
38150
|
deletedCount: 0,
|
|
@@ -37991,13 +38172,13 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
|
37991
38172
|
logger.verbose("All existing files will be preserved as user-owned");
|
|
37992
38173
|
return result;
|
|
37993
38174
|
}
|
|
37994
|
-
const entries = await
|
|
38175
|
+
const entries = await readdir14(commandsDir);
|
|
37995
38176
|
if (entries.length === 0) {
|
|
37996
38177
|
logger.verbose("Commands directory is empty");
|
|
37997
38178
|
return result;
|
|
37998
38179
|
}
|
|
37999
38180
|
for (const entry of entries) {
|
|
38000
|
-
const entryPath =
|
|
38181
|
+
const entryPath = join49(commandsDir, entry);
|
|
38001
38182
|
const stats = await lstat7(entryPath);
|
|
38002
38183
|
if (stats.isSymbolicLink()) {
|
|
38003
38184
|
addSymlinkSkip(entry, accumulator);
|
|
@@ -38049,7 +38230,7 @@ async function handleMerge(ctx) {
|
|
|
38049
38230
|
let customClaudeFiles = [];
|
|
38050
38231
|
if (!ctx.options.fresh) {
|
|
38051
38232
|
logger.info("Scanning for custom .claude files...");
|
|
38052
|
-
const scanSourceDir = ctx.options.global ?
|
|
38233
|
+
const scanSourceDir = ctx.options.global ? join50(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
38053
38234
|
const scanTargetSubdir = ctx.options.global ? "" : ".claude";
|
|
38054
38235
|
customClaudeFiles = await FileScanner2.findCustomFiles(ctx.resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
38055
38236
|
} else {
|
|
@@ -38113,7 +38294,7 @@ async function handleMerge(ctx) {
|
|
|
38113
38294
|
return { ...ctx, cancelled: true };
|
|
38114
38295
|
}
|
|
38115
38296
|
}
|
|
38116
|
-
const sourceDir = ctx.options.global ?
|
|
38297
|
+
const sourceDir = ctx.options.global ? join50(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
38117
38298
|
await merger.merge(sourceDir, ctx.resolvedDir, ctx.isNonInteractive);
|
|
38118
38299
|
const fileConflicts = merger.getFileConflicts();
|
|
38119
38300
|
if (fileConflicts.length > 0 && !ctx.isNonInteractive) {
|
|
@@ -38142,7 +38323,7 @@ async function handleMerge(ctx) {
|
|
|
38142
38323
|
};
|
|
38143
38324
|
}
|
|
38144
38325
|
// src/commands/init/phases/migration-handler.ts
|
|
38145
|
-
import { join as
|
|
38326
|
+
import { join as join58 } from "node:path";
|
|
38146
38327
|
|
|
38147
38328
|
// src/domains/skills/skills-detector.ts
|
|
38148
38329
|
init_logger();
|
|
@@ -38154,8 +38335,8 @@ init_logger();
|
|
|
38154
38335
|
// src/domains/skills/skills-manifest.ts
|
|
38155
38336
|
init_logger();
|
|
38156
38337
|
import { createHash as createHash2 } from "node:crypto";
|
|
38157
|
-
import { readFile as
|
|
38158
|
-
import { join as
|
|
38338
|
+
import { readFile as readFile18, readdir as readdir15, writeFile as writeFile15 } from "node:fs/promises";
|
|
38339
|
+
import { join as join51, relative as relative9 } from "node:path";
|
|
38159
38340
|
init_types2();
|
|
38160
38341
|
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
38161
38342
|
|
|
@@ -38179,18 +38360,18 @@ class SkillsManifestManager {
|
|
|
38179
38360
|
return manifest;
|
|
38180
38361
|
}
|
|
38181
38362
|
static async writeManifest(skillsDir, manifest) {
|
|
38182
|
-
const manifestPath =
|
|
38183
|
-
await
|
|
38363
|
+
const manifestPath = join51(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
38364
|
+
await writeFile15(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
38184
38365
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
38185
38366
|
}
|
|
38186
38367
|
static async readManifest(skillsDir) {
|
|
38187
|
-
const manifestPath =
|
|
38368
|
+
const manifestPath = join51(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
38188
38369
|
if (!await import_fs_extra17.pathExists(manifestPath)) {
|
|
38189
38370
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
38190
38371
|
return null;
|
|
38191
38372
|
}
|
|
38192
38373
|
try {
|
|
38193
|
-
const content = await
|
|
38374
|
+
const content = await readFile18(manifestPath, "utf-8");
|
|
38194
38375
|
const data = JSON.parse(content);
|
|
38195
38376
|
const manifest = SkillsManifestSchema.parse(data);
|
|
38196
38377
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -38201,14 +38382,14 @@ class SkillsManifestManager {
|
|
|
38201
38382
|
}
|
|
38202
38383
|
}
|
|
38203
38384
|
static async detectStructure(skillsDir) {
|
|
38204
|
-
const entries = await
|
|
38385
|
+
const entries = await readdir15(skillsDir, { withFileTypes: true });
|
|
38205
38386
|
const dirs = entries.filter((entry) => entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith("."));
|
|
38206
38387
|
if (dirs.length === 0) {
|
|
38207
38388
|
return "flat";
|
|
38208
38389
|
}
|
|
38209
38390
|
for (const dir of dirs.slice(0, 3)) {
|
|
38210
|
-
const dirPath =
|
|
38211
|
-
const subEntries = await
|
|
38391
|
+
const dirPath = join51(skillsDir, dir.name);
|
|
38392
|
+
const subEntries = await readdir15(dirPath, { withFileTypes: true });
|
|
38212
38393
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
38213
38394
|
if (hasSubdirs) {
|
|
38214
38395
|
return "categorized";
|
|
@@ -38223,10 +38404,10 @@ class SkillsManifestManager {
|
|
|
38223
38404
|
static async scanSkills(skillsDir, structure) {
|
|
38224
38405
|
const skills = [];
|
|
38225
38406
|
if (structure === "flat") {
|
|
38226
|
-
const entries = await
|
|
38407
|
+
const entries = await readdir15(skillsDir, { withFileTypes: true });
|
|
38227
38408
|
for (const entry of entries) {
|
|
38228
38409
|
if (entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith(".")) {
|
|
38229
|
-
const skillPath =
|
|
38410
|
+
const skillPath = join51(skillsDir, entry.name);
|
|
38230
38411
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
38231
38412
|
skills.push({
|
|
38232
38413
|
name: entry.name,
|
|
@@ -38235,14 +38416,14 @@ class SkillsManifestManager {
|
|
|
38235
38416
|
}
|
|
38236
38417
|
}
|
|
38237
38418
|
} else {
|
|
38238
|
-
const categories = await
|
|
38419
|
+
const categories = await readdir15(skillsDir, { withFileTypes: true });
|
|
38239
38420
|
for (const category of categories) {
|
|
38240
38421
|
if (category.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(category.name) && !category.name.startsWith(".")) {
|
|
38241
|
-
const categoryPath =
|
|
38242
|
-
const skillEntries = await
|
|
38422
|
+
const categoryPath = join51(skillsDir, category.name);
|
|
38423
|
+
const skillEntries = await readdir15(categoryPath, { withFileTypes: true });
|
|
38243
38424
|
for (const skillEntry of skillEntries) {
|
|
38244
38425
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
38245
|
-
const skillPath =
|
|
38426
|
+
const skillPath = join51(categoryPath, skillEntry.name);
|
|
38246
38427
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
38247
38428
|
skills.push({
|
|
38248
38429
|
name: skillEntry.name,
|
|
@@ -38262,7 +38443,7 @@ class SkillsManifestManager {
|
|
|
38262
38443
|
files.sort();
|
|
38263
38444
|
for (const file of files) {
|
|
38264
38445
|
const relativePath = relative9(dirPath, file);
|
|
38265
|
-
const content = await
|
|
38446
|
+
const content = await readFile18(file);
|
|
38266
38447
|
hash.update(relativePath);
|
|
38267
38448
|
hash.update(content);
|
|
38268
38449
|
}
|
|
@@ -38270,9 +38451,9 @@ class SkillsManifestManager {
|
|
|
38270
38451
|
}
|
|
38271
38452
|
static async getAllFiles(dirPath) {
|
|
38272
38453
|
const files = [];
|
|
38273
|
-
const entries = await
|
|
38454
|
+
const entries = await readdir15(dirPath, { withFileTypes: true });
|
|
38274
38455
|
for (const entry of entries) {
|
|
38275
|
-
const fullPath =
|
|
38456
|
+
const fullPath = join51(dirPath, entry.name);
|
|
38276
38457
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name)) {
|
|
38277
38458
|
continue;
|
|
38278
38459
|
}
|
|
@@ -38393,13 +38574,13 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
38393
38574
|
|
|
38394
38575
|
// src/domains/skills/detection/script-detector.ts
|
|
38395
38576
|
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
38396
|
-
import { readdir as
|
|
38397
|
-
import { join as
|
|
38577
|
+
import { readdir as readdir16 } from "node:fs/promises";
|
|
38578
|
+
import { join as join52 } from "node:path";
|
|
38398
38579
|
async function scanDirectory(skillsDir) {
|
|
38399
38580
|
if (!await import_fs_extra18.pathExists(skillsDir)) {
|
|
38400
38581
|
return ["flat", []];
|
|
38401
38582
|
}
|
|
38402
|
-
const entries = await
|
|
38583
|
+
const entries = await readdir16(skillsDir, { withFileTypes: true });
|
|
38403
38584
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
38404
38585
|
if (dirs.length === 0) {
|
|
38405
38586
|
return ["flat", []];
|
|
@@ -38407,13 +38588,13 @@ async function scanDirectory(skillsDir) {
|
|
|
38407
38588
|
let totalSkillLikeCount = 0;
|
|
38408
38589
|
const allSkills = [];
|
|
38409
38590
|
for (const dir of dirs) {
|
|
38410
|
-
const dirPath =
|
|
38411
|
-
const subEntries = await
|
|
38591
|
+
const dirPath = join52(skillsDir, dir.name);
|
|
38592
|
+
const subEntries = await readdir16(dirPath, { withFileTypes: true });
|
|
38412
38593
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
38413
38594
|
if (subdirs.length > 0) {
|
|
38414
38595
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
38415
|
-
const subdirPath =
|
|
38416
|
-
const subdirFiles = await
|
|
38596
|
+
const subdirPath = join52(dirPath, subdir.name);
|
|
38597
|
+
const subdirFiles = await readdir16(subdirPath, { withFileTypes: true });
|
|
38417
38598
|
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
38599
|
if (hasSkillMarker) {
|
|
38419
38600
|
totalSkillLikeCount++;
|
|
@@ -38569,12 +38750,12 @@ class SkillsMigrationDetector {
|
|
|
38569
38750
|
// src/domains/skills/skills-migrator.ts
|
|
38570
38751
|
init_logger();
|
|
38571
38752
|
init_types2();
|
|
38572
|
-
import { join as
|
|
38753
|
+
import { join as join57 } from "node:path";
|
|
38573
38754
|
|
|
38574
38755
|
// src/domains/skills/migrator/migration-executor.ts
|
|
38575
38756
|
init_logger();
|
|
38576
|
-
import { copyFile as copyFile4, mkdir as mkdir17, readdir as
|
|
38577
|
-
import { join as
|
|
38757
|
+
import { copyFile as copyFile4, mkdir as mkdir17, readdir as readdir17, rm as rm3 } from "node:fs/promises";
|
|
38758
|
+
import { join as join53 } from "node:path";
|
|
38578
38759
|
var import_fs_extra20 = __toESM(require_lib(), 1);
|
|
38579
38760
|
|
|
38580
38761
|
// src/domains/skills/skills-migration-prompts.ts
|
|
@@ -38737,10 +38918,10 @@ Detected changes:`;
|
|
|
38737
38918
|
// src/domains/skills/migrator/migration-executor.ts
|
|
38738
38919
|
async function copySkillDirectory(sourceDir, destDir) {
|
|
38739
38920
|
await mkdir17(destDir, { recursive: true });
|
|
38740
|
-
const entries = await
|
|
38921
|
+
const entries = await readdir17(sourceDir, { withFileTypes: true });
|
|
38741
38922
|
for (const entry of entries) {
|
|
38742
|
-
const sourcePath =
|
|
38743
|
-
const destPath =
|
|
38923
|
+
const sourcePath = join53(sourceDir, entry.name);
|
|
38924
|
+
const destPath = join53(destDir, entry.name);
|
|
38744
38925
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
38745
38926
|
continue;
|
|
38746
38927
|
}
|
|
@@ -38755,7 +38936,7 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
38755
38936
|
const migrated = [];
|
|
38756
38937
|
const preserved = [];
|
|
38757
38938
|
const errors2 = [];
|
|
38758
|
-
const tempDir =
|
|
38939
|
+
const tempDir = join53(currentSkillsDir, "..", ".skills-migration-temp");
|
|
38759
38940
|
await mkdir17(tempDir, { recursive: true });
|
|
38760
38941
|
try {
|
|
38761
38942
|
for (const mapping of mappings) {
|
|
@@ -38776,9 +38957,9 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
38776
38957
|
}
|
|
38777
38958
|
}
|
|
38778
38959
|
const category = mapping.category;
|
|
38779
|
-
const targetPath = category ?
|
|
38960
|
+
const targetPath = category ? join53(tempDir, category, skillName) : join53(tempDir, skillName);
|
|
38780
38961
|
if (category) {
|
|
38781
|
-
await mkdir17(
|
|
38962
|
+
await mkdir17(join53(tempDir, category), { recursive: true });
|
|
38782
38963
|
}
|
|
38783
38964
|
await copySkillDirectory(currentSkillPath, targetPath);
|
|
38784
38965
|
migrated.push(skillName);
|
|
@@ -38844,8 +39025,8 @@ function validateMigrationPath(path11, paramName) {
|
|
|
38844
39025
|
init_logger();
|
|
38845
39026
|
init_types2();
|
|
38846
39027
|
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
|
|
39028
|
+
import { copyFile as copyFile5, mkdir as mkdir18, readdir as readdir18, rm as rm4, stat as stat9 } from "node:fs/promises";
|
|
39029
|
+
import { basename as basename2, join as join54, normalize as normalize6 } from "node:path";
|
|
38849
39030
|
function validatePath2(path11, paramName) {
|
|
38850
39031
|
if (!path11 || typeof path11 !== "string") {
|
|
38851
39032
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -38871,7 +39052,7 @@ class SkillsBackupManager {
|
|
|
38871
39052
|
const timestamp = Date.now();
|
|
38872
39053
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
38873
39054
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
38874
|
-
const backupDir = parentDir ?
|
|
39055
|
+
const backupDir = parentDir ? join54(parentDir, backupDirName) : join54(skillsDir, "..", backupDirName);
|
|
38875
39056
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
38876
39057
|
try {
|
|
38877
39058
|
await mkdir18(backupDir, { recursive: true });
|
|
@@ -38921,8 +39102,8 @@ class SkillsBackupManager {
|
|
|
38921
39102
|
return [];
|
|
38922
39103
|
}
|
|
38923
39104
|
try {
|
|
38924
|
-
const entries = await
|
|
38925
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
39105
|
+
const entries = await readdir18(parentDir, { withFileTypes: true });
|
|
39106
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join54(parentDir, entry.name));
|
|
38926
39107
|
backups.sort().reverse();
|
|
38927
39108
|
return backups;
|
|
38928
39109
|
} catch (error) {
|
|
@@ -38948,10 +39129,10 @@ class SkillsBackupManager {
|
|
|
38948
39129
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
38949
39130
|
}
|
|
38950
39131
|
static async copyDirectory(sourceDir, destDir) {
|
|
38951
|
-
const entries = await
|
|
39132
|
+
const entries = await readdir18(sourceDir, { withFileTypes: true });
|
|
38952
39133
|
for (const entry of entries) {
|
|
38953
|
-
const sourcePath =
|
|
38954
|
-
const destPath =
|
|
39134
|
+
const sourcePath = join54(sourceDir, entry.name);
|
|
39135
|
+
const destPath = join54(destDir, entry.name);
|
|
38955
39136
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
38956
39137
|
continue;
|
|
38957
39138
|
}
|
|
@@ -38965,9 +39146,9 @@ class SkillsBackupManager {
|
|
|
38965
39146
|
}
|
|
38966
39147
|
static async getDirectorySize(dirPath) {
|
|
38967
39148
|
let size = 0;
|
|
38968
|
-
const entries = await
|
|
39149
|
+
const entries = await readdir18(dirPath, { withFileTypes: true });
|
|
38969
39150
|
for (const entry of entries) {
|
|
38970
|
-
const fullPath =
|
|
39151
|
+
const fullPath = join54(dirPath, entry.name);
|
|
38971
39152
|
if (entry.isSymbolicLink()) {
|
|
38972
39153
|
continue;
|
|
38973
39154
|
}
|
|
@@ -39001,13 +39182,13 @@ import { relative as relative11 } from "node:path";
|
|
|
39001
39182
|
// src/domains/skills/customization/hash-calculator.ts
|
|
39002
39183
|
import { createHash as createHash3 } from "node:crypto";
|
|
39003
39184
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
39004
|
-
import { readFile as
|
|
39005
|
-
import { join as
|
|
39185
|
+
import { readFile as readFile19, readdir as readdir19 } from "node:fs/promises";
|
|
39186
|
+
import { join as join55, relative as relative10 } from "node:path";
|
|
39006
39187
|
async function getAllFiles(dirPath) {
|
|
39007
39188
|
const files = [];
|
|
39008
|
-
const entries = await
|
|
39189
|
+
const entries = await readdir19(dirPath, { withFileTypes: true });
|
|
39009
39190
|
for (const entry of entries) {
|
|
39010
|
-
const fullPath =
|
|
39191
|
+
const fullPath = join55(dirPath, entry.name);
|
|
39011
39192
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name) || entry.isSymbolicLink()) {
|
|
39012
39193
|
continue;
|
|
39013
39194
|
}
|
|
@@ -39040,7 +39221,7 @@ async function hashDirectory(dirPath) {
|
|
|
39040
39221
|
files.sort();
|
|
39041
39222
|
for (const file of files) {
|
|
39042
39223
|
const relativePath = relative10(dirPath, file);
|
|
39043
|
-
const content = await
|
|
39224
|
+
const content = await readFile19(file);
|
|
39044
39225
|
hash.update(relativePath);
|
|
39045
39226
|
hash.update(content);
|
|
39046
39227
|
}
|
|
@@ -39133,8 +39314,8 @@ async function detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
|
39133
39314
|
// src/domains/skills/customization/scan-reporter.ts
|
|
39134
39315
|
init_types2();
|
|
39135
39316
|
var import_fs_extra23 = __toESM(require_lib(), 1);
|
|
39136
|
-
import { readdir as
|
|
39137
|
-
import { join as
|
|
39317
|
+
import { readdir as readdir20 } from "node:fs/promises";
|
|
39318
|
+
import { join as join56, normalize as normalize7 } from "node:path";
|
|
39138
39319
|
function validatePath3(path11, paramName) {
|
|
39139
39320
|
if (!path11 || typeof path11 !== "string") {
|
|
39140
39321
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -39150,19 +39331,19 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
39150
39331
|
if (!await import_fs_extra23.pathExists(skillsDir)) {
|
|
39151
39332
|
return ["flat", []];
|
|
39152
39333
|
}
|
|
39153
|
-
const entries = await
|
|
39334
|
+
const entries = await readdir20(skillsDir, { withFileTypes: true });
|
|
39154
39335
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
39155
39336
|
if (dirs.length === 0) {
|
|
39156
39337
|
return ["flat", []];
|
|
39157
39338
|
}
|
|
39158
|
-
const firstDirPath =
|
|
39159
|
-
const subEntries = await
|
|
39339
|
+
const firstDirPath = join56(skillsDir, dirs[0].name);
|
|
39340
|
+
const subEntries = await readdir20(firstDirPath, { withFileTypes: true });
|
|
39160
39341
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
39161
39342
|
if (subdirs.length > 0) {
|
|
39162
39343
|
let skillLikeCount = 0;
|
|
39163
39344
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
39164
|
-
const subdirPath =
|
|
39165
|
-
const subdirFiles = await
|
|
39345
|
+
const subdirPath = join56(firstDirPath, subdir.name);
|
|
39346
|
+
const subdirFiles = await readdir20(subdirPath, { withFileTypes: true });
|
|
39166
39347
|
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
39348
|
if (hasSkillMarker) {
|
|
39168
39349
|
skillLikeCount++;
|
|
@@ -39171,8 +39352,8 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
39171
39352
|
if (skillLikeCount > 0) {
|
|
39172
39353
|
const skills = [];
|
|
39173
39354
|
for (const dir of dirs) {
|
|
39174
|
-
const categoryPath =
|
|
39175
|
-
const skillDirs = await
|
|
39355
|
+
const categoryPath = join56(skillsDir, dir.name);
|
|
39356
|
+
const skillDirs = await readdir20(categoryPath, { withFileTypes: true });
|
|
39176
39357
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
39177
39358
|
}
|
|
39178
39359
|
return ["categorized", skills];
|
|
@@ -39181,17 +39362,17 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
39181
39362
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
39182
39363
|
}
|
|
39183
39364
|
async function findSkillPath(skillsDir, skillName) {
|
|
39184
|
-
const flatPath =
|
|
39365
|
+
const flatPath = join56(skillsDir, skillName);
|
|
39185
39366
|
if (await import_fs_extra23.pathExists(flatPath)) {
|
|
39186
39367
|
return { path: flatPath, category: undefined };
|
|
39187
39368
|
}
|
|
39188
|
-
const entries = await
|
|
39369
|
+
const entries = await readdir20(skillsDir, { withFileTypes: true });
|
|
39189
39370
|
for (const entry of entries) {
|
|
39190
39371
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
39191
39372
|
continue;
|
|
39192
39373
|
}
|
|
39193
|
-
const categoryPath =
|
|
39194
|
-
const skillPath =
|
|
39374
|
+
const categoryPath = join56(skillsDir, entry.name);
|
|
39375
|
+
const skillPath = join56(categoryPath, skillName);
|
|
39195
39376
|
if (await import_fs_extra23.pathExists(skillPath)) {
|
|
39196
39377
|
return { path: skillPath, category: entry.name };
|
|
39197
39378
|
}
|
|
@@ -39285,7 +39466,7 @@ class SkillsMigrator {
|
|
|
39285
39466
|
}
|
|
39286
39467
|
}
|
|
39287
39468
|
if (options.backup && !options.dryRun) {
|
|
39288
|
-
const claudeDir =
|
|
39469
|
+
const claudeDir = join57(currentSkillsDir, "..");
|
|
39289
39470
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
39290
39471
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
39291
39472
|
}
|
|
@@ -39345,7 +39526,7 @@ async function handleMigration(ctx) {
|
|
|
39345
39526
|
logger.debug("Skipping skills migration (fresh installation)");
|
|
39346
39527
|
return ctx;
|
|
39347
39528
|
}
|
|
39348
|
-
const newSkillsDir =
|
|
39529
|
+
const newSkillsDir = join58(ctx.extractDir, ".claude", "skills");
|
|
39349
39530
|
const currentSkillsDir = PathResolver.buildSkillsPath(ctx.resolvedDir, ctx.options.global);
|
|
39350
39531
|
if (!await import_fs_extra24.pathExists(newSkillsDir) || !await import_fs_extra24.pathExists(currentSkillsDir)) {
|
|
39351
39532
|
return ctx;
|
|
@@ -39370,10 +39551,10 @@ async function handleMigration(ctx) {
|
|
|
39370
39551
|
// src/domains/config/config-manager.ts
|
|
39371
39552
|
init_logger();
|
|
39372
39553
|
import { existsSync as existsSync18 } from "node:fs";
|
|
39373
|
-
import { mkdir as mkdir19, readFile as
|
|
39554
|
+
import { mkdir as mkdir19, readFile as readFile20, rename as rename2, rm as rm5, writeFile as writeFile16 } from "node:fs/promises";
|
|
39374
39555
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
39375
39556
|
import { platform as platform10 } from "node:os";
|
|
39376
|
-
import { join as
|
|
39557
|
+
import { join as join59 } from "node:path";
|
|
39377
39558
|
init_types2();
|
|
39378
39559
|
var PROJECT_CONFIG_FILE = ".ck.json";
|
|
39379
39560
|
|
|
@@ -39381,7 +39562,7 @@ class ConfigManager {
|
|
|
39381
39562
|
static config = null;
|
|
39382
39563
|
static globalFlag = false;
|
|
39383
39564
|
static getProjectConfigDir(projectDir, global3) {
|
|
39384
|
-
return global3 ? projectDir :
|
|
39565
|
+
return global3 ? projectDir : join59(projectDir, ".claude");
|
|
39385
39566
|
}
|
|
39386
39567
|
static setGlobalFlag(global3) {
|
|
39387
39568
|
ConfigManager.globalFlag = global3;
|
|
@@ -39397,7 +39578,7 @@ class ConfigManager {
|
|
|
39397
39578
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
39398
39579
|
try {
|
|
39399
39580
|
if (existsSync18(configFile)) {
|
|
39400
|
-
const content = await
|
|
39581
|
+
const content = await readFile20(configFile, "utf-8");
|
|
39401
39582
|
const data = JSON.parse(content);
|
|
39402
39583
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
39403
39584
|
logger.debug(`Config loaded from ${configFile}`);
|
|
@@ -39420,7 +39601,7 @@ class ConfigManager {
|
|
|
39420
39601
|
await chmod2(configDir, 448);
|
|
39421
39602
|
}
|
|
39422
39603
|
}
|
|
39423
|
-
await
|
|
39604
|
+
await writeFile16(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
39424
39605
|
if (platform10() !== "win32") {
|
|
39425
39606
|
await chmod2(configFile, 384);
|
|
39426
39607
|
}
|
|
@@ -39448,10 +39629,10 @@ class ConfigManager {
|
|
|
39448
39629
|
}
|
|
39449
39630
|
static async loadProjectConfig(projectDir, global3 = false) {
|
|
39450
39631
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
39451
|
-
const configPath =
|
|
39632
|
+
const configPath = join59(configDir, PROJECT_CONFIG_FILE);
|
|
39452
39633
|
try {
|
|
39453
39634
|
if (existsSync18(configPath)) {
|
|
39454
|
-
const content = await
|
|
39635
|
+
const content = await readFile20(configPath, "utf-8");
|
|
39455
39636
|
const data = JSON.parse(content);
|
|
39456
39637
|
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
39457
39638
|
logger.debug(`Project config loaded from ${configPath}`);
|
|
@@ -39464,7 +39645,7 @@ class ConfigManager {
|
|
|
39464
39645
|
}
|
|
39465
39646
|
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
39466
39647
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
39467
|
-
const configPath =
|
|
39648
|
+
const configPath = join59(configDir, PROJECT_CONFIG_FILE);
|
|
39468
39649
|
try {
|
|
39469
39650
|
if (!existsSync18(configDir)) {
|
|
39470
39651
|
await mkdir19(configDir, { recursive: true });
|
|
@@ -39472,7 +39653,7 @@ class ConfigManager {
|
|
|
39472
39653
|
let existingConfig = {};
|
|
39473
39654
|
if (existsSync18(configPath)) {
|
|
39474
39655
|
try {
|
|
39475
|
-
const content = await
|
|
39656
|
+
const content = await readFile20(configPath, "utf-8");
|
|
39476
39657
|
existingConfig = JSON.parse(content);
|
|
39477
39658
|
} catch (error) {
|
|
39478
39659
|
logger.debug(`Could not parse existing config, starting fresh: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -39487,7 +39668,7 @@ class ConfigManager {
|
|
|
39487
39668
|
...validFolders
|
|
39488
39669
|
}
|
|
39489
39670
|
};
|
|
39490
|
-
await
|
|
39671
|
+
await writeFile16(configPath, JSON.stringify(mergedConfig, null, 2), "utf-8");
|
|
39491
39672
|
logger.debug(`Project config saved to ${configPath}`);
|
|
39492
39673
|
} catch (error) {
|
|
39493
39674
|
throw new Error(`Failed to save project config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -39513,11 +39694,11 @@ class ConfigManager {
|
|
|
39513
39694
|
}
|
|
39514
39695
|
static projectConfigExists(projectDir, global3 = false) {
|
|
39515
39696
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
39516
|
-
return existsSync18(
|
|
39697
|
+
return existsSync18(join59(configDir, PROJECT_CONFIG_FILE));
|
|
39517
39698
|
}
|
|
39518
39699
|
static async migrateNestedConfig(globalDir) {
|
|
39519
|
-
const correctPath =
|
|
39520
|
-
const incorrectPath =
|
|
39700
|
+
const correctPath = join59(globalDir, PROJECT_CONFIG_FILE);
|
|
39701
|
+
const incorrectPath = join59(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
39521
39702
|
if (existsSync18(correctPath)) {
|
|
39522
39703
|
logger.debug("Config already exists at correct location, skipping migration");
|
|
39523
39704
|
return false;
|
|
@@ -39527,7 +39708,7 @@ class ConfigManager {
|
|
|
39527
39708
|
logger.info("Migrating .ck.json from nested location to correct location...");
|
|
39528
39709
|
await rename2(incorrectPath, correctPath);
|
|
39529
39710
|
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
39530
|
-
const nestedClaudeDir =
|
|
39711
|
+
const nestedClaudeDir = join59(globalDir, ".claude");
|
|
39531
39712
|
try {
|
|
39532
39713
|
await rm5(nestedClaudeDir, { recursive: false });
|
|
39533
39714
|
logger.debug("Removed empty nested .claude directory");
|
|
@@ -39618,14 +39799,14 @@ Please use only one download method.`);
|
|
|
39618
39799
|
};
|
|
39619
39800
|
}
|
|
39620
39801
|
// src/commands/init/phases/post-install-handler.ts
|
|
39621
|
-
import { join as
|
|
39802
|
+
import { join as join62 } from "node:path";
|
|
39622
39803
|
|
|
39623
39804
|
// src/domains/installation/setup-wizard.ts
|
|
39624
|
-
import { join as
|
|
39805
|
+
import { join as join61 } from "node:path";
|
|
39625
39806
|
|
|
39626
39807
|
// src/domains/config/config-generator.ts
|
|
39627
39808
|
var import_fs_extra25 = __toESM(require_lib(), 1);
|
|
39628
|
-
import { join as
|
|
39809
|
+
import { join as join60 } from "node:path";
|
|
39629
39810
|
async function generateEnvFile(targetDir, values) {
|
|
39630
39811
|
const lines = [
|
|
39631
39812
|
"# Generated by ClaudeKit CLI setup wizard",
|
|
@@ -39667,7 +39848,7 @@ async function generateEnvFile(targetDir, values) {
|
|
|
39667
39848
|
for (const [key, value] of otherValues) {
|
|
39668
39849
|
lines.push(`${key}=${value}`);
|
|
39669
39850
|
}
|
|
39670
|
-
const envPath =
|
|
39851
|
+
const envPath = join60(targetDir, ".env");
|
|
39671
39852
|
await import_fs_extra25.writeFile(envPath, `${lines.join(`
|
|
39672
39853
|
`)}
|
|
39673
39854
|
`, { mode: 384 });
|
|
@@ -39741,7 +39922,7 @@ async function parseEnvFile(path11) {
|
|
|
39741
39922
|
}
|
|
39742
39923
|
}
|
|
39743
39924
|
async function checkGlobalConfig() {
|
|
39744
|
-
const globalEnvPath =
|
|
39925
|
+
const globalEnvPath = join61(PathResolver.getGlobalKitDir(), ".env");
|
|
39745
39926
|
if (!await import_fs_extra26.pathExists(globalEnvPath))
|
|
39746
39927
|
return false;
|
|
39747
39928
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
@@ -39757,7 +39938,7 @@ async function runSetupWizard(options) {
|
|
|
39757
39938
|
let globalEnv = {};
|
|
39758
39939
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
39759
39940
|
if (!isGlobal) {
|
|
39760
|
-
const globalEnvPath =
|
|
39941
|
+
const globalEnvPath = join61(PathResolver.getGlobalKitDir(), ".env");
|
|
39761
39942
|
if (await import_fs_extra26.pathExists(globalEnvPath)) {
|
|
39762
39943
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
39763
39944
|
}
|
|
@@ -39820,7 +40001,7 @@ async function runSetupWizard(options) {
|
|
|
39820
40001
|
}
|
|
39821
40002
|
}
|
|
39822
40003
|
await generateEnvFile(targetDir, values);
|
|
39823
|
-
f2.success(`Configuration saved to ${
|
|
40004
|
+
f2.success(`Configuration saved to ${join61(targetDir, ".env")}`);
|
|
39824
40005
|
return true;
|
|
39825
40006
|
}
|
|
39826
40007
|
async function promptForAdditionalGeminiKeys(primaryKey) {
|
|
@@ -39876,8 +40057,8 @@ async function handlePostInstall(ctx) {
|
|
|
39876
40057
|
return ctx;
|
|
39877
40058
|
}
|
|
39878
40059
|
if (ctx.options.global) {
|
|
39879
|
-
const claudeMdSource =
|
|
39880
|
-
const claudeMdDest =
|
|
40060
|
+
const claudeMdSource = join62(ctx.extractDir, "CLAUDE.md");
|
|
40061
|
+
const claudeMdDest = join62(ctx.resolvedDir, "CLAUDE.md");
|
|
39881
40062
|
if (await import_fs_extra27.pathExists(claudeMdSource)) {
|
|
39882
40063
|
if (!await import_fs_extra27.pathExists(claudeMdDest)) {
|
|
39883
40064
|
await import_fs_extra27.copy(claudeMdSource, claudeMdDest);
|
|
@@ -39924,7 +40105,7 @@ async function handlePostInstall(ctx) {
|
|
|
39924
40105
|
}
|
|
39925
40106
|
}
|
|
39926
40107
|
if (!ctx.options.skipSetup && !ctx.isNonInteractive) {
|
|
39927
|
-
const envPath =
|
|
40108
|
+
const envPath = join62(ctx.claudeDir, ".env");
|
|
39928
40109
|
if (!await import_fs_extra27.pathExists(envPath)) {
|
|
39929
40110
|
const shouldSetup = await ctx.prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
39930
40111
|
if (shouldSetup) {
|
|
@@ -39946,7 +40127,7 @@ Optional: DISCORD_WEBHOOK_URL, TELEGRAM_BOT_TOKEN`, "Configuration skipped");
|
|
|
39946
40127
|
}
|
|
39947
40128
|
// src/commands/init/phases/selection-handler.ts
|
|
39948
40129
|
import { mkdir as mkdir20 } from "node:fs/promises";
|
|
39949
|
-
import { join as
|
|
40130
|
+
import { join as join64, resolve as resolve7 } from "node:path";
|
|
39950
40131
|
|
|
39951
40132
|
// src/domains/github/kit-access-checker.ts
|
|
39952
40133
|
init_logger();
|
|
@@ -39975,7 +40156,7 @@ async function detectAccessibleKits() {
|
|
|
39975
40156
|
|
|
39976
40157
|
// src/domains/installation/fresh-installer.ts
|
|
39977
40158
|
init_logger();
|
|
39978
|
-
import { join as
|
|
40159
|
+
import { join as join63 } from "node:path";
|
|
39979
40160
|
var import_fs_extra28 = __toESM(require_lib(), 1);
|
|
39980
40161
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
|
|
39981
40162
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
@@ -39994,7 +40175,7 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
39994
40175
|
const { rmSync } = await import("node:fs");
|
|
39995
40176
|
let removedCount = 0;
|
|
39996
40177
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
39997
|
-
const subdirPath =
|
|
40178
|
+
const subdirPath = join63(claudeDir, subdir);
|
|
39998
40179
|
if (await import_fs_extra28.pathExists(subdirPath)) {
|
|
39999
40180
|
rmSync(subdirPath, { recursive: true, force: true });
|
|
40000
40181
|
removedCount++;
|
|
@@ -40188,7 +40369,7 @@ async function handleSelection(ctx) {
|
|
|
40188
40369
|
}
|
|
40189
40370
|
if (!ctx.options.fresh) {
|
|
40190
40371
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
40191
|
-
const claudeDir = prefix ?
|
|
40372
|
+
const claudeDir = prefix ? join64(resolvedDir, prefix) : resolvedDir;
|
|
40192
40373
|
try {
|
|
40193
40374
|
const existingMetadata = await readManifest(claudeDir);
|
|
40194
40375
|
if (existingMetadata?.kits) {
|
|
@@ -40220,7 +40401,7 @@ async function handleSelection(ctx) {
|
|
|
40220
40401
|
}
|
|
40221
40402
|
if (ctx.options.fresh) {
|
|
40222
40403
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
40223
|
-
const claudeDir = prefix ?
|
|
40404
|
+
const claudeDir = prefix ? join64(resolvedDir, prefix) : resolvedDir;
|
|
40224
40405
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
40225
40406
|
if (!canProceed) {
|
|
40226
40407
|
return { ...ctx, cancelled: true };
|
|
@@ -40238,7 +40419,7 @@ async function handleSelection(ctx) {
|
|
|
40238
40419
|
logger.info("Fetching available versions...");
|
|
40239
40420
|
let currentVersion = null;
|
|
40240
40421
|
try {
|
|
40241
|
-
const metadataPath = ctx.options.global ?
|
|
40422
|
+
const metadataPath = ctx.options.global ? join64(PathResolver.getGlobalKitDir(), "metadata.json") : join64(resolvedDir, ".claude", "metadata.json");
|
|
40242
40423
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
40243
40424
|
currentVersion = metadata?.version || null;
|
|
40244
40425
|
if (currentVersion) {
|
|
@@ -40306,8 +40487,8 @@ async function handleSelection(ctx) {
|
|
|
40306
40487
|
};
|
|
40307
40488
|
}
|
|
40308
40489
|
// 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
|
|
40490
|
+
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as writeFile18 } from "node:fs/promises";
|
|
40491
|
+
import { dirname as dirname9, join as join65, resolve as resolve8 } from "node:path";
|
|
40311
40492
|
init_logger();
|
|
40312
40493
|
var import_fs_extra30 = __toESM(require_lib(), 1);
|
|
40313
40494
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
@@ -40316,13 +40497,13 @@ async function handleSync(ctx) {
|
|
|
40316
40497
|
return ctx;
|
|
40317
40498
|
}
|
|
40318
40499
|
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve8(ctx.options.dir || ".");
|
|
40319
|
-
const claudeDir = ctx.options.global ? resolvedDir :
|
|
40500
|
+
const claudeDir = ctx.options.global ? resolvedDir : join65(resolvedDir, ".claude");
|
|
40320
40501
|
if (!await import_fs_extra30.pathExists(claudeDir)) {
|
|
40321
40502
|
logger.error("Cannot sync: no .claude directory found");
|
|
40322
40503
|
ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
|
|
40323
40504
|
return { ...ctx, cancelled: true };
|
|
40324
40505
|
}
|
|
40325
|
-
const metadataPath =
|
|
40506
|
+
const metadataPath = join65(claudeDir, "metadata.json");
|
|
40326
40507
|
if (!await import_fs_extra30.pathExists(metadataPath)) {
|
|
40327
40508
|
logger.error("Cannot sync: no metadata.json found");
|
|
40328
40509
|
ctx.prompts.note(`Your installation may be from an older version.
|
|
@@ -40422,7 +40603,7 @@ function getLockTimeout() {
|
|
|
40422
40603
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
40423
40604
|
async function acquireSyncLock(global3) {
|
|
40424
40605
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
40425
|
-
const lockPath =
|
|
40606
|
+
const lockPath = join65(cacheDir, ".sync-lock");
|
|
40426
40607
|
const startTime = Date.now();
|
|
40427
40608
|
const lockTimeout = getLockTimeout();
|
|
40428
40609
|
await mkdir21(dirname9(lockPath), { recursive: true });
|
|
@@ -40468,7 +40649,7 @@ async function executeSyncMerge(ctx) {
|
|
|
40468
40649
|
const releaseLock = await acquireSyncLock(ctx.options.global);
|
|
40469
40650
|
try {
|
|
40470
40651
|
const trackedFiles = ctx.syncTrackedFiles;
|
|
40471
|
-
const upstreamDir = ctx.options.global ?
|
|
40652
|
+
const upstreamDir = ctx.options.global ? join65(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
40472
40653
|
logger.info("Analyzing file changes...");
|
|
40473
40654
|
const plan = await SyncEngine.createSyncPlan(trackedFiles, ctx.claudeDir, upstreamDir);
|
|
40474
40655
|
displaySyncPlan(plan);
|
|
@@ -40487,7 +40668,7 @@ async function executeSyncMerge(ctx) {
|
|
|
40487
40668
|
try {
|
|
40488
40669
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
40489
40670
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
40490
|
-
const targetDir =
|
|
40671
|
+
const targetDir = join65(targetPath, "..");
|
|
40491
40672
|
try {
|
|
40492
40673
|
await mkdir21(targetDir, { recursive: true });
|
|
40493
40674
|
} catch (mkdirError) {
|
|
@@ -40568,7 +40749,7 @@ async function executeSyncMerge(ctx) {
|
|
|
40568
40749
|
try {
|
|
40569
40750
|
const tempPath = `${currentPath}.tmp.${Date.now()}`;
|
|
40570
40751
|
try {
|
|
40571
|
-
await
|
|
40752
|
+
await writeFile18(tempPath, result.result, "utf-8");
|
|
40572
40753
|
await rename3(tempPath, currentPath);
|
|
40573
40754
|
} catch (atomicError) {
|
|
40574
40755
|
await unlink7(tempPath).catch(() => {});
|
|
@@ -40658,7 +40839,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
40658
40839
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
40659
40840
|
if (await import_fs_extra30.pathExists(sourcePath)) {
|
|
40660
40841
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
40661
|
-
const targetDir =
|
|
40842
|
+
const targetDir = join65(targetPath, "..");
|
|
40662
40843
|
await mkdir21(targetDir, { recursive: true });
|
|
40663
40844
|
await copyFile6(sourcePath, targetPath);
|
|
40664
40845
|
}
|
|
@@ -40672,7 +40853,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
40672
40853
|
}
|
|
40673
40854
|
}
|
|
40674
40855
|
// src/commands/init/phases/transform-handler.ts
|
|
40675
|
-
import { join as
|
|
40856
|
+
import { join as join69 } from "node:path";
|
|
40676
40857
|
|
|
40677
40858
|
// src/services/transformers/folder-path-transformer.ts
|
|
40678
40859
|
init_logger();
|
|
@@ -40683,38 +40864,38 @@ init_logger();
|
|
|
40683
40864
|
init_types2();
|
|
40684
40865
|
var import_fs_extra31 = __toESM(require_lib(), 1);
|
|
40685
40866
|
import { rename as rename4, rm as rm6 } from "node:fs/promises";
|
|
40686
|
-
import { join as
|
|
40867
|
+
import { join as join66, relative as relative12 } from "node:path";
|
|
40687
40868
|
async function collectDirsToRename(extractDir, folders) {
|
|
40688
40869
|
const dirsToRename = [];
|
|
40689
40870
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
40690
|
-
const docsPath =
|
|
40871
|
+
const docsPath = join66(extractDir, DEFAULT_FOLDERS.docs);
|
|
40691
40872
|
if (await import_fs_extra31.pathExists(docsPath)) {
|
|
40692
40873
|
dirsToRename.push({
|
|
40693
40874
|
from: docsPath,
|
|
40694
|
-
to:
|
|
40875
|
+
to: join66(extractDir, folders.docs)
|
|
40695
40876
|
});
|
|
40696
40877
|
}
|
|
40697
|
-
const claudeDocsPath =
|
|
40878
|
+
const claudeDocsPath = join66(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
40698
40879
|
if (await import_fs_extra31.pathExists(claudeDocsPath)) {
|
|
40699
40880
|
dirsToRename.push({
|
|
40700
40881
|
from: claudeDocsPath,
|
|
40701
|
-
to:
|
|
40882
|
+
to: join66(extractDir, ".claude", folders.docs)
|
|
40702
40883
|
});
|
|
40703
40884
|
}
|
|
40704
40885
|
}
|
|
40705
40886
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
40706
|
-
const plansPath =
|
|
40887
|
+
const plansPath = join66(extractDir, DEFAULT_FOLDERS.plans);
|
|
40707
40888
|
if (await import_fs_extra31.pathExists(plansPath)) {
|
|
40708
40889
|
dirsToRename.push({
|
|
40709
40890
|
from: plansPath,
|
|
40710
|
-
to:
|
|
40891
|
+
to: join66(extractDir, folders.plans)
|
|
40711
40892
|
});
|
|
40712
40893
|
}
|
|
40713
|
-
const claudePlansPath =
|
|
40894
|
+
const claudePlansPath = join66(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
40714
40895
|
if (await import_fs_extra31.pathExists(claudePlansPath)) {
|
|
40715
40896
|
dirsToRename.push({
|
|
40716
40897
|
from: claudePlansPath,
|
|
40717
|
-
to:
|
|
40898
|
+
to: join66(extractDir, ".claude", folders.plans)
|
|
40718
40899
|
});
|
|
40719
40900
|
}
|
|
40720
40901
|
}
|
|
@@ -40754,8 +40935,8 @@ async function renameFolders(dirsToRename, extractDir, options) {
|
|
|
40754
40935
|
// src/services/transformers/folder-transform/path-replacer.ts
|
|
40755
40936
|
init_logger();
|
|
40756
40937
|
init_types2();
|
|
40757
|
-
import { readFile as
|
|
40758
|
-
import { join as
|
|
40938
|
+
import { readFile as readFile22, readdir as readdir21, writeFile as writeFile19 } from "node:fs/promises";
|
|
40939
|
+
import { join as join67, relative as relative13 } from "node:path";
|
|
40759
40940
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
40760
40941
|
".md",
|
|
40761
40942
|
".txt",
|
|
@@ -40806,9 +40987,9 @@ function compileReplacements(replacements) {
|
|
|
40806
40987
|
async function transformFileContents(dir, compiledReplacements, options) {
|
|
40807
40988
|
let filesChanged = 0;
|
|
40808
40989
|
let replacementsCount = 0;
|
|
40809
|
-
const entries = await
|
|
40990
|
+
const entries = await readdir21(dir, { withFileTypes: true });
|
|
40810
40991
|
for (const entry of entries) {
|
|
40811
|
-
const fullPath =
|
|
40992
|
+
const fullPath = join67(dir, entry.name);
|
|
40812
40993
|
if (entry.isDirectory()) {
|
|
40813
40994
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
40814
40995
|
continue;
|
|
@@ -40821,7 +41002,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
40821
41002
|
if (!shouldTransform)
|
|
40822
41003
|
continue;
|
|
40823
41004
|
try {
|
|
40824
|
-
const content = await
|
|
41005
|
+
const content = await readFile22(fullPath, "utf-8");
|
|
40825
41006
|
let newContent = content;
|
|
40826
41007
|
let changeCount = 0;
|
|
40827
41008
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -40837,7 +41018,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
40837
41018
|
if (options.dryRun) {
|
|
40838
41019
|
logger.debug(`[dry-run] Would update ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
40839
41020
|
} else {
|
|
40840
|
-
await
|
|
41021
|
+
await writeFile19(fullPath, newContent, "utf-8");
|
|
40841
41022
|
logger.debug(`Updated ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
40842
41023
|
}
|
|
40843
41024
|
filesChanged++;
|
|
@@ -40943,15 +41124,15 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
40943
41124
|
|
|
40944
41125
|
// src/services/transformers/global-path-transformer.ts
|
|
40945
41126
|
init_logger();
|
|
40946
|
-
import { readFile as
|
|
41127
|
+
import { readFile as readFile23, readdir as readdir22, writeFile as writeFile20 } from "node:fs/promises";
|
|
40947
41128
|
import { platform as platform11 } from "node:os";
|
|
40948
|
-
import { extname as extname2, join as
|
|
41129
|
+
import { extname as extname2, join as join68 } from "node:path";
|
|
40949
41130
|
var IS_WINDOWS3 = platform11() === "win32";
|
|
40950
41131
|
var HOME_PREFIX = IS_WINDOWS3 ? "%USERPROFILE%" : "$HOME";
|
|
40951
41132
|
function getHomeDirPrefix() {
|
|
40952
41133
|
return HOME_PREFIX;
|
|
40953
41134
|
}
|
|
40954
|
-
var
|
|
41135
|
+
var TRANSFORMABLE_EXTENSIONS2 = new Set([
|
|
40955
41136
|
".md",
|
|
40956
41137
|
".js",
|
|
40957
41138
|
".ts",
|
|
@@ -41042,10 +41223,10 @@ function transformContent(content) {
|
|
|
41042
41223
|
});
|
|
41043
41224
|
return { transformed, changes };
|
|
41044
41225
|
}
|
|
41045
|
-
function
|
|
41226
|
+
function shouldTransformFile2(filename) {
|
|
41046
41227
|
const ext2 = extname2(filename).toLowerCase();
|
|
41047
41228
|
const basename3 = filename.split("/").pop() || filename;
|
|
41048
|
-
return
|
|
41229
|
+
return TRANSFORMABLE_EXTENSIONS2.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename3);
|
|
41049
41230
|
}
|
|
41050
41231
|
async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
41051
41232
|
let filesTransformed = 0;
|
|
@@ -41053,20 +41234,20 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
41053
41234
|
let filesSkipped = 0;
|
|
41054
41235
|
const skippedFiles = [];
|
|
41055
41236
|
async function processDirectory2(dir) {
|
|
41056
|
-
const entries = await
|
|
41237
|
+
const entries = await readdir22(dir, { withFileTypes: true });
|
|
41057
41238
|
for (const entry of entries) {
|
|
41058
|
-
const fullPath =
|
|
41239
|
+
const fullPath = join68(dir, entry.name);
|
|
41059
41240
|
if (entry.isDirectory()) {
|
|
41060
41241
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
41061
41242
|
continue;
|
|
41062
41243
|
}
|
|
41063
41244
|
await processDirectory2(fullPath);
|
|
41064
|
-
} else if (entry.isFile() &&
|
|
41245
|
+
} else if (entry.isFile() && shouldTransformFile2(entry.name)) {
|
|
41065
41246
|
try {
|
|
41066
|
-
const content = await
|
|
41247
|
+
const content = await readFile23(fullPath, "utf-8");
|
|
41067
41248
|
const { transformed, changes } = transformContent(content);
|
|
41068
41249
|
if (changes > 0) {
|
|
41069
|
-
await
|
|
41250
|
+
await writeFile20(fullPath, transformed, "utf-8");
|
|
41070
41251
|
filesTransformed++;
|
|
41071
41252
|
totalChanges += changes;
|
|
41072
41253
|
if (options.verbose) {
|
|
@@ -41131,7 +41312,7 @@ async function handleTransforms(ctx) {
|
|
|
41131
41312
|
logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
|
|
41132
41313
|
}
|
|
41133
41314
|
}
|
|
41134
|
-
const claudeDir = ctx.options.global ? ctx.resolvedDir :
|
|
41315
|
+
const claudeDir = ctx.options.global ? ctx.resolvedDir : join69(ctx.resolvedDir, ".claude");
|
|
41135
41316
|
return {
|
|
41136
41317
|
...ctx,
|
|
41137
41318
|
foldersConfig,
|
|
@@ -41452,7 +41633,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
41452
41633
|
};
|
|
41453
41634
|
}
|
|
41454
41635
|
// src/commands/new/phases/project-creation.ts
|
|
41455
|
-
import { join as
|
|
41636
|
+
import { join as join70 } from "node:path";
|
|
41456
41637
|
init_logger();
|
|
41457
41638
|
init_output_manager();
|
|
41458
41639
|
init_types2();
|
|
@@ -41562,7 +41743,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
41562
41743
|
output.section("Installing");
|
|
41563
41744
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
41564
41745
|
const merger = new FileMerger;
|
|
41565
|
-
const claudeDir =
|
|
41746
|
+
const claudeDir = join70(resolvedDir, ".claude");
|
|
41566
41747
|
merger.setMultiKitContext(claudeDir, kit);
|
|
41567
41748
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
41568
41749
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -41723,13 +41904,13 @@ async function detectInstallations() {
|
|
|
41723
41904
|
|
|
41724
41905
|
// src/commands/uninstall/removal-handler.ts
|
|
41725
41906
|
import { readdirSync as readdirSync2, rmSync as rmSync2 } from "node:fs";
|
|
41726
|
-
import { join as
|
|
41907
|
+
import { join as join72 } from "node:path";
|
|
41727
41908
|
init_logger();
|
|
41728
41909
|
var import_fs_extra34 = __toESM(require_lib(), 1);
|
|
41729
41910
|
|
|
41730
41911
|
// src/commands/uninstall/analysis-handler.ts
|
|
41731
41912
|
import { readdirSync, rmSync } from "node:fs";
|
|
41732
|
-
import { dirname as dirname10, join as
|
|
41913
|
+
import { dirname as dirname10, join as join71 } from "node:path";
|
|
41733
41914
|
init_logger();
|
|
41734
41915
|
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
41735
41916
|
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
@@ -41776,7 +41957,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
41776
41957
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
41777
41958
|
const kitFiles = metadata.kits[kit].files || [];
|
|
41778
41959
|
for (const trackedFile of kitFiles) {
|
|
41779
|
-
const filePath =
|
|
41960
|
+
const filePath = join71(installation.path, trackedFile.path);
|
|
41780
41961
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
41781
41962
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
41782
41963
|
continue;
|
|
@@ -41806,7 +41987,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
41806
41987
|
return result;
|
|
41807
41988
|
}
|
|
41808
41989
|
for (const trackedFile of allTrackedFiles) {
|
|
41809
|
-
const filePath =
|
|
41990
|
+
const filePath = join71(installation.path, trackedFile.path);
|
|
41810
41991
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
41811
41992
|
if (!ownershipResult.exists)
|
|
41812
41993
|
continue;
|
|
@@ -41866,7 +42047,7 @@ async function removeInstallations(installations, options) {
|
|
|
41866
42047
|
let removedCount = 0;
|
|
41867
42048
|
let cleanedDirs = 0;
|
|
41868
42049
|
for (const item of analysis.toDelete) {
|
|
41869
|
-
const filePath =
|
|
42050
|
+
const filePath = join72(installation.path, item.path);
|
|
41870
42051
|
if (await import_fs_extra34.pathExists(filePath)) {
|
|
41871
42052
|
await import_fs_extra34.remove(filePath);
|
|
41872
42053
|
removedCount++;
|
|
@@ -42198,14 +42379,14 @@ init_types2();
|
|
|
42198
42379
|
// src/domains/versioning/version-cache.ts
|
|
42199
42380
|
init_logger();
|
|
42200
42381
|
import { existsSync as existsSync19 } from "node:fs";
|
|
42201
|
-
import { mkdir as mkdir22, readFile as
|
|
42202
|
-
import { join as
|
|
42382
|
+
import { mkdir as mkdir22, readFile as readFile24, writeFile as writeFile21 } from "node:fs/promises";
|
|
42383
|
+
import { join as join73 } from "node:path";
|
|
42203
42384
|
class VersionCacheManager {
|
|
42204
42385
|
static CACHE_FILENAME = "version-check.json";
|
|
42205
42386
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
42206
42387
|
static getCacheFile() {
|
|
42207
42388
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
42208
|
-
return
|
|
42389
|
+
return join73(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
42209
42390
|
}
|
|
42210
42391
|
static async load() {
|
|
42211
42392
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -42214,7 +42395,7 @@ class VersionCacheManager {
|
|
|
42214
42395
|
logger.debug("Version check cache not found");
|
|
42215
42396
|
return null;
|
|
42216
42397
|
}
|
|
42217
|
-
const content = await
|
|
42398
|
+
const content = await readFile24(cacheFile, "utf-8");
|
|
42218
42399
|
const cache2 = JSON.parse(content);
|
|
42219
42400
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
42220
42401
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -42234,7 +42415,7 @@ class VersionCacheManager {
|
|
|
42234
42415
|
if (!existsSync19(cacheDir)) {
|
|
42235
42416
|
await mkdir22(cacheDir, { recursive: true, mode: 448 });
|
|
42236
42417
|
}
|
|
42237
|
-
await
|
|
42418
|
+
await writeFile21(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
42238
42419
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
42239
42420
|
} catch (error) {
|
|
42240
42421
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -42447,7 +42628,7 @@ var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
|
42447
42628
|
// package.json
|
|
42448
42629
|
var package_default = {
|
|
42449
42630
|
name: "claudekit-cli",
|
|
42450
|
-
version: "3.
|
|
42631
|
+
version: "3.23.0",
|
|
42451
42632
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
42452
42633
|
type: "module",
|
|
42453
42634
|
repository: {
|
|
@@ -42872,7 +43053,7 @@ function registerCommands(cli) {
|
|
|
42872
43053
|
|
|
42873
43054
|
// src/cli/version-display.ts
|
|
42874
43055
|
import { existsSync as existsSync20, readFileSync as readFileSync6 } from "node:fs";
|
|
42875
|
-
import { join as
|
|
43056
|
+
import { join as join74 } from "node:path";
|
|
42876
43057
|
init_logger();
|
|
42877
43058
|
init_types2();
|
|
42878
43059
|
var packageVersion = package_default.version;
|
|
@@ -42906,9 +43087,9 @@ async function displayVersion() {
|
|
|
42906
43087
|
let localKitVersion = null;
|
|
42907
43088
|
let isGlobalOnlyKit = false;
|
|
42908
43089
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
42909
|
-
const globalMetadataPath =
|
|
43090
|
+
const globalMetadataPath = join74(globalKitDir, "metadata.json");
|
|
42910
43091
|
const prefix = PathResolver.getPathPrefix(false);
|
|
42911
|
-
const localMetadataPath = prefix ?
|
|
43092
|
+
const localMetadataPath = prefix ? join74(process.cwd(), prefix, "metadata.json") : join74(process.cwd(), "metadata.json");
|
|
42912
43093
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
42913
43094
|
if (!isLocalSameAsGlobal && existsSync20(localMetadataPath)) {
|
|
42914
43095
|
try {
|