claudekit-cli 3.30.0-dev.1 → 3.30.0-dev.2
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 +558 -383
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18149,7 +18149,7 @@ function getPagerArgs(pagerCmd) {
|
|
|
18149
18149
|
return [];
|
|
18150
18150
|
}
|
|
18151
18151
|
async function trySystemPager(content) {
|
|
18152
|
-
return new Promise((
|
|
18152
|
+
return new Promise((resolve12) => {
|
|
18153
18153
|
const pagerCmd = process.env.PAGER || "less";
|
|
18154
18154
|
const pagerArgs = getPagerArgs(pagerCmd);
|
|
18155
18155
|
try {
|
|
@@ -18159,20 +18159,20 @@ async function trySystemPager(content) {
|
|
|
18159
18159
|
});
|
|
18160
18160
|
const timeout = setTimeout(() => {
|
|
18161
18161
|
pager.kill();
|
|
18162
|
-
|
|
18162
|
+
resolve12(false);
|
|
18163
18163
|
}, 30000);
|
|
18164
18164
|
pager.stdin.write(content);
|
|
18165
18165
|
pager.stdin.end();
|
|
18166
18166
|
pager.on("close", (code2) => {
|
|
18167
18167
|
clearTimeout(timeout);
|
|
18168
|
-
|
|
18168
|
+
resolve12(code2 === 0);
|
|
18169
18169
|
});
|
|
18170
18170
|
pager.on("error", () => {
|
|
18171
18171
|
clearTimeout(timeout);
|
|
18172
|
-
|
|
18172
|
+
resolve12(false);
|
|
18173
18173
|
});
|
|
18174
18174
|
} catch {
|
|
18175
|
-
|
|
18175
|
+
resolve12(false);
|
|
18176
18176
|
}
|
|
18177
18177
|
});
|
|
18178
18178
|
}
|
|
@@ -18199,16 +18199,16 @@ async function basicPager(content) {
|
|
|
18199
18199
|
break;
|
|
18200
18200
|
}
|
|
18201
18201
|
const remaining = lines.length - currentLine;
|
|
18202
|
-
await new Promise((
|
|
18202
|
+
await new Promise((resolve12) => {
|
|
18203
18203
|
rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
|
|
18204
18204
|
if (answer.toLowerCase() === "q") {
|
|
18205
18205
|
rl.close();
|
|
18206
18206
|
process.exitCode = 0;
|
|
18207
|
-
|
|
18207
|
+
resolve12();
|
|
18208
18208
|
return;
|
|
18209
18209
|
}
|
|
18210
18210
|
process.stdout.write("\x1B[1A\x1B[2K");
|
|
18211
|
-
|
|
18211
|
+
resolve12();
|
|
18212
18212
|
});
|
|
18213
18213
|
});
|
|
18214
18214
|
}
|
|
@@ -35225,22 +35225,11 @@ async function handleDownload(ctx) {
|
|
|
35225
35225
|
};
|
|
35226
35226
|
}
|
|
35227
35227
|
// src/commands/init/phases/merge-handler.ts
|
|
35228
|
-
import { join as
|
|
35229
|
-
|
|
35230
|
-
// src/domains/installation/file-merger.ts
|
|
35231
|
-
init_logger();
|
|
35232
|
-
init_types2();
|
|
35233
|
-
init_dist2();
|
|
35234
|
-
|
|
35235
|
-
// src/domains/installation/merger/copy-executor.ts
|
|
35236
|
-
init_logger();
|
|
35237
|
-
init_types2();
|
|
35238
|
-
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
35239
|
-
var import_ignore3 = __toESM(require_ignore(), 1);
|
|
35240
|
-
import { dirname as dirname8, join as join43, relative as relative6 } from "node:path";
|
|
35228
|
+
import { join as join54 } from "node:path";
|
|
35241
35229
|
|
|
35242
|
-
// src/domains/installation/
|
|
35243
|
-
import {
|
|
35230
|
+
// src/domains/installation/deletion-handler.ts
|
|
35231
|
+
import { existsSync as existsSync17, lstatSync as lstatSync2, readdirSync, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
35232
|
+
import { dirname as dirname6, join as join40, resolve as resolve6 } from "node:path";
|
|
35244
35233
|
|
|
35245
35234
|
// src/services/file-operations/manifest/manifest-reader.ts
|
|
35246
35235
|
import { join as join39 } from "node:path";
|
|
@@ -35389,7 +35378,172 @@ async function getUninstallManifest(claudeDir, kit) {
|
|
|
35389
35378
|
};
|
|
35390
35379
|
}
|
|
35391
35380
|
|
|
35381
|
+
// src/domains/installation/deletion-handler.ts
|
|
35382
|
+
init_logger();
|
|
35383
|
+
var import_fs_extra7 = __toESM(require_lib(), 1);
|
|
35384
|
+
function findFileInMetadata(metadata, path10) {
|
|
35385
|
+
if (!metadata)
|
|
35386
|
+
return null;
|
|
35387
|
+
if (metadata.kits) {
|
|
35388
|
+
for (const kitMeta of Object.values(metadata.kits)) {
|
|
35389
|
+
if (kitMeta?.files) {
|
|
35390
|
+
const found = kitMeta.files.find((f3) => f3.path === path10);
|
|
35391
|
+
if (found)
|
|
35392
|
+
return found;
|
|
35393
|
+
}
|
|
35394
|
+
}
|
|
35395
|
+
}
|
|
35396
|
+
if (metadata.files) {
|
|
35397
|
+
const found = metadata.files.find((f3) => f3.path === path10);
|
|
35398
|
+
if (found)
|
|
35399
|
+
return found;
|
|
35400
|
+
}
|
|
35401
|
+
return null;
|
|
35402
|
+
}
|
|
35403
|
+
function shouldDeletePath(path10, metadata) {
|
|
35404
|
+
const tracked = findFileInMetadata(metadata, path10);
|
|
35405
|
+
if (!tracked)
|
|
35406
|
+
return true;
|
|
35407
|
+
return tracked.ownership !== "user";
|
|
35408
|
+
}
|
|
35409
|
+
var MAX_CLEANUP_ITERATIONS = 50;
|
|
35410
|
+
function cleanupEmptyDirectories(filePath, claudeDir) {
|
|
35411
|
+
const normalizedClaudeDir = resolve6(claudeDir);
|
|
35412
|
+
let currentDir = resolve6(dirname6(filePath));
|
|
35413
|
+
let iterations = 0;
|
|
35414
|
+
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir) && iterations < MAX_CLEANUP_ITERATIONS) {
|
|
35415
|
+
iterations++;
|
|
35416
|
+
try {
|
|
35417
|
+
const entries = readdirSync(currentDir);
|
|
35418
|
+
if (entries.length === 0) {
|
|
35419
|
+
rmdirSync(currentDir);
|
|
35420
|
+
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
35421
|
+
currentDir = resolve6(dirname6(currentDir));
|
|
35422
|
+
} else {
|
|
35423
|
+
break;
|
|
35424
|
+
}
|
|
35425
|
+
} catch {
|
|
35426
|
+
break;
|
|
35427
|
+
}
|
|
35428
|
+
}
|
|
35429
|
+
}
|
|
35430
|
+
function deletePath(fullPath, claudeDir) {
|
|
35431
|
+
const normalizedPath = resolve6(fullPath);
|
|
35432
|
+
const normalizedClaudeDir = resolve6(claudeDir);
|
|
35433
|
+
if (!normalizedPath.startsWith(`${normalizedClaudeDir}/`) && normalizedPath !== normalizedClaudeDir) {
|
|
35434
|
+
throw new Error(`Path traversal detected: ${fullPath}`);
|
|
35435
|
+
}
|
|
35436
|
+
try {
|
|
35437
|
+
const stat6 = lstatSync2(fullPath);
|
|
35438
|
+
if (stat6.isDirectory()) {
|
|
35439
|
+
rmSync2(fullPath, { recursive: true, force: true });
|
|
35440
|
+
} else {
|
|
35441
|
+
unlinkSync3(fullPath);
|
|
35442
|
+
cleanupEmptyDirectories(fullPath, claudeDir);
|
|
35443
|
+
}
|
|
35444
|
+
} catch (error) {
|
|
35445
|
+
throw new Error(`Failed to delete ${fullPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
35446
|
+
}
|
|
35447
|
+
}
|
|
35448
|
+
async function updateMetadataAfterDeletion(claudeDir, deletedPaths) {
|
|
35449
|
+
const metadataPath = join40(claudeDir, "metadata.json");
|
|
35450
|
+
if (!await import_fs_extra7.pathExists(metadataPath)) {
|
|
35451
|
+
return;
|
|
35452
|
+
}
|
|
35453
|
+
let content;
|
|
35454
|
+
try {
|
|
35455
|
+
content = await import_fs_extra7.readFile(metadataPath, "utf-8");
|
|
35456
|
+
} catch {
|
|
35457
|
+
logger.debug("Failed to read metadata.json for cleanup");
|
|
35458
|
+
return;
|
|
35459
|
+
}
|
|
35460
|
+
let metadata;
|
|
35461
|
+
try {
|
|
35462
|
+
metadata = JSON.parse(content);
|
|
35463
|
+
} catch {
|
|
35464
|
+
logger.debug("Failed to parse metadata.json for cleanup");
|
|
35465
|
+
return;
|
|
35466
|
+
}
|
|
35467
|
+
const deletedSet = new Set(deletedPaths);
|
|
35468
|
+
const isDeletedOrInDeletedDir = (path10) => {
|
|
35469
|
+
if (deletedSet.has(path10))
|
|
35470
|
+
return true;
|
|
35471
|
+
for (const deleted of deletedPaths) {
|
|
35472
|
+
if (path10.startsWith(`${deleted}/`))
|
|
35473
|
+
return true;
|
|
35474
|
+
}
|
|
35475
|
+
return false;
|
|
35476
|
+
};
|
|
35477
|
+
if (metadata.kits) {
|
|
35478
|
+
for (const kitName of Object.keys(metadata.kits)) {
|
|
35479
|
+
const kit = metadata.kits[kitName];
|
|
35480
|
+
if (kit?.files) {
|
|
35481
|
+
kit.files = kit.files.filter((f3) => !isDeletedOrInDeletedDir(f3.path));
|
|
35482
|
+
}
|
|
35483
|
+
}
|
|
35484
|
+
}
|
|
35485
|
+
if (metadata.files) {
|
|
35486
|
+
metadata.files = metadata.files.filter((f3) => !isDeletedOrInDeletedDir(f3.path));
|
|
35487
|
+
}
|
|
35488
|
+
try {
|
|
35489
|
+
await import_fs_extra7.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
|
|
35490
|
+
logger.debug(`Updated metadata.json, removed ${deletedPaths.length} entries`);
|
|
35491
|
+
} catch {
|
|
35492
|
+
logger.debug("Failed to write updated metadata.json");
|
|
35493
|
+
}
|
|
35494
|
+
}
|
|
35495
|
+
async function handleDeletions(sourceMetadata, claudeDir) {
|
|
35496
|
+
const deletions = sourceMetadata.deletions || [];
|
|
35497
|
+
if (deletions.length === 0) {
|
|
35498
|
+
return { deletedPaths: [], preservedPaths: [], errors: [] };
|
|
35499
|
+
}
|
|
35500
|
+
const userMetadata = await readManifest(claudeDir);
|
|
35501
|
+
const result = { deletedPaths: [], preservedPaths: [], errors: [] };
|
|
35502
|
+
for (const path10 of deletions) {
|
|
35503
|
+
const fullPath = join40(claudeDir, path10);
|
|
35504
|
+
const normalizedPath = resolve6(fullPath);
|
|
35505
|
+
const normalizedClaudeDir = resolve6(claudeDir);
|
|
35506
|
+
if (!normalizedPath.startsWith(`${normalizedClaudeDir}/`)) {
|
|
35507
|
+
logger.warning(`Skipping invalid path: ${path10}`);
|
|
35508
|
+
result.errors.push(path10);
|
|
35509
|
+
continue;
|
|
35510
|
+
}
|
|
35511
|
+
if (!shouldDeletePath(path10, userMetadata)) {
|
|
35512
|
+
result.preservedPaths.push(path10);
|
|
35513
|
+
logger.verbose(`Preserved user file: ${path10}`);
|
|
35514
|
+
continue;
|
|
35515
|
+
}
|
|
35516
|
+
if (existsSync17(fullPath)) {
|
|
35517
|
+
try {
|
|
35518
|
+
deletePath(fullPath, claudeDir);
|
|
35519
|
+
result.deletedPaths.push(path10);
|
|
35520
|
+
logger.verbose(`Deleted: ${path10}`);
|
|
35521
|
+
} catch (error) {
|
|
35522
|
+
result.errors.push(path10);
|
|
35523
|
+
logger.debug(`Failed to delete ${path10}: ${error}`);
|
|
35524
|
+
}
|
|
35525
|
+
}
|
|
35526
|
+
}
|
|
35527
|
+
if (result.deletedPaths.length > 0) {
|
|
35528
|
+
await updateMetadataAfterDeletion(claudeDir, result.deletedPaths);
|
|
35529
|
+
}
|
|
35530
|
+
return result;
|
|
35531
|
+
}
|
|
35532
|
+
|
|
35533
|
+
// src/domains/installation/file-merger.ts
|
|
35534
|
+
init_logger();
|
|
35535
|
+
init_types2();
|
|
35536
|
+
init_dist2();
|
|
35537
|
+
|
|
35538
|
+
// src/domains/installation/merger/copy-executor.ts
|
|
35539
|
+
init_logger();
|
|
35540
|
+
init_types2();
|
|
35541
|
+
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
35542
|
+
var import_ignore3 = __toESM(require_ignore(), 1);
|
|
35543
|
+
import { dirname as dirname9, join as join44, relative as relative6 } from "node:path";
|
|
35544
|
+
|
|
35392
35545
|
// src/domains/installation/selective-merger.ts
|
|
35546
|
+
import { stat as stat6 } from "node:fs/promises";
|
|
35393
35547
|
init_logger();
|
|
35394
35548
|
var import_semver = __toESM(require_semver2(), 1);
|
|
35395
35549
|
|
|
@@ -35562,10 +35716,10 @@ class SelectiveMerger {
|
|
|
35562
35716
|
|
|
35563
35717
|
// src/domains/installation/merger/file-scanner.ts
|
|
35564
35718
|
init_logger();
|
|
35565
|
-
var
|
|
35719
|
+
var import_fs_extra8 = __toESM(require_lib(), 1);
|
|
35566
35720
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
35567
35721
|
import { relative as relative5 } from "node:path";
|
|
35568
|
-
import { join as
|
|
35722
|
+
import { join as join41 } from "node:path";
|
|
35569
35723
|
|
|
35570
35724
|
// node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
35571
35725
|
var balanced = (a3, b3, str) => {
|
|
@@ -37019,12 +37173,12 @@ class FileScanner {
|
|
|
37019
37173
|
}
|
|
37020
37174
|
async getFiles(dir, baseDir = dir) {
|
|
37021
37175
|
const files = [];
|
|
37022
|
-
const entries = await
|
|
37176
|
+
const entries = await import_fs_extra8.readdir(dir, { encoding: "utf8" });
|
|
37023
37177
|
for (const entry of entries) {
|
|
37024
|
-
const fullPath =
|
|
37178
|
+
const fullPath = join41(dir, entry);
|
|
37025
37179
|
const relativePath = relative5(baseDir, fullPath);
|
|
37026
37180
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
37027
|
-
const stats = await
|
|
37181
|
+
const stats = await import_fs_extra8.lstat(fullPath);
|
|
37028
37182
|
if (stats.isSymbolicLink()) {
|
|
37029
37183
|
logger.warning(`Skipping symbolic link: ${normalizedRelativePath}`);
|
|
37030
37184
|
continue;
|
|
@@ -37055,9 +37209,9 @@ class FileScanner {
|
|
|
37055
37209
|
}
|
|
37056
37210
|
|
|
37057
37211
|
// src/domains/config/installed-settings-tracker.ts
|
|
37058
|
-
import { existsSync as
|
|
37059
|
-
import { mkdir as mkdir15, readFile as
|
|
37060
|
-
import { dirname as
|
|
37212
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
37213
|
+
import { mkdir as mkdir15, readFile as readFile14, writeFile as writeFile11 } from "node:fs/promises";
|
|
37214
|
+
import { dirname as dirname7, join as join42 } from "node:path";
|
|
37061
37215
|
|
|
37062
37216
|
// src/shared/index.ts
|
|
37063
37217
|
init_logger();
|
|
@@ -37097,17 +37251,17 @@ class InstalledSettingsTracker {
|
|
|
37097
37251
|
}
|
|
37098
37252
|
getCkJsonPath() {
|
|
37099
37253
|
if (this.isGlobal) {
|
|
37100
|
-
return
|
|
37254
|
+
return join42(this.projectDir, CK_JSON_FILE);
|
|
37101
37255
|
}
|
|
37102
|
-
return
|
|
37256
|
+
return join42(this.projectDir, ".claude", CK_JSON_FILE);
|
|
37103
37257
|
}
|
|
37104
37258
|
async loadInstalledSettings() {
|
|
37105
37259
|
const ckJsonPath = this.getCkJsonPath();
|
|
37106
|
-
if (!
|
|
37260
|
+
if (!existsSync18(ckJsonPath)) {
|
|
37107
37261
|
return { hooks: [], mcpServers: [] };
|
|
37108
37262
|
}
|
|
37109
37263
|
try {
|
|
37110
|
-
const content = await
|
|
37264
|
+
const content = await readFile14(ckJsonPath, "utf-8");
|
|
37111
37265
|
const data = JSON.parse(content);
|
|
37112
37266
|
const installed = data.kits?.[this.kitName]?.installedSettings;
|
|
37113
37267
|
if (installed) {
|
|
@@ -37123,8 +37277,8 @@ class InstalledSettingsTracker {
|
|
|
37123
37277
|
const ckJsonPath = this.getCkJsonPath();
|
|
37124
37278
|
try {
|
|
37125
37279
|
let data = {};
|
|
37126
|
-
if (
|
|
37127
|
-
const content = await
|
|
37280
|
+
if (existsSync18(ckJsonPath)) {
|
|
37281
|
+
const content = await readFile14(ckJsonPath, "utf-8");
|
|
37128
37282
|
data = JSON.parse(content);
|
|
37129
37283
|
}
|
|
37130
37284
|
if (!data.kits) {
|
|
@@ -37134,8 +37288,8 @@ class InstalledSettingsTracker {
|
|
|
37134
37288
|
data.kits[this.kitName] = {};
|
|
37135
37289
|
}
|
|
37136
37290
|
data.kits[this.kitName].installedSettings = settings;
|
|
37137
|
-
await mkdir15(
|
|
37138
|
-
await
|
|
37291
|
+
await mkdir15(dirname7(ckJsonPath), { recursive: true });
|
|
37292
|
+
await writeFile11(ckJsonPath, JSON.stringify(data, null, 2), "utf-8");
|
|
37139
37293
|
logger.debug(`Saved installed settings to ${ckJsonPath}`);
|
|
37140
37294
|
} catch (error) {
|
|
37141
37295
|
logger.warning(`Failed to save installed settings: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -37556,18 +37710,18 @@ function mergeSettings(source, destination, options) {
|
|
|
37556
37710
|
}
|
|
37557
37711
|
// src/domains/config/merger/file-io.ts
|
|
37558
37712
|
init_logger();
|
|
37559
|
-
var
|
|
37713
|
+
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
37560
37714
|
import { randomUUID } from "node:crypto";
|
|
37561
|
-
import { dirname as
|
|
37715
|
+
import { dirname as dirname8, join as join43 } from "node:path";
|
|
37562
37716
|
function stripBOM(content) {
|
|
37563
37717
|
return content.charCodeAt(0) === 65279 ? content.slice(1) : content;
|
|
37564
37718
|
}
|
|
37565
37719
|
async function readSettingsFile(filePath) {
|
|
37566
37720
|
try {
|
|
37567
|
-
if (!await
|
|
37721
|
+
if (!await import_fs_extra9.pathExists(filePath)) {
|
|
37568
37722
|
return null;
|
|
37569
37723
|
}
|
|
37570
|
-
const rawContent = await
|
|
37724
|
+
const rawContent = await import_fs_extra9.readFile(filePath, "utf-8");
|
|
37571
37725
|
const content = stripBOM(rawContent);
|
|
37572
37726
|
const parsed = JSON.parse(content);
|
|
37573
37727
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -37581,15 +37735,15 @@ async function readSettingsFile(filePath) {
|
|
|
37581
37735
|
}
|
|
37582
37736
|
}
|
|
37583
37737
|
async function atomicWriteFile(filePath, content) {
|
|
37584
|
-
const dir =
|
|
37585
|
-
const tempPath =
|
|
37738
|
+
const dir = dirname8(filePath);
|
|
37739
|
+
const tempPath = join43(dir, `.settings-${randomUUID()}.tmp`);
|
|
37586
37740
|
try {
|
|
37587
|
-
await
|
|
37588
|
-
await
|
|
37741
|
+
await import_fs_extra9.writeFile(tempPath, content, "utf-8");
|
|
37742
|
+
await import_fs_extra9.rename(tempPath, filePath);
|
|
37589
37743
|
} catch (error) {
|
|
37590
37744
|
try {
|
|
37591
|
-
if (await
|
|
37592
|
-
await
|
|
37745
|
+
if (await import_fs_extra9.pathExists(tempPath)) {
|
|
37746
|
+
await import_fs_extra9.unlink(tempPath);
|
|
37593
37747
|
}
|
|
37594
37748
|
} catch {}
|
|
37595
37749
|
throw error;
|
|
@@ -37618,7 +37772,7 @@ class SettingsMerger {
|
|
|
37618
37772
|
// src/domains/installation/merger/settings-processor.ts
|
|
37619
37773
|
init_environment();
|
|
37620
37774
|
init_logger();
|
|
37621
|
-
var
|
|
37775
|
+
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
37622
37776
|
|
|
37623
37777
|
class SettingsProcessor {
|
|
37624
37778
|
isGlobal = false;
|
|
@@ -37651,7 +37805,7 @@ class SettingsProcessor {
|
|
|
37651
37805
|
}
|
|
37652
37806
|
async processSettingsJson(sourceFile, destFile) {
|
|
37653
37807
|
try {
|
|
37654
|
-
const sourceContent = await
|
|
37808
|
+
const sourceContent = await import_fs_extra10.readFile(sourceFile, "utf-8");
|
|
37655
37809
|
let transformedSource = sourceContent;
|
|
37656
37810
|
if (this.isGlobal) {
|
|
37657
37811
|
const homeVar = isWindows() ? '"%USERPROFILE%"' : '"$HOME"';
|
|
@@ -37666,12 +37820,12 @@ class SettingsProcessor {
|
|
|
37666
37820
|
logger.debug(`Transformed .claude/ paths to ${projectDirVar}/.claude/ in settings.json for local installation`);
|
|
37667
37821
|
}
|
|
37668
37822
|
}
|
|
37669
|
-
const destExists = await
|
|
37823
|
+
const destExists = await import_fs_extra10.pathExists(destFile);
|
|
37670
37824
|
if (destExists && !this.forceOverwriteSettings) {
|
|
37671
37825
|
await this.selectiveMergeSettings(transformedSource, destFile);
|
|
37672
37826
|
} else {
|
|
37673
37827
|
const formattedContent = this.formatJsonContent(transformedSource);
|
|
37674
|
-
await
|
|
37828
|
+
await import_fs_extra10.writeFile(destFile, formattedContent, "utf-8");
|
|
37675
37829
|
try {
|
|
37676
37830
|
const parsedSettings = JSON.parse(formattedContent);
|
|
37677
37831
|
if (this.forceOverwriteSettings && destExists) {
|
|
@@ -37685,7 +37839,7 @@ class SettingsProcessor {
|
|
|
37685
37839
|
}
|
|
37686
37840
|
} catch (error) {
|
|
37687
37841
|
logger.error(`Failed to process settings.json: ${error}`);
|
|
37688
|
-
await
|
|
37842
|
+
await import_fs_extra10.copy(sourceFile, destFile, { overwrite: true });
|
|
37689
37843
|
}
|
|
37690
37844
|
}
|
|
37691
37845
|
async selectiveMergeSettings(transformedSourceContent, destFile) {
|
|
@@ -37695,7 +37849,7 @@ class SettingsProcessor {
|
|
|
37695
37849
|
} catch {
|
|
37696
37850
|
logger.warning("Failed to parse source settings.json, falling back to overwrite");
|
|
37697
37851
|
const formattedContent = this.formatJsonContent(transformedSourceContent);
|
|
37698
|
-
await
|
|
37852
|
+
await import_fs_extra10.writeFile(destFile, formattedContent, "utf-8");
|
|
37699
37853
|
return;
|
|
37700
37854
|
}
|
|
37701
37855
|
let destSettings;
|
|
@@ -37781,7 +37935,7 @@ class SettingsProcessor {
|
|
|
37781
37935
|
}
|
|
37782
37936
|
async readAndNormalizeGlobalSettings(destFile) {
|
|
37783
37937
|
try {
|
|
37784
|
-
const content = await
|
|
37938
|
+
const content = await import_fs_extra10.readFile(destFile, "utf-8");
|
|
37785
37939
|
if (!content.trim())
|
|
37786
37940
|
return null;
|
|
37787
37941
|
const homeVar = isWindows() ? "%USERPROFILE%" : "$HOME";
|
|
@@ -37892,8 +38046,8 @@ class CopyExecutor {
|
|
|
37892
38046
|
for (const file of files) {
|
|
37893
38047
|
const relativePath = relative6(sourceDir, file);
|
|
37894
38048
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
37895
|
-
const destPath =
|
|
37896
|
-
if (await
|
|
38049
|
+
const destPath = join44(destDir, relativePath);
|
|
38050
|
+
if (await import_fs_extra11.pathExists(destPath)) {
|
|
37897
38051
|
if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
|
|
37898
38052
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
37899
38053
|
continue;
|
|
@@ -37914,14 +38068,14 @@ class CopyExecutor {
|
|
|
37914
38068
|
for (const file of files) {
|
|
37915
38069
|
const relativePath = relative6(sourceDir, file);
|
|
37916
38070
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
37917
|
-
const destPath =
|
|
38071
|
+
const destPath = join44(destDir, relativePath);
|
|
37918
38072
|
if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
|
|
37919
38073
|
logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
|
|
37920
38074
|
skippedCount++;
|
|
37921
38075
|
continue;
|
|
37922
38076
|
}
|
|
37923
38077
|
if (this.userConfigChecker.ignores(normalizedRelativePath)) {
|
|
37924
|
-
const fileExists = await
|
|
38078
|
+
const fileExists = await import_fs_extra11.pathExists(destPath);
|
|
37925
38079
|
if (fileExists) {
|
|
37926
38080
|
logger.debug(`Preserving user config: ${normalizedRelativePath}`);
|
|
37927
38081
|
skippedCount++;
|
|
@@ -37952,7 +38106,7 @@ class CopyExecutor {
|
|
|
37952
38106
|
continue;
|
|
37953
38107
|
}
|
|
37954
38108
|
}
|
|
37955
|
-
await withRetry2(() =>
|
|
38109
|
+
await withRetry2(() => import_fs_extra11.copy(file, destPath, { overwrite: true }));
|
|
37956
38110
|
this.trackInstalledFile(normalizedRelativePath);
|
|
37957
38111
|
copiedCount++;
|
|
37958
38112
|
}
|
|
@@ -37991,10 +38145,10 @@ class CopyExecutor {
|
|
|
37991
38145
|
}
|
|
37992
38146
|
trackInstalledFile(relativePath) {
|
|
37993
38147
|
this.installedFiles.add(relativePath);
|
|
37994
|
-
let dir =
|
|
38148
|
+
let dir = dirname9(relativePath);
|
|
37995
38149
|
while (dir && dir !== "." && dir !== "/") {
|
|
37996
38150
|
this.installedDirectories.add(`${dir}/`);
|
|
37997
|
-
dir =
|
|
38151
|
+
dir = dirname9(dir);
|
|
37998
38152
|
}
|
|
37999
38153
|
}
|
|
38000
38154
|
}
|
|
@@ -38084,15 +38238,15 @@ class FileMerger {
|
|
|
38084
38238
|
|
|
38085
38239
|
// src/domains/migration/legacy-migration.ts
|
|
38086
38240
|
import { readdir as readdir9, stat as stat7 } from "node:fs/promises";
|
|
38087
|
-
import { join as
|
|
38241
|
+
import { join as join48, relative as relative7 } from "node:path";
|
|
38088
38242
|
// src/services/file-operations/manifest/manifest-tracker.ts
|
|
38089
|
-
import { join as
|
|
38243
|
+
import { join as join47 } from "node:path";
|
|
38090
38244
|
|
|
38091
38245
|
// src/domains/migration/release-manifest.ts
|
|
38092
38246
|
init_logger();
|
|
38093
38247
|
init_zod();
|
|
38094
|
-
var
|
|
38095
|
-
import { join as
|
|
38248
|
+
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
38249
|
+
import { join as join45 } from "node:path";
|
|
38096
38250
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
38097
38251
|
path: exports_external.string(),
|
|
38098
38252
|
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
@@ -38107,9 +38261,9 @@ var ReleaseManifestSchema = exports_external.object({
|
|
|
38107
38261
|
|
|
38108
38262
|
class ReleaseManifestLoader {
|
|
38109
38263
|
static async load(extractDir) {
|
|
38110
|
-
const manifestPath =
|
|
38264
|
+
const manifestPath = join45(extractDir, "release-manifest.json");
|
|
38111
38265
|
try {
|
|
38112
|
-
const content = await
|
|
38266
|
+
const content = await import_fs_extra12.readFile(manifestPath, "utf-8");
|
|
38113
38267
|
const parsed = JSON.parse(content);
|
|
38114
38268
|
return ReleaseManifestSchema.parse(parsed);
|
|
38115
38269
|
} catch (error) {
|
|
@@ -38127,15 +38281,15 @@ init_environment();
|
|
|
38127
38281
|
init_logger();
|
|
38128
38282
|
|
|
38129
38283
|
// src/services/file-operations/manifest/manifest-updater.ts
|
|
38130
|
-
import { join as
|
|
38284
|
+
import { join as join46 } from "node:path";
|
|
38131
38285
|
init_logger();
|
|
38132
38286
|
init_types2();
|
|
38133
|
-
var
|
|
38287
|
+
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
38134
38288
|
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
38135
38289
|
async function writeManifest(claudeDir, kitName, version, scope, kitType, trackedFiles, userConfigFiles) {
|
|
38136
|
-
const metadataPath =
|
|
38290
|
+
const metadataPath = join46(claudeDir, "metadata.json");
|
|
38137
38291
|
const kit = kitType || (/\bmarketing\b/i.test(kitName) ? "marketing" : "engineer");
|
|
38138
|
-
await
|
|
38292
|
+
await import_fs_extra13.ensureFile(metadataPath);
|
|
38139
38293
|
let release = null;
|
|
38140
38294
|
try {
|
|
38141
38295
|
release = await import_proper_lockfile2.lock(metadataPath, {
|
|
@@ -38148,9 +38302,9 @@ async function writeManifest(claudeDir, kitName, version, scope, kitType, tracke
|
|
|
38148
38302
|
logger.warning(`Metadata migration warning: ${migrationResult.error}`);
|
|
38149
38303
|
}
|
|
38150
38304
|
let existingMetadata = { kits: {} };
|
|
38151
|
-
if (await
|
|
38305
|
+
if (await import_fs_extra13.pathExists(metadataPath)) {
|
|
38152
38306
|
try {
|
|
38153
|
-
const content = await
|
|
38307
|
+
const content = await import_fs_extra13.readFile(metadataPath, "utf-8");
|
|
38154
38308
|
const parsed = JSON.parse(content);
|
|
38155
38309
|
if (parsed && typeof parsed === "object" && Object.keys(parsed).length > 0) {
|
|
38156
38310
|
existingMetadata = parsed;
|
|
@@ -38179,7 +38333,7 @@ async function writeManifest(claudeDir, kitName, version, scope, kitType, tracke
|
|
|
38179
38333
|
userConfigFiles: [...USER_CONFIG_PATTERNS, ...userConfigFiles]
|
|
38180
38334
|
};
|
|
38181
38335
|
const validated = MetadataSchema.parse(metadata);
|
|
38182
|
-
await
|
|
38336
|
+
await import_fs_extra13.writeFile(metadataPath, JSON.stringify(validated, null, 2), "utf-8");
|
|
38183
38337
|
logger.debug(`Wrote manifest for kit "${kit}" with ${trackedFiles.length} tracked files`);
|
|
38184
38338
|
} finally {
|
|
38185
38339
|
if (release) {
|
|
@@ -38189,8 +38343,8 @@ async function writeManifest(claudeDir, kitName, version, scope, kitType, tracke
|
|
|
38189
38343
|
}
|
|
38190
38344
|
}
|
|
38191
38345
|
async function removeKitFromManifest(claudeDir, kit) {
|
|
38192
|
-
const metadataPath =
|
|
38193
|
-
if (!await
|
|
38346
|
+
const metadataPath = join46(claudeDir, "metadata.json");
|
|
38347
|
+
if (!await import_fs_extra13.pathExists(metadataPath))
|
|
38194
38348
|
return false;
|
|
38195
38349
|
let release = null;
|
|
38196
38350
|
try {
|
|
@@ -38211,7 +38365,7 @@ async function removeKitFromManifest(claudeDir, kit) {
|
|
|
38211
38365
|
...metadata,
|
|
38212
38366
|
kits: remainingKits
|
|
38213
38367
|
};
|
|
38214
|
-
await
|
|
38368
|
+
await import_fs_extra13.writeFile(metadataPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
38215
38369
|
logger.debug(`Removed kit "${kit}" from metadata, ${Object.keys(remainingKits).length} kit(s) remaining`);
|
|
38216
38370
|
return true;
|
|
38217
38371
|
} finally {
|
|
@@ -38319,7 +38473,7 @@ function buildFileTrackingList(options) {
|
|
|
38319
38473
|
if (!isGlobal && !installedPath.startsWith(".claude/"))
|
|
38320
38474
|
continue;
|
|
38321
38475
|
const relativePath = isGlobal ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
38322
|
-
const filePath =
|
|
38476
|
+
const filePath = join47(claudeDir, relativePath);
|
|
38323
38477
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
38324
38478
|
const ownership = manifestEntry ? "ck" : "user";
|
|
38325
38479
|
filesToTrack.push({
|
|
@@ -38392,7 +38546,7 @@ class ManifestWriter {
|
|
|
38392
38546
|
|
|
38393
38547
|
// src/domains/migration/legacy-migration.ts
|
|
38394
38548
|
init_logger();
|
|
38395
|
-
var
|
|
38549
|
+
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
38396
38550
|
class LegacyMigration {
|
|
38397
38551
|
static async detectLegacy(claudeDir) {
|
|
38398
38552
|
const metadata = await ManifestWriter.readManifest(claudeDir);
|
|
@@ -38425,7 +38579,7 @@ class LegacyMigration {
|
|
|
38425
38579
|
continue;
|
|
38426
38580
|
if (SKIP_DIRS_ALL.includes(entry))
|
|
38427
38581
|
continue;
|
|
38428
|
-
const fullPath =
|
|
38582
|
+
const fullPath = join48(dir, entry);
|
|
38429
38583
|
let stats;
|
|
38430
38584
|
try {
|
|
38431
38585
|
stats = await stat7(fullPath);
|
|
@@ -38527,7 +38681,7 @@ User-created files (sample):`);
|
|
|
38527
38681
|
];
|
|
38528
38682
|
if (filesToChecksum.length > 0) {
|
|
38529
38683
|
const checksumResults = await mapWithLimit(filesToChecksum, async ({ relativePath, ownership }) => {
|
|
38530
|
-
const fullPath =
|
|
38684
|
+
const fullPath = join48(claudeDir, relativePath);
|
|
38531
38685
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
38532
38686
|
return { relativePath, checksum, ownership };
|
|
38533
38687
|
});
|
|
@@ -38548,8 +38702,8 @@ User-created files (sample):`);
|
|
|
38548
38702
|
installedAt: new Date().toISOString(),
|
|
38549
38703
|
files: trackedFiles
|
|
38550
38704
|
};
|
|
38551
|
-
const metadataPath =
|
|
38552
|
-
await
|
|
38705
|
+
const metadataPath = join48(claudeDir, "metadata.json");
|
|
38706
|
+
await import_fs_extra14.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
38553
38707
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
38554
38708
|
return true;
|
|
38555
38709
|
}
|
|
@@ -38651,32 +38805,32 @@ function buildConflictSummary(fileConflicts, hookConflicts, mcpConflicts) {
|
|
|
38651
38805
|
}
|
|
38652
38806
|
|
|
38653
38807
|
// src/services/file-operations/file-scanner.ts
|
|
38654
|
-
import { join as
|
|
38808
|
+
import { join as join49, relative as relative8, resolve as resolve7 } from "node:path";
|
|
38655
38809
|
init_logger();
|
|
38656
|
-
var
|
|
38810
|
+
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
38657
38811
|
|
|
38658
38812
|
class FileScanner2 {
|
|
38659
38813
|
static async getFiles(dirPath, relativeTo) {
|
|
38660
38814
|
const basePath = relativeTo || dirPath;
|
|
38661
38815
|
const files = [];
|
|
38662
|
-
if (!await
|
|
38816
|
+
if (!await import_fs_extra15.pathExists(dirPath)) {
|
|
38663
38817
|
return files;
|
|
38664
38818
|
}
|
|
38665
38819
|
try {
|
|
38666
|
-
const entries = await
|
|
38820
|
+
const entries = await import_fs_extra15.readdir(dirPath, { encoding: "utf8" });
|
|
38667
38821
|
for (const entry of entries) {
|
|
38668
38822
|
if (SKIP_DIRS_ALL.includes(entry)) {
|
|
38669
38823
|
logger.debug(`Skipping directory: ${entry}`);
|
|
38670
38824
|
continue;
|
|
38671
38825
|
}
|
|
38672
|
-
const fullPath =
|
|
38826
|
+
const fullPath = join49(dirPath, entry);
|
|
38673
38827
|
if (!FileScanner2.isSafePath(basePath, fullPath)) {
|
|
38674
38828
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
38675
38829
|
continue;
|
|
38676
38830
|
}
|
|
38677
38831
|
let stats;
|
|
38678
38832
|
try {
|
|
38679
|
-
stats = await
|
|
38833
|
+
stats = await import_fs_extra15.lstat(fullPath);
|
|
38680
38834
|
} catch (error) {
|
|
38681
38835
|
if (error instanceof Error && "code" in error && (error.code === "EACCES" || error.code === "EPERM")) {
|
|
38682
38836
|
logger.warning(`Skipping inaccessible path: ${entry}`);
|
|
@@ -38704,8 +38858,8 @@ class FileScanner2 {
|
|
|
38704
38858
|
return files;
|
|
38705
38859
|
}
|
|
38706
38860
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
38707
|
-
const destSubDir =
|
|
38708
|
-
const sourceSubDir =
|
|
38861
|
+
const destSubDir = join49(destDir, subPath);
|
|
38862
|
+
const sourceSubDir = join49(sourceDir, subPath);
|
|
38709
38863
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
38710
38864
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
38711
38865
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -38715,7 +38869,7 @@ class FileScanner2 {
|
|
|
38715
38869
|
const sourceFiles = await FileScanner2.getFiles(sourceSubDir, sourceDir);
|
|
38716
38870
|
logger.debug(`findCustomFiles - destFiles count: ${destFiles.length}`);
|
|
38717
38871
|
logger.debug(`findCustomFiles - sourceFiles count: ${sourceFiles.length}`);
|
|
38718
|
-
const sourceExists = await
|
|
38872
|
+
const sourceExists = await import_fs_extra15.pathExists(sourceSubDir);
|
|
38719
38873
|
if (sourceExists && sourceFiles.length === 0 && destFiles.length > 100) {
|
|
38720
38874
|
logger.warning(`Source directory exists but is empty while destination has ${destFiles.length} files. This may indicate an extraction issue. Skipping custom file detection.`);
|
|
38721
38875
|
return [];
|
|
@@ -38733,8 +38887,8 @@ class FileScanner2 {
|
|
|
38733
38887
|
return customFiles;
|
|
38734
38888
|
}
|
|
38735
38889
|
static isSafePath(basePath, targetPath) {
|
|
38736
|
-
const resolvedBase =
|
|
38737
|
-
const resolvedTarget =
|
|
38890
|
+
const resolvedBase = resolve7(basePath);
|
|
38891
|
+
const resolvedTarget = resolve7(targetPath);
|
|
38738
38892
|
return resolvedTarget.startsWith(resolvedBase);
|
|
38739
38893
|
}
|
|
38740
38894
|
static toPosixPath(path11) {
|
|
@@ -38744,14 +38898,14 @@ class FileScanner2 {
|
|
|
38744
38898
|
|
|
38745
38899
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
38746
38900
|
init_logger();
|
|
38747
|
-
var
|
|
38901
|
+
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
38748
38902
|
import { lstat as lstat5, mkdir as mkdir16, readdir as readdir12, stat as stat8 } from "node:fs/promises";
|
|
38749
|
-
import { join as
|
|
38903
|
+
import { join as join51 } from "node:path";
|
|
38750
38904
|
|
|
38751
38905
|
// src/services/transformers/commands-prefix/content-transformer.ts
|
|
38752
38906
|
init_logger();
|
|
38753
|
-
import { readFile as
|
|
38754
|
-
import { join as
|
|
38907
|
+
import { readFile as readFile19, readdir as readdir11, writeFile as writeFile16 } from "node:fs/promises";
|
|
38908
|
+
import { join as join50 } from "node:path";
|
|
38755
38909
|
var TRANSFORMABLE_EXTENSIONS = new Set([
|
|
38756
38910
|
".md",
|
|
38757
38911
|
".txt",
|
|
@@ -38819,7 +38973,7 @@ async function transformCommandReferences(directory, options = {}) {
|
|
|
38819
38973
|
async function processDirectory(dir) {
|
|
38820
38974
|
const entries = await readdir11(dir, { withFileTypes: true });
|
|
38821
38975
|
for (const entry of entries) {
|
|
38822
|
-
const fullPath =
|
|
38976
|
+
const fullPath = join50(dir, entry.name);
|
|
38823
38977
|
if (entry.isDirectory()) {
|
|
38824
38978
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
38825
38979
|
continue;
|
|
@@ -38827,13 +38981,13 @@ async function transformCommandReferences(directory, options = {}) {
|
|
|
38827
38981
|
await processDirectory(fullPath);
|
|
38828
38982
|
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
38829
38983
|
try {
|
|
38830
|
-
const content = await
|
|
38984
|
+
const content = await readFile19(fullPath, "utf-8");
|
|
38831
38985
|
const { transformed, changes } = transformCommandContent(content);
|
|
38832
38986
|
if (changes > 0) {
|
|
38833
38987
|
if (options.dryRun) {
|
|
38834
38988
|
logger.debug(`[dry-run] Would transform ${changes} command ref(s) in ${fullPath}`);
|
|
38835
38989
|
} else {
|
|
38836
|
-
await
|
|
38990
|
+
await writeFile16(fullPath, transformed, "utf-8");
|
|
38837
38991
|
if (options.verbose) {
|
|
38838
38992
|
logger.verbose(`Transformed ${changes} command ref(s) in ${fullPath}`);
|
|
38839
38993
|
}
|
|
@@ -38894,14 +39048,14 @@ function shouldApplyPrefix(options) {
|
|
|
38894
39048
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
38895
39049
|
async function applyPrefix(extractDir) {
|
|
38896
39050
|
validatePath(extractDir, "extractDir");
|
|
38897
|
-
const commandsDir =
|
|
38898
|
-
if (!await
|
|
39051
|
+
const commandsDir = join51(extractDir, ".claude", "commands");
|
|
39052
|
+
if (!await import_fs_extra16.pathExists(commandsDir)) {
|
|
38899
39053
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
38900
39054
|
return;
|
|
38901
39055
|
}
|
|
38902
39056
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
38903
|
-
const backupDir =
|
|
38904
|
-
const tempDir =
|
|
39057
|
+
const backupDir = join51(extractDir, ".commands-backup");
|
|
39058
|
+
const tempDir = join51(extractDir, ".commands-prefix-temp");
|
|
38905
39059
|
try {
|
|
38906
39060
|
const entries = await readdir12(commandsDir);
|
|
38907
39061
|
if (entries.length === 0) {
|
|
@@ -38909,28 +39063,28 @@ async function applyPrefix(extractDir) {
|
|
|
38909
39063
|
return;
|
|
38910
39064
|
}
|
|
38911
39065
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
38912
|
-
const ckDir2 =
|
|
39066
|
+
const ckDir2 = join51(commandsDir, "ck");
|
|
38913
39067
|
const ckStat = await stat8(ckDir2);
|
|
38914
39068
|
if (ckStat.isDirectory()) {
|
|
38915
39069
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
38916
39070
|
return;
|
|
38917
39071
|
}
|
|
38918
39072
|
}
|
|
38919
|
-
await
|
|
39073
|
+
await import_fs_extra16.copy(commandsDir, backupDir);
|
|
38920
39074
|
logger.verbose("Created backup of commands directory");
|
|
38921
39075
|
await mkdir16(tempDir, { recursive: true });
|
|
38922
|
-
const ckDir =
|
|
39076
|
+
const ckDir = join51(tempDir, "ck");
|
|
38923
39077
|
await mkdir16(ckDir, { recursive: true });
|
|
38924
39078
|
let processedCount = 0;
|
|
38925
39079
|
for (const entry of entries) {
|
|
38926
|
-
const sourcePath =
|
|
39080
|
+
const sourcePath = join51(commandsDir, entry);
|
|
38927
39081
|
const stats = await lstat5(sourcePath);
|
|
38928
39082
|
if (stats.isSymbolicLink()) {
|
|
38929
39083
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
38930
39084
|
continue;
|
|
38931
39085
|
}
|
|
38932
|
-
const destPath =
|
|
38933
|
-
await
|
|
39086
|
+
const destPath = join51(ckDir, entry);
|
|
39087
|
+
await import_fs_extra16.copy(sourcePath, destPath, {
|
|
38934
39088
|
overwrite: false,
|
|
38935
39089
|
errorOnExist: true
|
|
38936
39090
|
});
|
|
@@ -38939,15 +39093,15 @@ async function applyPrefix(extractDir) {
|
|
|
38939
39093
|
}
|
|
38940
39094
|
if (processedCount === 0) {
|
|
38941
39095
|
logger.warning("No files to move (all were symlinks or invalid)");
|
|
38942
|
-
await
|
|
38943
|
-
await
|
|
39096
|
+
await import_fs_extra16.remove(backupDir);
|
|
39097
|
+
await import_fs_extra16.remove(tempDir);
|
|
38944
39098
|
return;
|
|
38945
39099
|
}
|
|
38946
|
-
await
|
|
38947
|
-
await
|
|
38948
|
-
await
|
|
39100
|
+
await import_fs_extra16.remove(commandsDir);
|
|
39101
|
+
await import_fs_extra16.move(tempDir, commandsDir);
|
|
39102
|
+
await import_fs_extra16.remove(backupDir);
|
|
38949
39103
|
logger.success("Successfully reorganized commands to /ck: prefix");
|
|
38950
|
-
const claudeDir =
|
|
39104
|
+
const claudeDir = join51(extractDir, ".claude");
|
|
38951
39105
|
logger.info("Transforming command references in file contents...");
|
|
38952
39106
|
const transformResult = await transformCommandReferences(claudeDir, {
|
|
38953
39107
|
verbose: logger.isVerbose()
|
|
@@ -38958,46 +39112,46 @@ async function applyPrefix(extractDir) {
|
|
|
38958
39112
|
logger.verbose("No command references needed transformation");
|
|
38959
39113
|
}
|
|
38960
39114
|
} catch (error) {
|
|
38961
|
-
if (await
|
|
39115
|
+
if (await import_fs_extra16.pathExists(backupDir)) {
|
|
38962
39116
|
try {
|
|
38963
|
-
await
|
|
38964
|
-
await
|
|
39117
|
+
await import_fs_extra16.remove(commandsDir).catch(() => {});
|
|
39118
|
+
await import_fs_extra16.move(backupDir, commandsDir);
|
|
38965
39119
|
logger.info("Restored original commands directory from backup");
|
|
38966
39120
|
} catch (rollbackError) {
|
|
38967
39121
|
logger.error(`Rollback failed: ${rollbackError}`);
|
|
38968
39122
|
}
|
|
38969
39123
|
}
|
|
38970
|
-
if (await
|
|
38971
|
-
await
|
|
39124
|
+
if (await import_fs_extra16.pathExists(tempDir)) {
|
|
39125
|
+
await import_fs_extra16.remove(tempDir).catch(() => {});
|
|
38972
39126
|
}
|
|
38973
39127
|
logger.error("Failed to apply /ck: prefix to commands");
|
|
38974
39128
|
throw error;
|
|
38975
39129
|
} finally {
|
|
38976
|
-
if (await
|
|
38977
|
-
await
|
|
39130
|
+
if (await import_fs_extra16.pathExists(backupDir)) {
|
|
39131
|
+
await import_fs_extra16.remove(backupDir).catch(() => {});
|
|
38978
39132
|
}
|
|
38979
|
-
if (await
|
|
38980
|
-
await
|
|
39133
|
+
if (await import_fs_extra16.pathExists(tempDir)) {
|
|
39134
|
+
await import_fs_extra16.remove(tempDir).catch(() => {});
|
|
38981
39135
|
}
|
|
38982
39136
|
}
|
|
38983
39137
|
}
|
|
38984
39138
|
|
|
38985
39139
|
// src/services/transformers/commands-prefix/prefix-cleaner.ts
|
|
38986
39140
|
import { lstat as lstat7, readdir as readdir14 } from "node:fs/promises";
|
|
38987
|
-
import { join as
|
|
39141
|
+
import { join as join53 } from "node:path";
|
|
38988
39142
|
init_logger();
|
|
38989
|
-
var
|
|
39143
|
+
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
38990
39144
|
|
|
38991
39145
|
// src/services/transformers/commands-prefix/file-processor.ts
|
|
38992
39146
|
import { lstat as lstat6, readdir as readdir13 } from "node:fs/promises";
|
|
38993
|
-
import { join as
|
|
39147
|
+
import { join as join52 } from "node:path";
|
|
38994
39148
|
init_logger();
|
|
38995
|
-
var
|
|
39149
|
+
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
38996
39150
|
async function scanDirectoryFiles(dir) {
|
|
38997
39151
|
const files = [];
|
|
38998
39152
|
const entries = await readdir13(dir);
|
|
38999
39153
|
for (const entry of entries) {
|
|
39000
|
-
const fullPath =
|
|
39154
|
+
const fullPath = join52(dir, entry);
|
|
39001
39155
|
const stats = await lstat6(fullPath);
|
|
39002
39156
|
if (stats.isSymbolicLink()) {
|
|
39003
39157
|
continue;
|
|
@@ -39020,7 +39174,7 @@ async function processFileOwnership(file, relativePath, metadata, claudeDir, opt
|
|
|
39020
39174
|
action: "delete"
|
|
39021
39175
|
});
|
|
39022
39176
|
if (!dryRun) {
|
|
39023
|
-
await
|
|
39177
|
+
await import_fs_extra17.remove(file);
|
|
39024
39178
|
logger.verbose(`Deleted CK file: ${relativePath}`);
|
|
39025
39179
|
}
|
|
39026
39180
|
accumulator.deletedCount++;
|
|
@@ -39035,7 +39189,7 @@ async function processFileOwnership(file, relativePath, metadata, claudeDir, opt
|
|
|
39035
39189
|
reason: "force overwrite"
|
|
39036
39190
|
});
|
|
39037
39191
|
if (!dryRun) {
|
|
39038
|
-
await
|
|
39192
|
+
await import_fs_extra17.remove(file);
|
|
39039
39193
|
logger.verbose(`Force-deleted modified file: ${relativePath}`);
|
|
39040
39194
|
}
|
|
39041
39195
|
accumulator.deletedCount++;
|
|
@@ -39059,7 +39213,7 @@ async function processFileOwnership(file, relativePath, metadata, claudeDir, opt
|
|
|
39059
39213
|
reason: "force overwrite"
|
|
39060
39214
|
});
|
|
39061
39215
|
if (!dryRun) {
|
|
39062
|
-
await
|
|
39216
|
+
await import_fs_extra17.remove(file);
|
|
39063
39217
|
logger.verbose(`Force-deleted user file: ${relativePath}`);
|
|
39064
39218
|
}
|
|
39065
39219
|
accumulator.deletedCount++;
|
|
@@ -39105,8 +39259,8 @@ function logCleanupSummary(deletedCount, preservedCount, dryRun, results) {
|
|
|
39105
39259
|
async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
39106
39260
|
const { dryRun = false } = options;
|
|
39107
39261
|
validatePath(targetDir, "targetDir");
|
|
39108
|
-
const claudeDir = isGlobal ? targetDir :
|
|
39109
|
-
const commandsDir =
|
|
39262
|
+
const claudeDir = isGlobal ? targetDir : join53(targetDir, ".claude");
|
|
39263
|
+
const commandsDir = join53(claudeDir, "commands");
|
|
39110
39264
|
const accumulator = {
|
|
39111
39265
|
results: [],
|
|
39112
39266
|
deletedCount: 0,
|
|
@@ -39118,7 +39272,7 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
|
39118
39272
|
preservedCount: 0,
|
|
39119
39273
|
wasDryRun: dryRun
|
|
39120
39274
|
};
|
|
39121
|
-
if (!await
|
|
39275
|
+
if (!await import_fs_extra18.pathExists(commandsDir)) {
|
|
39122
39276
|
logger.verbose(`Commands directory does not exist: ${commandsDir}`);
|
|
39123
39277
|
return result;
|
|
39124
39278
|
}
|
|
@@ -39140,7 +39294,7 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
|
39140
39294
|
return result;
|
|
39141
39295
|
}
|
|
39142
39296
|
for (const entry of entries) {
|
|
39143
|
-
const entryPath =
|
|
39297
|
+
const entryPath = join53(commandsDir, entry);
|
|
39144
39298
|
const stats = await lstat7(entryPath);
|
|
39145
39299
|
if (stats.isSymbolicLink()) {
|
|
39146
39300
|
addSymlinkSkip(entry, accumulator);
|
|
@@ -39169,7 +39323,7 @@ async function processDirectory(entryPath, entry, claudeDir, metadata, options,
|
|
|
39169
39323
|
}
|
|
39170
39324
|
}
|
|
39171
39325
|
if (canDeleteDir && !dryRun) {
|
|
39172
|
-
await
|
|
39326
|
+
await import_fs_extra18.remove(entryPath);
|
|
39173
39327
|
logger.verbose(`Removed directory: ${entry}`);
|
|
39174
39328
|
}
|
|
39175
39329
|
}
|
|
@@ -39184,7 +39338,7 @@ class CommandsPrefix {
|
|
|
39184
39338
|
// src/commands/init/phases/merge-handler.ts
|
|
39185
39339
|
init_logger();
|
|
39186
39340
|
init_output_manager();
|
|
39187
|
-
var
|
|
39341
|
+
var import_fs_extra19 = __toESM(require_lib(), 1);
|
|
39188
39342
|
async function handleMerge(ctx) {
|
|
39189
39343
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir || !ctx.claudeDir || !ctx.kit || !ctx.kitType) {
|
|
39190
39344
|
return ctx;
|
|
@@ -39193,7 +39347,7 @@ async function handleMerge(ctx) {
|
|
|
39193
39347
|
let customClaudeFiles = [];
|
|
39194
39348
|
if (!ctx.options.fresh) {
|
|
39195
39349
|
logger.info("Scanning for custom .claude files...");
|
|
39196
|
-
const scanSourceDir = ctx.options.global ?
|
|
39350
|
+
const scanSourceDir = ctx.options.global ? join54(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
39197
39351
|
const scanTargetSubdir = ctx.options.global ? "" : ".claude";
|
|
39198
39352
|
customClaudeFiles = await FileScanner2.findCustomFiles(ctx.resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
39199
39353
|
} else {
|
|
@@ -39237,7 +39391,7 @@ async function handleMerge(ctx) {
|
|
|
39237
39391
|
if (releaseManifest) {
|
|
39238
39392
|
merger.setManifest(releaseManifest);
|
|
39239
39393
|
}
|
|
39240
|
-
if (!ctx.options.fresh && await
|
|
39394
|
+
if (!ctx.options.fresh && await import_fs_extra19.pathExists(ctx.claudeDir)) {
|
|
39241
39395
|
const legacyDetection = await LegacyMigration.detectLegacy(ctx.claudeDir);
|
|
39242
39396
|
if (legacyDetection.isLegacy && releaseManifest) {
|
|
39243
39397
|
logger.info("Legacy installation detected - migrating to ownership tracking...");
|
|
@@ -39257,13 +39411,34 @@ async function handleMerge(ctx) {
|
|
|
39257
39411
|
return { ...ctx, cancelled: true };
|
|
39258
39412
|
}
|
|
39259
39413
|
}
|
|
39260
|
-
const sourceDir = ctx.options.global ?
|
|
39414
|
+
const sourceDir = ctx.options.global ? join54(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
39261
39415
|
await merger.merge(sourceDir, ctx.resolvedDir, ctx.isNonInteractive);
|
|
39262
39416
|
const fileConflicts = merger.getFileConflicts();
|
|
39263
39417
|
if (fileConflicts.length > 0 && !ctx.isNonInteractive) {
|
|
39264
39418
|
const summary = buildConflictSummary(fileConflicts, [], []);
|
|
39265
39419
|
displayConflictSummary(summary);
|
|
39266
39420
|
}
|
|
39421
|
+
try {
|
|
39422
|
+
const sourceMetadataPath = join54(sourceDir, "metadata.json");
|
|
39423
|
+
if (await import_fs_extra19.pathExists(sourceMetadataPath)) {
|
|
39424
|
+
const metadataContent = await import_fs_extra19.readFile(sourceMetadataPath, "utf-8");
|
|
39425
|
+
const sourceMetadata = JSON.parse(metadataContent);
|
|
39426
|
+
if (sourceMetadata.deletions && sourceMetadata.deletions.length > 0) {
|
|
39427
|
+
const deletionResult = await handleDeletions(sourceMetadata, ctx.claudeDir);
|
|
39428
|
+
if (deletionResult.deletedPaths.length > 0) {
|
|
39429
|
+
logger.info(`Removed ${deletionResult.deletedPaths.length} deprecated file(s)`);
|
|
39430
|
+
for (const path11 of deletionResult.deletedPaths) {
|
|
39431
|
+
logger.verbose(` - ${path11}`);
|
|
39432
|
+
}
|
|
39433
|
+
}
|
|
39434
|
+
if (deletionResult.preservedPaths.length > 0) {
|
|
39435
|
+
logger.verbose(`Preserved ${deletionResult.preservedPaths.length} user-owned file(s)`);
|
|
39436
|
+
}
|
|
39437
|
+
}
|
|
39438
|
+
}
|
|
39439
|
+
} catch (error) {
|
|
39440
|
+
logger.debug(`Cleanup of deprecated files failed: ${error}`);
|
|
39441
|
+
}
|
|
39267
39442
|
const installedFiles = merger.getAllInstalledFiles();
|
|
39268
39443
|
const filesToTrack = buildFileTrackingList({
|
|
39269
39444
|
installedFiles,
|
|
@@ -39286,11 +39461,11 @@ async function handleMerge(ctx) {
|
|
|
39286
39461
|
};
|
|
39287
39462
|
}
|
|
39288
39463
|
// src/commands/init/phases/migration-handler.ts
|
|
39289
|
-
import { join as
|
|
39464
|
+
import { join as join62 } from "node:path";
|
|
39290
39465
|
|
|
39291
39466
|
// src/domains/skills/skills-detector.ts
|
|
39292
39467
|
init_logger();
|
|
39293
|
-
var
|
|
39468
|
+
var import_fs_extra22 = __toESM(require_lib(), 1);
|
|
39294
39469
|
|
|
39295
39470
|
// src/domains/skills/detection/config-detector.ts
|
|
39296
39471
|
init_logger();
|
|
@@ -39298,17 +39473,17 @@ init_logger();
|
|
|
39298
39473
|
// src/domains/skills/skills-manifest.ts
|
|
39299
39474
|
init_logger();
|
|
39300
39475
|
import { createHash as createHash2 } from "node:crypto";
|
|
39301
|
-
import { readFile as
|
|
39302
|
-
import { join as
|
|
39476
|
+
import { readFile as readFile21, readdir as readdir15, writeFile as writeFile17 } from "node:fs/promises";
|
|
39477
|
+
import { join as join55, relative as relative9 } from "node:path";
|
|
39303
39478
|
init_types2();
|
|
39304
|
-
var
|
|
39479
|
+
var import_fs_extra20 = __toESM(require_lib(), 1);
|
|
39305
39480
|
|
|
39306
39481
|
class SkillsManifestManager {
|
|
39307
39482
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
39308
39483
|
static MANIFEST_VERSION = "1.0.0";
|
|
39309
39484
|
static async generateManifest(skillsDir) {
|
|
39310
39485
|
logger.debug(`Generating manifest for: ${skillsDir}`);
|
|
39311
|
-
if (!await
|
|
39486
|
+
if (!await import_fs_extra20.pathExists(skillsDir)) {
|
|
39312
39487
|
throw new SkillsMigrationError(`Skills directory does not exist: ${skillsDir}`);
|
|
39313
39488
|
}
|
|
39314
39489
|
const structure = await SkillsManifestManager.detectStructure(skillsDir);
|
|
@@ -39323,18 +39498,18 @@ class SkillsManifestManager {
|
|
|
39323
39498
|
return manifest;
|
|
39324
39499
|
}
|
|
39325
39500
|
static async writeManifest(skillsDir, manifest) {
|
|
39326
|
-
const manifestPath =
|
|
39327
|
-
await
|
|
39501
|
+
const manifestPath = join55(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
39502
|
+
await writeFile17(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
39328
39503
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
39329
39504
|
}
|
|
39330
39505
|
static async readManifest(skillsDir) {
|
|
39331
|
-
const manifestPath =
|
|
39332
|
-
if (!await
|
|
39506
|
+
const manifestPath = join55(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
39507
|
+
if (!await import_fs_extra20.pathExists(manifestPath)) {
|
|
39333
39508
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
39334
39509
|
return null;
|
|
39335
39510
|
}
|
|
39336
39511
|
try {
|
|
39337
|
-
const content = await
|
|
39512
|
+
const content = await readFile21(manifestPath, "utf-8");
|
|
39338
39513
|
const data = JSON.parse(content);
|
|
39339
39514
|
const manifest = SkillsManifestSchema.parse(data);
|
|
39340
39515
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -39351,7 +39526,7 @@ class SkillsManifestManager {
|
|
|
39351
39526
|
return "flat";
|
|
39352
39527
|
}
|
|
39353
39528
|
for (const dir of dirs.slice(0, 3)) {
|
|
39354
|
-
const dirPath =
|
|
39529
|
+
const dirPath = join55(skillsDir, dir.name);
|
|
39355
39530
|
const subEntries = await readdir15(dirPath, { withFileTypes: true });
|
|
39356
39531
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
39357
39532
|
if (hasSubdirs) {
|
|
@@ -39370,7 +39545,7 @@ class SkillsManifestManager {
|
|
|
39370
39545
|
const entries = await readdir15(skillsDir, { withFileTypes: true });
|
|
39371
39546
|
for (const entry of entries) {
|
|
39372
39547
|
if (entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith(".")) {
|
|
39373
|
-
const skillPath =
|
|
39548
|
+
const skillPath = join55(skillsDir, entry.name);
|
|
39374
39549
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
39375
39550
|
skills.push({
|
|
39376
39551
|
name: entry.name,
|
|
@@ -39382,11 +39557,11 @@ class SkillsManifestManager {
|
|
|
39382
39557
|
const categories = await readdir15(skillsDir, { withFileTypes: true });
|
|
39383
39558
|
for (const category of categories) {
|
|
39384
39559
|
if (category.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(category.name) && !category.name.startsWith(".")) {
|
|
39385
|
-
const categoryPath =
|
|
39560
|
+
const categoryPath = join55(skillsDir, category.name);
|
|
39386
39561
|
const skillEntries = await readdir15(categoryPath, { withFileTypes: true });
|
|
39387
39562
|
for (const skillEntry of skillEntries) {
|
|
39388
39563
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
39389
|
-
const skillPath =
|
|
39564
|
+
const skillPath = join55(categoryPath, skillEntry.name);
|
|
39390
39565
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
39391
39566
|
skills.push({
|
|
39392
39567
|
name: skillEntry.name,
|
|
@@ -39406,7 +39581,7 @@ class SkillsManifestManager {
|
|
|
39406
39581
|
files.sort();
|
|
39407
39582
|
for (const file of files) {
|
|
39408
39583
|
const relativePath = relative9(dirPath, file);
|
|
39409
|
-
const content = await
|
|
39584
|
+
const content = await readFile21(file);
|
|
39410
39585
|
hash.update(relativePath);
|
|
39411
39586
|
hash.update(content);
|
|
39412
39587
|
}
|
|
@@ -39416,7 +39591,7 @@ class SkillsManifestManager {
|
|
|
39416
39591
|
const files = [];
|
|
39417
39592
|
const entries = await readdir15(dirPath, { withFileTypes: true });
|
|
39418
39593
|
for (const entry of entries) {
|
|
39419
|
-
const fullPath =
|
|
39594
|
+
const fullPath = join55(dirPath, entry.name);
|
|
39420
39595
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name)) {
|
|
39421
39596
|
continue;
|
|
39422
39597
|
}
|
|
@@ -39536,11 +39711,11 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
39536
39711
|
}
|
|
39537
39712
|
|
|
39538
39713
|
// src/domains/skills/detection/script-detector.ts
|
|
39539
|
-
var
|
|
39714
|
+
var import_fs_extra21 = __toESM(require_lib(), 1);
|
|
39540
39715
|
import { readdir as readdir16 } from "node:fs/promises";
|
|
39541
|
-
import { join as
|
|
39716
|
+
import { join as join56 } from "node:path";
|
|
39542
39717
|
async function scanDirectory(skillsDir) {
|
|
39543
|
-
if (!await
|
|
39718
|
+
if (!await import_fs_extra21.pathExists(skillsDir)) {
|
|
39544
39719
|
return ["flat", []];
|
|
39545
39720
|
}
|
|
39546
39721
|
const entries = await readdir16(skillsDir, { withFileTypes: true });
|
|
@@ -39551,12 +39726,12 @@ async function scanDirectory(skillsDir) {
|
|
|
39551
39726
|
let totalSkillLikeCount = 0;
|
|
39552
39727
|
const allSkills = [];
|
|
39553
39728
|
for (const dir of dirs) {
|
|
39554
|
-
const dirPath =
|
|
39729
|
+
const dirPath = join56(skillsDir, dir.name);
|
|
39555
39730
|
const subEntries = await readdir16(dirPath, { withFileTypes: true });
|
|
39556
39731
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
39557
39732
|
if (subdirs.length > 0) {
|
|
39558
39733
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
39559
|
-
const subdirPath =
|
|
39734
|
+
const subdirPath = join56(dirPath, subdir.name);
|
|
39560
39735
|
const subdirFiles = await readdir16(subdirPath, { withFileTypes: true });
|
|
39561
39736
|
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"));
|
|
39562
39737
|
if (hasSkillMarker) {
|
|
@@ -39678,8 +39853,8 @@ async function detectViaManifest(oldSkillsDir, currentSkillsDir) {
|
|
|
39678
39853
|
class SkillsMigrationDetector {
|
|
39679
39854
|
static async detectMigration(oldSkillsDir, currentSkillsDir) {
|
|
39680
39855
|
logger.debug("Detecting skills migration need...");
|
|
39681
|
-
const oldExists = await
|
|
39682
|
-
const currentExists = await
|
|
39856
|
+
const oldExists = await import_fs_extra22.pathExists(oldSkillsDir);
|
|
39857
|
+
const currentExists = await import_fs_extra22.pathExists(currentSkillsDir);
|
|
39683
39858
|
if (!oldExists && !currentExists) {
|
|
39684
39859
|
logger.debug("No skills directories found, migration not needed");
|
|
39685
39860
|
return {
|
|
@@ -39713,13 +39888,13 @@ class SkillsMigrationDetector {
|
|
|
39713
39888
|
// src/domains/skills/skills-migrator.ts
|
|
39714
39889
|
init_logger();
|
|
39715
39890
|
init_types2();
|
|
39716
|
-
import { join as
|
|
39891
|
+
import { join as join61 } from "node:path";
|
|
39717
39892
|
|
|
39718
39893
|
// src/domains/skills/migrator/migration-executor.ts
|
|
39719
39894
|
init_logger();
|
|
39720
39895
|
import { copyFile as copyFile4, mkdir as mkdir17, readdir as readdir17, rm as rm3 } from "node:fs/promises";
|
|
39721
|
-
import { join as
|
|
39722
|
-
var
|
|
39896
|
+
import { join as join57 } from "node:path";
|
|
39897
|
+
var import_fs_extra23 = __toESM(require_lib(), 1);
|
|
39723
39898
|
|
|
39724
39899
|
// src/domains/skills/skills-migration-prompts.ts
|
|
39725
39900
|
init_environment();
|
|
@@ -39883,8 +40058,8 @@ async function copySkillDirectory(sourceDir, destDir) {
|
|
|
39883
40058
|
await mkdir17(destDir, { recursive: true });
|
|
39884
40059
|
const entries = await readdir17(sourceDir, { withFileTypes: true });
|
|
39885
40060
|
for (const entry of entries) {
|
|
39886
|
-
const sourcePath =
|
|
39887
|
-
const destPath =
|
|
40061
|
+
const sourcePath = join57(sourceDir, entry.name);
|
|
40062
|
+
const destPath = join57(destDir, entry.name);
|
|
39888
40063
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
39889
40064
|
continue;
|
|
39890
40065
|
}
|
|
@@ -39899,14 +40074,14 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
39899
40074
|
const migrated = [];
|
|
39900
40075
|
const preserved = [];
|
|
39901
40076
|
const errors2 = [];
|
|
39902
|
-
const tempDir =
|
|
40077
|
+
const tempDir = join57(currentSkillsDir, "..", ".skills-migration-temp");
|
|
39903
40078
|
await mkdir17(tempDir, { recursive: true });
|
|
39904
40079
|
try {
|
|
39905
40080
|
for (const mapping of mappings) {
|
|
39906
40081
|
try {
|
|
39907
40082
|
const skillName = mapping.skillName;
|
|
39908
40083
|
const currentSkillPath = mapping.oldPath;
|
|
39909
|
-
if (!await
|
|
40084
|
+
if (!await import_fs_extra23.pathExists(currentSkillPath)) {
|
|
39910
40085
|
logger.warning(`Skill not found, skipping: ${skillName}`);
|
|
39911
40086
|
continue;
|
|
39912
40087
|
}
|
|
@@ -39920,9 +40095,9 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
39920
40095
|
}
|
|
39921
40096
|
}
|
|
39922
40097
|
const category = mapping.category;
|
|
39923
|
-
const targetPath = category ?
|
|
40098
|
+
const targetPath = category ? join57(tempDir, category, skillName) : join57(tempDir, skillName);
|
|
39924
40099
|
if (category) {
|
|
39925
|
-
await mkdir17(
|
|
40100
|
+
await mkdir17(join57(tempDir, category), { recursive: true });
|
|
39926
40101
|
}
|
|
39927
40102
|
await copySkillDirectory(currentSkillPath, targetPath);
|
|
39928
40103
|
migrated.push(skillName);
|
|
@@ -39987,9 +40162,9 @@ function validateMigrationPath(path11, paramName) {
|
|
|
39987
40162
|
// src/domains/skills/skills-backup-manager.ts
|
|
39988
40163
|
init_logger();
|
|
39989
40164
|
init_types2();
|
|
39990
|
-
var
|
|
40165
|
+
var import_fs_extra24 = __toESM(require_lib(), 1);
|
|
39991
40166
|
import { copyFile as copyFile5, mkdir as mkdir18, readdir as readdir18, rm as rm4, stat as stat9 } from "node:fs/promises";
|
|
39992
|
-
import { basename as basename2, join as
|
|
40167
|
+
import { basename as basename2, join as join58, normalize as normalize6 } from "node:path";
|
|
39993
40168
|
function validatePath2(path11, paramName) {
|
|
39994
40169
|
if (!path11 || typeof path11 !== "string") {
|
|
39995
40170
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -40009,13 +40184,13 @@ class SkillsBackupManager {
|
|
|
40009
40184
|
if (parentDir) {
|
|
40010
40185
|
validatePath2(parentDir, "parentDir");
|
|
40011
40186
|
}
|
|
40012
|
-
if (!await
|
|
40187
|
+
if (!await import_fs_extra24.pathExists(skillsDir)) {
|
|
40013
40188
|
throw new SkillsMigrationError(`Cannot create backup: Skills directory does not exist: ${skillsDir}`);
|
|
40014
40189
|
}
|
|
40015
40190
|
const timestamp = Date.now();
|
|
40016
40191
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
40017
40192
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
40018
|
-
const backupDir = parentDir ?
|
|
40193
|
+
const backupDir = parentDir ? join58(parentDir, backupDirName) : join58(skillsDir, "..", backupDirName);
|
|
40019
40194
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
40020
40195
|
try {
|
|
40021
40196
|
await mkdir18(backupDir, { recursive: true });
|
|
@@ -40032,12 +40207,12 @@ class SkillsBackupManager {
|
|
|
40032
40207
|
static async restoreBackup(backupDir, targetDir) {
|
|
40033
40208
|
validatePath2(backupDir, "backupDir");
|
|
40034
40209
|
validatePath2(targetDir, "targetDir");
|
|
40035
|
-
if (!await
|
|
40210
|
+
if (!await import_fs_extra24.pathExists(backupDir)) {
|
|
40036
40211
|
throw new SkillsMigrationError(`Cannot restore: Backup directory does not exist: ${backupDir}`);
|
|
40037
40212
|
}
|
|
40038
40213
|
logger.info(`Restoring from backup: ${backupDir}`);
|
|
40039
40214
|
try {
|
|
40040
|
-
if (await
|
|
40215
|
+
if (await import_fs_extra24.pathExists(targetDir)) {
|
|
40041
40216
|
await rm4(targetDir, { recursive: true, force: true });
|
|
40042
40217
|
}
|
|
40043
40218
|
await mkdir18(targetDir, { recursive: true });
|
|
@@ -40048,7 +40223,7 @@ class SkillsBackupManager {
|
|
|
40048
40223
|
}
|
|
40049
40224
|
}
|
|
40050
40225
|
static async deleteBackup(backupDir) {
|
|
40051
|
-
if (!await
|
|
40226
|
+
if (!await import_fs_extra24.pathExists(backupDir)) {
|
|
40052
40227
|
logger.warning(`Backup directory does not exist: ${backupDir}`);
|
|
40053
40228
|
return;
|
|
40054
40229
|
}
|
|
@@ -40061,12 +40236,12 @@ class SkillsBackupManager {
|
|
|
40061
40236
|
}
|
|
40062
40237
|
}
|
|
40063
40238
|
static async listBackups(parentDir) {
|
|
40064
|
-
if (!await
|
|
40239
|
+
if (!await import_fs_extra24.pathExists(parentDir)) {
|
|
40065
40240
|
return [];
|
|
40066
40241
|
}
|
|
40067
40242
|
try {
|
|
40068
40243
|
const entries = await readdir18(parentDir, { withFileTypes: true });
|
|
40069
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
40244
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join58(parentDir, entry.name));
|
|
40070
40245
|
backups.sort().reverse();
|
|
40071
40246
|
return backups;
|
|
40072
40247
|
} catch (error) {
|
|
@@ -40086,7 +40261,7 @@ class SkillsBackupManager {
|
|
|
40086
40261
|
}
|
|
40087
40262
|
}
|
|
40088
40263
|
static async getBackupSize(backupDir) {
|
|
40089
|
-
if (!await
|
|
40264
|
+
if (!await import_fs_extra24.pathExists(backupDir)) {
|
|
40090
40265
|
return 0;
|
|
40091
40266
|
}
|
|
40092
40267
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
@@ -40094,8 +40269,8 @@ class SkillsBackupManager {
|
|
|
40094
40269
|
static async copyDirectory(sourceDir, destDir) {
|
|
40095
40270
|
const entries = await readdir18(sourceDir, { withFileTypes: true });
|
|
40096
40271
|
for (const entry of entries) {
|
|
40097
|
-
const sourcePath =
|
|
40098
|
-
const destPath =
|
|
40272
|
+
const sourcePath = join58(sourceDir, entry.name);
|
|
40273
|
+
const destPath = join58(destDir, entry.name);
|
|
40099
40274
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
40100
40275
|
continue;
|
|
40101
40276
|
}
|
|
@@ -40111,7 +40286,7 @@ class SkillsBackupManager {
|
|
|
40111
40286
|
let size = 0;
|
|
40112
40287
|
const entries = await readdir18(dirPath, { withFileTypes: true });
|
|
40113
40288
|
for (const entry of entries) {
|
|
40114
|
-
const fullPath =
|
|
40289
|
+
const fullPath = join58(dirPath, entry.name);
|
|
40115
40290
|
if (entry.isSymbolicLink()) {
|
|
40116
40291
|
continue;
|
|
40117
40292
|
}
|
|
@@ -40139,19 +40314,19 @@ class SkillsBackupManager {
|
|
|
40139
40314
|
init_logger();
|
|
40140
40315
|
|
|
40141
40316
|
// src/domains/skills/customization/comparison-engine.ts
|
|
40142
|
-
var
|
|
40317
|
+
var import_fs_extra25 = __toESM(require_lib(), 1);
|
|
40143
40318
|
import { relative as relative11 } from "node:path";
|
|
40144
40319
|
|
|
40145
40320
|
// src/domains/skills/customization/hash-calculator.ts
|
|
40146
40321
|
import { createHash as createHash3 } from "node:crypto";
|
|
40147
40322
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
40148
|
-
import { readFile as
|
|
40149
|
-
import { join as
|
|
40323
|
+
import { readFile as readFile22, readdir as readdir19 } from "node:fs/promises";
|
|
40324
|
+
import { join as join59, relative as relative10 } from "node:path";
|
|
40150
40325
|
async function getAllFiles(dirPath) {
|
|
40151
40326
|
const files = [];
|
|
40152
40327
|
const entries = await readdir19(dirPath, { withFileTypes: true });
|
|
40153
40328
|
for (const entry of entries) {
|
|
40154
|
-
const fullPath =
|
|
40329
|
+
const fullPath = join59(dirPath, entry.name);
|
|
40155
40330
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name) || entry.isSymbolicLink()) {
|
|
40156
40331
|
continue;
|
|
40157
40332
|
}
|
|
@@ -40165,12 +40340,12 @@ async function getAllFiles(dirPath) {
|
|
|
40165
40340
|
return files;
|
|
40166
40341
|
}
|
|
40167
40342
|
async function hashFile(filePath) {
|
|
40168
|
-
return new Promise((
|
|
40343
|
+
return new Promise((resolve8, reject) => {
|
|
40169
40344
|
const hash = createHash3("sha256");
|
|
40170
40345
|
const stream = createReadStream2(filePath);
|
|
40171
40346
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
40172
40347
|
stream.on("end", () => {
|
|
40173
|
-
|
|
40348
|
+
resolve8(hash.digest("hex"));
|
|
40174
40349
|
});
|
|
40175
40350
|
stream.on("error", (error) => {
|
|
40176
40351
|
stream.destroy();
|
|
@@ -40184,7 +40359,7 @@ async function hashDirectory(dirPath) {
|
|
|
40184
40359
|
files.sort();
|
|
40185
40360
|
for (const file of files) {
|
|
40186
40361
|
const relativePath = relative10(dirPath, file);
|
|
40187
|
-
const content = await
|
|
40362
|
+
const content = await readFile22(file);
|
|
40188
40363
|
hash.update(relativePath);
|
|
40189
40364
|
hash.update(content);
|
|
40190
40365
|
}
|
|
@@ -40234,7 +40409,7 @@ async function compareDirectories(dir1, dir2) {
|
|
|
40234
40409
|
async function detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
40235
40410
|
const changes = [];
|
|
40236
40411
|
const currentFiles = await getAllFiles(currentSkillPath);
|
|
40237
|
-
const baselineFiles = await
|
|
40412
|
+
const baselineFiles = await import_fs_extra25.pathExists(baselineSkillPath) ? await getAllFiles(baselineSkillPath) : [];
|
|
40238
40413
|
const currentFileMap = new Map(await Promise.all(currentFiles.map(async (f3) => {
|
|
40239
40414
|
const relPath = relative11(currentSkillPath, f3);
|
|
40240
40415
|
const hash = await hashFile(f3);
|
|
@@ -40276,9 +40451,9 @@ async function detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
|
40276
40451
|
|
|
40277
40452
|
// src/domains/skills/customization/scan-reporter.ts
|
|
40278
40453
|
init_types2();
|
|
40279
|
-
var
|
|
40454
|
+
var import_fs_extra26 = __toESM(require_lib(), 1);
|
|
40280
40455
|
import { readdir as readdir20 } from "node:fs/promises";
|
|
40281
|
-
import { join as
|
|
40456
|
+
import { join as join60, normalize as normalize7 } from "node:path";
|
|
40282
40457
|
function validatePath3(path11, paramName) {
|
|
40283
40458
|
if (!path11 || typeof path11 !== "string") {
|
|
40284
40459
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -40291,7 +40466,7 @@ function validatePath3(path11, paramName) {
|
|
|
40291
40466
|
}
|
|
40292
40467
|
}
|
|
40293
40468
|
async function scanSkillsDirectory(skillsDir) {
|
|
40294
|
-
if (!await
|
|
40469
|
+
if (!await import_fs_extra26.pathExists(skillsDir)) {
|
|
40295
40470
|
return ["flat", []];
|
|
40296
40471
|
}
|
|
40297
40472
|
const entries = await readdir20(skillsDir, { withFileTypes: true });
|
|
@@ -40299,13 +40474,13 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
40299
40474
|
if (dirs.length === 0) {
|
|
40300
40475
|
return ["flat", []];
|
|
40301
40476
|
}
|
|
40302
|
-
const firstDirPath =
|
|
40477
|
+
const firstDirPath = join60(skillsDir, dirs[0].name);
|
|
40303
40478
|
const subEntries = await readdir20(firstDirPath, { withFileTypes: true });
|
|
40304
40479
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
40305
40480
|
if (subdirs.length > 0) {
|
|
40306
40481
|
let skillLikeCount = 0;
|
|
40307
40482
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
40308
|
-
const subdirPath =
|
|
40483
|
+
const subdirPath = join60(firstDirPath, subdir.name);
|
|
40309
40484
|
const subdirFiles = await readdir20(subdirPath, { withFileTypes: true });
|
|
40310
40485
|
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"));
|
|
40311
40486
|
if (hasSkillMarker) {
|
|
@@ -40315,7 +40490,7 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
40315
40490
|
if (skillLikeCount > 0) {
|
|
40316
40491
|
const skills = [];
|
|
40317
40492
|
for (const dir of dirs) {
|
|
40318
|
-
const categoryPath =
|
|
40493
|
+
const categoryPath = join60(skillsDir, dir.name);
|
|
40319
40494
|
const skillDirs = await readdir20(categoryPath, { withFileTypes: true });
|
|
40320
40495
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
40321
40496
|
}
|
|
@@ -40325,8 +40500,8 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
40325
40500
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
40326
40501
|
}
|
|
40327
40502
|
async function findSkillPath(skillsDir, skillName) {
|
|
40328
|
-
const flatPath =
|
|
40329
|
-
if (await
|
|
40503
|
+
const flatPath = join60(skillsDir, skillName);
|
|
40504
|
+
if (await import_fs_extra26.pathExists(flatPath)) {
|
|
40330
40505
|
return { path: flatPath, category: undefined };
|
|
40331
40506
|
}
|
|
40332
40507
|
const entries = await readdir20(skillsDir, { withFileTypes: true });
|
|
@@ -40334,9 +40509,9 @@ async function findSkillPath(skillsDir, skillName) {
|
|
|
40334
40509
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
40335
40510
|
continue;
|
|
40336
40511
|
}
|
|
40337
|
-
const categoryPath =
|
|
40338
|
-
const skillPath =
|
|
40339
|
-
if (await
|
|
40512
|
+
const categoryPath = join60(skillsDir, entry.name);
|
|
40513
|
+
const skillPath = join60(categoryPath, skillName);
|
|
40514
|
+
if (await import_fs_extra26.pathExists(skillPath)) {
|
|
40340
40515
|
return { path: skillPath, category: entry.name };
|
|
40341
40516
|
}
|
|
40342
40517
|
}
|
|
@@ -40429,7 +40604,7 @@ class SkillsMigrator {
|
|
|
40429
40604
|
}
|
|
40430
40605
|
}
|
|
40431
40606
|
if (options.backup && !options.dryRun) {
|
|
40432
|
-
const claudeDir =
|
|
40607
|
+
const claudeDir = join61(currentSkillsDir, "..");
|
|
40433
40608
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
40434
40609
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
40435
40610
|
}
|
|
@@ -40482,7 +40657,7 @@ class SkillsMigrator {
|
|
|
40482
40657
|
// src/commands/init/phases/migration-handler.ts
|
|
40483
40658
|
init_logger();
|
|
40484
40659
|
init_path_resolver();
|
|
40485
|
-
var
|
|
40660
|
+
var import_fs_extra27 = __toESM(require_lib(), 1);
|
|
40486
40661
|
async function handleMigration(ctx) {
|
|
40487
40662
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir)
|
|
40488
40663
|
return ctx;
|
|
@@ -40490,9 +40665,9 @@ async function handleMigration(ctx) {
|
|
|
40490
40665
|
logger.debug("Skipping skills migration (fresh installation)");
|
|
40491
40666
|
return ctx;
|
|
40492
40667
|
}
|
|
40493
|
-
const newSkillsDir =
|
|
40668
|
+
const newSkillsDir = join62(ctx.extractDir, ".claude", "skills");
|
|
40494
40669
|
const currentSkillsDir = PathResolver.buildSkillsPath(ctx.resolvedDir, ctx.options.global);
|
|
40495
|
-
if (!await
|
|
40670
|
+
if (!await import_fs_extra27.pathExists(newSkillsDir) || !await import_fs_extra27.pathExists(currentSkillsDir)) {
|
|
40496
40671
|
return ctx;
|
|
40497
40672
|
}
|
|
40498
40673
|
logger.info("Checking for skills directory migration...");
|
|
@@ -40514,13 +40689,13 @@ async function handleMigration(ctx) {
|
|
|
40514
40689
|
}
|
|
40515
40690
|
// src/commands/init/phases/opencode-handler.ts
|
|
40516
40691
|
import { cp, readdir as readdir22, rm as rm5 } from "node:fs/promises";
|
|
40517
|
-
import { join as
|
|
40692
|
+
import { join as join64 } from "node:path";
|
|
40518
40693
|
|
|
40519
40694
|
// src/services/transformers/opencode-path-transformer.ts
|
|
40520
40695
|
init_logger();
|
|
40521
|
-
import { readFile as
|
|
40696
|
+
import { readFile as readFile23, readdir as readdir21, writeFile as writeFile18 } from "node:fs/promises";
|
|
40522
40697
|
import { platform as platform10 } from "node:os";
|
|
40523
|
-
import { extname as extname2, join as
|
|
40698
|
+
import { extname as extname2, join as join63 } from "node:path";
|
|
40524
40699
|
var IS_WINDOWS3 = platform10() === "win32";
|
|
40525
40700
|
function getOpenCodeGlobalPath() {
|
|
40526
40701
|
return "$HOME/.config/opencode/";
|
|
@@ -40581,7 +40756,7 @@ async function transformPathsForGlobalOpenCode(directory, options = {}) {
|
|
|
40581
40756
|
async function processDirectory2(dir) {
|
|
40582
40757
|
const entries = await readdir21(dir, { withFileTypes: true });
|
|
40583
40758
|
for (const entry of entries) {
|
|
40584
|
-
const fullPath =
|
|
40759
|
+
const fullPath = join63(dir, entry.name);
|
|
40585
40760
|
if (entry.isDirectory()) {
|
|
40586
40761
|
if (entry.name === "node_modules" || entry.name.startsWith(".")) {
|
|
40587
40762
|
continue;
|
|
@@ -40589,10 +40764,10 @@ async function transformPathsForGlobalOpenCode(directory, options = {}) {
|
|
|
40589
40764
|
await processDirectory2(fullPath);
|
|
40590
40765
|
} else if (entry.isFile() && shouldTransformFile2(entry.name)) {
|
|
40591
40766
|
try {
|
|
40592
|
-
const content = await
|
|
40767
|
+
const content = await readFile23(fullPath, "utf-8");
|
|
40593
40768
|
const { transformed, changes } = transformOpenCodeContent(content);
|
|
40594
40769
|
if (changes > 0) {
|
|
40595
|
-
await
|
|
40770
|
+
await writeFile18(fullPath, transformed, "utf-8");
|
|
40596
40771
|
filesTransformed++;
|
|
40597
40772
|
totalChanges += changes;
|
|
40598
40773
|
if (options.verbose) {
|
|
@@ -40615,13 +40790,13 @@ async function transformPathsForGlobalOpenCode(directory, options = {}) {
|
|
|
40615
40790
|
// src/commands/init/phases/opencode-handler.ts
|
|
40616
40791
|
init_logger();
|
|
40617
40792
|
init_path_resolver();
|
|
40618
|
-
var
|
|
40793
|
+
var import_fs_extra28 = __toESM(require_lib(), 1);
|
|
40619
40794
|
async function handleOpenCode(ctx) {
|
|
40620
40795
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir) {
|
|
40621
40796
|
return ctx;
|
|
40622
40797
|
}
|
|
40623
|
-
const openCodeSource =
|
|
40624
|
-
if (!await
|
|
40798
|
+
const openCodeSource = join64(ctx.extractDir, ".opencode");
|
|
40799
|
+
if (!await import_fs_extra28.pathExists(openCodeSource)) {
|
|
40625
40800
|
logger.debug("No .opencode directory in archive, skipping");
|
|
40626
40801
|
return ctx;
|
|
40627
40802
|
}
|
|
@@ -40635,12 +40810,12 @@ async function handleOpenCode(ctx) {
|
|
|
40635
40810
|
if (transformResult.totalChanges > 0) {
|
|
40636
40811
|
logger.success(`Transformed ${transformResult.totalChanges} OpenCode path(s) in ${transformResult.filesTransformed} file(s)`);
|
|
40637
40812
|
}
|
|
40638
|
-
await
|
|
40813
|
+
await import_fs_extra28.ensureDir(targetDir);
|
|
40639
40814
|
const entries = await readdir22(openCodeSource, { withFileTypes: true });
|
|
40640
40815
|
for (const entry of entries) {
|
|
40641
|
-
const sourcePath =
|
|
40642
|
-
const targetPath =
|
|
40643
|
-
if (await
|
|
40816
|
+
const sourcePath = join64(openCodeSource, entry.name);
|
|
40817
|
+
const targetPath = join64(targetDir, entry.name);
|
|
40818
|
+
if (await import_fs_extra28.pathExists(targetPath)) {
|
|
40644
40819
|
if (!ctx.options.forceOverwrite) {
|
|
40645
40820
|
logger.verbose(`Skipping existing: ${entry.name}`);
|
|
40646
40821
|
continue;
|
|
@@ -40660,18 +40835,18 @@ async function handleOpenCode(ctx) {
|
|
|
40660
40835
|
init_logger();
|
|
40661
40836
|
init_path_resolver();
|
|
40662
40837
|
init_types2();
|
|
40663
|
-
import { existsSync as
|
|
40664
|
-
import { mkdir as mkdir19, readFile as
|
|
40838
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
40839
|
+
import { mkdir as mkdir19, readFile as readFile24, rename as rename2, rm as rm6, writeFile as writeFile19 } from "node:fs/promises";
|
|
40665
40840
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
40666
40841
|
import { platform as platform11 } from "node:os";
|
|
40667
|
-
import { join as
|
|
40842
|
+
import { join as join65 } from "node:path";
|
|
40668
40843
|
var PROJECT_CONFIG_FILE = ".ck.json";
|
|
40669
40844
|
|
|
40670
40845
|
class ConfigManager {
|
|
40671
40846
|
static config = null;
|
|
40672
40847
|
static globalFlag = false;
|
|
40673
40848
|
static getProjectConfigDir(projectDir, global3) {
|
|
40674
|
-
return global3 ? projectDir :
|
|
40849
|
+
return global3 ? projectDir : join65(projectDir, ".claude");
|
|
40675
40850
|
}
|
|
40676
40851
|
static setGlobalFlag(global3) {
|
|
40677
40852
|
ConfigManager.globalFlag = global3;
|
|
@@ -40686,8 +40861,8 @@ class ConfigManager {
|
|
|
40686
40861
|
}
|
|
40687
40862
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
40688
40863
|
try {
|
|
40689
|
-
if (
|
|
40690
|
-
const content = await
|
|
40864
|
+
if (existsSync19(configFile)) {
|
|
40865
|
+
const content = await readFile24(configFile, "utf-8");
|
|
40691
40866
|
const data = JSON.parse(content);
|
|
40692
40867
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
40693
40868
|
logger.debug(`Config loaded from ${configFile}`);
|
|
@@ -40704,13 +40879,13 @@ class ConfigManager {
|
|
|
40704
40879
|
const validConfig = ConfigSchema.parse(config);
|
|
40705
40880
|
const configDir = PathResolver.getConfigDir(ConfigManager.globalFlag);
|
|
40706
40881
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
40707
|
-
if (!
|
|
40882
|
+
if (!existsSync19(configDir)) {
|
|
40708
40883
|
await mkdir19(configDir, { recursive: true });
|
|
40709
40884
|
if (platform11() !== "win32") {
|
|
40710
40885
|
await chmod2(configDir, 448);
|
|
40711
40886
|
}
|
|
40712
40887
|
}
|
|
40713
|
-
await
|
|
40888
|
+
await writeFile19(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
40714
40889
|
if (platform11() !== "win32") {
|
|
40715
40890
|
await chmod2(configFile, 384);
|
|
40716
40891
|
}
|
|
@@ -40738,10 +40913,10 @@ class ConfigManager {
|
|
|
40738
40913
|
}
|
|
40739
40914
|
static async loadProjectConfig(projectDir, global3 = false) {
|
|
40740
40915
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
40741
|
-
const configPath =
|
|
40916
|
+
const configPath = join65(configDir, PROJECT_CONFIG_FILE);
|
|
40742
40917
|
try {
|
|
40743
|
-
if (
|
|
40744
|
-
const content = await
|
|
40918
|
+
if (existsSync19(configPath)) {
|
|
40919
|
+
const content = await readFile24(configPath, "utf-8");
|
|
40745
40920
|
const data = JSON.parse(content);
|
|
40746
40921
|
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
40747
40922
|
logger.debug(`Project config loaded from ${configPath}`);
|
|
@@ -40754,15 +40929,15 @@ class ConfigManager {
|
|
|
40754
40929
|
}
|
|
40755
40930
|
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
40756
40931
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
40757
|
-
const configPath =
|
|
40932
|
+
const configPath = join65(configDir, PROJECT_CONFIG_FILE);
|
|
40758
40933
|
try {
|
|
40759
|
-
if (!
|
|
40934
|
+
if (!existsSync19(configDir)) {
|
|
40760
40935
|
await mkdir19(configDir, { recursive: true });
|
|
40761
40936
|
}
|
|
40762
40937
|
let existingConfig = {};
|
|
40763
|
-
if (
|
|
40938
|
+
if (existsSync19(configPath)) {
|
|
40764
40939
|
try {
|
|
40765
|
-
const content = await
|
|
40940
|
+
const content = await readFile24(configPath, "utf-8");
|
|
40766
40941
|
existingConfig = JSON.parse(content);
|
|
40767
40942
|
} catch (error) {
|
|
40768
40943
|
logger.debug(`Could not parse existing config, starting fresh: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -40777,7 +40952,7 @@ class ConfigManager {
|
|
|
40777
40952
|
...validFolders
|
|
40778
40953
|
}
|
|
40779
40954
|
};
|
|
40780
|
-
await
|
|
40955
|
+
await writeFile19(configPath, JSON.stringify(mergedConfig, null, 2), "utf-8");
|
|
40781
40956
|
logger.debug(`Project config saved to ${configPath}`);
|
|
40782
40957
|
} catch (error) {
|
|
40783
40958
|
throw new Error(`Failed to save project config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -40803,21 +40978,21 @@ class ConfigManager {
|
|
|
40803
40978
|
}
|
|
40804
40979
|
static projectConfigExists(projectDir, global3 = false) {
|
|
40805
40980
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
40806
|
-
return
|
|
40981
|
+
return existsSync19(join65(configDir, PROJECT_CONFIG_FILE));
|
|
40807
40982
|
}
|
|
40808
40983
|
static async migrateNestedConfig(globalDir) {
|
|
40809
|
-
const correctPath =
|
|
40810
|
-
const incorrectPath =
|
|
40811
|
-
if (
|
|
40984
|
+
const correctPath = join65(globalDir, PROJECT_CONFIG_FILE);
|
|
40985
|
+
const incorrectPath = join65(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
40986
|
+
if (existsSync19(correctPath)) {
|
|
40812
40987
|
logger.debug("Config already exists at correct location, skipping migration");
|
|
40813
40988
|
return false;
|
|
40814
40989
|
}
|
|
40815
|
-
if (
|
|
40990
|
+
if (existsSync19(incorrectPath)) {
|
|
40816
40991
|
try {
|
|
40817
40992
|
logger.info("Migrating .ck.json from nested location to correct location...");
|
|
40818
40993
|
await rename2(incorrectPath, correctPath);
|
|
40819
40994
|
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
40820
|
-
const nestedClaudeDir =
|
|
40995
|
+
const nestedClaudeDir = join65(globalDir, ".claude");
|
|
40821
40996
|
try {
|
|
40822
40997
|
await rm6(nestedClaudeDir, { recursive: false });
|
|
40823
40998
|
logger.debug("Removed empty nested .claude directory");
|
|
@@ -40908,20 +41083,20 @@ Please use only one download method.`);
|
|
|
40908
41083
|
};
|
|
40909
41084
|
}
|
|
40910
41085
|
// src/commands/init/phases/post-install-handler.ts
|
|
40911
|
-
import { join as
|
|
41086
|
+
import { join as join66 } from "node:path";
|
|
40912
41087
|
init_logger();
|
|
40913
41088
|
init_path_resolver();
|
|
40914
|
-
var
|
|
41089
|
+
var import_fs_extra29 = __toESM(require_lib(), 1);
|
|
40915
41090
|
async function handlePostInstall(ctx) {
|
|
40916
41091
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir || !ctx.claudeDir) {
|
|
40917
41092
|
return ctx;
|
|
40918
41093
|
}
|
|
40919
41094
|
if (ctx.options.global) {
|
|
40920
|
-
const claudeMdSource =
|
|
40921
|
-
const claudeMdDest =
|
|
40922
|
-
if (await
|
|
40923
|
-
if (!await
|
|
40924
|
-
await
|
|
41095
|
+
const claudeMdSource = join66(ctx.extractDir, "CLAUDE.md");
|
|
41096
|
+
const claudeMdDest = join66(ctx.resolvedDir, "CLAUDE.md");
|
|
41097
|
+
if (await import_fs_extra29.pathExists(claudeMdSource)) {
|
|
41098
|
+
if (!await import_fs_extra29.pathExists(claudeMdDest)) {
|
|
41099
|
+
await import_fs_extra29.copy(claudeMdSource, claudeMdDest);
|
|
40925
41100
|
logger.success("Copied CLAUDE.md to global directory");
|
|
40926
41101
|
} else {
|
|
40927
41102
|
logger.debug("CLAUDE.md already exists in global directory (preserved)");
|
|
@@ -40966,7 +41141,7 @@ async function handlePostInstall(ctx) {
|
|
|
40966
41141
|
}
|
|
40967
41142
|
if (!ctx.options.skipSetup) {
|
|
40968
41143
|
await promptSetupWizardIfNeeded({
|
|
40969
|
-
envPath:
|
|
41144
|
+
envPath: join66(ctx.claudeDir, ".env"),
|
|
40970
41145
|
claudeDir: ctx.claudeDir,
|
|
40971
41146
|
isGlobal: ctx.options.global,
|
|
40972
41147
|
isNonInteractive: ctx.isNonInteractive,
|
|
@@ -40980,7 +41155,7 @@ async function handlePostInstall(ctx) {
|
|
|
40980
41155
|
}
|
|
40981
41156
|
// src/commands/init/phases/selection-handler.ts
|
|
40982
41157
|
import { mkdir as mkdir20 } from "node:fs/promises";
|
|
40983
|
-
import { join as
|
|
41158
|
+
import { join as join68, resolve as resolve9 } from "node:path";
|
|
40984
41159
|
init_github_client();
|
|
40985
41160
|
|
|
40986
41161
|
// src/domains/github/kit-access-checker.ts
|
|
@@ -41109,10 +41284,10 @@ async function runPreflightChecks() {
|
|
|
41109
41284
|
}
|
|
41110
41285
|
|
|
41111
41286
|
// src/domains/installation/fresh-installer.ts
|
|
41112
|
-
import { existsSync as
|
|
41113
|
-
import { dirname as
|
|
41287
|
+
import { existsSync as existsSync20, readdirSync as readdirSync2, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
|
|
41288
|
+
import { dirname as dirname10, join as join67, resolve as resolve8 } from "node:path";
|
|
41114
41289
|
init_logger();
|
|
41115
|
-
var
|
|
41290
|
+
var import_fs_extra30 = __toESM(require_lib(), 1);
|
|
41116
41291
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
|
|
41117
41292
|
async function analyzeFreshInstallation(claudeDir) {
|
|
41118
41293
|
const metadata = await readManifest(claudeDir);
|
|
@@ -41156,16 +41331,16 @@ async function analyzeFreshInstallation(claudeDir) {
|
|
|
41156
41331
|
hasMetadata: true
|
|
41157
41332
|
};
|
|
41158
41333
|
}
|
|
41159
|
-
function
|
|
41160
|
-
const normalizedClaudeDir =
|
|
41161
|
-
let currentDir =
|
|
41334
|
+
function cleanupEmptyDirectories2(filePath, claudeDir) {
|
|
41335
|
+
const normalizedClaudeDir = resolve8(claudeDir);
|
|
41336
|
+
let currentDir = resolve8(dirname10(filePath));
|
|
41162
41337
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
41163
41338
|
try {
|
|
41164
|
-
const entries =
|
|
41339
|
+
const entries = readdirSync2(currentDir);
|
|
41165
41340
|
if (entries.length === 0) {
|
|
41166
|
-
|
|
41341
|
+
rmdirSync2(currentDir);
|
|
41167
41342
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
41168
|
-
currentDir =
|
|
41343
|
+
currentDir = resolve8(dirname10(currentDir));
|
|
41169
41344
|
} else {
|
|
41170
41345
|
break;
|
|
41171
41346
|
}
|
|
@@ -41182,13 +41357,13 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
41182
41357
|
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
41183
41358
|
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
41184
41359
|
for (const file of filesToRemove) {
|
|
41185
|
-
const fullPath =
|
|
41360
|
+
const fullPath = join67(claudeDir, file.path);
|
|
41186
41361
|
try {
|
|
41187
|
-
if (
|
|
41188
|
-
|
|
41362
|
+
if (existsSync20(fullPath)) {
|
|
41363
|
+
unlinkSync4(fullPath);
|
|
41189
41364
|
removedFiles.push(file.path);
|
|
41190
41365
|
logger.debug(`Removed: ${file.path}`);
|
|
41191
|
-
|
|
41366
|
+
cleanupEmptyDirectories2(fullPath, claudeDir);
|
|
41192
41367
|
}
|
|
41193
41368
|
} catch (error) {
|
|
41194
41369
|
logger.debug(`Failed to remove ${file.path}: ${error}`);
|
|
@@ -41207,13 +41382,13 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
41207
41382
|
};
|
|
41208
41383
|
}
|
|
41209
41384
|
async function updateMetadataAfterFresh(claudeDir, removedFiles) {
|
|
41210
|
-
const metadataPath =
|
|
41211
|
-
if (!await
|
|
41385
|
+
const metadataPath = join67(claudeDir, "metadata.json");
|
|
41386
|
+
if (!await import_fs_extra30.pathExists(metadataPath)) {
|
|
41212
41387
|
return;
|
|
41213
41388
|
}
|
|
41214
41389
|
let content;
|
|
41215
41390
|
try {
|
|
41216
|
-
content = await
|
|
41391
|
+
content = await import_fs_extra30.readFile(metadataPath, "utf-8");
|
|
41217
41392
|
} catch (readError) {
|
|
41218
41393
|
logger.warning(`Failed to read metadata.json: ${readError instanceof Error ? readError.message : String(readError)}`);
|
|
41219
41394
|
return;
|
|
@@ -41239,7 +41414,7 @@ async function updateMetadataAfterFresh(claudeDir, removedFiles) {
|
|
|
41239
41414
|
metadata.files = metadata.files.filter((f3) => !removedSet.has(f3.path));
|
|
41240
41415
|
}
|
|
41241
41416
|
try {
|
|
41242
|
-
await
|
|
41417
|
+
await import_fs_extra30.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
|
|
41243
41418
|
logger.debug(`Updated metadata.json, removed ${removedFiles.length} file entries`);
|
|
41244
41419
|
} catch (writeError) {
|
|
41245
41420
|
logger.warning(`Failed to write metadata.json: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -41250,17 +41425,17 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
41250
41425
|
const removedFiles = [];
|
|
41251
41426
|
let removedDirCount = 0;
|
|
41252
41427
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
41253
|
-
const subdirPath =
|
|
41254
|
-
if (await
|
|
41255
|
-
|
|
41428
|
+
const subdirPath = join67(claudeDir, subdir);
|
|
41429
|
+
if (await import_fs_extra30.pathExists(subdirPath)) {
|
|
41430
|
+
rmSync3(subdirPath, { recursive: true, force: true });
|
|
41256
41431
|
removedDirCount++;
|
|
41257
41432
|
removedFiles.push(`${subdir}/ (entire directory)`);
|
|
41258
41433
|
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
41259
41434
|
}
|
|
41260
41435
|
}
|
|
41261
|
-
const metadataPath =
|
|
41262
|
-
if (await
|
|
41263
|
-
|
|
41436
|
+
const metadataPath = join67(claudeDir, "metadata.json");
|
|
41437
|
+
if (await import_fs_extra30.pathExists(metadataPath)) {
|
|
41438
|
+
unlinkSync4(metadataPath);
|
|
41264
41439
|
removedFiles.push("metadata.json");
|
|
41265
41440
|
}
|
|
41266
41441
|
return {
|
|
@@ -41272,7 +41447,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
41272
41447
|
};
|
|
41273
41448
|
}
|
|
41274
41449
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
41275
|
-
if (!await
|
|
41450
|
+
if (!await import_fs_extra30.pathExists(claudeDir)) {
|
|
41276
41451
|
logger.info(".claude directory does not exist, proceeding with fresh installation");
|
|
41277
41452
|
return true;
|
|
41278
41453
|
}
|
|
@@ -41306,7 +41481,7 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
41306
41481
|
init_logger();
|
|
41307
41482
|
init_path_resolver();
|
|
41308
41483
|
init_types2();
|
|
41309
|
-
var
|
|
41484
|
+
var import_fs_extra31 = __toESM(require_lib(), 1);
|
|
41310
41485
|
|
|
41311
41486
|
// src/commands/init/types.ts
|
|
41312
41487
|
function isSyncContext(ctx) {
|
|
@@ -41475,7 +41650,7 @@ async function handleSelection(ctx) {
|
|
|
41475
41650
|
}
|
|
41476
41651
|
}
|
|
41477
41652
|
}
|
|
41478
|
-
const resolvedDir =
|
|
41653
|
+
const resolvedDir = resolve9(targetDir);
|
|
41479
41654
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
41480
41655
|
if (!ctx.options.global && PathResolver.isLocalSameAsGlobal(resolvedDir)) {
|
|
41481
41656
|
logger.warning("You're at HOME directory. Installing here modifies your GLOBAL ClaudeKit.");
|
|
@@ -41497,7 +41672,7 @@ async function handleSelection(ctx) {
|
|
|
41497
41672
|
return { ...ctx, cancelled: true };
|
|
41498
41673
|
}
|
|
41499
41674
|
}
|
|
41500
|
-
if (!await
|
|
41675
|
+
if (!await import_fs_extra31.pathExists(resolvedDir)) {
|
|
41501
41676
|
if (ctx.options.global) {
|
|
41502
41677
|
await mkdir20(resolvedDir, { recursive: true });
|
|
41503
41678
|
logger.info(`Created global directory: ${resolvedDir}`);
|
|
@@ -41509,7 +41684,7 @@ async function handleSelection(ctx) {
|
|
|
41509
41684
|
}
|
|
41510
41685
|
if (!ctx.options.fresh) {
|
|
41511
41686
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
41512
|
-
const claudeDir = prefix ?
|
|
41687
|
+
const claudeDir = prefix ? join68(resolvedDir, prefix) : resolvedDir;
|
|
41513
41688
|
try {
|
|
41514
41689
|
const existingMetadata = await readManifest(claudeDir);
|
|
41515
41690
|
if (existingMetadata?.kits) {
|
|
@@ -41541,7 +41716,7 @@ async function handleSelection(ctx) {
|
|
|
41541
41716
|
}
|
|
41542
41717
|
if (ctx.options.fresh) {
|
|
41543
41718
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
41544
|
-
const claudeDir = prefix ?
|
|
41719
|
+
const claudeDir = prefix ? join68(resolvedDir, prefix) : resolvedDir;
|
|
41545
41720
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
41546
41721
|
if (!canProceed) {
|
|
41547
41722
|
return { ...ctx, cancelled: true };
|
|
@@ -41560,7 +41735,7 @@ async function handleSelection(ctx) {
|
|
|
41560
41735
|
logger.info("Fetching available versions...");
|
|
41561
41736
|
let currentVersion = null;
|
|
41562
41737
|
try {
|
|
41563
|
-
const metadataPath = ctx.options.global ?
|
|
41738
|
+
const metadataPath = ctx.options.global ? join68(PathResolver.getGlobalKitDir(), "metadata.json") : join68(resolvedDir, ".claude", "metadata.json");
|
|
41564
41739
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
41565
41740
|
currentVersion = metadata?.version || null;
|
|
41566
41741
|
if (currentVersion) {
|
|
@@ -41634,25 +41809,25 @@ async function handleSelection(ctx) {
|
|
|
41634
41809
|
};
|
|
41635
41810
|
}
|
|
41636
41811
|
// src/commands/init/phases/sync-handler.ts
|
|
41637
|
-
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as
|
|
41638
|
-
import { dirname as
|
|
41812
|
+
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as writeFile21 } from "node:fs/promises";
|
|
41813
|
+
import { dirname as dirname11, join as join69, resolve as resolve10 } from "node:path";
|
|
41639
41814
|
init_logger();
|
|
41640
41815
|
init_path_resolver();
|
|
41641
|
-
var
|
|
41816
|
+
var import_fs_extra32 = __toESM(require_lib(), 1);
|
|
41642
41817
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
41643
41818
|
async function handleSync(ctx) {
|
|
41644
41819
|
if (!ctx.options.sync) {
|
|
41645
41820
|
return ctx;
|
|
41646
41821
|
}
|
|
41647
|
-
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() :
|
|
41648
|
-
const claudeDir = ctx.options.global ? resolvedDir :
|
|
41649
|
-
if (!await
|
|
41822
|
+
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve10(ctx.options.dir || ".");
|
|
41823
|
+
const claudeDir = ctx.options.global ? resolvedDir : join69(resolvedDir, ".claude");
|
|
41824
|
+
if (!await import_fs_extra32.pathExists(claudeDir)) {
|
|
41650
41825
|
logger.error("Cannot sync: no .claude directory found");
|
|
41651
41826
|
ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
|
|
41652
41827
|
return { ...ctx, cancelled: true };
|
|
41653
41828
|
}
|
|
41654
|
-
const metadataPath =
|
|
41655
|
-
if (!await
|
|
41829
|
+
const metadataPath = join69(claudeDir, "metadata.json");
|
|
41830
|
+
if (!await import_fs_extra32.pathExists(metadataPath)) {
|
|
41656
41831
|
logger.error("Cannot sync: no metadata.json found");
|
|
41657
41832
|
ctx.prompts.note(`Your installation may be from an older version.
|
|
41658
41833
|
Run 'ck init' to update.`, "Legacy Installation");
|
|
@@ -41751,10 +41926,10 @@ function getLockTimeout() {
|
|
|
41751
41926
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
41752
41927
|
async function acquireSyncLock(global3) {
|
|
41753
41928
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
41754
|
-
const lockPath =
|
|
41929
|
+
const lockPath = join69(cacheDir, ".sync-lock");
|
|
41755
41930
|
const startTime = Date.now();
|
|
41756
41931
|
const lockTimeout = getLockTimeout();
|
|
41757
|
-
await mkdir21(
|
|
41932
|
+
await mkdir21(dirname11(lockPath), { recursive: true });
|
|
41758
41933
|
while (Date.now() - startTime < lockTimeout) {
|
|
41759
41934
|
try {
|
|
41760
41935
|
const handle = await open(lockPath, "wx");
|
|
@@ -41778,7 +41953,7 @@ async function acquireSyncLock(global3) {
|
|
|
41778
41953
|
}
|
|
41779
41954
|
logger.debug(`Lock stat failed: ${statError}`);
|
|
41780
41955
|
}
|
|
41781
|
-
await new Promise((
|
|
41956
|
+
await new Promise((resolve11) => setTimeout(resolve11, 100));
|
|
41782
41957
|
continue;
|
|
41783
41958
|
}
|
|
41784
41959
|
throw err;
|
|
@@ -41797,7 +41972,7 @@ async function executeSyncMerge(ctx) {
|
|
|
41797
41972
|
const releaseLock = await acquireSyncLock(ctx.options.global);
|
|
41798
41973
|
try {
|
|
41799
41974
|
const trackedFiles = ctx.syncTrackedFiles;
|
|
41800
|
-
const upstreamDir = ctx.options.global ?
|
|
41975
|
+
const upstreamDir = ctx.options.global ? join69(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
41801
41976
|
logger.info("Analyzing file changes...");
|
|
41802
41977
|
const plan = await SyncEngine.createSyncPlan(trackedFiles, ctx.claudeDir, upstreamDir);
|
|
41803
41978
|
displaySyncPlan(plan);
|
|
@@ -41816,7 +41991,7 @@ async function executeSyncMerge(ctx) {
|
|
|
41816
41991
|
try {
|
|
41817
41992
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
41818
41993
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
41819
|
-
const targetDir =
|
|
41994
|
+
const targetDir = join69(targetPath, "..");
|
|
41820
41995
|
try {
|
|
41821
41996
|
await mkdir21(targetDir, { recursive: true });
|
|
41822
41997
|
} catch (mkdirError) {
|
|
@@ -41897,7 +42072,7 @@ async function executeSyncMerge(ctx) {
|
|
|
41897
42072
|
try {
|
|
41898
42073
|
const tempPath = `${currentPath}.tmp.${Date.now()}`;
|
|
41899
42074
|
try {
|
|
41900
|
-
await
|
|
42075
|
+
await writeFile21(tempPath, result.result, "utf-8");
|
|
41901
42076
|
await rename3(tempPath, currentPath);
|
|
41902
42077
|
} catch (atomicError) {
|
|
41903
42078
|
await unlink7(tempPath).catch(() => {});
|
|
@@ -41985,9 +42160,9 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
41985
42160
|
for (const file of files) {
|
|
41986
42161
|
try {
|
|
41987
42162
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
41988
|
-
if (await
|
|
42163
|
+
if (await import_fs_extra32.pathExists(sourcePath)) {
|
|
41989
42164
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
41990
|
-
const targetDir =
|
|
42165
|
+
const targetDir = join69(targetPath, "..");
|
|
41991
42166
|
await mkdir21(targetDir, { recursive: true });
|
|
41992
42167
|
await copyFile6(sourcePath, targetPath);
|
|
41993
42168
|
}
|
|
@@ -42001,7 +42176,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
42001
42176
|
}
|
|
42002
42177
|
}
|
|
42003
42178
|
// src/commands/init/phases/transform-handler.ts
|
|
42004
|
-
import { join as
|
|
42179
|
+
import { join as join73 } from "node:path";
|
|
42005
42180
|
|
|
42006
42181
|
// src/services/transformers/folder-path-transformer.ts
|
|
42007
42182
|
init_logger();
|
|
@@ -42010,40 +42185,40 @@ init_types2();
|
|
|
42010
42185
|
// src/services/transformers/folder-transform/folder-renamer.ts
|
|
42011
42186
|
init_logger();
|
|
42012
42187
|
init_types2();
|
|
42013
|
-
var
|
|
42188
|
+
var import_fs_extra33 = __toESM(require_lib(), 1);
|
|
42014
42189
|
import { rename as rename4, rm as rm7 } from "node:fs/promises";
|
|
42015
|
-
import { join as
|
|
42190
|
+
import { join as join70, relative as relative12 } from "node:path";
|
|
42016
42191
|
async function collectDirsToRename(extractDir, folders) {
|
|
42017
42192
|
const dirsToRename = [];
|
|
42018
42193
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
42019
|
-
const docsPath =
|
|
42020
|
-
if (await
|
|
42194
|
+
const docsPath = join70(extractDir, DEFAULT_FOLDERS.docs);
|
|
42195
|
+
if (await import_fs_extra33.pathExists(docsPath)) {
|
|
42021
42196
|
dirsToRename.push({
|
|
42022
42197
|
from: docsPath,
|
|
42023
|
-
to:
|
|
42198
|
+
to: join70(extractDir, folders.docs)
|
|
42024
42199
|
});
|
|
42025
42200
|
}
|
|
42026
|
-
const claudeDocsPath =
|
|
42027
|
-
if (await
|
|
42201
|
+
const claudeDocsPath = join70(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
42202
|
+
if (await import_fs_extra33.pathExists(claudeDocsPath)) {
|
|
42028
42203
|
dirsToRename.push({
|
|
42029
42204
|
from: claudeDocsPath,
|
|
42030
|
-
to:
|
|
42205
|
+
to: join70(extractDir, ".claude", folders.docs)
|
|
42031
42206
|
});
|
|
42032
42207
|
}
|
|
42033
42208
|
}
|
|
42034
42209
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
42035
|
-
const plansPath =
|
|
42036
|
-
if (await
|
|
42210
|
+
const plansPath = join70(extractDir, DEFAULT_FOLDERS.plans);
|
|
42211
|
+
if (await import_fs_extra33.pathExists(plansPath)) {
|
|
42037
42212
|
dirsToRename.push({
|
|
42038
42213
|
from: plansPath,
|
|
42039
|
-
to:
|
|
42214
|
+
to: join70(extractDir, folders.plans)
|
|
42040
42215
|
});
|
|
42041
42216
|
}
|
|
42042
|
-
const claudePlansPath =
|
|
42043
|
-
if (await
|
|
42217
|
+
const claudePlansPath = join70(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
42218
|
+
if (await import_fs_extra33.pathExists(claudePlansPath)) {
|
|
42044
42219
|
dirsToRename.push({
|
|
42045
42220
|
from: claudePlansPath,
|
|
42046
|
-
to:
|
|
42221
|
+
to: join70(extractDir, ".claude", folders.plans)
|
|
42047
42222
|
});
|
|
42048
42223
|
}
|
|
42049
42224
|
}
|
|
@@ -42055,7 +42230,7 @@ async function moveAcrossDevices(src, dest) {
|
|
|
42055
42230
|
} catch (e2) {
|
|
42056
42231
|
if (e2.code === "EXDEV") {
|
|
42057
42232
|
logger.debug(`Cross-device move detected, using copy+delete: ${src} -> ${dest}`);
|
|
42058
|
-
await
|
|
42233
|
+
await import_fs_extra33.copy(src, dest, { overwrite: true });
|
|
42059
42234
|
await rm7(src, { recursive: true, force: true });
|
|
42060
42235
|
} else {
|
|
42061
42236
|
throw e2;
|
|
@@ -42083,8 +42258,8 @@ async function renameFolders(dirsToRename, extractDir, options) {
|
|
|
42083
42258
|
// src/services/transformers/folder-transform/path-replacer.ts
|
|
42084
42259
|
init_logger();
|
|
42085
42260
|
init_types2();
|
|
42086
|
-
import { readFile as
|
|
42087
|
-
import { join as
|
|
42261
|
+
import { readFile as readFile26, readdir as readdir23, writeFile as writeFile22 } from "node:fs/promises";
|
|
42262
|
+
import { join as join71, relative as relative13 } from "node:path";
|
|
42088
42263
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
42089
42264
|
".md",
|
|
42090
42265
|
".txt",
|
|
@@ -42137,7 +42312,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
42137
42312
|
let replacementsCount = 0;
|
|
42138
42313
|
const entries = await readdir23(dir, { withFileTypes: true });
|
|
42139
42314
|
for (const entry of entries) {
|
|
42140
|
-
const fullPath =
|
|
42315
|
+
const fullPath = join71(dir, entry.name);
|
|
42141
42316
|
if (entry.isDirectory()) {
|
|
42142
42317
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
42143
42318
|
continue;
|
|
@@ -42150,7 +42325,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
42150
42325
|
if (!shouldTransform)
|
|
42151
42326
|
continue;
|
|
42152
42327
|
try {
|
|
42153
|
-
const content = await
|
|
42328
|
+
const content = await readFile26(fullPath, "utf-8");
|
|
42154
42329
|
let newContent = content;
|
|
42155
42330
|
let changeCount = 0;
|
|
42156
42331
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -42166,7 +42341,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
42166
42341
|
if (options.dryRun) {
|
|
42167
42342
|
logger.debug(`[dry-run] Would update ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
42168
42343
|
} else {
|
|
42169
|
-
await
|
|
42344
|
+
await writeFile22(fullPath, newContent, "utf-8");
|
|
42170
42345
|
logger.debug(`Updated ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
42171
42346
|
}
|
|
42172
42347
|
filesChanged++;
|
|
@@ -42272,9 +42447,9 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
42272
42447
|
|
|
42273
42448
|
// src/services/transformers/global-path-transformer.ts
|
|
42274
42449
|
init_logger();
|
|
42275
|
-
import { readFile as
|
|
42450
|
+
import { readFile as readFile27, readdir as readdir24, writeFile as writeFile23 } from "node:fs/promises";
|
|
42276
42451
|
import { platform as platform12 } from "node:os";
|
|
42277
|
-
import { extname as extname3, join as
|
|
42452
|
+
import { extname as extname3, join as join72 } from "node:path";
|
|
42278
42453
|
var IS_WINDOWS4 = platform12() === "win32";
|
|
42279
42454
|
var HOME_PREFIX = IS_WINDOWS4 ? "%USERPROFILE%" : "$HOME";
|
|
42280
42455
|
function getHomeDirPrefix() {
|
|
@@ -42384,7 +42559,7 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
42384
42559
|
async function processDirectory2(dir) {
|
|
42385
42560
|
const entries = await readdir24(dir, { withFileTypes: true });
|
|
42386
42561
|
for (const entry of entries) {
|
|
42387
|
-
const fullPath =
|
|
42562
|
+
const fullPath = join72(dir, entry.name);
|
|
42388
42563
|
if (entry.isDirectory()) {
|
|
42389
42564
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
42390
42565
|
continue;
|
|
@@ -42392,10 +42567,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
42392
42567
|
await processDirectory2(fullPath);
|
|
42393
42568
|
} else if (entry.isFile() && shouldTransformFile3(entry.name)) {
|
|
42394
42569
|
try {
|
|
42395
|
-
const content = await
|
|
42570
|
+
const content = await readFile27(fullPath, "utf-8");
|
|
42396
42571
|
const { transformed, changes } = transformContent(content);
|
|
42397
42572
|
if (changes > 0) {
|
|
42398
|
-
await
|
|
42573
|
+
await writeFile23(fullPath, transformed, "utf-8");
|
|
42399
42574
|
filesTransformed++;
|
|
42400
42575
|
totalChanges += changes;
|
|
42401
42576
|
if (options.verbose) {
|
|
@@ -42460,7 +42635,7 @@ async function handleTransforms(ctx) {
|
|
|
42460
42635
|
logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
|
|
42461
42636
|
}
|
|
42462
42637
|
}
|
|
42463
|
-
const claudeDir = ctx.options.global ? ctx.resolvedDir :
|
|
42638
|
+
const claudeDir = ctx.options.global ? ctx.resolvedDir : join73(ctx.resolvedDir, ".claude");
|
|
42464
42639
|
return {
|
|
42465
42640
|
...ctx,
|
|
42466
42641
|
foldersConfig,
|
|
@@ -42650,11 +42825,11 @@ init_types2();
|
|
|
42650
42825
|
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
42651
42826
|
|
|
42652
42827
|
// src/commands/new/phases/directory-setup.ts
|
|
42653
|
-
import { resolve as
|
|
42828
|
+
import { resolve as resolve11 } from "node:path";
|
|
42654
42829
|
init_logger();
|
|
42655
42830
|
init_path_resolver();
|
|
42656
42831
|
init_types2();
|
|
42657
|
-
var
|
|
42832
|
+
var import_fs_extra34 = __toESM(require_lib(), 1);
|
|
42658
42833
|
async function directorySetup(validOptions, prompts) {
|
|
42659
42834
|
const isNonInteractive2 = !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
|
|
42660
42835
|
const config = await ConfigManager.get();
|
|
@@ -42735,7 +42910,7 @@ async function directorySetup(validOptions, prompts) {
|
|
|
42735
42910
|
targetDir = await prompts.getDirectory(targetDir);
|
|
42736
42911
|
}
|
|
42737
42912
|
}
|
|
42738
|
-
const resolvedDir =
|
|
42913
|
+
const resolvedDir = resolve11(targetDir);
|
|
42739
42914
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
42740
42915
|
if (PathResolver.isLocalSameAsGlobal(resolvedDir)) {
|
|
42741
42916
|
logger.warning("You're creating a project at HOME directory.");
|
|
@@ -42753,8 +42928,8 @@ async function directorySetup(validOptions, prompts) {
|
|
|
42753
42928
|
return null;
|
|
42754
42929
|
}
|
|
42755
42930
|
}
|
|
42756
|
-
if (await
|
|
42757
|
-
const files = await
|
|
42931
|
+
if (await import_fs_extra34.pathExists(resolvedDir)) {
|
|
42932
|
+
const files = await import_fs_extra34.readdir(resolvedDir);
|
|
42758
42933
|
const isEmpty = files.length === 0;
|
|
42759
42934
|
if (!isEmpty) {
|
|
42760
42935
|
if (isNonInteractive2) {
|
|
@@ -42790,7 +42965,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
42790
42965
|
};
|
|
42791
42966
|
}
|
|
42792
42967
|
// src/commands/new/phases/project-creation.ts
|
|
42793
|
-
import { join as
|
|
42968
|
+
import { join as join74 } from "node:path";
|
|
42794
42969
|
init_github_client();
|
|
42795
42970
|
init_logger();
|
|
42796
42971
|
init_output_manager();
|
|
@@ -42917,7 +43092,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
42917
43092
|
output.section("Installing");
|
|
42918
43093
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
42919
43094
|
const merger = new FileMerger;
|
|
42920
|
-
const claudeDir =
|
|
43095
|
+
const claudeDir = join74(resolvedDir, ".claude");
|
|
42921
43096
|
merger.setMultiKitContext(claudeDir, kit);
|
|
42922
43097
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
42923
43098
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -42963,7 +43138,7 @@ async function handleProjectCreation(ctx) {
|
|
|
42963
43138
|
};
|
|
42964
43139
|
}
|
|
42965
43140
|
// src/commands/new/phases/post-setup.ts
|
|
42966
|
-
import { join as
|
|
43141
|
+
import { join as join75 } from "node:path";
|
|
42967
43142
|
init_package_installer();
|
|
42968
43143
|
init_logger();
|
|
42969
43144
|
init_path_resolver();
|
|
@@ -42995,9 +43170,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
|
|
|
42995
43170
|
withSudo: validOptions.withSudo
|
|
42996
43171
|
});
|
|
42997
43172
|
}
|
|
42998
|
-
const claudeDir =
|
|
43173
|
+
const claudeDir = join75(resolvedDir, ".claude");
|
|
42999
43174
|
await promptSetupWizardIfNeeded({
|
|
43000
|
-
envPath:
|
|
43175
|
+
envPath: join75(claudeDir, ".env"),
|
|
43001
43176
|
claudeDir,
|
|
43002
43177
|
isGlobal: false,
|
|
43003
43178
|
isNonInteractive: isNonInteractive2,
|
|
@@ -43066,7 +43241,7 @@ var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
|
43066
43241
|
|
|
43067
43242
|
// src/commands/uninstall/installation-detector.ts
|
|
43068
43243
|
init_path_resolver();
|
|
43069
|
-
var
|
|
43244
|
+
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
43070
43245
|
async function detectInstallations() {
|
|
43071
43246
|
const installations = [];
|
|
43072
43247
|
const setup = await getClaudeKitSetup(process.cwd());
|
|
@@ -43075,28 +43250,28 @@ async function detectInstallations() {
|
|
|
43075
43250
|
installations.push({
|
|
43076
43251
|
type: "local",
|
|
43077
43252
|
path: setup.project.path,
|
|
43078
|
-
exists: await
|
|
43253
|
+
exists: await import_fs_extra35.pathExists(setup.project.path)
|
|
43079
43254
|
});
|
|
43080
43255
|
}
|
|
43081
43256
|
if (setup.global.path && setup.global.metadata) {
|
|
43082
43257
|
installations.push({
|
|
43083
43258
|
type: "global",
|
|
43084
43259
|
path: setup.global.path,
|
|
43085
|
-
exists: await
|
|
43260
|
+
exists: await import_fs_extra35.pathExists(setup.global.path)
|
|
43086
43261
|
});
|
|
43087
43262
|
}
|
|
43088
43263
|
return installations.filter((i) => i.exists);
|
|
43089
43264
|
}
|
|
43090
43265
|
|
|
43091
43266
|
// src/commands/uninstall/removal-handler.ts
|
|
43092
|
-
import { readdirSync as
|
|
43093
|
-
import { join as
|
|
43267
|
+
import { readdirSync as readdirSync4, rmSync as rmSync5 } from "node:fs";
|
|
43268
|
+
import { join as join77 } from "node:path";
|
|
43094
43269
|
init_logger();
|
|
43095
|
-
var
|
|
43270
|
+
var import_fs_extra36 = __toESM(require_lib(), 1);
|
|
43096
43271
|
|
|
43097
43272
|
// src/commands/uninstall/analysis-handler.ts
|
|
43098
|
-
import { readdirSync as
|
|
43099
|
-
import { dirname as
|
|
43273
|
+
import { readdirSync as readdirSync3, rmSync as rmSync4 } from "node:fs";
|
|
43274
|
+
import { dirname as dirname12, join as join76 } from "node:path";
|
|
43100
43275
|
init_logger();
|
|
43101
43276
|
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
43102
43277
|
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
@@ -43111,17 +43286,17 @@ function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
|
43111
43286
|
}
|
|
43112
43287
|
return { action: "preserve", reason: "user-created" };
|
|
43113
43288
|
}
|
|
43114
|
-
async function
|
|
43289
|
+
async function cleanupEmptyDirectories3(filePath, installationRoot) {
|
|
43115
43290
|
let cleaned = 0;
|
|
43116
|
-
let currentDir =
|
|
43291
|
+
let currentDir = dirname12(filePath);
|
|
43117
43292
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
43118
43293
|
try {
|
|
43119
|
-
const entries =
|
|
43294
|
+
const entries = readdirSync3(currentDir);
|
|
43120
43295
|
if (entries.length === 0) {
|
|
43121
|
-
|
|
43296
|
+
rmSync4(currentDir, { recursive: true });
|
|
43122
43297
|
cleaned++;
|
|
43123
43298
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
43124
|
-
currentDir =
|
|
43299
|
+
currentDir = dirname12(currentDir);
|
|
43125
43300
|
} else {
|
|
43126
43301
|
break;
|
|
43127
43302
|
}
|
|
@@ -43143,7 +43318,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
43143
43318
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
43144
43319
|
const kitFiles = metadata.kits[kit].files || [];
|
|
43145
43320
|
for (const trackedFile of kitFiles) {
|
|
43146
|
-
const filePath =
|
|
43321
|
+
const filePath = join76(installation.path, trackedFile.path);
|
|
43147
43322
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
43148
43323
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
43149
43324
|
continue;
|
|
@@ -43173,7 +43348,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
43173
43348
|
return result;
|
|
43174
43349
|
}
|
|
43175
43350
|
for (const trackedFile of allTrackedFiles) {
|
|
43176
|
-
const filePath =
|
|
43351
|
+
const filePath = join76(installation.path, trackedFile.path);
|
|
43177
43352
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
43178
43353
|
if (!ownershipResult.exists)
|
|
43179
43354
|
continue;
|
|
@@ -43233,21 +43408,21 @@ async function removeInstallations(installations, options) {
|
|
|
43233
43408
|
let removedCount = 0;
|
|
43234
43409
|
let cleanedDirs = 0;
|
|
43235
43410
|
for (const item of analysis.toDelete) {
|
|
43236
|
-
const filePath =
|
|
43237
|
-
if (await
|
|
43238
|
-
await
|
|
43411
|
+
const filePath = join77(installation.path, item.path);
|
|
43412
|
+
if (await import_fs_extra36.pathExists(filePath)) {
|
|
43413
|
+
await import_fs_extra36.remove(filePath);
|
|
43239
43414
|
removedCount++;
|
|
43240
43415
|
logger.debug(`Removed: ${item.path}`);
|
|
43241
|
-
cleanedDirs += await
|
|
43416
|
+
cleanedDirs += await cleanupEmptyDirectories3(filePath, installation.path);
|
|
43242
43417
|
}
|
|
43243
43418
|
}
|
|
43244
43419
|
if (options.kit && analysis.remainingKits.length > 0) {
|
|
43245
43420
|
await ManifestWriter.removeKitFromManifest(installation.path, options.kit);
|
|
43246
43421
|
}
|
|
43247
43422
|
try {
|
|
43248
|
-
const remaining =
|
|
43423
|
+
const remaining = readdirSync4(installation.path);
|
|
43249
43424
|
if (remaining.length === 0) {
|
|
43250
|
-
|
|
43425
|
+
rmSync5(installation.path, { recursive: true });
|
|
43251
43426
|
logger.debug(`Removed empty installation directory: ${installation.path}`);
|
|
43252
43427
|
}
|
|
43253
43428
|
} catch {}
|
|
@@ -43404,7 +43579,7 @@ ${import_picocolors22.default.yellow("User modifications will be permanently del
|
|
|
43404
43579
|
}
|
|
43405
43580
|
// src/commands/update-cli.ts
|
|
43406
43581
|
import { exec as exec8 } from "node:child_process";
|
|
43407
|
-
import { join as
|
|
43582
|
+
import { join as join78 } from "node:path";
|
|
43408
43583
|
import { promisify as promisify8 } from "node:util";
|
|
43409
43584
|
|
|
43410
43585
|
// src/domains/github/npm-registry.ts
|
|
@@ -43547,11 +43722,11 @@ init_logger();
|
|
|
43547
43722
|
init_types2();
|
|
43548
43723
|
init_types2();
|
|
43549
43724
|
var import_compare_versions3 = __toESM(require_umd(), 1);
|
|
43550
|
-
var
|
|
43725
|
+
var import_fs_extra37 = __toESM(require_lib(), 1);
|
|
43551
43726
|
// package.json
|
|
43552
43727
|
var package_default = {
|
|
43553
43728
|
name: "claudekit-cli",
|
|
43554
|
-
version: "3.30.0-dev.
|
|
43729
|
+
version: "3.30.0-dev.2",
|
|
43555
43730
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
43556
43731
|
type: "module",
|
|
43557
43732
|
repository: {
|
|
@@ -43698,12 +43873,12 @@ function selectKitForUpdate(params) {
|
|
|
43698
43873
|
};
|
|
43699
43874
|
}
|
|
43700
43875
|
async function readMetadataFile(claudeDir) {
|
|
43701
|
-
const metadataPath =
|
|
43876
|
+
const metadataPath = join78(claudeDir, "metadata.json");
|
|
43702
43877
|
try {
|
|
43703
|
-
if (!await
|
|
43878
|
+
if (!await import_fs_extra37.pathExists(metadataPath)) {
|
|
43704
43879
|
return null;
|
|
43705
43880
|
}
|
|
43706
|
-
const content = await
|
|
43881
|
+
const content = await import_fs_extra37.readFile(metadataPath, "utf-8");
|
|
43707
43882
|
const parsed = JSON.parse(content);
|
|
43708
43883
|
const validated = MetadataSchema.safeParse(parsed);
|
|
43709
43884
|
if (!validated.success) {
|
|
@@ -44030,8 +44205,8 @@ function registerCommands(cli) {
|
|
|
44030
44205
|
}
|
|
44031
44206
|
|
|
44032
44207
|
// src/cli/version-display.ts
|
|
44033
|
-
import { existsSync as
|
|
44034
|
-
import { join as
|
|
44208
|
+
import { existsSync as existsSync22, readFileSync as readFileSync7 } from "node:fs";
|
|
44209
|
+
import { join as join80 } from "node:path";
|
|
44035
44210
|
|
|
44036
44211
|
// src/domains/versioning/checking/version-utils.ts
|
|
44037
44212
|
var import_compare_versions4 = __toESM(require_umd(), 1);
|
|
@@ -44058,25 +44233,25 @@ init_types2();
|
|
|
44058
44233
|
// src/domains/versioning/version-cache.ts
|
|
44059
44234
|
init_logger();
|
|
44060
44235
|
init_path_resolver();
|
|
44061
|
-
import { existsSync as
|
|
44062
|
-
import { mkdir as mkdir22, readFile as
|
|
44063
|
-
import { join as
|
|
44236
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
44237
|
+
import { mkdir as mkdir22, readFile as readFile29, writeFile as writeFile24 } from "node:fs/promises";
|
|
44238
|
+
import { join as join79 } from "node:path";
|
|
44064
44239
|
|
|
44065
44240
|
class VersionCacheManager {
|
|
44066
44241
|
static CACHE_FILENAME = "version-check.json";
|
|
44067
44242
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
44068
44243
|
static getCacheFile() {
|
|
44069
44244
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
44070
|
-
return
|
|
44245
|
+
return join79(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
44071
44246
|
}
|
|
44072
44247
|
static async load() {
|
|
44073
44248
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
44074
44249
|
try {
|
|
44075
|
-
if (!
|
|
44250
|
+
if (!existsSync21(cacheFile)) {
|
|
44076
44251
|
logger.debug("Version check cache not found");
|
|
44077
44252
|
return null;
|
|
44078
44253
|
}
|
|
44079
|
-
const content = await
|
|
44254
|
+
const content = await readFile29(cacheFile, "utf-8");
|
|
44080
44255
|
const cache2 = JSON.parse(content);
|
|
44081
44256
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
44082
44257
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -44093,10 +44268,10 @@ class VersionCacheManager {
|
|
|
44093
44268
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
44094
44269
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
44095
44270
|
try {
|
|
44096
|
-
if (!
|
|
44271
|
+
if (!existsSync21(cacheDir)) {
|
|
44097
44272
|
await mkdir22(cacheDir, { recursive: true, mode: 448 });
|
|
44098
44273
|
}
|
|
44099
|
-
await
|
|
44274
|
+
await writeFile24(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
44100
44275
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
44101
44276
|
} catch (error) {
|
|
44102
44277
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -44115,7 +44290,7 @@ class VersionCacheManager {
|
|
|
44115
44290
|
static async clear() {
|
|
44116
44291
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
44117
44292
|
try {
|
|
44118
|
-
if (
|
|
44293
|
+
if (existsSync21(cacheFile)) {
|
|
44119
44294
|
const fs14 = await import("node:fs/promises");
|
|
44120
44295
|
await fs14.unlink(cacheFile);
|
|
44121
44296
|
logger.debug("Version check cache cleared");
|
|
@@ -44335,11 +44510,11 @@ async function displayVersion() {
|
|
|
44335
44510
|
let localKitVersion = null;
|
|
44336
44511
|
let isGlobalOnlyKit = false;
|
|
44337
44512
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
44338
|
-
const globalMetadataPath =
|
|
44513
|
+
const globalMetadataPath = join80(globalKitDir, "metadata.json");
|
|
44339
44514
|
const prefix = PathResolver.getPathPrefix(false);
|
|
44340
|
-
const localMetadataPath = prefix ?
|
|
44515
|
+
const localMetadataPath = prefix ? join80(process.cwd(), prefix, "metadata.json") : join80(process.cwd(), "metadata.json");
|
|
44341
44516
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
44342
|
-
if (!isLocalSameAsGlobal &&
|
|
44517
|
+
if (!isLocalSameAsGlobal && existsSync22(localMetadataPath)) {
|
|
44343
44518
|
try {
|
|
44344
44519
|
const rawMetadata = JSON.parse(readFileSync7(localMetadataPath, "utf-8"));
|
|
44345
44520
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
@@ -44353,7 +44528,7 @@ async function displayVersion() {
|
|
|
44353
44528
|
logger.verbose("Failed to parse local metadata.json", { error });
|
|
44354
44529
|
}
|
|
44355
44530
|
}
|
|
44356
|
-
if (
|
|
44531
|
+
if (existsSync22(globalMetadataPath)) {
|
|
44357
44532
|
try {
|
|
44358
44533
|
const rawMetadata = JSON.parse(readFileSync7(globalMetadataPath, "utf-8"));
|
|
44359
44534
|
const metadata = MetadataSchema.parse(rawMetadata);
|