claudekit-cli 3.23.0 → 3.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +380 -156
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18468,6 +18468,25 @@ class PathResolver {
|
|
|
18468
18468
|
}
|
|
18469
18469
|
return join(homedir(), ".claude");
|
|
18470
18470
|
}
|
|
18471
|
+
static getOpenCodeDir(global2, baseDir) {
|
|
18472
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
18473
|
+
if (testHome) {
|
|
18474
|
+
return global2 ? join(testHome, ".config", "opencode") : join(baseDir || testHome, ".opencode");
|
|
18475
|
+
}
|
|
18476
|
+
if (!global2) {
|
|
18477
|
+
return join(baseDir || process.cwd(), ".opencode");
|
|
18478
|
+
}
|
|
18479
|
+
const os = platform();
|
|
18480
|
+
if (os === "win32") {
|
|
18481
|
+
const appData = process.env.APPDATA || join(homedir(), "AppData", "Roaming");
|
|
18482
|
+
return join(appData, "opencode");
|
|
18483
|
+
}
|
|
18484
|
+
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
18485
|
+
if (xdgConfigHome) {
|
|
18486
|
+
return join(xdgConfigHome, "opencode");
|
|
18487
|
+
}
|
|
18488
|
+
return join(homedir(), ".config", "opencode");
|
|
18489
|
+
}
|
|
18471
18490
|
static getPathPrefix(global2) {
|
|
18472
18491
|
return global2 ? "" : ".claude";
|
|
18473
18492
|
}
|
|
@@ -39548,13 +39567,156 @@ async function handleMigration(ctx) {
|
|
|
39548
39567
|
}
|
|
39549
39568
|
return ctx;
|
|
39550
39569
|
}
|
|
39570
|
+
// src/commands/init/phases/opencode-handler.ts
|
|
39571
|
+
import { cp, readdir as readdir22, rm as rm5 } from "node:fs/promises";
|
|
39572
|
+
import { join as join60 } from "node:path";
|
|
39573
|
+
|
|
39574
|
+
// src/services/transformers/opencode-path-transformer.ts
|
|
39575
|
+
init_logger();
|
|
39576
|
+
import { readFile as readFile20, readdir as readdir21, writeFile as writeFile16 } from "node:fs/promises";
|
|
39577
|
+
import { platform as platform10 } from "node:os";
|
|
39578
|
+
import { extname as extname2, join as join59 } from "node:path";
|
|
39579
|
+
var IS_WINDOWS3 = platform10() === "win32";
|
|
39580
|
+
function getOpenCodeGlobalPath() {
|
|
39581
|
+
return IS_WINDOWS3 ? "%APPDATA%/opencode/" : "$HOME/.config/opencode/";
|
|
39582
|
+
}
|
|
39583
|
+
var TRANSFORMABLE_EXTENSIONS2 = new Set([
|
|
39584
|
+
".md",
|
|
39585
|
+
".js",
|
|
39586
|
+
".ts",
|
|
39587
|
+
".json",
|
|
39588
|
+
".sh",
|
|
39589
|
+
".ps1",
|
|
39590
|
+
".yaml",
|
|
39591
|
+
".yml",
|
|
39592
|
+
".toml"
|
|
39593
|
+
]);
|
|
39594
|
+
function transformOpenCodeContent(content) {
|
|
39595
|
+
let changes = 0;
|
|
39596
|
+
let transformed = content;
|
|
39597
|
+
const globalPath = getOpenCodeGlobalPath();
|
|
39598
|
+
transformed = transformed.replace(/\.\/\.opencode\//g, () => {
|
|
39599
|
+
changes++;
|
|
39600
|
+
return globalPath;
|
|
39601
|
+
});
|
|
39602
|
+
transformed = transformed.replace(/(["'`])\.opencode\//g, (_match, quote) => {
|
|
39603
|
+
changes++;
|
|
39604
|
+
return `${quote}${globalPath}`;
|
|
39605
|
+
});
|
|
39606
|
+
transformed = transformed.replace(/\(\.opencode\//g, () => {
|
|
39607
|
+
changes++;
|
|
39608
|
+
return `(${globalPath}`;
|
|
39609
|
+
});
|
|
39610
|
+
transformed = transformed.replace(/ \.opencode\//g, () => {
|
|
39611
|
+
changes++;
|
|
39612
|
+
return ` ${globalPath}`;
|
|
39613
|
+
});
|
|
39614
|
+
transformed = transformed.replace(/^\.opencode\//gm, () => {
|
|
39615
|
+
changes++;
|
|
39616
|
+
return globalPath;
|
|
39617
|
+
});
|
|
39618
|
+
transformed = transformed.replace(/: \.opencode\//g, () => {
|
|
39619
|
+
changes++;
|
|
39620
|
+
return `: ${globalPath}`;
|
|
39621
|
+
});
|
|
39622
|
+
transformed = transformed.replace(/:\.opencode\//g, () => {
|
|
39623
|
+
changes++;
|
|
39624
|
+
return `:${globalPath}`;
|
|
39625
|
+
});
|
|
39626
|
+
return { transformed, changes };
|
|
39627
|
+
}
|
|
39628
|
+
function shouldTransformFile2(filename) {
|
|
39629
|
+
const ext2 = extname2(filename).toLowerCase();
|
|
39630
|
+
return TRANSFORMABLE_EXTENSIONS2.has(ext2);
|
|
39631
|
+
}
|
|
39632
|
+
async function transformPathsForGlobalOpenCode(directory, options = {}) {
|
|
39633
|
+
let filesTransformed = 0;
|
|
39634
|
+
let totalChanges = 0;
|
|
39635
|
+
let filesSkipped = 0;
|
|
39636
|
+
async function processDirectory2(dir) {
|
|
39637
|
+
const entries = await readdir21(dir, { withFileTypes: true });
|
|
39638
|
+
for (const entry of entries) {
|
|
39639
|
+
const fullPath = join59(dir, entry.name);
|
|
39640
|
+
if (entry.isDirectory()) {
|
|
39641
|
+
if (entry.name === "node_modules" || entry.name.startsWith(".")) {
|
|
39642
|
+
continue;
|
|
39643
|
+
}
|
|
39644
|
+
await processDirectory2(fullPath);
|
|
39645
|
+
} else if (entry.isFile() && shouldTransformFile2(entry.name)) {
|
|
39646
|
+
try {
|
|
39647
|
+
const content = await readFile20(fullPath, "utf-8");
|
|
39648
|
+
const { transformed, changes } = transformOpenCodeContent(content);
|
|
39649
|
+
if (changes > 0) {
|
|
39650
|
+
await writeFile16(fullPath, transformed, "utf-8");
|
|
39651
|
+
filesTransformed++;
|
|
39652
|
+
totalChanges += changes;
|
|
39653
|
+
if (options.verbose) {
|
|
39654
|
+
logger.verbose(`Transformed ${changes} OpenCode path(s) in ${fullPath}`);
|
|
39655
|
+
}
|
|
39656
|
+
}
|
|
39657
|
+
} catch (error) {
|
|
39658
|
+
filesSkipped++;
|
|
39659
|
+
if (options.verbose) {
|
|
39660
|
+
logger.verbose(`Skipping ${fullPath}: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
39661
|
+
}
|
|
39662
|
+
}
|
|
39663
|
+
}
|
|
39664
|
+
}
|
|
39665
|
+
}
|
|
39666
|
+
await processDirectory2(directory);
|
|
39667
|
+
return { filesTransformed, totalChanges, filesSkipped };
|
|
39668
|
+
}
|
|
39669
|
+
|
|
39670
|
+
// src/commands/init/phases/opencode-handler.ts
|
|
39671
|
+
init_logger();
|
|
39672
|
+
var import_fs_extra25 = __toESM(require_lib(), 1);
|
|
39673
|
+
async function handleOpenCode(ctx) {
|
|
39674
|
+
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir) {
|
|
39675
|
+
return ctx;
|
|
39676
|
+
}
|
|
39677
|
+
const openCodeSource = join60(ctx.extractDir, ".opencode");
|
|
39678
|
+
if (!await import_fs_extra25.pathExists(openCodeSource)) {
|
|
39679
|
+
logger.debug("No .opencode directory in archive, skipping");
|
|
39680
|
+
return ctx;
|
|
39681
|
+
}
|
|
39682
|
+
logger.info("Processing .opencode configuration...");
|
|
39683
|
+
if (ctx.options.global) {
|
|
39684
|
+
const targetDir = PathResolver.getOpenCodeDir(true);
|
|
39685
|
+
logger.verbose(`Relocating .opencode to ${targetDir}`);
|
|
39686
|
+
const transformResult = await transformPathsForGlobalOpenCode(openCodeSource, {
|
|
39687
|
+
verbose: logger.isVerbose()
|
|
39688
|
+
});
|
|
39689
|
+
if (transformResult.totalChanges > 0) {
|
|
39690
|
+
logger.success(`Transformed ${transformResult.totalChanges} OpenCode path(s) in ${transformResult.filesTransformed} file(s)`);
|
|
39691
|
+
}
|
|
39692
|
+
await import_fs_extra25.ensureDir(targetDir);
|
|
39693
|
+
const entries = await readdir22(openCodeSource, { withFileTypes: true });
|
|
39694
|
+
for (const entry of entries) {
|
|
39695
|
+
const sourcePath = join60(openCodeSource, entry.name);
|
|
39696
|
+
const targetPath = join60(targetDir, entry.name);
|
|
39697
|
+
if (await import_fs_extra25.pathExists(targetPath)) {
|
|
39698
|
+
if (!ctx.options.forceOverwrite) {
|
|
39699
|
+
logger.verbose(`Skipping existing: ${entry.name}`);
|
|
39700
|
+
continue;
|
|
39701
|
+
}
|
|
39702
|
+
}
|
|
39703
|
+
await cp(sourcePath, targetPath, { recursive: true });
|
|
39704
|
+
logger.verbose(`Copied: ${entry.name}`);
|
|
39705
|
+
}
|
|
39706
|
+
await rm5(openCodeSource, { recursive: true, force: true });
|
|
39707
|
+
logger.success(`OpenCode config installed to ${targetDir}`);
|
|
39708
|
+
} else {
|
|
39709
|
+
logger.debug("Local mode: .opencode will be placed at project root");
|
|
39710
|
+
}
|
|
39711
|
+
return ctx;
|
|
39712
|
+
}
|
|
39551
39713
|
// src/domains/config/config-manager.ts
|
|
39552
39714
|
init_logger();
|
|
39553
39715
|
import { existsSync as existsSync18 } from "node:fs";
|
|
39554
|
-
import { mkdir as mkdir19, readFile as
|
|
39716
|
+
import { mkdir as mkdir19, readFile as readFile21, rename as rename2, rm as rm6, writeFile as writeFile17 } from "node:fs/promises";
|
|
39555
39717
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
39556
|
-
import { platform as
|
|
39557
|
-
import { join as
|
|
39718
|
+
import { platform as platform11 } from "node:os";
|
|
39719
|
+
import { join as join61 } from "node:path";
|
|
39558
39720
|
init_types2();
|
|
39559
39721
|
var PROJECT_CONFIG_FILE = ".ck.json";
|
|
39560
39722
|
|
|
@@ -39562,7 +39724,7 @@ class ConfigManager {
|
|
|
39562
39724
|
static config = null;
|
|
39563
39725
|
static globalFlag = false;
|
|
39564
39726
|
static getProjectConfigDir(projectDir, global3) {
|
|
39565
|
-
return global3 ? projectDir :
|
|
39727
|
+
return global3 ? projectDir : join61(projectDir, ".claude");
|
|
39566
39728
|
}
|
|
39567
39729
|
static setGlobalFlag(global3) {
|
|
39568
39730
|
ConfigManager.globalFlag = global3;
|
|
@@ -39578,7 +39740,7 @@ class ConfigManager {
|
|
|
39578
39740
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
39579
39741
|
try {
|
|
39580
39742
|
if (existsSync18(configFile)) {
|
|
39581
|
-
const content = await
|
|
39743
|
+
const content = await readFile21(configFile, "utf-8");
|
|
39582
39744
|
const data = JSON.parse(content);
|
|
39583
39745
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
39584
39746
|
logger.debug(`Config loaded from ${configFile}`);
|
|
@@ -39597,12 +39759,12 @@ class ConfigManager {
|
|
|
39597
39759
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
39598
39760
|
if (!existsSync18(configDir)) {
|
|
39599
39761
|
await mkdir19(configDir, { recursive: true });
|
|
39600
|
-
if (
|
|
39762
|
+
if (platform11() !== "win32") {
|
|
39601
39763
|
await chmod2(configDir, 448);
|
|
39602
39764
|
}
|
|
39603
39765
|
}
|
|
39604
|
-
await
|
|
39605
|
-
if (
|
|
39766
|
+
await writeFile17(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
39767
|
+
if (platform11() !== "win32") {
|
|
39606
39768
|
await chmod2(configFile, 384);
|
|
39607
39769
|
}
|
|
39608
39770
|
ConfigManager.config = validConfig;
|
|
@@ -39629,10 +39791,10 @@ class ConfigManager {
|
|
|
39629
39791
|
}
|
|
39630
39792
|
static async loadProjectConfig(projectDir, global3 = false) {
|
|
39631
39793
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
39632
|
-
const configPath =
|
|
39794
|
+
const configPath = join61(configDir, PROJECT_CONFIG_FILE);
|
|
39633
39795
|
try {
|
|
39634
39796
|
if (existsSync18(configPath)) {
|
|
39635
|
-
const content = await
|
|
39797
|
+
const content = await readFile21(configPath, "utf-8");
|
|
39636
39798
|
const data = JSON.parse(content);
|
|
39637
39799
|
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
39638
39800
|
logger.debug(`Project config loaded from ${configPath}`);
|
|
@@ -39645,7 +39807,7 @@ class ConfigManager {
|
|
|
39645
39807
|
}
|
|
39646
39808
|
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
39647
39809
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
39648
|
-
const configPath =
|
|
39810
|
+
const configPath = join61(configDir, PROJECT_CONFIG_FILE);
|
|
39649
39811
|
try {
|
|
39650
39812
|
if (!existsSync18(configDir)) {
|
|
39651
39813
|
await mkdir19(configDir, { recursive: true });
|
|
@@ -39653,7 +39815,7 @@ class ConfigManager {
|
|
|
39653
39815
|
let existingConfig = {};
|
|
39654
39816
|
if (existsSync18(configPath)) {
|
|
39655
39817
|
try {
|
|
39656
|
-
const content = await
|
|
39818
|
+
const content = await readFile21(configPath, "utf-8");
|
|
39657
39819
|
existingConfig = JSON.parse(content);
|
|
39658
39820
|
} catch (error) {
|
|
39659
39821
|
logger.debug(`Could not parse existing config, starting fresh: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -39668,7 +39830,7 @@ class ConfigManager {
|
|
|
39668
39830
|
...validFolders
|
|
39669
39831
|
}
|
|
39670
39832
|
};
|
|
39671
|
-
await
|
|
39833
|
+
await writeFile17(configPath, JSON.stringify(mergedConfig, null, 2), "utf-8");
|
|
39672
39834
|
logger.debug(`Project config saved to ${configPath}`);
|
|
39673
39835
|
} catch (error) {
|
|
39674
39836
|
throw new Error(`Failed to save project config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -39694,11 +39856,11 @@ class ConfigManager {
|
|
|
39694
39856
|
}
|
|
39695
39857
|
static projectConfigExists(projectDir, global3 = false) {
|
|
39696
39858
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
39697
|
-
return existsSync18(
|
|
39859
|
+
return existsSync18(join61(configDir, PROJECT_CONFIG_FILE));
|
|
39698
39860
|
}
|
|
39699
39861
|
static async migrateNestedConfig(globalDir) {
|
|
39700
|
-
const correctPath =
|
|
39701
|
-
const incorrectPath =
|
|
39862
|
+
const correctPath = join61(globalDir, PROJECT_CONFIG_FILE);
|
|
39863
|
+
const incorrectPath = join61(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
39702
39864
|
if (existsSync18(correctPath)) {
|
|
39703
39865
|
logger.debug("Config already exists at correct location, skipping migration");
|
|
39704
39866
|
return false;
|
|
@@ -39708,9 +39870,9 @@ class ConfigManager {
|
|
|
39708
39870
|
logger.info("Migrating .ck.json from nested location to correct location...");
|
|
39709
39871
|
await rename2(incorrectPath, correctPath);
|
|
39710
39872
|
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
39711
|
-
const nestedClaudeDir =
|
|
39873
|
+
const nestedClaudeDir = join61(globalDir, ".claude");
|
|
39712
39874
|
try {
|
|
39713
|
-
await
|
|
39875
|
+
await rm6(nestedClaudeDir, { recursive: false });
|
|
39714
39876
|
logger.debug("Removed empty nested .claude directory");
|
|
39715
39877
|
} catch (rmError) {
|
|
39716
39878
|
logger.debug(`Could not remove nested .claude dir (may contain other files): ${rmError instanceof Error ? rmError.message : "Unknown"}`);
|
|
@@ -39799,14 +39961,14 @@ Please use only one download method.`);
|
|
|
39799
39961
|
};
|
|
39800
39962
|
}
|
|
39801
39963
|
// src/commands/init/phases/post-install-handler.ts
|
|
39802
|
-
import { join as
|
|
39964
|
+
import { join as join64 } from "node:path";
|
|
39803
39965
|
|
|
39804
39966
|
// src/domains/installation/setup-wizard.ts
|
|
39805
|
-
import { join as
|
|
39967
|
+
import { join as join63 } from "node:path";
|
|
39806
39968
|
|
|
39807
39969
|
// src/domains/config/config-generator.ts
|
|
39808
|
-
var
|
|
39809
|
-
import { join as
|
|
39970
|
+
var import_fs_extra26 = __toESM(require_lib(), 1);
|
|
39971
|
+
import { join as join62 } from "node:path";
|
|
39810
39972
|
async function generateEnvFile(targetDir, values) {
|
|
39811
39973
|
const lines = [
|
|
39812
39974
|
"# Generated by ClaudeKit CLI setup wizard",
|
|
@@ -39848,8 +40010,8 @@ async function generateEnvFile(targetDir, values) {
|
|
|
39848
40010
|
for (const [key, value] of otherValues) {
|
|
39849
40011
|
lines.push(`${key}=${value}`);
|
|
39850
40012
|
}
|
|
39851
|
-
const envPath =
|
|
39852
|
-
await
|
|
40013
|
+
const envPath = join62(targetDir, ".env");
|
|
40014
|
+
await import_fs_extra26.writeFile(envPath, `${lines.join(`
|
|
39853
40015
|
`)}
|
|
39854
40016
|
`, { mode: 384 });
|
|
39855
40017
|
}
|
|
@@ -39867,7 +40029,7 @@ function validateApiKey(value, pattern) {
|
|
|
39867
40029
|
// src/domains/installation/setup-wizard.ts
|
|
39868
40030
|
init_logger();
|
|
39869
40031
|
init_dist2();
|
|
39870
|
-
var
|
|
40032
|
+
var import_fs_extra27 = __toESM(require_lib(), 1);
|
|
39871
40033
|
var ESSENTIAL_CONFIGS = [
|
|
39872
40034
|
{
|
|
39873
40035
|
key: "GEMINI_API_KEY",
|
|
@@ -39896,7 +40058,7 @@ var ESSENTIAL_CONFIGS = [
|
|
|
39896
40058
|
];
|
|
39897
40059
|
async function parseEnvFile(path11) {
|
|
39898
40060
|
try {
|
|
39899
|
-
const content = await
|
|
40061
|
+
const content = await import_fs_extra27.readFile(path11, "utf-8");
|
|
39900
40062
|
const env2 = {};
|
|
39901
40063
|
for (const line of content.split(`
|
|
39902
40064
|
`)) {
|
|
@@ -39922,8 +40084,8 @@ async function parseEnvFile(path11) {
|
|
|
39922
40084
|
}
|
|
39923
40085
|
}
|
|
39924
40086
|
async function checkGlobalConfig() {
|
|
39925
|
-
const globalEnvPath =
|
|
39926
|
-
if (!await
|
|
40087
|
+
const globalEnvPath = join63(PathResolver.getGlobalKitDir(), ".env");
|
|
40088
|
+
if (!await import_fs_extra27.pathExists(globalEnvPath))
|
|
39927
40089
|
return false;
|
|
39928
40090
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
39929
40091
|
return Object.keys(env2).length > 0;
|
|
@@ -39938,8 +40100,8 @@ async function runSetupWizard(options) {
|
|
|
39938
40100
|
let globalEnv = {};
|
|
39939
40101
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
39940
40102
|
if (!isGlobal) {
|
|
39941
|
-
const globalEnvPath =
|
|
39942
|
-
if (await
|
|
40103
|
+
const globalEnvPath = join63(PathResolver.getGlobalKitDir(), ".env");
|
|
40104
|
+
if (await import_fs_extra27.pathExists(globalEnvPath)) {
|
|
39943
40105
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
39944
40106
|
}
|
|
39945
40107
|
}
|
|
@@ -40001,7 +40163,7 @@ async function runSetupWizard(options) {
|
|
|
40001
40163
|
}
|
|
40002
40164
|
}
|
|
40003
40165
|
await generateEnvFile(targetDir, values);
|
|
40004
|
-
f2.success(`Configuration saved to ${
|
|
40166
|
+
f2.success(`Configuration saved to ${join63(targetDir, ".env")}`);
|
|
40005
40167
|
return true;
|
|
40006
40168
|
}
|
|
40007
40169
|
async function promptForAdditionalGeminiKeys(primaryKey) {
|
|
@@ -40051,17 +40213,17 @@ async function promptForAdditionalGeminiKeys(primaryKey) {
|
|
|
40051
40213
|
|
|
40052
40214
|
// src/commands/init/phases/post-install-handler.ts
|
|
40053
40215
|
init_logger();
|
|
40054
|
-
var
|
|
40216
|
+
var import_fs_extra28 = __toESM(require_lib(), 1);
|
|
40055
40217
|
async function handlePostInstall(ctx) {
|
|
40056
40218
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir || !ctx.claudeDir) {
|
|
40057
40219
|
return ctx;
|
|
40058
40220
|
}
|
|
40059
40221
|
if (ctx.options.global) {
|
|
40060
|
-
const claudeMdSource =
|
|
40061
|
-
const claudeMdDest =
|
|
40062
|
-
if (await
|
|
40063
|
-
if (!await
|
|
40064
|
-
await
|
|
40222
|
+
const claudeMdSource = join64(ctx.extractDir, "CLAUDE.md");
|
|
40223
|
+
const claudeMdDest = join64(ctx.resolvedDir, "CLAUDE.md");
|
|
40224
|
+
if (await import_fs_extra28.pathExists(claudeMdSource)) {
|
|
40225
|
+
if (!await import_fs_extra28.pathExists(claudeMdDest)) {
|
|
40226
|
+
await import_fs_extra28.copy(claudeMdSource, claudeMdDest);
|
|
40065
40227
|
logger.success("Copied CLAUDE.md to global directory");
|
|
40066
40228
|
} else {
|
|
40067
40229
|
logger.debug("CLAUDE.md already exists in global directory (preserved)");
|
|
@@ -40105,8 +40267,8 @@ async function handlePostInstall(ctx) {
|
|
|
40105
40267
|
}
|
|
40106
40268
|
}
|
|
40107
40269
|
if (!ctx.options.skipSetup && !ctx.isNonInteractive) {
|
|
40108
|
-
const envPath =
|
|
40109
|
-
if (!await
|
|
40270
|
+
const envPath = join64(ctx.claudeDir, ".env");
|
|
40271
|
+
if (!await import_fs_extra28.pathExists(envPath)) {
|
|
40110
40272
|
const shouldSetup = await ctx.prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
40111
40273
|
if (shouldSetup) {
|
|
40112
40274
|
await runSetupWizard({
|
|
@@ -40127,7 +40289,7 @@ Optional: DISCORD_WEBHOOK_URL, TELEGRAM_BOT_TOKEN`, "Configuration skipped");
|
|
|
40127
40289
|
}
|
|
40128
40290
|
// src/commands/init/phases/selection-handler.ts
|
|
40129
40291
|
import { mkdir as mkdir20 } from "node:fs/promises";
|
|
40130
|
-
import { join as
|
|
40292
|
+
import { join as join66, resolve as resolve7 } from "node:path";
|
|
40131
40293
|
|
|
40132
40294
|
// src/domains/github/kit-access-checker.ts
|
|
40133
40295
|
init_logger();
|
|
@@ -40156,11 +40318,11 @@ async function detectAccessibleKits() {
|
|
|
40156
40318
|
|
|
40157
40319
|
// src/domains/installation/fresh-installer.ts
|
|
40158
40320
|
init_logger();
|
|
40159
|
-
import { join as
|
|
40160
|
-
var
|
|
40321
|
+
import { join as join65 } from "node:path";
|
|
40322
|
+
var import_fs_extra29 = __toESM(require_lib(), 1);
|
|
40161
40323
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
|
|
40162
40324
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
40163
|
-
if (!await
|
|
40325
|
+
if (!await import_fs_extra29.pathExists(claudeDir)) {
|
|
40164
40326
|
logger.info(".claude directory does not exist, proceeding with fresh installation");
|
|
40165
40327
|
return true;
|
|
40166
40328
|
}
|
|
@@ -40175,8 +40337,8 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
40175
40337
|
const { rmSync } = await import("node:fs");
|
|
40176
40338
|
let removedCount = 0;
|
|
40177
40339
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
40178
|
-
const subdirPath =
|
|
40179
|
-
if (await
|
|
40340
|
+
const subdirPath = join65(claudeDir, subdir);
|
|
40341
|
+
if (await import_fs_extra29.pathExists(subdirPath)) {
|
|
40180
40342
|
rmSync(subdirPath, { recursive: true, force: true });
|
|
40181
40343
|
removedCount++;
|
|
40182
40344
|
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
@@ -40193,7 +40355,7 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
40193
40355
|
// src/commands/init/phases/selection-handler.ts
|
|
40194
40356
|
init_logger();
|
|
40195
40357
|
init_types2();
|
|
40196
|
-
var
|
|
40358
|
+
var import_fs_extra30 = __toESM(require_lib(), 1);
|
|
40197
40359
|
|
|
40198
40360
|
// src/commands/init/types.ts
|
|
40199
40361
|
function isSyncContext(ctx) {
|
|
@@ -40357,7 +40519,7 @@ async function handleSelection(ctx) {
|
|
|
40357
40519
|
return { ...ctx, cancelled: true };
|
|
40358
40520
|
}
|
|
40359
40521
|
}
|
|
40360
|
-
if (!await
|
|
40522
|
+
if (!await import_fs_extra30.pathExists(resolvedDir)) {
|
|
40361
40523
|
if (ctx.options.global) {
|
|
40362
40524
|
await mkdir20(resolvedDir, { recursive: true });
|
|
40363
40525
|
logger.info(`Created global directory: ${resolvedDir}`);
|
|
@@ -40369,7 +40531,7 @@ async function handleSelection(ctx) {
|
|
|
40369
40531
|
}
|
|
40370
40532
|
if (!ctx.options.fresh) {
|
|
40371
40533
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
40372
|
-
const claudeDir = prefix ?
|
|
40534
|
+
const claudeDir = prefix ? join66(resolvedDir, prefix) : resolvedDir;
|
|
40373
40535
|
try {
|
|
40374
40536
|
const existingMetadata = await readManifest(claudeDir);
|
|
40375
40537
|
if (existingMetadata?.kits) {
|
|
@@ -40401,7 +40563,7 @@ async function handleSelection(ctx) {
|
|
|
40401
40563
|
}
|
|
40402
40564
|
if (ctx.options.fresh) {
|
|
40403
40565
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
40404
|
-
const claudeDir = prefix ?
|
|
40566
|
+
const claudeDir = prefix ? join66(resolvedDir, prefix) : resolvedDir;
|
|
40405
40567
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
40406
40568
|
if (!canProceed) {
|
|
40407
40569
|
return { ...ctx, cancelled: true };
|
|
@@ -40419,7 +40581,7 @@ async function handleSelection(ctx) {
|
|
|
40419
40581
|
logger.info("Fetching available versions...");
|
|
40420
40582
|
let currentVersion = null;
|
|
40421
40583
|
try {
|
|
40422
|
-
const metadataPath = ctx.options.global ?
|
|
40584
|
+
const metadataPath = ctx.options.global ? join66(PathResolver.getGlobalKitDir(), "metadata.json") : join66(resolvedDir, ".claude", "metadata.json");
|
|
40423
40585
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
40424
40586
|
currentVersion = metadata?.version || null;
|
|
40425
40587
|
if (currentVersion) {
|
|
@@ -40487,24 +40649,24 @@ async function handleSelection(ctx) {
|
|
|
40487
40649
|
};
|
|
40488
40650
|
}
|
|
40489
40651
|
// src/commands/init/phases/sync-handler.ts
|
|
40490
|
-
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as
|
|
40491
|
-
import { dirname as dirname9, join as
|
|
40652
|
+
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as writeFile19 } from "node:fs/promises";
|
|
40653
|
+
import { dirname as dirname9, join as join67, resolve as resolve8 } from "node:path";
|
|
40492
40654
|
init_logger();
|
|
40493
|
-
var
|
|
40655
|
+
var import_fs_extra31 = __toESM(require_lib(), 1);
|
|
40494
40656
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
40495
40657
|
async function handleSync(ctx) {
|
|
40496
40658
|
if (!ctx.options.sync) {
|
|
40497
40659
|
return ctx;
|
|
40498
40660
|
}
|
|
40499
40661
|
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve8(ctx.options.dir || ".");
|
|
40500
|
-
const claudeDir = ctx.options.global ? resolvedDir :
|
|
40501
|
-
if (!await
|
|
40662
|
+
const claudeDir = ctx.options.global ? resolvedDir : join67(resolvedDir, ".claude");
|
|
40663
|
+
if (!await import_fs_extra31.pathExists(claudeDir)) {
|
|
40502
40664
|
logger.error("Cannot sync: no .claude directory found");
|
|
40503
40665
|
ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
|
|
40504
40666
|
return { ...ctx, cancelled: true };
|
|
40505
40667
|
}
|
|
40506
|
-
const metadataPath =
|
|
40507
|
-
if (!await
|
|
40668
|
+
const metadataPath = join67(claudeDir, "metadata.json");
|
|
40669
|
+
if (!await import_fs_extra31.pathExists(metadataPath)) {
|
|
40508
40670
|
logger.error("Cannot sync: no metadata.json found");
|
|
40509
40671
|
ctx.prompts.note(`Your installation may be from an older version.
|
|
40510
40672
|
Run 'ck init' to update.`, "Legacy Installation");
|
|
@@ -40603,7 +40765,7 @@ function getLockTimeout() {
|
|
|
40603
40765
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
40604
40766
|
async function acquireSyncLock(global3) {
|
|
40605
40767
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
40606
|
-
const lockPath =
|
|
40768
|
+
const lockPath = join67(cacheDir, ".sync-lock");
|
|
40607
40769
|
const startTime = Date.now();
|
|
40608
40770
|
const lockTimeout = getLockTimeout();
|
|
40609
40771
|
await mkdir21(dirname9(lockPath), { recursive: true });
|
|
@@ -40649,7 +40811,7 @@ async function executeSyncMerge(ctx) {
|
|
|
40649
40811
|
const releaseLock = await acquireSyncLock(ctx.options.global);
|
|
40650
40812
|
try {
|
|
40651
40813
|
const trackedFiles = ctx.syncTrackedFiles;
|
|
40652
|
-
const upstreamDir = ctx.options.global ?
|
|
40814
|
+
const upstreamDir = ctx.options.global ? join67(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
40653
40815
|
logger.info("Analyzing file changes...");
|
|
40654
40816
|
const plan = await SyncEngine.createSyncPlan(trackedFiles, ctx.claudeDir, upstreamDir);
|
|
40655
40817
|
displaySyncPlan(plan);
|
|
@@ -40668,7 +40830,7 @@ async function executeSyncMerge(ctx) {
|
|
|
40668
40830
|
try {
|
|
40669
40831
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
40670
40832
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
40671
|
-
const targetDir =
|
|
40833
|
+
const targetDir = join67(targetPath, "..");
|
|
40672
40834
|
try {
|
|
40673
40835
|
await mkdir21(targetDir, { recursive: true });
|
|
40674
40836
|
} catch (mkdirError) {
|
|
@@ -40749,7 +40911,7 @@ async function executeSyncMerge(ctx) {
|
|
|
40749
40911
|
try {
|
|
40750
40912
|
const tempPath = `${currentPath}.tmp.${Date.now()}`;
|
|
40751
40913
|
try {
|
|
40752
|
-
await
|
|
40914
|
+
await writeFile19(tempPath, result.result, "utf-8");
|
|
40753
40915
|
await rename3(tempPath, currentPath);
|
|
40754
40916
|
} catch (atomicError) {
|
|
40755
40917
|
await unlink7(tempPath).catch(() => {});
|
|
@@ -40837,9 +40999,9 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
40837
40999
|
for (const file of files) {
|
|
40838
41000
|
try {
|
|
40839
41001
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
40840
|
-
if (await
|
|
41002
|
+
if (await import_fs_extra31.pathExists(sourcePath)) {
|
|
40841
41003
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
40842
|
-
const targetDir =
|
|
41004
|
+
const targetDir = join67(targetPath, "..");
|
|
40843
41005
|
await mkdir21(targetDir, { recursive: true });
|
|
40844
41006
|
await copyFile6(sourcePath, targetPath);
|
|
40845
41007
|
}
|
|
@@ -40853,7 +41015,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
40853
41015
|
}
|
|
40854
41016
|
}
|
|
40855
41017
|
// src/commands/init/phases/transform-handler.ts
|
|
40856
|
-
import { join as
|
|
41018
|
+
import { join as join71 } from "node:path";
|
|
40857
41019
|
|
|
40858
41020
|
// src/services/transformers/folder-path-transformer.ts
|
|
40859
41021
|
init_logger();
|
|
@@ -40862,40 +41024,40 @@ init_types2();
|
|
|
40862
41024
|
// src/services/transformers/folder-transform/folder-renamer.ts
|
|
40863
41025
|
init_logger();
|
|
40864
41026
|
init_types2();
|
|
40865
|
-
var
|
|
40866
|
-
import { rename as rename4, rm as
|
|
40867
|
-
import { join as
|
|
41027
|
+
var import_fs_extra32 = __toESM(require_lib(), 1);
|
|
41028
|
+
import { rename as rename4, rm as rm7 } from "node:fs/promises";
|
|
41029
|
+
import { join as join68, relative as relative12 } from "node:path";
|
|
40868
41030
|
async function collectDirsToRename(extractDir, folders) {
|
|
40869
41031
|
const dirsToRename = [];
|
|
40870
41032
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
40871
|
-
const docsPath =
|
|
40872
|
-
if (await
|
|
41033
|
+
const docsPath = join68(extractDir, DEFAULT_FOLDERS.docs);
|
|
41034
|
+
if (await import_fs_extra32.pathExists(docsPath)) {
|
|
40873
41035
|
dirsToRename.push({
|
|
40874
41036
|
from: docsPath,
|
|
40875
|
-
to:
|
|
41037
|
+
to: join68(extractDir, folders.docs)
|
|
40876
41038
|
});
|
|
40877
41039
|
}
|
|
40878
|
-
const claudeDocsPath =
|
|
40879
|
-
if (await
|
|
41040
|
+
const claudeDocsPath = join68(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
41041
|
+
if (await import_fs_extra32.pathExists(claudeDocsPath)) {
|
|
40880
41042
|
dirsToRename.push({
|
|
40881
41043
|
from: claudeDocsPath,
|
|
40882
|
-
to:
|
|
41044
|
+
to: join68(extractDir, ".claude", folders.docs)
|
|
40883
41045
|
});
|
|
40884
41046
|
}
|
|
40885
41047
|
}
|
|
40886
41048
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
40887
|
-
const plansPath =
|
|
40888
|
-
if (await
|
|
41049
|
+
const plansPath = join68(extractDir, DEFAULT_FOLDERS.plans);
|
|
41050
|
+
if (await import_fs_extra32.pathExists(plansPath)) {
|
|
40889
41051
|
dirsToRename.push({
|
|
40890
41052
|
from: plansPath,
|
|
40891
|
-
to:
|
|
41053
|
+
to: join68(extractDir, folders.plans)
|
|
40892
41054
|
});
|
|
40893
41055
|
}
|
|
40894
|
-
const claudePlansPath =
|
|
40895
|
-
if (await
|
|
41056
|
+
const claudePlansPath = join68(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
41057
|
+
if (await import_fs_extra32.pathExists(claudePlansPath)) {
|
|
40896
41058
|
dirsToRename.push({
|
|
40897
41059
|
from: claudePlansPath,
|
|
40898
|
-
to:
|
|
41060
|
+
to: join68(extractDir, ".claude", folders.plans)
|
|
40899
41061
|
});
|
|
40900
41062
|
}
|
|
40901
41063
|
}
|
|
@@ -40907,8 +41069,8 @@ async function moveAcrossDevices(src, dest) {
|
|
|
40907
41069
|
} catch (e2) {
|
|
40908
41070
|
if (e2.code === "EXDEV") {
|
|
40909
41071
|
logger.debug(`Cross-device move detected, using copy+delete: ${src} -> ${dest}`);
|
|
40910
|
-
await
|
|
40911
|
-
await
|
|
41072
|
+
await import_fs_extra32.copy(src, dest, { overwrite: true });
|
|
41073
|
+
await rm7(src, { recursive: true, force: true });
|
|
40912
41074
|
} else {
|
|
40913
41075
|
throw e2;
|
|
40914
41076
|
}
|
|
@@ -40935,8 +41097,8 @@ async function renameFolders(dirsToRename, extractDir, options) {
|
|
|
40935
41097
|
// src/services/transformers/folder-transform/path-replacer.ts
|
|
40936
41098
|
init_logger();
|
|
40937
41099
|
init_types2();
|
|
40938
|
-
import { readFile as
|
|
40939
|
-
import { join as
|
|
41100
|
+
import { readFile as readFile23, readdir as readdir23, writeFile as writeFile20 } from "node:fs/promises";
|
|
41101
|
+
import { join as join69, relative as relative13 } from "node:path";
|
|
40940
41102
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
40941
41103
|
".md",
|
|
40942
41104
|
".txt",
|
|
@@ -40987,9 +41149,9 @@ function compileReplacements(replacements) {
|
|
|
40987
41149
|
async function transformFileContents(dir, compiledReplacements, options) {
|
|
40988
41150
|
let filesChanged = 0;
|
|
40989
41151
|
let replacementsCount = 0;
|
|
40990
|
-
const entries = await
|
|
41152
|
+
const entries = await readdir23(dir, { withFileTypes: true });
|
|
40991
41153
|
for (const entry of entries) {
|
|
40992
|
-
const fullPath =
|
|
41154
|
+
const fullPath = join69(dir, entry.name);
|
|
40993
41155
|
if (entry.isDirectory()) {
|
|
40994
41156
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
40995
41157
|
continue;
|
|
@@ -41002,7 +41164,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
41002
41164
|
if (!shouldTransform)
|
|
41003
41165
|
continue;
|
|
41004
41166
|
try {
|
|
41005
|
-
const content = await
|
|
41167
|
+
const content = await readFile23(fullPath, "utf-8");
|
|
41006
41168
|
let newContent = content;
|
|
41007
41169
|
let changeCount = 0;
|
|
41008
41170
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -41018,7 +41180,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
41018
41180
|
if (options.dryRun) {
|
|
41019
41181
|
logger.debug(`[dry-run] Would update ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
41020
41182
|
} else {
|
|
41021
|
-
await
|
|
41183
|
+
await writeFile20(fullPath, newContent, "utf-8");
|
|
41022
41184
|
logger.debug(`Updated ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
41023
41185
|
}
|
|
41024
41186
|
filesChanged++;
|
|
@@ -41124,15 +41286,15 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
41124
41286
|
|
|
41125
41287
|
// src/services/transformers/global-path-transformer.ts
|
|
41126
41288
|
init_logger();
|
|
41127
|
-
import { readFile as
|
|
41128
|
-
import { platform as
|
|
41129
|
-
import { extname as
|
|
41130
|
-
var
|
|
41131
|
-
var HOME_PREFIX =
|
|
41289
|
+
import { readFile as readFile24, readdir as readdir24, writeFile as writeFile21 } from "node:fs/promises";
|
|
41290
|
+
import { platform as platform12 } from "node:os";
|
|
41291
|
+
import { extname as extname3, join as join70 } from "node:path";
|
|
41292
|
+
var IS_WINDOWS4 = platform12() === "win32";
|
|
41293
|
+
var HOME_PREFIX = IS_WINDOWS4 ? "%USERPROFILE%" : "$HOME";
|
|
41132
41294
|
function getHomeDirPrefix() {
|
|
41133
41295
|
return HOME_PREFIX;
|
|
41134
41296
|
}
|
|
41135
|
-
var
|
|
41297
|
+
var TRANSFORMABLE_EXTENSIONS3 = new Set([
|
|
41136
41298
|
".md",
|
|
41137
41299
|
".js",
|
|
41138
41300
|
".ts",
|
|
@@ -41149,7 +41311,7 @@ function transformContent(content) {
|
|
|
41149
41311
|
let transformed = content;
|
|
41150
41312
|
const homePrefix = getHomeDirPrefix();
|
|
41151
41313
|
const claudePath = `${homePrefix}/.claude/`;
|
|
41152
|
-
if (
|
|
41314
|
+
if (IS_WINDOWS4) {
|
|
41153
41315
|
transformed = transformed.replace(/\$HOME\/\.claude\//g, () => {
|
|
41154
41316
|
changes++;
|
|
41155
41317
|
return claudePath;
|
|
@@ -41179,7 +41341,7 @@ function transformContent(content) {
|
|
|
41179
41341
|
changes++;
|
|
41180
41342
|
return claudePath;
|
|
41181
41343
|
});
|
|
41182
|
-
if (
|
|
41344
|
+
if (IS_WINDOWS4) {
|
|
41183
41345
|
transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%\/\.claude\//g, () => {
|
|
41184
41346
|
changes++;
|
|
41185
41347
|
return claudePath;
|
|
@@ -41223,10 +41385,10 @@ function transformContent(content) {
|
|
|
41223
41385
|
});
|
|
41224
41386
|
return { transformed, changes };
|
|
41225
41387
|
}
|
|
41226
|
-
function
|
|
41227
|
-
const ext2 =
|
|
41388
|
+
function shouldTransformFile3(filename) {
|
|
41389
|
+
const ext2 = extname3(filename).toLowerCase();
|
|
41228
41390
|
const basename3 = filename.split("/").pop() || filename;
|
|
41229
|
-
return
|
|
41391
|
+
return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename3);
|
|
41230
41392
|
}
|
|
41231
41393
|
async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
41232
41394
|
let filesTransformed = 0;
|
|
@@ -41234,20 +41396,20 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
41234
41396
|
let filesSkipped = 0;
|
|
41235
41397
|
const skippedFiles = [];
|
|
41236
41398
|
async function processDirectory2(dir) {
|
|
41237
|
-
const entries = await
|
|
41399
|
+
const entries = await readdir24(dir, { withFileTypes: true });
|
|
41238
41400
|
for (const entry of entries) {
|
|
41239
|
-
const fullPath =
|
|
41401
|
+
const fullPath = join70(dir, entry.name);
|
|
41240
41402
|
if (entry.isDirectory()) {
|
|
41241
41403
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
41242
41404
|
continue;
|
|
41243
41405
|
}
|
|
41244
41406
|
await processDirectory2(fullPath);
|
|
41245
|
-
} else if (entry.isFile() &&
|
|
41407
|
+
} else if (entry.isFile() && shouldTransformFile3(entry.name)) {
|
|
41246
41408
|
try {
|
|
41247
|
-
const content = await
|
|
41409
|
+
const content = await readFile24(fullPath, "utf-8");
|
|
41248
41410
|
const { transformed, changes } = transformContent(content);
|
|
41249
41411
|
if (changes > 0) {
|
|
41250
|
-
await
|
|
41412
|
+
await writeFile21(fullPath, transformed, "utf-8");
|
|
41251
41413
|
filesTransformed++;
|
|
41252
41414
|
totalChanges += changes;
|
|
41253
41415
|
if (options.verbose) {
|
|
@@ -41312,7 +41474,7 @@ async function handleTransforms(ctx) {
|
|
|
41312
41474
|
logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
|
|
41313
41475
|
}
|
|
41314
41476
|
}
|
|
41315
|
-
const claudeDir = ctx.options.global ? ctx.resolvedDir :
|
|
41477
|
+
const claudeDir = ctx.options.global ? ctx.resolvedDir : join71(ctx.resolvedDir, ".claude");
|
|
41316
41478
|
return {
|
|
41317
41479
|
...ctx,
|
|
41318
41480
|
foldersConfig,
|
|
@@ -41350,6 +41512,9 @@ Installing additional kit: ${kit.name}`);
|
|
|
41350
41512
|
extractDir: undefined
|
|
41351
41513
|
};
|
|
41352
41514
|
ctx = await handleDownload(ctx);
|
|
41515
|
+
if (ctx.cancelled)
|
|
41516
|
+
return ctx;
|
|
41517
|
+
ctx = await handleOpenCode(ctx);
|
|
41353
41518
|
if (ctx.cancelled)
|
|
41354
41519
|
return ctx;
|
|
41355
41520
|
ctx = await handleTransforms(ctx);
|
|
@@ -41416,6 +41581,11 @@ async function executeInit(options, prompts) {
|
|
|
41416
41581
|
ctx = await handleDownload(ctx);
|
|
41417
41582
|
if (ctx.cancelled)
|
|
41418
41583
|
return;
|
|
41584
|
+
if (!isSyncMode) {
|
|
41585
|
+
ctx = await handleOpenCode(ctx);
|
|
41586
|
+
if (ctx.cancelled)
|
|
41587
|
+
return;
|
|
41588
|
+
}
|
|
41419
41589
|
if (!isSyncMode) {
|
|
41420
41590
|
ctx = await handleTransforms(ctx);
|
|
41421
41591
|
if (ctx.cancelled)
|
|
@@ -41497,7 +41667,7 @@ var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
|
41497
41667
|
import { resolve as resolve9 } from "node:path";
|
|
41498
41668
|
init_logger();
|
|
41499
41669
|
init_types2();
|
|
41500
|
-
var
|
|
41670
|
+
var import_fs_extra33 = __toESM(require_lib(), 1);
|
|
41501
41671
|
async function directorySetup(validOptions, prompts) {
|
|
41502
41672
|
const isNonInteractive2 = !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
|
|
41503
41673
|
const config = await ConfigManager.get();
|
|
@@ -41596,8 +41766,8 @@ async function directorySetup(validOptions, prompts) {
|
|
|
41596
41766
|
return null;
|
|
41597
41767
|
}
|
|
41598
41768
|
}
|
|
41599
|
-
if (await
|
|
41600
|
-
const files = await
|
|
41769
|
+
if (await import_fs_extra33.pathExists(resolvedDir)) {
|
|
41770
|
+
const files = await import_fs_extra33.readdir(resolvedDir);
|
|
41601
41771
|
const isEmpty = files.length === 0;
|
|
41602
41772
|
if (!isEmpty) {
|
|
41603
41773
|
if (isNonInteractive2) {
|
|
@@ -41633,7 +41803,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
41633
41803
|
};
|
|
41634
41804
|
}
|
|
41635
41805
|
// src/commands/new/phases/project-creation.ts
|
|
41636
|
-
import { join as
|
|
41806
|
+
import { join as join72 } from "node:path";
|
|
41637
41807
|
init_logger();
|
|
41638
41808
|
init_output_manager();
|
|
41639
41809
|
init_types2();
|
|
@@ -41743,7 +41913,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
41743
41913
|
output.section("Installing");
|
|
41744
41914
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
41745
41915
|
const merger = new FileMerger;
|
|
41746
|
-
const claudeDir =
|
|
41916
|
+
const claudeDir = join72(resolvedDir, ".claude");
|
|
41747
41917
|
merger.setMultiKitContext(claudeDir, kit);
|
|
41748
41918
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
41749
41919
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -41880,7 +42050,7 @@ init_types2();
|
|
|
41880
42050
|
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
41881
42051
|
|
|
41882
42052
|
// src/commands/uninstall/installation-detector.ts
|
|
41883
|
-
var
|
|
42053
|
+
var import_fs_extra34 = __toESM(require_lib(), 1);
|
|
41884
42054
|
async function detectInstallations() {
|
|
41885
42055
|
const installations = [];
|
|
41886
42056
|
const setup = await getClaudeKitSetup(process.cwd());
|
|
@@ -41889,14 +42059,14 @@ async function detectInstallations() {
|
|
|
41889
42059
|
installations.push({
|
|
41890
42060
|
type: "local",
|
|
41891
42061
|
path: setup.project.path,
|
|
41892
|
-
exists: await
|
|
42062
|
+
exists: await import_fs_extra34.pathExists(setup.project.path)
|
|
41893
42063
|
});
|
|
41894
42064
|
}
|
|
41895
42065
|
if (setup.global.path && setup.global.metadata) {
|
|
41896
42066
|
installations.push({
|
|
41897
42067
|
type: "global",
|
|
41898
42068
|
path: setup.global.path,
|
|
41899
|
-
exists: await
|
|
42069
|
+
exists: await import_fs_extra34.pathExists(setup.global.path)
|
|
41900
42070
|
});
|
|
41901
42071
|
}
|
|
41902
42072
|
return installations.filter((i) => i.exists);
|
|
@@ -41904,13 +42074,13 @@ async function detectInstallations() {
|
|
|
41904
42074
|
|
|
41905
42075
|
// src/commands/uninstall/removal-handler.ts
|
|
41906
42076
|
import { readdirSync as readdirSync2, rmSync as rmSync2 } from "node:fs";
|
|
41907
|
-
import { join as
|
|
42077
|
+
import { join as join74 } from "node:path";
|
|
41908
42078
|
init_logger();
|
|
41909
|
-
var
|
|
42079
|
+
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
41910
42080
|
|
|
41911
42081
|
// src/commands/uninstall/analysis-handler.ts
|
|
41912
42082
|
import { readdirSync, rmSync } from "node:fs";
|
|
41913
|
-
import { dirname as dirname10, join as
|
|
42083
|
+
import { dirname as dirname10, join as join73 } from "node:path";
|
|
41914
42084
|
init_logger();
|
|
41915
42085
|
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
41916
42086
|
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
@@ -41957,7 +42127,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
41957
42127
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
41958
42128
|
const kitFiles = metadata.kits[kit].files || [];
|
|
41959
42129
|
for (const trackedFile of kitFiles) {
|
|
41960
|
-
const filePath =
|
|
42130
|
+
const filePath = join73(installation.path, trackedFile.path);
|
|
41961
42131
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
41962
42132
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
41963
42133
|
continue;
|
|
@@ -41987,7 +42157,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
41987
42157
|
return result;
|
|
41988
42158
|
}
|
|
41989
42159
|
for (const trackedFile of allTrackedFiles) {
|
|
41990
|
-
const filePath =
|
|
42160
|
+
const filePath = join73(installation.path, trackedFile.path);
|
|
41991
42161
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
41992
42162
|
if (!ownershipResult.exists)
|
|
41993
42163
|
continue;
|
|
@@ -42047,9 +42217,9 @@ async function removeInstallations(installations, options) {
|
|
|
42047
42217
|
let removedCount = 0;
|
|
42048
42218
|
let cleanedDirs = 0;
|
|
42049
42219
|
for (const item of analysis.toDelete) {
|
|
42050
|
-
const filePath =
|
|
42051
|
-
if (await
|
|
42052
|
-
await
|
|
42220
|
+
const filePath = join74(installation.path, item.path);
|
|
42221
|
+
if (await import_fs_extra35.pathExists(filePath)) {
|
|
42222
|
+
await import_fs_extra35.remove(filePath);
|
|
42053
42223
|
removedCount++;
|
|
42054
42224
|
logger.debug(`Removed: ${item.path}`);
|
|
42055
42225
|
cleanedDirs += await cleanupEmptyDirectories(filePath, installation.path);
|
|
@@ -42218,6 +42388,7 @@ ${import_picocolors22.default.yellow("User modifications will be permanently del
|
|
|
42218
42388
|
}
|
|
42219
42389
|
// src/commands/update-cli.ts
|
|
42220
42390
|
import { exec as exec7 } from "node:child_process";
|
|
42391
|
+
import { join as join76 } from "node:path";
|
|
42221
42392
|
import { promisify as promisify7 } from "node:util";
|
|
42222
42393
|
|
|
42223
42394
|
// src/domains/github/npm-registry.ts
|
|
@@ -42379,14 +42550,14 @@ init_types2();
|
|
|
42379
42550
|
// src/domains/versioning/version-cache.ts
|
|
42380
42551
|
init_logger();
|
|
42381
42552
|
import { existsSync as existsSync19 } from "node:fs";
|
|
42382
|
-
import { mkdir as mkdir22, readFile as
|
|
42383
|
-
import { join as
|
|
42553
|
+
import { mkdir as mkdir22, readFile as readFile25, writeFile as writeFile22 } from "node:fs/promises";
|
|
42554
|
+
import { join as join75 } from "node:path";
|
|
42384
42555
|
class VersionCacheManager {
|
|
42385
42556
|
static CACHE_FILENAME = "version-check.json";
|
|
42386
42557
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
42387
42558
|
static getCacheFile() {
|
|
42388
42559
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
42389
|
-
return
|
|
42560
|
+
return join75(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
42390
42561
|
}
|
|
42391
42562
|
static async load() {
|
|
42392
42563
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -42395,7 +42566,7 @@ class VersionCacheManager {
|
|
|
42395
42566
|
logger.debug("Version check cache not found");
|
|
42396
42567
|
return null;
|
|
42397
42568
|
}
|
|
42398
|
-
const content = await
|
|
42569
|
+
const content = await readFile25(cacheFile, "utf-8");
|
|
42399
42570
|
const cache2 = JSON.parse(content);
|
|
42400
42571
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
42401
42572
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -42415,7 +42586,7 @@ class VersionCacheManager {
|
|
|
42415
42586
|
if (!existsSync19(cacheDir)) {
|
|
42416
42587
|
await mkdir22(cacheDir, { recursive: true, mode: 448 });
|
|
42417
42588
|
}
|
|
42418
|
-
await
|
|
42589
|
+
await writeFile22(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
42419
42590
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
42420
42591
|
} catch (error) {
|
|
42421
42592
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -42624,11 +42795,12 @@ init_logger();
|
|
|
42624
42795
|
init_types2();
|
|
42625
42796
|
init_types2();
|
|
42626
42797
|
var import_compare_versions5 = __toESM(require_umd(), 1);
|
|
42798
|
+
var import_fs_extra36 = __toESM(require_lib(), 1);
|
|
42627
42799
|
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
42628
42800
|
// package.json
|
|
42629
42801
|
var package_default = {
|
|
42630
42802
|
name: "claudekit-cli",
|
|
42631
|
-
version: "3.
|
|
42803
|
+
version: "3.24.0",
|
|
42632
42804
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
42633
42805
|
type: "module",
|
|
42634
42806
|
repository: {
|
|
@@ -42729,18 +42901,51 @@ class CliUpdateError extends ClaudeKitError {
|
|
|
42729
42901
|
}
|
|
42730
42902
|
var PACKAGE_NAME2 = "claudekit-cli";
|
|
42731
42903
|
var KIT_UPDATE_REMINDER_HEADER = "Note: 'ck update' only updates the CLI tool itself.";
|
|
42904
|
+
function buildInitCommand(isGlobal, kit) {
|
|
42905
|
+
const parts = ["ck init"];
|
|
42906
|
+
if (isGlobal)
|
|
42907
|
+
parts.push("-g");
|
|
42908
|
+
if (kit)
|
|
42909
|
+
parts.push(`--kit ${kit}`);
|
|
42910
|
+
parts.push("--yes --install-skills");
|
|
42911
|
+
return parts.join(" ");
|
|
42912
|
+
}
|
|
42913
|
+
async function readMetadataFile(claudeDir) {
|
|
42914
|
+
const metadataPath = join76(claudeDir, "metadata.json");
|
|
42915
|
+
try {
|
|
42916
|
+
if (!await import_fs_extra36.pathExists(metadataPath)) {
|
|
42917
|
+
return null;
|
|
42918
|
+
}
|
|
42919
|
+
const content = await import_fs_extra36.readFile(metadataPath, "utf-8");
|
|
42920
|
+
return JSON.parse(content);
|
|
42921
|
+
} catch {
|
|
42922
|
+
return null;
|
|
42923
|
+
}
|
|
42924
|
+
}
|
|
42732
42925
|
async function displayKitUpdateReminder() {
|
|
42733
42926
|
try {
|
|
42734
42927
|
const setup = await getClaudeKitSetup();
|
|
42735
42928
|
const hasLocal = !!setup.project.metadata;
|
|
42736
42929
|
const hasGlobal = !!setup.global.metadata;
|
|
42737
|
-
const
|
|
42738
|
-
const
|
|
42930
|
+
const localMetadata = hasLocal ? await readMetadataFile(setup.project.path) : null;
|
|
42931
|
+
const globalMetadata = hasGlobal ? await readMetadataFile(setup.global.path) : null;
|
|
42932
|
+
const localKits = localMetadata ? getInstalledKits(localMetadata) : [];
|
|
42933
|
+
const globalKits = globalMetadata ? getInstalledKits(globalMetadata) : [];
|
|
42739
42934
|
const versionsToCheck = new Set;
|
|
42740
|
-
if (
|
|
42741
|
-
|
|
42742
|
-
|
|
42743
|
-
|
|
42935
|
+
if (localMetadata) {
|
|
42936
|
+
for (const kit of localKits) {
|
|
42937
|
+
const version = localMetadata.kits?.[kit]?.version || localMetadata.version;
|
|
42938
|
+
if (version)
|
|
42939
|
+
versionsToCheck.add(version);
|
|
42940
|
+
}
|
|
42941
|
+
}
|
|
42942
|
+
if (globalMetadata) {
|
|
42943
|
+
for (const kit of globalKits) {
|
|
42944
|
+
const version = globalMetadata.kits?.[kit]?.version || globalMetadata.version;
|
|
42945
|
+
if (version)
|
|
42946
|
+
versionsToCheck.add(version);
|
|
42947
|
+
}
|
|
42948
|
+
}
|
|
42744
42949
|
const versionCheckResults = new Map;
|
|
42745
42950
|
if (versionsToCheck.size > 0) {
|
|
42746
42951
|
const checkPromises = [...versionsToCheck].map(async (version) => {
|
|
@@ -42752,33 +42957,52 @@ async function displayKitUpdateReminder() {
|
|
|
42752
42957
|
versionCheckResults.set(version, result);
|
|
42753
42958
|
}
|
|
42754
42959
|
}
|
|
42755
|
-
const
|
|
42756
|
-
|
|
42757
|
-
|
|
42960
|
+
const commands = [];
|
|
42961
|
+
if (localKits.length > 0) {
|
|
42962
|
+
for (const kit of localKits) {
|
|
42963
|
+
const cmd = buildInitCommand(false, kit);
|
|
42964
|
+
const version = localMetadata?.kits?.[kit]?.version || localMetadata?.version;
|
|
42965
|
+
commands.push({
|
|
42966
|
+
cmd,
|
|
42967
|
+
desc: `Update local project (${kit}${version ? `@${version}` : ""})`,
|
|
42968
|
+
version
|
|
42969
|
+
});
|
|
42970
|
+
}
|
|
42971
|
+
} else if (hasLocal) {
|
|
42972
|
+
commands.push({ cmd: "ck init", desc: "Update local project" });
|
|
42973
|
+
} else {
|
|
42974
|
+
commands.push({ cmd: "ck init", desc: "Initialize in current project" });
|
|
42975
|
+
}
|
|
42976
|
+
if (globalKits.length > 0) {
|
|
42977
|
+
for (const kit of globalKits) {
|
|
42978
|
+
const cmd = buildInitCommand(true, kit);
|
|
42979
|
+
const version = globalMetadata?.kits?.[kit]?.version || globalMetadata?.version;
|
|
42980
|
+
commands.push({
|
|
42981
|
+
cmd,
|
|
42982
|
+
desc: `Update global ~/.claude (${kit}${version ? `@${version}` : ""})`,
|
|
42983
|
+
version
|
|
42984
|
+
});
|
|
42985
|
+
}
|
|
42986
|
+
} else if (hasGlobal) {
|
|
42987
|
+
commands.push({ cmd: "ck init -g", desc: "Update global ~/.claude" });
|
|
42988
|
+
} else {
|
|
42989
|
+
commands.push({ cmd: "ck init -g", desc: "Initialize global ~/.claude" });
|
|
42990
|
+
}
|
|
42991
|
+
const maxCmdLen = Math.max(...commands.map((c2) => c2.cmd.length));
|
|
42758
42992
|
const pad = (cmd) => cmd.padEnd(maxCmdLen);
|
|
42759
42993
|
const lines = [];
|
|
42760
42994
|
lines.push(import_picocolors24.default.yellow(KIT_UPDATE_REMINDER_HEADER));
|
|
42761
42995
|
lines.push("");
|
|
42762
42996
|
lines.push("To update your ClaudeKit content (skills, commands, workflows):");
|
|
42763
|
-
|
|
42764
|
-
lines.push(` ${import_picocolors24.default.cyan(pad(
|
|
42765
|
-
|
|
42766
|
-
|
|
42767
|
-
|
|
42768
|
-
|
|
42769
|
-
|
|
42770
|
-
|
|
42771
|
-
lines.push(` ${import_picocolors24.default.cyan(pad(cmdLocal))} Initialize in current project`);
|
|
42772
|
-
}
|
|
42773
|
-
if (hasGlobal && globalVersion) {
|
|
42774
|
-
lines.push(` ${import_picocolors24.default.cyan(pad(cmdGlobal))} Update global ~/.claude (${globalVersion})`);
|
|
42775
|
-
const globalCheck = versionCheckResults.get(globalVersion);
|
|
42776
|
-
if (globalCheck?.updateAvailable) {
|
|
42777
|
-
const indent = " ".repeat(maxCmdLen + 4);
|
|
42778
|
-
lines.push(`${indent}${import_picocolors24.default.green(`→ ${globalCheck.latestVersion} available!`)}`);
|
|
42997
|
+
for (const { cmd, desc: desc2, version } of commands) {
|
|
42998
|
+
lines.push(` ${import_picocolors24.default.cyan(pad(cmd))} ${desc2}`);
|
|
42999
|
+
if (version) {
|
|
43000
|
+
const versionCheck = versionCheckResults.get(version);
|
|
43001
|
+
if (versionCheck?.updateAvailable) {
|
|
43002
|
+
const indent = " ".repeat(maxCmdLen + 4);
|
|
43003
|
+
lines.push(`${indent}${import_picocolors24.default.green(`→ ${versionCheck.latestVersion} available!`)}`);
|
|
43004
|
+
}
|
|
42779
43005
|
}
|
|
42780
|
-
} else {
|
|
42781
|
-
lines.push(` ${import_picocolors24.default.cyan(pad(cmdGlobal))} Initialize global ~/.claude`);
|
|
42782
43006
|
}
|
|
42783
43007
|
logger.info("");
|
|
42784
43008
|
log.info(lines.join(`
|
|
@@ -43053,7 +43277,7 @@ function registerCommands(cli) {
|
|
|
43053
43277
|
|
|
43054
43278
|
// src/cli/version-display.ts
|
|
43055
43279
|
import { existsSync as existsSync20, readFileSync as readFileSync6 } from "node:fs";
|
|
43056
|
-
import { join as
|
|
43280
|
+
import { join as join77 } from "node:path";
|
|
43057
43281
|
init_logger();
|
|
43058
43282
|
init_types2();
|
|
43059
43283
|
var packageVersion = package_default.version;
|
|
@@ -43087,9 +43311,9 @@ async function displayVersion() {
|
|
|
43087
43311
|
let localKitVersion = null;
|
|
43088
43312
|
let isGlobalOnlyKit = false;
|
|
43089
43313
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
43090
|
-
const globalMetadataPath =
|
|
43314
|
+
const globalMetadataPath = join77(globalKitDir, "metadata.json");
|
|
43091
43315
|
const prefix = PathResolver.getPathPrefix(false);
|
|
43092
|
-
const localMetadataPath = prefix ?
|
|
43316
|
+
const localMetadataPath = prefix ? join77(process.cwd(), prefix, "metadata.json") : join77(process.cwd(), "metadata.json");
|
|
43093
43317
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
43094
43318
|
if (!isLocalSameAsGlobal && existsSync20(localMetadataPath)) {
|
|
43095
43319
|
try {
|