claudekit-cli 4.3.1-dev.16 → 4.3.1-dev.18
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/cli-manifest.json +6 -2
- package/dist/index.js +793 -495
- package/dist/ui/assets/{index-BqgqWXbq.js → index-D3Q_VrJU.js} +18 -2
- package/dist/ui/index.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12622,6 +12622,217 @@ var init_converters = __esm(() => {
|
|
|
12622
12622
|
init_skill_md();
|
|
12623
12623
|
});
|
|
12624
12624
|
|
|
12625
|
+
// src/shared/path-resolver.ts
|
|
12626
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
12627
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
12628
|
+
import { homedir as homedir3, platform as platform2 } from "node:os";
|
|
12629
|
+
import { join as join2, normalize, resolve } from "node:path";
|
|
12630
|
+
function getEnvVar(name) {
|
|
12631
|
+
const val = process.env[name];
|
|
12632
|
+
if (!val || val.trim() === "")
|
|
12633
|
+
return;
|
|
12634
|
+
if (val.includes("..")) {
|
|
12635
|
+
console.warn(`Environment variable ${name} contains path traversal: ${val}`);
|
|
12636
|
+
return;
|
|
12637
|
+
}
|
|
12638
|
+
return val;
|
|
12639
|
+
}
|
|
12640
|
+
function isWSL() {
|
|
12641
|
+
try {
|
|
12642
|
+
return process.platform === "linux" && existsSync2("/proc/version") && readFileSync2("/proc/version", "utf8").toLowerCase().includes("microsoft");
|
|
12643
|
+
} catch {
|
|
12644
|
+
return false;
|
|
12645
|
+
}
|
|
12646
|
+
}
|
|
12647
|
+
function normalizeWSLPath(p) {
|
|
12648
|
+
if (!isWSL())
|
|
12649
|
+
return p;
|
|
12650
|
+
const windowsMatch = p.match(/^([A-Za-z]):(.*)/);
|
|
12651
|
+
if (windowsMatch) {
|
|
12652
|
+
const drive = windowsMatch[1].toLowerCase();
|
|
12653
|
+
const rest = windowsMatch[2].replace(/\\/g, "/");
|
|
12654
|
+
return `/mnt/${drive}${rest}`;
|
|
12655
|
+
}
|
|
12656
|
+
return p;
|
|
12657
|
+
}
|
|
12658
|
+
|
|
12659
|
+
class PathResolver {
|
|
12660
|
+
static getTestHomeDir() {
|
|
12661
|
+
return process.env.CK_TEST_HOME;
|
|
12662
|
+
}
|
|
12663
|
+
static isValidComponentName(name) {
|
|
12664
|
+
if (!name || typeof name !== "string") {
|
|
12665
|
+
return false;
|
|
12666
|
+
}
|
|
12667
|
+
const dangerousPatterns = [
|
|
12668
|
+
"..",
|
|
12669
|
+
"~"
|
|
12670
|
+
];
|
|
12671
|
+
for (const pattern of dangerousPatterns) {
|
|
12672
|
+
if (name.includes(pattern)) {
|
|
12673
|
+
return false;
|
|
12674
|
+
}
|
|
12675
|
+
}
|
|
12676
|
+
const normalized = normalize(name);
|
|
12677
|
+
for (const pattern of dangerousPatterns) {
|
|
12678
|
+
if (normalized.includes(pattern)) {
|
|
12679
|
+
return false;
|
|
12680
|
+
}
|
|
12681
|
+
}
|
|
12682
|
+
if (name.startsWith("/") || normalized.startsWith("/") || /^[a-zA-Z]:/.test(name) || name.startsWith("\\\\") || normalized.startsWith("\\\\")) {
|
|
12683
|
+
return false;
|
|
12684
|
+
}
|
|
12685
|
+
return true;
|
|
12686
|
+
}
|
|
12687
|
+
static getConfigDir(global2 = false) {
|
|
12688
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12689
|
+
if (testHome) {
|
|
12690
|
+
return global2 ? join2(testHome, ".config", "claude") : join2(testHome, ".claudekit");
|
|
12691
|
+
}
|
|
12692
|
+
if (!global2) {
|
|
12693
|
+
return join2(homedir3(), ".claudekit");
|
|
12694
|
+
}
|
|
12695
|
+
const os = platform2();
|
|
12696
|
+
if (os === "win32") {
|
|
12697
|
+
const localAppData = getEnvVar("LOCALAPPDATA") ?? join2(homedir3(), "AppData", "Local");
|
|
12698
|
+
return join2(localAppData, "claude");
|
|
12699
|
+
}
|
|
12700
|
+
const xdgConfigHome = getEnvVar("XDG_CONFIG_HOME");
|
|
12701
|
+
if (xdgConfigHome) {
|
|
12702
|
+
return join2(xdgConfigHome, "claude");
|
|
12703
|
+
}
|
|
12704
|
+
return join2(homedir3(), ".config", "claude");
|
|
12705
|
+
}
|
|
12706
|
+
static getConfigFile(global2 = false) {
|
|
12707
|
+
return join2(PathResolver.getConfigDir(global2), "config.json");
|
|
12708
|
+
}
|
|
12709
|
+
static getCacheDir(global2 = false) {
|
|
12710
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12711
|
+
if (testHome) {
|
|
12712
|
+
return global2 ? join2(testHome, ".cache", "claude") : join2(testHome, ".claudekit", "cache");
|
|
12713
|
+
}
|
|
12714
|
+
if (!global2) {
|
|
12715
|
+
return join2(homedir3(), ".claudekit", "cache");
|
|
12716
|
+
}
|
|
12717
|
+
const os = platform2();
|
|
12718
|
+
if (os === "win32") {
|
|
12719
|
+
const localAppData = getEnvVar("LOCALAPPDATA") ?? join2(homedir3(), "AppData", "Local");
|
|
12720
|
+
return join2(localAppData, "claude", "cache");
|
|
12721
|
+
}
|
|
12722
|
+
const xdgCacheHome = getEnvVar("XDG_CACHE_HOME");
|
|
12723
|
+
if (xdgCacheHome) {
|
|
12724
|
+
return join2(xdgCacheHome, "claude");
|
|
12725
|
+
}
|
|
12726
|
+
return join2(homedir3(), ".cache", "claude");
|
|
12727
|
+
}
|
|
12728
|
+
static getGlobalKitDir() {
|
|
12729
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12730
|
+
if (testHome) {
|
|
12731
|
+
return join2(testHome, ".claude");
|
|
12732
|
+
}
|
|
12733
|
+
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR;
|
|
12734
|
+
if (claudeConfigDir) {
|
|
12735
|
+
return claudeConfigDir;
|
|
12736
|
+
}
|
|
12737
|
+
return join2(homedir3(), ".claude");
|
|
12738
|
+
}
|
|
12739
|
+
static getClaudeKitDir() {
|
|
12740
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12741
|
+
if (testHome) {
|
|
12742
|
+
return join2(testHome, ".claudekit");
|
|
12743
|
+
}
|
|
12744
|
+
return join2(homedir3(), ".claudekit");
|
|
12745
|
+
}
|
|
12746
|
+
static getProjectsRegistryPath() {
|
|
12747
|
+
return join2(PathResolver.getClaudeKitDir(), "projects.json");
|
|
12748
|
+
}
|
|
12749
|
+
static getOpenCodeDir(global2, baseDir) {
|
|
12750
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12751
|
+
if (testHome) {
|
|
12752
|
+
return global2 ? join2(testHome, ".config", "opencode") : join2(baseDir || testHome, ".opencode");
|
|
12753
|
+
}
|
|
12754
|
+
if (!global2) {
|
|
12755
|
+
return join2(baseDir || process.cwd(), ".opencode");
|
|
12756
|
+
}
|
|
12757
|
+
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
12758
|
+
if (xdgConfigHome) {
|
|
12759
|
+
return join2(xdgConfigHome, "opencode");
|
|
12760
|
+
}
|
|
12761
|
+
return join2(homedir3(), ".config", "opencode");
|
|
12762
|
+
}
|
|
12763
|
+
static getPathPrefix(global2) {
|
|
12764
|
+
return global2 ? "" : ".claude";
|
|
12765
|
+
}
|
|
12766
|
+
static buildSkillsPath(baseDir, global2) {
|
|
12767
|
+
const prefix = PathResolver.getPathPrefix(global2);
|
|
12768
|
+
if (prefix) {
|
|
12769
|
+
return join2(baseDir, prefix, "skills");
|
|
12770
|
+
}
|
|
12771
|
+
return join2(baseDir, "skills");
|
|
12772
|
+
}
|
|
12773
|
+
static buildComponentPath(baseDir, component, global2) {
|
|
12774
|
+
if (!PathResolver.isValidComponentName(component)) {
|
|
12775
|
+
throw new Error(`Invalid component name: "${component}" contains path traversal patterns. Valid names are simple directory names like "agents", "commands", "rules", "skills", or "hooks".`);
|
|
12776
|
+
}
|
|
12777
|
+
const prefix = PathResolver.getPathPrefix(global2);
|
|
12778
|
+
if (prefix) {
|
|
12779
|
+
return join2(baseDir, prefix, component);
|
|
12780
|
+
}
|
|
12781
|
+
return join2(baseDir, component);
|
|
12782
|
+
}
|
|
12783
|
+
static getBackupDir(timestamp) {
|
|
12784
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12785
|
+
const baseDir = testHome ? join2(testHome, ".claudekit") : join2(homedir3(), ".claudekit");
|
|
12786
|
+
if (timestamp) {
|
|
12787
|
+
return join2(baseDir, "backups", timestamp);
|
|
12788
|
+
}
|
|
12789
|
+
const now = new Date;
|
|
12790
|
+
const dateStr = now.toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
12791
|
+
const ms = now.getMilliseconds().toString().padStart(3, "0");
|
|
12792
|
+
const random = Math.random().toString(36).slice(2, 6);
|
|
12793
|
+
const ts = `${dateStr}-${ms}-${random}`;
|
|
12794
|
+
return join2(baseDir, "backups", ts);
|
|
12795
|
+
}
|
|
12796
|
+
static normalizeWSLPath(p) {
|
|
12797
|
+
return normalizeWSLPath(p);
|
|
12798
|
+
}
|
|
12799
|
+
static isWSL() {
|
|
12800
|
+
return isWSL();
|
|
12801
|
+
}
|
|
12802
|
+
static isAtHomeDirectory(cwd2) {
|
|
12803
|
+
const currentDir = normalize(cwd2 || process.cwd());
|
|
12804
|
+
const homeDir = normalize(homedir3());
|
|
12805
|
+
return currentDir === homeDir;
|
|
12806
|
+
}
|
|
12807
|
+
static getLocalClaudeDir(baseDir) {
|
|
12808
|
+
const dir = baseDir || process.cwd();
|
|
12809
|
+
return join2(dir, ".claude");
|
|
12810
|
+
}
|
|
12811
|
+
static isLocalSameAsGlobal(cwd2) {
|
|
12812
|
+
const localPath = normalize(PathResolver.getLocalClaudeDir(cwd2));
|
|
12813
|
+
const globalPath = normalize(PathResolver.getGlobalKitDir());
|
|
12814
|
+
return localPath === globalPath;
|
|
12815
|
+
}
|
|
12816
|
+
static isGlobPattern(pattern) {
|
|
12817
|
+
return pattern.includes("*") || pattern.includes("?") || pattern.includes("{");
|
|
12818
|
+
}
|
|
12819
|
+
static computeProjectHash(projectRoot) {
|
|
12820
|
+
let normalized = resolve(projectRoot).replace(/[/\\]+$/, "");
|
|
12821
|
+
if (process.platform === "darwin" || process.platform === "win32") {
|
|
12822
|
+
normalized = normalized.toLowerCase();
|
|
12823
|
+
}
|
|
12824
|
+
return createHash3("sha256").update(normalized).digest("hex").slice(0, 12);
|
|
12825
|
+
}
|
|
12826
|
+
static getPlansRegistriesDir() {
|
|
12827
|
+
return join2(PathResolver.getGlobalKitDir(), "plans-registries");
|
|
12828
|
+
}
|
|
12829
|
+
static getPlansRegistryPath(projectRoot) {
|
|
12830
|
+
const hash = PathResolver.computeProjectHash(projectRoot);
|
|
12831
|
+
return join2(PathResolver.getPlansRegistriesDir(), `${hash}.json`);
|
|
12832
|
+
}
|
|
12833
|
+
}
|
|
12834
|
+
var init_path_resolver = () => {};
|
|
12835
|
+
|
|
12625
12836
|
// src/commands/portable/reconcile-types.ts
|
|
12626
12837
|
function normalizeChecksum(checksum) {
|
|
12627
12838
|
if (!checksum)
|
|
@@ -12686,18 +12897,16 @@ function providerConfigAppliesToType(config, type) {
|
|
|
12686
12897
|
var UNKNOWN_CHECKSUM = "unknown";
|
|
12687
12898
|
|
|
12688
12899
|
// src/commands/portable/portable-registry.ts
|
|
12689
|
-
import { existsSync as
|
|
12900
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
12690
12901
|
import { mkdir, readFile as readFile2, rename, unlink, writeFile } from "node:fs/promises";
|
|
12691
|
-
import {
|
|
12692
|
-
import { dirname, join as join2, resolve } from "node:path";
|
|
12902
|
+
import { dirname, join as join3, resolve as resolve2 } from "node:path";
|
|
12693
12903
|
function getPortableRegistryPaths() {
|
|
12694
|
-
const
|
|
12695
|
-
const claudekitDir = join2(home2, ".claudekit");
|
|
12904
|
+
const claudekitDir = PathResolver.getConfigDir(false);
|
|
12696
12905
|
return {
|
|
12697
|
-
registryPath:
|
|
12698
|
-
registryLockPath:
|
|
12699
|
-
legacyRegistryPath:
|
|
12700
|
-
migrationLockPath:
|
|
12906
|
+
registryPath: join3(claudekitDir, "portable-registry.json"),
|
|
12907
|
+
registryLockPath: join3(claudekitDir, "portable-registry.lock"),
|
|
12908
|
+
legacyRegistryPath: join3(claudekitDir, "skill-registry.json"),
|
|
12909
|
+
migrationLockPath: join3(claudekitDir, ".migration.lock")
|
|
12701
12910
|
};
|
|
12702
12911
|
}
|
|
12703
12912
|
function isErrnoCode(error, code) {
|
|
@@ -12721,12 +12930,12 @@ function getCliVersion() {
|
|
|
12721
12930
|
if (process.env.npm_package_version) {
|
|
12722
12931
|
return process.env.npm_package_version;
|
|
12723
12932
|
}
|
|
12724
|
-
const { readFileSync:
|
|
12933
|
+
const { readFileSync: readFileSync3 } = __require("node:fs");
|
|
12725
12934
|
const { dirname: dn, join: jp } = __require("node:path");
|
|
12726
12935
|
const { fileURLToPath } = __require("node:url");
|
|
12727
12936
|
const __dirname2 = dn(fileURLToPath(import.meta.url));
|
|
12728
12937
|
const pkgPath = jp(__dirname2, "../../../package.json");
|
|
12729
|
-
const pkg = JSON.parse(
|
|
12938
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
12730
12939
|
return pkg.version || "unknown";
|
|
12731
12940
|
} catch {
|
|
12732
12941
|
return "unknown";
|
|
@@ -12762,7 +12971,7 @@ async function migrateRegistryV2ToV3(v2Registry) {
|
|
|
12762
12971
|
for (const item of v2Registry.installations) {
|
|
12763
12972
|
let targetChecksum = UNKNOWN_CHECKSUM;
|
|
12764
12973
|
try {
|
|
12765
|
-
if (
|
|
12974
|
+
if (existsSync3(item.path)) {
|
|
12766
12975
|
targetChecksum = await computeFileChecksum(item.path);
|
|
12767
12976
|
}
|
|
12768
12977
|
} catch (error) {
|
|
@@ -12819,7 +13028,7 @@ async function repairStaleRegistryV3(registry) {
|
|
|
12819
13028
|
const installations = [];
|
|
12820
13029
|
for (const item of registry.installations) {
|
|
12821
13030
|
let targetChecksum = normalizeChecksum(getStringField(item, "targetChecksum")) || UNKNOWN_CHECKSUM;
|
|
12822
|
-
if (targetChecksum === UNKNOWN_CHECKSUM &&
|
|
13031
|
+
if (targetChecksum === UNKNOWN_CHECKSUM && existsSync3(item.path)) {
|
|
12823
13032
|
try {
|
|
12824
13033
|
targetChecksum = await computeFileChecksum(item.path);
|
|
12825
13034
|
} catch {
|
|
@@ -12906,7 +13115,7 @@ async function isMigrationLocked() {
|
|
|
12906
13115
|
async function createMigrationLock() {
|
|
12907
13116
|
const { migrationLockPath } = getPortableRegistryPaths();
|
|
12908
13117
|
const lockDir = dirname(migrationLockPath);
|
|
12909
|
-
if (!
|
|
13118
|
+
if (!existsSync3(lockDir)) {
|
|
12910
13119
|
await mkdir(lockDir, { recursive: true });
|
|
12911
13120
|
}
|
|
12912
13121
|
await writeFile(migrationLockPath, Date.now().toString(), "utf-8");
|
|
@@ -12994,7 +13203,7 @@ async function readPortableRegistryWithinRegistryLock() {
|
|
|
12994
13203
|
async function writePortableRegistry(registry) {
|
|
12995
13204
|
const { registryPath } = getPortableRegistryPaths();
|
|
12996
13205
|
const dir = dirname(registryPath);
|
|
12997
|
-
if (!
|
|
13206
|
+
if (!existsSync3(dir)) {
|
|
12998
13207
|
await mkdir(dir, { recursive: true });
|
|
12999
13208
|
}
|
|
13000
13209
|
const normalizedRegistry = normalizePortableRegistryChecksums(registry);
|
|
@@ -13012,10 +13221,10 @@ async function writePortableRegistry(registry) {
|
|
|
13012
13221
|
async function withRegistryLock(operation) {
|
|
13013
13222
|
const { registryLockPath } = getPortableRegistryPaths();
|
|
13014
13223
|
const lockDir = dirname(registryLockPath);
|
|
13015
|
-
if (!
|
|
13224
|
+
if (!existsSync3(lockDir)) {
|
|
13016
13225
|
await mkdir(lockDir, { recursive: true });
|
|
13017
13226
|
}
|
|
13018
|
-
if (!
|
|
13227
|
+
if (!existsSync3(registryLockPath)) {
|
|
13019
13228
|
await writeFile(registryLockPath, "", "utf-8");
|
|
13020
13229
|
}
|
|
13021
13230
|
const release = await import_proper_lockfile.default.lock(registryLockPath, {
|
|
@@ -13057,7 +13266,7 @@ async function addPortableInstallation(item, type, provider, global2, path2, sou
|
|
|
13057
13266
|
async function removePortableInstallation(item, type, provider, global2, options2) {
|
|
13058
13267
|
return withRegistryLock(async () => {
|
|
13059
13268
|
const registry = await readPortableRegistryWithinRegistryLock();
|
|
13060
|
-
const index = registry.installations.findIndex((i) => i.item === item && i.type === type && i.provider === provider && i.global === global2 && (!options2?.path ||
|
|
13269
|
+
const index = registry.installations.findIndex((i) => i.item === item && i.type === type && i.provider === provider && i.global === global2 && (!options2?.path || resolve2(i.path) === resolve2(options2.path)));
|
|
13061
13270
|
if (index === -1)
|
|
13062
13271
|
return null;
|
|
13063
13272
|
const [removed] = registry.installations.splice(index, 1);
|
|
@@ -13107,7 +13316,7 @@ async function syncPortableRegistry() {
|
|
|
13107
13316
|
const registry = await readPortableRegistryWithinRegistryLock();
|
|
13108
13317
|
const removed = [];
|
|
13109
13318
|
registry.installations = registry.installations.filter((i) => {
|
|
13110
|
-
if (!
|
|
13319
|
+
if (!existsSync3(i.path)) {
|
|
13111
13320
|
removed.push(i);
|
|
13112
13321
|
return false;
|
|
13113
13322
|
}
|
|
@@ -13123,6 +13332,7 @@ var import_proper_lockfile, PortableInstallationSchema, PortableRegistrySchema,
|
|
|
13123
13332
|
var init_portable_registry = __esm(() => {
|
|
13124
13333
|
init_zod();
|
|
13125
13334
|
init_logger();
|
|
13335
|
+
init_path_resolver();
|
|
13126
13336
|
init_checksum_utils();
|
|
13127
13337
|
import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
13128
13338
|
PortableInstallationSchema = exports_external.object({
|
|
@@ -13181,10 +13391,10 @@ var init_portable_registry = __esm(() => {
|
|
|
13181
13391
|
});
|
|
13182
13392
|
|
|
13183
13393
|
// src/commands/portable/codex-toml-installer.ts
|
|
13184
|
-
import { existsSync as
|
|
13394
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
13185
13395
|
import { mkdir as mkdir2, readFile as readFile3, realpath, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
|
|
13186
13396
|
import { homedir as homedir4 } from "node:os";
|
|
13187
|
-
import { basename, dirname as dirname2, isAbsolute, join as
|
|
13397
|
+
import { basename, dirname as dirname2, isAbsolute, join as join4, relative, resolve as resolve3 } from "node:path";
|
|
13188
13398
|
function resolveCodexTomlRegistryDeps(deps) {
|
|
13189
13399
|
return {
|
|
13190
13400
|
...defaultCodexTomlRegistryDeps,
|
|
@@ -13193,7 +13403,7 @@ function resolveCodexTomlRegistryDeps(deps) {
|
|
|
13193
13403
|
}
|
|
13194
13404
|
async function ensureDir(filePath) {
|
|
13195
13405
|
const dir = dirname2(filePath);
|
|
13196
|
-
if (!
|
|
13406
|
+
if (!existsSync4(dir)) {
|
|
13197
13407
|
await mkdir2(dir, { recursive: true });
|
|
13198
13408
|
}
|
|
13199
13409
|
}
|
|
@@ -13201,7 +13411,7 @@ function isErrnoCode2(error, code) {
|
|
|
13201
13411
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
13202
13412
|
}
|
|
13203
13413
|
function normalizePathForComparison(path2) {
|
|
13204
|
-
const normalized =
|
|
13414
|
+
const normalized = resolve3(path2);
|
|
13205
13415
|
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
13206
13416
|
}
|
|
13207
13417
|
function isPathWithinBoundary(targetPath, boundaryPath) {
|
|
@@ -13217,7 +13427,7 @@ async function resolveRealPathSafe(path2) {
|
|
|
13217
13427
|
try {
|
|
13218
13428
|
return await realpath(path2);
|
|
13219
13429
|
} catch {
|
|
13220
|
-
return
|
|
13430
|
+
return resolve3(path2);
|
|
13221
13431
|
}
|
|
13222
13432
|
}
|
|
13223
13433
|
async function isCanonicalPathWithinBoundary(targetPath, boundaryPath) {
|
|
@@ -13391,10 +13601,10 @@ function mergeConfigTomlWithDiagnostics(existing, managedBlock) {
|
|
|
13391
13601
|
};
|
|
13392
13602
|
}
|
|
13393
13603
|
function getCodexLockPath(configTomlPath) {
|
|
13394
|
-
return
|
|
13604
|
+
return join4(dirname2(configTomlPath), `.${basename(configTomlPath)}.ck-codex.lock`);
|
|
13395
13605
|
}
|
|
13396
13606
|
async function withCodexTargetLock(configTomlPath, operation) {
|
|
13397
|
-
const resolvedTargetPath =
|
|
13607
|
+
const resolvedTargetPath = resolve3(configTomlPath);
|
|
13398
13608
|
await ensureDir(resolvedTargetPath);
|
|
13399
13609
|
const release = await import_proper_lockfile2.default.lock(dirname2(resolvedTargetPath), {
|
|
13400
13610
|
realpath: false,
|
|
@@ -13473,8 +13683,8 @@ async function installCodexToml(items, provider, portableType, options2, deps) {
|
|
|
13473
13683
|
};
|
|
13474
13684
|
}
|
|
13475
13685
|
const boundary = options2.global ? homedir4() : process.cwd();
|
|
13476
|
-
const agentsDir =
|
|
13477
|
-
const configTomlPath =
|
|
13686
|
+
const agentsDir = resolve3(basePath);
|
|
13687
|
+
const configTomlPath = join4(dirname2(agentsDir), "config.toml");
|
|
13478
13688
|
if (!isPathWithinBoundary(agentsDir, boundary)) {
|
|
13479
13689
|
return {
|
|
13480
13690
|
provider,
|
|
@@ -13568,7 +13778,7 @@ async function installCodexToml(items, provider, portableType, options2, deps) {
|
|
|
13568
13778
|
continue;
|
|
13569
13779
|
}
|
|
13570
13780
|
seenSlugOwners.set(slug, item.name);
|
|
13571
|
-
const agentTomlPath =
|
|
13781
|
+
const agentTomlPath = join4(agentsDir, `${slug}.toml`);
|
|
13572
13782
|
if (process.platform === "win32" && agentTomlPath.length > MAX_WINDOWS_PATH_LENGTH) {
|
|
13573
13783
|
allWarnings.push(`Skipped ${item.name}: target path exceeds ${MAX_WINDOWS_PATH_LENGTH} characters on Windows`);
|
|
13574
13784
|
continue;
|
|
@@ -13695,9 +13905,9 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
13695
13905
|
const basePath = options2.global ? pathConfig.globalPath : pathConfig.projectPath;
|
|
13696
13906
|
if (!basePath)
|
|
13697
13907
|
return [];
|
|
13698
|
-
const agentsDir =
|
|
13699
|
-
const configTomlPath =
|
|
13700
|
-
if (!
|
|
13908
|
+
const agentsDir = resolve3(basePath);
|
|
13909
|
+
const configTomlPath = join4(dirname2(agentsDir), "config.toml");
|
|
13910
|
+
if (!existsSync4(configTomlPath))
|
|
13701
13911
|
return [];
|
|
13702
13912
|
try {
|
|
13703
13913
|
return await withCodexTargetLock(configTomlPath, async () => {
|
|
@@ -13713,8 +13923,8 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
13713
13923
|
if (managedEntries.size > 0) {
|
|
13714
13924
|
const validEntries = new Map;
|
|
13715
13925
|
for (const [slug, entry] of managedEntries) {
|
|
13716
|
-
const tomlPath =
|
|
13717
|
-
if (
|
|
13926
|
+
const tomlPath = join4(agentsDir, `${slug}.toml`);
|
|
13927
|
+
if (existsSync4(tomlPath)) {
|
|
13718
13928
|
validEntries.set(slug, entry);
|
|
13719
13929
|
} else {
|
|
13720
13930
|
allStaleSlugs.push(slug);
|
|
@@ -13744,10 +13954,10 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
13744
13954
|
const unmanagedSlugs = extractUnmanagedAgentSlugs(analysis.unmanagedContent);
|
|
13745
13955
|
const legacyStaleSlugs = [];
|
|
13746
13956
|
for (const slug of unmanagedSlugs) {
|
|
13747
|
-
const tomlPath =
|
|
13957
|
+
const tomlPath = join4(agentsDir, `${slug}.toml`);
|
|
13748
13958
|
if (!isPathWithinBoundary(tomlPath, agentsDir))
|
|
13749
13959
|
continue;
|
|
13750
|
-
if (!
|
|
13960
|
+
if (!existsSync4(tomlPath)) {
|
|
13751
13961
|
legacyStaleSlugs.push(slug);
|
|
13752
13962
|
}
|
|
13753
13963
|
}
|
|
@@ -13992,13 +14202,13 @@ var init_merge_single_sections = __esm(() => {
|
|
|
13992
14202
|
});
|
|
13993
14203
|
|
|
13994
14204
|
// src/commands/portable/portable-installer.ts
|
|
13995
|
-
import { existsSync as
|
|
14205
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
13996
14206
|
import { lstat, mkdir as mkdir3, readFile as readFile4, realpath as realpath2, unlink as unlink3, writeFile as writeFile3 } from "node:fs/promises";
|
|
13997
14207
|
import { homedir as homedir5 } from "node:os";
|
|
13998
|
-
import { basename as basename2, dirname as dirname3, join as
|
|
14208
|
+
import { basename as basename2, dirname as dirname3, join as join5, relative as relative2, resolve as resolve4, sep } from "node:path";
|
|
13999
14209
|
function isSamePath(path1, path2) {
|
|
14000
14210
|
try {
|
|
14001
|
-
return
|
|
14211
|
+
return resolve4(path1) === resolve4(path2);
|
|
14002
14212
|
} catch {
|
|
14003
14213
|
return false;
|
|
14004
14214
|
}
|
|
@@ -14027,8 +14237,8 @@ function isWindowsAbsolutePath(path2) {
|
|
|
14027
14237
|
return /^[a-zA-Z]:[\\/]/.test(path2) || /^\\\\/.test(path2);
|
|
14028
14238
|
}
|
|
14029
14239
|
function isPathWithinBoundary2(targetPath, boundaryPath) {
|
|
14030
|
-
const resolvedTarget =
|
|
14031
|
-
const resolvedBoundary =
|
|
14240
|
+
const resolvedTarget = resolve4(targetPath);
|
|
14241
|
+
const resolvedBoundary = resolve4(boundaryPath);
|
|
14032
14242
|
return resolvedTarget === resolvedBoundary || resolvedTarget.startsWith(`${resolvedBoundary}${sep}`);
|
|
14033
14243
|
}
|
|
14034
14244
|
function validateStrategyTargetPath(targetPath, options2) {
|
|
@@ -14054,16 +14264,16 @@ function resolvePerFileOutputFilename(filename, pathConfig) {
|
|
|
14054
14264
|
return `${nameWithoutExt.replace(/\//g, "-")}${ext}`;
|
|
14055
14265
|
}
|
|
14056
14266
|
function validateResolvedTargetWithinBase(targetPath, basePath, pathConfig) {
|
|
14057
|
-
const resolvedTarget =
|
|
14058
|
-
const resolvedBase = pathConfig.writeStrategy === "single-file" ?
|
|
14267
|
+
const resolvedTarget = resolve4(targetPath);
|
|
14268
|
+
const resolvedBase = pathConfig.writeStrategy === "single-file" ? resolve4(dirname3(basePath)) : resolve4(basePath);
|
|
14059
14269
|
if (!resolvedTarget.startsWith(`${resolvedBase}${sep}`) && resolvedTarget !== resolvedBase) {
|
|
14060
14270
|
return "Unsafe path: target escapes base directory";
|
|
14061
14271
|
}
|
|
14062
14272
|
return null;
|
|
14063
14273
|
}
|
|
14064
14274
|
async function validateNoSymlinkComponents(targetPath, boundaryPath) {
|
|
14065
|
-
const resolvedTarget =
|
|
14066
|
-
const resolvedBoundary =
|
|
14275
|
+
const resolvedTarget = resolve4(targetPath);
|
|
14276
|
+
const resolvedBoundary = resolve4(boundaryPath);
|
|
14067
14277
|
if (!isPathWithinBoundary2(resolvedTarget, resolvedBoundary)) {
|
|
14068
14278
|
return `Unsafe path: target escapes ${resolvedBoundary}`;
|
|
14069
14279
|
}
|
|
@@ -14071,7 +14281,7 @@ async function validateNoSymlinkComponents(targetPath, boundaryPath) {
|
|
|
14071
14281
|
let cursor = resolvedBoundary;
|
|
14072
14282
|
let deepestExisting = resolvedBoundary;
|
|
14073
14283
|
for (const segment of segments) {
|
|
14074
|
-
cursor =
|
|
14284
|
+
cursor = join5(cursor, segment);
|
|
14075
14285
|
try {
|
|
14076
14286
|
await lstat(cursor);
|
|
14077
14287
|
deepestExisting = cursor;
|
|
@@ -14181,13 +14391,13 @@ function buildPerFileCollisionSkips(items, provider, configDisplayName, basePath
|
|
|
14181
14391
|
continue;
|
|
14182
14392
|
}
|
|
14183
14393
|
const resolvedFilename = resolvePerFileOutputFilename(result.filename, pathConfig);
|
|
14184
|
-
const targetPath = pathConfig.writeStrategy === "single-file" ? basePath :
|
|
14394
|
+
const targetPath = pathConfig.writeStrategy === "single-file" ? basePath : join5(basePath, resolvedFilename);
|
|
14185
14395
|
if (validateResolvedTargetWithinBase(targetPath, basePath, pathConfig)) {
|
|
14186
14396
|
continue;
|
|
14187
14397
|
}
|
|
14188
|
-
const first = seenTargets.get(
|
|
14398
|
+
const first = seenTargets.get(resolve4(targetPath));
|
|
14189
14399
|
if (!first) {
|
|
14190
|
-
seenTargets.set(
|
|
14400
|
+
seenTargets.set(resolve4(targetPath), { itemName: item.name, targetPath });
|
|
14191
14401
|
continue;
|
|
14192
14402
|
}
|
|
14193
14403
|
skipped.set(index, {
|
|
@@ -14267,16 +14477,16 @@ async function installPerFileItems(items, provider, portableType, pathConfig, op
|
|
|
14267
14477
|
}
|
|
14268
14478
|
async function ensureDir2(filePath) {
|
|
14269
14479
|
const dir = dirname3(filePath);
|
|
14270
|
-
if (!
|
|
14480
|
+
if (!existsSync5(dir)) {
|
|
14271
14481
|
await mkdir3(dir, { recursive: true });
|
|
14272
14482
|
}
|
|
14273
14483
|
}
|
|
14274
14484
|
function getMergeTargetLockPath(targetPath) {
|
|
14275
14485
|
const lockName = `.${basename2(targetPath)}.ck-merge.lock`;
|
|
14276
|
-
return
|
|
14486
|
+
return join5(dirname3(targetPath), lockName);
|
|
14277
14487
|
}
|
|
14278
14488
|
async function withMergeTargetLock(targetPath, operation) {
|
|
14279
|
-
const resolvedTargetPath =
|
|
14489
|
+
const resolvedTargetPath = resolve4(targetPath);
|
|
14280
14490
|
await ensureDir2(resolvedTargetPath);
|
|
14281
14491
|
const release = await import_proper_lockfile3.default.lock(dirname3(resolvedTargetPath), {
|
|
14282
14492
|
realpath: false,
|
|
@@ -14393,7 +14603,7 @@ async function installPerFile(item, provider, portableType, options2, registryDe
|
|
|
14393
14603
|
};
|
|
14394
14604
|
}
|
|
14395
14605
|
const resolvedFilename = resolvePerFileOutputFilename(result.filename, pathConfig);
|
|
14396
|
-
targetPath = pathConfig.writeStrategy === "single-file" ? basePath :
|
|
14606
|
+
targetPath = pathConfig.writeStrategy === "single-file" ? basePath : join5(basePath, resolvedFilename);
|
|
14397
14607
|
const targetPathError = validateResolvedTargetWithinBase(targetPath, basePath, pathConfig);
|
|
14398
14608
|
if (targetPathError) {
|
|
14399
14609
|
return {
|
|
@@ -14520,7 +14730,7 @@ async function installMergeSingle(items, provider, portableType, options2, regis
|
|
|
14520
14730
|
error: "Config merge target accepts only one item per install"
|
|
14521
14731
|
};
|
|
14522
14732
|
}
|
|
14523
|
-
const alreadyExists =
|
|
14733
|
+
const alreadyExists = existsSync5(targetPath);
|
|
14524
14734
|
let existingSections = [];
|
|
14525
14735
|
let existingPreamble = "";
|
|
14526
14736
|
const allWarnings = [];
|
|
@@ -14723,7 +14933,7 @@ async function installYamlMerge(items, provider, portableType, options2, registr
|
|
|
14723
14933
|
}
|
|
14724
14934
|
let targetSnapshot = null;
|
|
14725
14935
|
try {
|
|
14726
|
-
const alreadyExists =
|
|
14936
|
+
const alreadyExists = existsSync5(targetPath);
|
|
14727
14937
|
let existingModes = new Map;
|
|
14728
14938
|
if (alreadyExists) {
|
|
14729
14939
|
try {
|
|
@@ -14899,7 +15109,7 @@ async function installJsonMerge(items, provider, portableType, options2, registr
|
|
|
14899
15109
|
}
|
|
14900
15110
|
modes.push(parsedMode.data);
|
|
14901
15111
|
}
|
|
14902
|
-
const modesPath =
|
|
15112
|
+
const modesPath = join5(basePath, "cline_custom_modes.json");
|
|
14903
15113
|
failurePath = modesPath;
|
|
14904
15114
|
const modesSymlinkError = await validateWritableTargetPath(modesPath, options2);
|
|
14905
15115
|
if (modesSymlinkError) {
|
|
@@ -14912,7 +15122,7 @@ async function installJsonMerge(items, provider, portableType, options2, registr
|
|
|
14912
15122
|
};
|
|
14913
15123
|
}
|
|
14914
15124
|
await ensureDir2(modesPath);
|
|
14915
|
-
const alreadyExists =
|
|
15125
|
+
const alreadyExists = existsSync5(modesPath);
|
|
14916
15126
|
if (alreadyExists) {
|
|
14917
15127
|
try {
|
|
14918
15128
|
const existingRaw = JSON.parse(await readFile4(modesPath, "utf-8"));
|
|
@@ -14948,7 +15158,7 @@ async function installJsonMerge(items, provider, portableType, options2, registr
|
|
|
14948
15158
|
await writeFile3(modesPath, modesJson, "utf-8");
|
|
14949
15159
|
const targetChecksum = computeContentChecksum(modesJson);
|
|
14950
15160
|
const ownedSections = modes.map((m2) => m2.slug);
|
|
14951
|
-
const rulesDir =
|
|
15161
|
+
const rulesDir = join5(dirname3(basePath), ".clinerules");
|
|
14952
15162
|
await mkdir3(rulesDir, { recursive: true });
|
|
14953
15163
|
const capturedRuleSnapshots = new Set;
|
|
14954
15164
|
for (const item of items) {
|
|
@@ -14970,10 +15180,10 @@ async function installJsonMerge(items, provider, portableType, options2, registr
|
|
|
14970
15180
|
}
|
|
14971
15181
|
}
|
|
14972
15182
|
const filename = `${namespacedName}.md`;
|
|
14973
|
-
const rulePath =
|
|
15183
|
+
const rulePath = join5(rulesDir, filename);
|
|
14974
15184
|
failurePath = rulePath;
|
|
14975
|
-
const resolvedRulePath =
|
|
14976
|
-
const resolvedRulesDir =
|
|
15185
|
+
const resolvedRulePath = resolve4(rulePath);
|
|
15186
|
+
const resolvedRulesDir = resolve4(rulesDir);
|
|
14977
15187
|
if (!resolvedRulePath.startsWith(resolvedRulesDir + sep) && resolvedRulePath !== resolvedRulesDir) {
|
|
14978
15188
|
throw new Error(`Unsafe path: rule target escapes rules directory (${rulePath})`);
|
|
14979
15189
|
}
|
|
@@ -15349,6 +15559,7 @@ var init_commands = __esm(() => {
|
|
|
15349
15559
|
dryRun: exports_external.boolean().default(false),
|
|
15350
15560
|
forceOverwrite: exports_external.boolean().default(false),
|
|
15351
15561
|
forceOverwriteSettings: exports_external.boolean().default(false),
|
|
15562
|
+
restoreCkHooks: exports_external.boolean().default(false),
|
|
15352
15563
|
skipSetup: exports_external.boolean().default(false),
|
|
15353
15564
|
refresh: exports_external.boolean().default(false),
|
|
15354
15565
|
docsDir: exports_external.string().optional(),
|
|
@@ -15891,8 +16102,12 @@ var init_ck_config = __esm(() => {
|
|
|
15891
16102
|
CkHooksConfigSchema = exports_external.object({
|
|
15892
16103
|
"session-init": exports_external.boolean().optional(),
|
|
15893
16104
|
"subagent-init": exports_external.boolean().optional(),
|
|
16105
|
+
"session-state": exports_external.boolean().optional(),
|
|
16106
|
+
"cook-after-plan-reminder": exports_external.boolean().optional(),
|
|
15894
16107
|
"descriptive-name": exports_external.boolean().optional(),
|
|
15895
16108
|
"dev-rules-reminder": exports_external.boolean().optional(),
|
|
16109
|
+
"plan-format-kanban": exports_external.boolean().optional(),
|
|
16110
|
+
"usage-quota-cache-refresh": exports_external.boolean().optional(),
|
|
15896
16111
|
"usage-context-awareness": exports_external.boolean().optional(),
|
|
15897
16112
|
"context-tracking": exports_external.boolean().optional(),
|
|
15898
16113
|
"scout-block": exports_external.boolean().optional(),
|
|
@@ -15989,8 +16204,12 @@ var init_ck_config = __esm(() => {
|
|
|
15989
16204
|
hooks: {
|
|
15990
16205
|
"session-init": true,
|
|
15991
16206
|
"subagent-init": true,
|
|
16207
|
+
"session-state": true,
|
|
16208
|
+
"cook-after-plan-reminder": true,
|
|
15992
16209
|
"descriptive-name": true,
|
|
15993
16210
|
"dev-rules-reminder": true,
|
|
16211
|
+
"plan-format-kanban": true,
|
|
16212
|
+
"usage-quota-cache-refresh": true,
|
|
15994
16213
|
"usage-context-awareness": true,
|
|
15995
16214
|
"context-tracking": true,
|
|
15996
16215
|
"scout-block": true,
|
|
@@ -16014,8 +16233,12 @@ var init_ck_config = __esm(() => {
|
|
|
16014
16233
|
CK_HOOK_NAMES = [
|
|
16015
16234
|
"session-init",
|
|
16016
16235
|
"subagent-init",
|
|
16236
|
+
"session-state",
|
|
16237
|
+
"cook-after-plan-reminder",
|
|
16017
16238
|
"descriptive-name",
|
|
16018
16239
|
"dev-rules-reminder",
|
|
16240
|
+
"plan-format-kanban",
|
|
16241
|
+
"usage-quota-cache-refresh",
|
|
16019
16242
|
"usage-context-awareness",
|
|
16020
16243
|
"context-tracking",
|
|
16021
16244
|
"scout-block",
|
|
@@ -16169,26 +16392,26 @@ var init_types3 = __esm(() => {
|
|
|
16169
16392
|
});
|
|
16170
16393
|
|
|
16171
16394
|
// src/shared/kit-layout.ts
|
|
16172
|
-
import { existsSync as
|
|
16173
|
-
import { join as
|
|
16395
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3 } from "node:fs";
|
|
16396
|
+
import { join as join6 } from "node:path";
|
|
16174
16397
|
function uniquePaths(paths) {
|
|
16175
16398
|
return [...new Set(paths)];
|
|
16176
16399
|
}
|
|
16177
16400
|
function findFirstExistingPath(paths) {
|
|
16178
16401
|
for (const candidate of paths) {
|
|
16179
|
-
if (
|
|
16402
|
+
if (existsSync6(candidate)) {
|
|
16180
16403
|
return candidate;
|
|
16181
16404
|
}
|
|
16182
16405
|
}
|
|
16183
16406
|
return null;
|
|
16184
16407
|
}
|
|
16185
16408
|
function resolveKitLayout(projectRoot) {
|
|
16186
|
-
const packageJsonPath =
|
|
16187
|
-
if (!
|
|
16409
|
+
const packageJsonPath = join6(projectRoot, "package.json");
|
|
16410
|
+
if (!existsSync6(packageJsonPath)) {
|
|
16188
16411
|
return DEFAULT_KIT_LAYOUT;
|
|
16189
16412
|
}
|
|
16190
16413
|
try {
|
|
16191
|
-
const parsed = ClaudeKitPackageMetadataSchema.parse(JSON.parse(
|
|
16414
|
+
const parsed = ClaudeKitPackageMetadataSchema.parse(JSON.parse(readFileSync3(packageJsonPath, "utf8")));
|
|
16192
16415
|
return KitLayoutSchema.parse({
|
|
16193
16416
|
...DEFAULT_KIT_LAYOUT,
|
|
16194
16417
|
...parsed.claudekit ?? {}
|
|
@@ -16200,8 +16423,8 @@ function resolveKitLayout(projectRoot) {
|
|
|
16200
16423
|
function getProjectLayoutCandidates(projectRoot, subPath) {
|
|
16201
16424
|
const layout = resolveKitLayout(projectRoot);
|
|
16202
16425
|
return uniquePaths([
|
|
16203
|
-
|
|
16204
|
-
|
|
16426
|
+
join6(projectRoot, layout.sourceDir, subPath),
|
|
16427
|
+
join6(projectRoot, DEFAULT_KIT_LAYOUT.sourceDir, subPath)
|
|
16205
16428
|
]);
|
|
16206
16429
|
}
|
|
16207
16430
|
function findExistingProjectLayoutPath(projectRoot, subPath) {
|
|
@@ -16210,9 +16433,9 @@ function findExistingProjectLayoutPath(projectRoot, subPath) {
|
|
|
16210
16433
|
function getProjectConfigCandidates(projectRoot) {
|
|
16211
16434
|
const layout = resolveKitLayout(projectRoot);
|
|
16212
16435
|
return uniquePaths([
|
|
16213
|
-
|
|
16214
|
-
|
|
16215
|
-
|
|
16436
|
+
join6(projectRoot, "CLAUDE.md"),
|
|
16437
|
+
join6(projectRoot, layout.sourceDir, "CLAUDE.md"),
|
|
16438
|
+
join6(projectRoot, DEFAULT_KIT_LAYOUT.sourceDir, "CLAUDE.md")
|
|
16216
16439
|
]);
|
|
16217
16440
|
}
|
|
16218
16441
|
function findExistingProjectConfigPath(projectRoot) {
|
|
@@ -16326,9 +16549,9 @@ var init_frontmatter_parser = __esm(() => {
|
|
|
16326
16549
|
// src/commands/agents/agents-discovery.ts
|
|
16327
16550
|
import { readdir } from "node:fs/promises";
|
|
16328
16551
|
import { homedir as homedir6 } from "node:os";
|
|
16329
|
-
import { join as
|
|
16552
|
+
import { join as join7 } from "node:path";
|
|
16330
16553
|
function getAgentSourcePath(globalOnly = false) {
|
|
16331
|
-
const globalPath =
|
|
16554
|
+
const globalPath = join7(homedir6(), ".claude/agents");
|
|
16332
16555
|
if (globalOnly) {
|
|
16333
16556
|
return findFirstExistingPath([globalPath]);
|
|
16334
16557
|
}
|
|
@@ -16347,7 +16570,7 @@ async function discoverAgents(sourcePath) {
|
|
|
16347
16570
|
for (const entry of entries) {
|
|
16348
16571
|
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
16349
16572
|
continue;
|
|
16350
|
-
const filePath =
|
|
16573
|
+
const filePath = join7(searchPath, entry.name);
|
|
16351
16574
|
try {
|
|
16352
16575
|
const { frontmatter, body } = await parseFrontmatterFile(filePath);
|
|
16353
16576
|
const name = entry.name.replace(/\.md$/, "");
|
|
@@ -19410,217 +19633,6 @@ var init_safe_spinner = __esm(() => {
|
|
|
19410
19633
|
};
|
|
19411
19634
|
});
|
|
19412
19635
|
|
|
19413
|
-
// src/shared/path-resolver.ts
|
|
19414
|
-
import { createHash as createHash3 } from "node:crypto";
|
|
19415
|
-
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
|
|
19416
|
-
import { homedir as homedir9, platform as platform2 } from "node:os";
|
|
19417
|
-
import { join as join11, normalize, resolve as resolve4 } from "node:path";
|
|
19418
|
-
function getEnvVar(name) {
|
|
19419
|
-
const val = process.env[name];
|
|
19420
|
-
if (!val || val.trim() === "")
|
|
19421
|
-
return;
|
|
19422
|
-
if (val.includes("..")) {
|
|
19423
|
-
console.warn(`Environment variable ${name} contains path traversal: ${val}`);
|
|
19424
|
-
return;
|
|
19425
|
-
}
|
|
19426
|
-
return val;
|
|
19427
|
-
}
|
|
19428
|
-
function isWSL() {
|
|
19429
|
-
try {
|
|
19430
|
-
return process.platform === "linux" && existsSync8("/proc/version") && readFileSync4("/proc/version", "utf8").toLowerCase().includes("microsoft");
|
|
19431
|
-
} catch {
|
|
19432
|
-
return false;
|
|
19433
|
-
}
|
|
19434
|
-
}
|
|
19435
|
-
function normalizeWSLPath(p) {
|
|
19436
|
-
if (!isWSL())
|
|
19437
|
-
return p;
|
|
19438
|
-
const windowsMatch = p.match(/^([A-Za-z]):(.*)/);
|
|
19439
|
-
if (windowsMatch) {
|
|
19440
|
-
const drive = windowsMatch[1].toLowerCase();
|
|
19441
|
-
const rest = windowsMatch[2].replace(/\\/g, "/");
|
|
19442
|
-
return `/mnt/${drive}${rest}`;
|
|
19443
|
-
}
|
|
19444
|
-
return p;
|
|
19445
|
-
}
|
|
19446
|
-
|
|
19447
|
-
class PathResolver {
|
|
19448
|
-
static getTestHomeDir() {
|
|
19449
|
-
return process.env.CK_TEST_HOME;
|
|
19450
|
-
}
|
|
19451
|
-
static isValidComponentName(name) {
|
|
19452
|
-
if (!name || typeof name !== "string") {
|
|
19453
|
-
return false;
|
|
19454
|
-
}
|
|
19455
|
-
const dangerousPatterns = [
|
|
19456
|
-
"..",
|
|
19457
|
-
"~"
|
|
19458
|
-
];
|
|
19459
|
-
for (const pattern of dangerousPatterns) {
|
|
19460
|
-
if (name.includes(pattern)) {
|
|
19461
|
-
return false;
|
|
19462
|
-
}
|
|
19463
|
-
}
|
|
19464
|
-
const normalized = normalize(name);
|
|
19465
|
-
for (const pattern of dangerousPatterns) {
|
|
19466
|
-
if (normalized.includes(pattern)) {
|
|
19467
|
-
return false;
|
|
19468
|
-
}
|
|
19469
|
-
}
|
|
19470
|
-
if (name.startsWith("/") || normalized.startsWith("/") || /^[a-zA-Z]:/.test(name) || name.startsWith("\\\\") || normalized.startsWith("\\\\")) {
|
|
19471
|
-
return false;
|
|
19472
|
-
}
|
|
19473
|
-
return true;
|
|
19474
|
-
}
|
|
19475
|
-
static getConfigDir(global3 = false) {
|
|
19476
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19477
|
-
if (testHome) {
|
|
19478
|
-
return global3 ? join11(testHome, ".config", "claude") : join11(testHome, ".claudekit");
|
|
19479
|
-
}
|
|
19480
|
-
if (!global3) {
|
|
19481
|
-
return join11(homedir9(), ".claudekit");
|
|
19482
|
-
}
|
|
19483
|
-
const os2 = platform2();
|
|
19484
|
-
if (os2 === "win32") {
|
|
19485
|
-
const localAppData = getEnvVar("LOCALAPPDATA") ?? join11(homedir9(), "AppData", "Local");
|
|
19486
|
-
return join11(localAppData, "claude");
|
|
19487
|
-
}
|
|
19488
|
-
const xdgConfigHome = getEnvVar("XDG_CONFIG_HOME");
|
|
19489
|
-
if (xdgConfigHome) {
|
|
19490
|
-
return join11(xdgConfigHome, "claude");
|
|
19491
|
-
}
|
|
19492
|
-
return join11(homedir9(), ".config", "claude");
|
|
19493
|
-
}
|
|
19494
|
-
static getConfigFile(global3 = false) {
|
|
19495
|
-
return join11(PathResolver.getConfigDir(global3), "config.json");
|
|
19496
|
-
}
|
|
19497
|
-
static getCacheDir(global3 = false) {
|
|
19498
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19499
|
-
if (testHome) {
|
|
19500
|
-
return global3 ? join11(testHome, ".cache", "claude") : join11(testHome, ".claudekit", "cache");
|
|
19501
|
-
}
|
|
19502
|
-
if (!global3) {
|
|
19503
|
-
return join11(homedir9(), ".claudekit", "cache");
|
|
19504
|
-
}
|
|
19505
|
-
const os2 = platform2();
|
|
19506
|
-
if (os2 === "win32") {
|
|
19507
|
-
const localAppData = getEnvVar("LOCALAPPDATA") ?? join11(homedir9(), "AppData", "Local");
|
|
19508
|
-
return join11(localAppData, "claude", "cache");
|
|
19509
|
-
}
|
|
19510
|
-
const xdgCacheHome = getEnvVar("XDG_CACHE_HOME");
|
|
19511
|
-
if (xdgCacheHome) {
|
|
19512
|
-
return join11(xdgCacheHome, "claude");
|
|
19513
|
-
}
|
|
19514
|
-
return join11(homedir9(), ".cache", "claude");
|
|
19515
|
-
}
|
|
19516
|
-
static getGlobalKitDir() {
|
|
19517
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19518
|
-
if (testHome) {
|
|
19519
|
-
return join11(testHome, ".claude");
|
|
19520
|
-
}
|
|
19521
|
-
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR;
|
|
19522
|
-
if (claudeConfigDir) {
|
|
19523
|
-
return claudeConfigDir;
|
|
19524
|
-
}
|
|
19525
|
-
return join11(homedir9(), ".claude");
|
|
19526
|
-
}
|
|
19527
|
-
static getClaudeKitDir() {
|
|
19528
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19529
|
-
if (testHome) {
|
|
19530
|
-
return join11(testHome, ".claudekit");
|
|
19531
|
-
}
|
|
19532
|
-
return join11(homedir9(), ".claudekit");
|
|
19533
|
-
}
|
|
19534
|
-
static getProjectsRegistryPath() {
|
|
19535
|
-
return join11(PathResolver.getClaudeKitDir(), "projects.json");
|
|
19536
|
-
}
|
|
19537
|
-
static getOpenCodeDir(global3, baseDir) {
|
|
19538
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19539
|
-
if (testHome) {
|
|
19540
|
-
return global3 ? join11(testHome, ".config", "opencode") : join11(baseDir || testHome, ".opencode");
|
|
19541
|
-
}
|
|
19542
|
-
if (!global3) {
|
|
19543
|
-
return join11(baseDir || process.cwd(), ".opencode");
|
|
19544
|
-
}
|
|
19545
|
-
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
19546
|
-
if (xdgConfigHome) {
|
|
19547
|
-
return join11(xdgConfigHome, "opencode");
|
|
19548
|
-
}
|
|
19549
|
-
return join11(homedir9(), ".config", "opencode");
|
|
19550
|
-
}
|
|
19551
|
-
static getPathPrefix(global3) {
|
|
19552
|
-
return global3 ? "" : ".claude";
|
|
19553
|
-
}
|
|
19554
|
-
static buildSkillsPath(baseDir, global3) {
|
|
19555
|
-
const prefix = PathResolver.getPathPrefix(global3);
|
|
19556
|
-
if (prefix) {
|
|
19557
|
-
return join11(baseDir, prefix, "skills");
|
|
19558
|
-
}
|
|
19559
|
-
return join11(baseDir, "skills");
|
|
19560
|
-
}
|
|
19561
|
-
static buildComponentPath(baseDir, component, global3) {
|
|
19562
|
-
if (!PathResolver.isValidComponentName(component)) {
|
|
19563
|
-
throw new Error(`Invalid component name: "${component}" contains path traversal patterns. Valid names are simple directory names like "agents", "commands", "rules", "skills", or "hooks".`);
|
|
19564
|
-
}
|
|
19565
|
-
const prefix = PathResolver.getPathPrefix(global3);
|
|
19566
|
-
if (prefix) {
|
|
19567
|
-
return join11(baseDir, prefix, component);
|
|
19568
|
-
}
|
|
19569
|
-
return join11(baseDir, component);
|
|
19570
|
-
}
|
|
19571
|
-
static getBackupDir(timestamp) {
|
|
19572
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19573
|
-
const baseDir = testHome ? join11(testHome, ".claudekit") : join11(homedir9(), ".claudekit");
|
|
19574
|
-
if (timestamp) {
|
|
19575
|
-
return join11(baseDir, "backups", timestamp);
|
|
19576
|
-
}
|
|
19577
|
-
const now = new Date;
|
|
19578
|
-
const dateStr = now.toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
19579
|
-
const ms = now.getMilliseconds().toString().padStart(3, "0");
|
|
19580
|
-
const random = Math.random().toString(36).slice(2, 6);
|
|
19581
|
-
const ts = `${dateStr}-${ms}-${random}`;
|
|
19582
|
-
return join11(baseDir, "backups", ts);
|
|
19583
|
-
}
|
|
19584
|
-
static normalizeWSLPath(p) {
|
|
19585
|
-
return normalizeWSLPath(p);
|
|
19586
|
-
}
|
|
19587
|
-
static isWSL() {
|
|
19588
|
-
return isWSL();
|
|
19589
|
-
}
|
|
19590
|
-
static isAtHomeDirectory(cwd2) {
|
|
19591
|
-
const currentDir = normalize(cwd2 || process.cwd());
|
|
19592
|
-
const homeDir = normalize(homedir9());
|
|
19593
|
-
return currentDir === homeDir;
|
|
19594
|
-
}
|
|
19595
|
-
static getLocalClaudeDir(baseDir) {
|
|
19596
|
-
const dir = baseDir || process.cwd();
|
|
19597
|
-
return join11(dir, ".claude");
|
|
19598
|
-
}
|
|
19599
|
-
static isLocalSameAsGlobal(cwd2) {
|
|
19600
|
-
const localPath = normalize(PathResolver.getLocalClaudeDir(cwd2));
|
|
19601
|
-
const globalPath = normalize(PathResolver.getGlobalKitDir());
|
|
19602
|
-
return localPath === globalPath;
|
|
19603
|
-
}
|
|
19604
|
-
static isGlobPattern(pattern) {
|
|
19605
|
-
return pattern.includes("*") || pattern.includes("?") || pattern.includes("{");
|
|
19606
|
-
}
|
|
19607
|
-
static computeProjectHash(projectRoot) {
|
|
19608
|
-
let normalized = resolve4(projectRoot).replace(/[/\\]+$/, "");
|
|
19609
|
-
if (process.platform === "darwin" || process.platform === "win32") {
|
|
19610
|
-
normalized = normalized.toLowerCase();
|
|
19611
|
-
}
|
|
19612
|
-
return createHash3("sha256").update(normalized).digest("hex").slice(0, 12);
|
|
19613
|
-
}
|
|
19614
|
-
static getPlansRegistriesDir() {
|
|
19615
|
-
return join11(PathResolver.getGlobalKitDir(), "plans-registries");
|
|
19616
|
-
}
|
|
19617
|
-
static getPlansRegistryPath(projectRoot) {
|
|
19618
|
-
const hash = PathResolver.computeProjectHash(projectRoot);
|
|
19619
|
-
return join11(PathResolver.getPlansRegistriesDir(), `${hash}.json`);
|
|
19620
|
-
}
|
|
19621
|
-
}
|
|
19622
|
-
var init_path_resolver = () => {};
|
|
19623
|
-
|
|
19624
19636
|
// node_modules/universalify/index.js
|
|
19625
19637
|
var require_universalify = __commonJS((exports) => {
|
|
19626
19638
|
exports.fromCallback = function(fn) {
|
|
@@ -21009,10 +21021,10 @@ var init_safe_prompts = __esm(() => {
|
|
|
21009
21021
|
|
|
21010
21022
|
// src/commands/commands/commands-discovery.ts
|
|
21011
21023
|
import { readdir as readdir4 } from "node:fs/promises";
|
|
21012
|
-
import { homedir as
|
|
21024
|
+
import { homedir as homedir9 } from "node:os";
|
|
21013
21025
|
import { join as join16, relative as relative3 } from "node:path";
|
|
21014
21026
|
function getCommandSourcePath(globalOnly = false) {
|
|
21015
|
-
const globalPath = join16(
|
|
21027
|
+
const globalPath = join16(homedir9(), ".claude/commands");
|
|
21016
21028
|
if (globalOnly) {
|
|
21017
21029
|
return findFirstExistingPath([globalPath]);
|
|
21018
21030
|
}
|
|
@@ -45197,6 +45209,14 @@ var init_open = __esm(() => {
|
|
|
45197
45209
|
open_default = open;
|
|
45198
45210
|
});
|
|
45199
45211
|
|
|
45212
|
+
// src/shared/json-content.ts
|
|
45213
|
+
function stripJsonBom(content) {
|
|
45214
|
+
return content.charCodeAt(0) === 65279 ? content.slice(1) : content;
|
|
45215
|
+
}
|
|
45216
|
+
function parseJsonContent(content) {
|
|
45217
|
+
return JSON.parse(stripJsonBom(content));
|
|
45218
|
+
}
|
|
45219
|
+
|
|
45200
45220
|
// src/domains/config/config-manager.ts
|
|
45201
45221
|
import { existsSync as existsSync10 } from "node:fs";
|
|
45202
45222
|
import { mkdir as mkdir6, readFile as readFile7, rename as rename3, rm as rm3, writeFile as writeFile5 } from "node:fs/promises";
|
|
@@ -45225,7 +45245,7 @@ class ConfigManager {
|
|
|
45225
45245
|
try {
|
|
45226
45246
|
if (existsSync10(configFile)) {
|
|
45227
45247
|
const content = await readFile7(configFile, "utf-8");
|
|
45228
|
-
const data =
|
|
45248
|
+
const data = parseJsonContent(content);
|
|
45229
45249
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
45230
45250
|
logger.debug(`Config loaded from ${configFile}`);
|
|
45231
45251
|
return ConfigManager.config;
|
|
@@ -45279,7 +45299,7 @@ class ConfigManager {
|
|
|
45279
45299
|
try {
|
|
45280
45300
|
if (existsSync10(configPath)) {
|
|
45281
45301
|
const content = await readFile7(configPath, "utf-8");
|
|
45282
|
-
const data =
|
|
45302
|
+
const data = parseJsonContent(content);
|
|
45283
45303
|
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
45284
45304
|
logger.debug(`Project config loaded from ${configPath}`);
|
|
45285
45305
|
return folders;
|
|
@@ -45300,7 +45320,7 @@ class ConfigManager {
|
|
|
45300
45320
|
if (existsSync10(configPath)) {
|
|
45301
45321
|
try {
|
|
45302
45322
|
const content = await readFile7(configPath, "utf-8");
|
|
45303
|
-
existingConfig =
|
|
45323
|
+
existingConfig = parseJsonContent(content);
|
|
45304
45324
|
} catch (error) {
|
|
45305
45325
|
logger.debug(`Could not parse existing config, starting fresh: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
45306
45326
|
}
|
|
@@ -45384,7 +45404,7 @@ __export(exports_ck_config_manager, {
|
|
|
45384
45404
|
});
|
|
45385
45405
|
import { existsSync as existsSync11 } from "node:fs";
|
|
45386
45406
|
import { mkdir as mkdir7, readFile as readFile8, writeFile as writeFile6 } from "node:fs/promises";
|
|
45387
|
-
import { homedir as
|
|
45407
|
+
import { homedir as homedir10 } from "node:os";
|
|
45388
45408
|
import { join as join19 } from "node:path";
|
|
45389
45409
|
function getNestedValue(obj, path4) {
|
|
45390
45410
|
if (!obj || typeof obj !== "object")
|
|
@@ -45459,7 +45479,7 @@ function valuesEqual(a3, b3) {
|
|
|
45459
45479
|
|
|
45460
45480
|
class CkConfigManager {
|
|
45461
45481
|
static getGlobalConfigDir() {
|
|
45462
|
-
return join19(
|
|
45482
|
+
return join19(homedir10(), ".claude");
|
|
45463
45483
|
}
|
|
45464
45484
|
static getGlobalConfigPath() {
|
|
45465
45485
|
return join19(CkConfigManager.getGlobalConfigDir(), CK_CONFIG_FILE);
|
|
@@ -45475,7 +45495,7 @@ class CkConfigManager {
|
|
|
45475
45495
|
if (!existsSync11(configPath))
|
|
45476
45496
|
return null;
|
|
45477
45497
|
const content = await readFile8(configPath, "utf-8");
|
|
45478
|
-
const data = normalizeCkConfigInput(
|
|
45498
|
+
const data = normalizeCkConfigInput(parseJsonContent(content));
|
|
45479
45499
|
return CkConfigSchema.parse(data);
|
|
45480
45500
|
} catch (error) {
|
|
45481
45501
|
logger.warning(`Failed to load config from ${configPath}: ${error instanceof Error ? error.message : "Unknown"}`);
|
|
@@ -45542,7 +45562,7 @@ class CkConfigManager {
|
|
|
45542
45562
|
if (!existingConfig && existsSync11(configPath)) {
|
|
45543
45563
|
try {
|
|
45544
45564
|
const content = await readFile8(configPath, "utf-8");
|
|
45545
|
-
const parsed =
|
|
45565
|
+
const parsed = parseJsonContent(content);
|
|
45546
45566
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
45547
45567
|
existingConfig = normalizeCkConfigInput(parsed);
|
|
45548
45568
|
}
|
|
@@ -45718,7 +45738,7 @@ function notFoundError(type, name, hint) {
|
|
|
45718
45738
|
}
|
|
45719
45739
|
|
|
45720
45740
|
// src/shared/command-normalizer.ts
|
|
45721
|
-
import { homedir as
|
|
45741
|
+
import { homedir as homedir11 } from "node:os";
|
|
45722
45742
|
import { join as join20 } from "node:path";
|
|
45723
45743
|
function escapeRegex(value) {
|
|
45724
45744
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -45758,7 +45778,7 @@ function resolveClaudePathArg(arg, root) {
|
|
|
45758
45778
|
const isWin2 = process.platform === "win32";
|
|
45759
45779
|
const cmp = (s) => isWin2 ? s.toLowerCase() : s;
|
|
45760
45780
|
const globalRoots = [
|
|
45761
|
-
`${
|
|
45781
|
+
`${homedir11().replace(/\\/g, "/").replace(/\/+$/, "")}/.claude/`,
|
|
45762
45782
|
`${PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "")}/`
|
|
45763
45783
|
];
|
|
45764
45784
|
const isUnderGlobal = globalRoots.some((g2) => cmp(absolutePath).startsWith(cmp(g2)));
|
|
@@ -45794,6 +45814,12 @@ function repairClaudeNodeCommandPath(cmd, root) {
|
|
|
45794
45814
|
const command = formatCanonicalClaudeCommand(nodePrefix, root, relativePath, suffix);
|
|
45795
45815
|
return { command, changed: command !== cmd, issue: "raw-relative" };
|
|
45796
45816
|
}
|
|
45817
|
+
const quotedRelativeMatch = cmd.match(/^(node\s+)["'](?:\.\/)?(\.claude[/\\][^"']+)["'](.*)$/);
|
|
45818
|
+
if (quotedRelativeMatch) {
|
|
45819
|
+
const [, nodePrefix, relativePath, suffix] = quotedRelativeMatch;
|
|
45820
|
+
const command = formatCanonicalClaudeCommand(nodePrefix, root, relativePath, suffix);
|
|
45821
|
+
return { command, changed: command !== cmd, issue: "raw-relative" };
|
|
45822
|
+
}
|
|
45797
45823
|
const embeddedQuotedMatch = cmd.match(/^(node\s+)"(?:\$HOME|\$CLAUDE_PROJECT_DIR|%USERPROFILE%|%CLAUDE_PROJECT_DIR%)[/\\](\.claude[/\\][^"]+)"(.*)$/);
|
|
45798
45824
|
if (embeddedQuotedMatch) {
|
|
45799
45825
|
const [, nodePrefix, relativePath, suffix] = embeddedQuotedMatch;
|
|
@@ -45829,7 +45855,7 @@ function repairClaudeNodeCommandPath(cmd, root) {
|
|
|
45829
45855
|
const isWin2 = process.platform === "win32";
|
|
45830
45856
|
const cmp = (s) => isWin2 ? s.toLowerCase() : s;
|
|
45831
45857
|
const globalRoots = [
|
|
45832
|
-
`${
|
|
45858
|
+
`${homedir11().replace(/\\/g, "/").replace(/\/+$/, "")}/.claude/`,
|
|
45833
45859
|
`${PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "")}/`
|
|
45834
45860
|
];
|
|
45835
45861
|
const isUnderGlobal = globalRoots.some((g2) => cmp(normalizedAbsPath).startsWith(cmp(g2)));
|
|
@@ -45878,7 +45904,7 @@ function normalizeCommand(cmd) {
|
|
|
45878
45904
|
return "";
|
|
45879
45905
|
let normalized = cmd;
|
|
45880
45906
|
const globalKitDir = PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "");
|
|
45881
|
-
const defaultGlobalKitDir = join20(
|
|
45907
|
+
const defaultGlobalKitDir = join20(homedir11(), ".claude").replace(/\\/g, "/");
|
|
45882
45908
|
normalized = normalized.replace(/"/g, "");
|
|
45883
45909
|
normalized = normalized.replace(/~\//g, "$HOME/");
|
|
45884
45910
|
normalized = normalized.replace(/\$CLAUDE_PROJECT_DIR/g, "$HOME");
|
|
@@ -46076,11 +46102,15 @@ function mergeHookEntries(sourceEntries, destEntries, eventName, result, install
|
|
|
46076
46102
|
const isFullyDuplicated = commands.length > 0 && commands.every((cmd) => existingCommands.has(normalizeCommand(cmd)));
|
|
46077
46103
|
const duplicateCommands = commands.filter((cmd) => existingCommands.has(normalizeCommand(cmd)));
|
|
46078
46104
|
logDuplicates(duplicateCommands, eventName, result);
|
|
46079
|
-
const
|
|
46105
|
+
const newCommands = commands.filter((cmd) => !existingCommands.has(normalizeCommand(cmd)) && !wasCommandInstalled(cmd, installedHooks));
|
|
46106
|
+
const hasNonRemovedCommands = commands.length === 0 || newCommands.length > 0;
|
|
46080
46107
|
if (!isFullyDuplicated && hasNonRemovedCommands) {
|
|
46081
46108
|
let filteredEntry = entry;
|
|
46082
|
-
if ("hooks" in entry && entry.hooks &&
|
|
46083
|
-
const filteredHooks = entry.hooks.filter((h2) => !h2.command || !wasCommandInstalled(h2.command, installedHooks));
|
|
46109
|
+
if ("hooks" in entry && entry.hooks && commands.length > 0) {
|
|
46110
|
+
const filteredHooks = entry.hooks.filter((h2) => !h2.command || !existingCommands.has(normalizeCommand(h2.command)) && !wasCommandInstalled(h2.command, installedHooks));
|
|
46111
|
+
if (filteredHooks.length === 0) {
|
|
46112
|
+
continue;
|
|
46113
|
+
}
|
|
46084
46114
|
filteredEntry = { ...entry, hooks: filteredHooks };
|
|
46085
46115
|
} else if ("command" in entry && wasCommandInstalled(entry.command, installedHooks)) {
|
|
46086
46116
|
continue;
|
|
@@ -46091,16 +46121,12 @@ function mergeHookEntries(sourceEntries, destEntries, eventName, result, install
|
|
|
46091
46121
|
if (sourceMatcher) {
|
|
46092
46122
|
matcherIndex.set(sourceMatcher, merged.length - 1);
|
|
46093
46123
|
}
|
|
46094
|
-
for (const cmd of
|
|
46124
|
+
for (const cmd of newCommands) {
|
|
46095
46125
|
const normalizedCmd = normalizeCommand(cmd);
|
|
46096
|
-
|
|
46097
|
-
|
|
46098
|
-
|
|
46099
|
-
|
|
46100
|
-
trackHookOrigin(result, sourceKit, cmd);
|
|
46101
|
-
}
|
|
46102
|
-
} else if (!existingCommands.has(normalizedCmd)) {
|
|
46103
|
-
existingCommands.add(normalizedCmd);
|
|
46126
|
+
existingCommands.add(normalizedCmd);
|
|
46127
|
+
result.newlyInstalledHooks.push(cmd);
|
|
46128
|
+
if (sourceKit) {
|
|
46129
|
+
trackHookOrigin(result, sourceKit, cmd);
|
|
46104
46130
|
}
|
|
46105
46131
|
}
|
|
46106
46132
|
}
|
|
@@ -48071,7 +48097,7 @@ var init_chokidar = __esm(() => {
|
|
|
48071
48097
|
});
|
|
48072
48098
|
|
|
48073
48099
|
// src/domains/web-server/file-watcher.ts
|
|
48074
|
-
import { homedir as
|
|
48100
|
+
import { homedir as homedir12 } from "node:os";
|
|
48075
48101
|
import { join as join25 } from "node:path";
|
|
48076
48102
|
|
|
48077
48103
|
class FileWatcher {
|
|
@@ -48094,9 +48120,9 @@ class FileWatcher {
|
|
|
48094
48120
|
}
|
|
48095
48121
|
getWatchPaths() {
|
|
48096
48122
|
const paths = [];
|
|
48097
|
-
const globalDir = join25(
|
|
48123
|
+
const globalDir = join25(homedir12(), ".claudekit");
|
|
48098
48124
|
paths.push(join25(globalDir, "config.json"));
|
|
48099
|
-
const globalKitDir = join25(
|
|
48125
|
+
const globalKitDir = join25(homedir12(), ".claude");
|
|
48100
48126
|
paths.push(join25(globalKitDir, ".ck.json"));
|
|
48101
48127
|
paths.push(join25(globalKitDir, "settings.json"));
|
|
48102
48128
|
paths.push(join25(globalKitDir, "settings.local.json"));
|
|
@@ -48146,8 +48172,8 @@ class FileWatcher {
|
|
|
48146
48172
|
return path4.endsWith("config.json") || path4.endsWith(".ck.json") || path4.endsWith("settings.json") || path4.endsWith("settings.local.json");
|
|
48147
48173
|
}
|
|
48148
48174
|
getConfigScope(path4) {
|
|
48149
|
-
const globalDir = join25(
|
|
48150
|
-
const globalKitDir = join25(
|
|
48175
|
+
const globalDir = join25(homedir12(), ".claudekit");
|
|
48176
|
+
const globalKitDir = join25(homedir12(), ".claude");
|
|
48151
48177
|
return path4.startsWith(globalDir) || path4.startsWith(globalKitDir) ? "global" : "local";
|
|
48152
48178
|
}
|
|
48153
48179
|
stop() {
|
|
@@ -48638,7 +48664,7 @@ var init_claudekit_data2 = __esm(() => {
|
|
|
48638
48664
|
// src/domains/web-server/routes/action-routes.ts
|
|
48639
48665
|
import { spawn, spawnSync } from "node:child_process";
|
|
48640
48666
|
import { existsSync as existsSync14 } from "node:fs";
|
|
48641
|
-
import { homedir as
|
|
48667
|
+
import { homedir as homedir13 } from "node:os";
|
|
48642
48668
|
import { join as join27, resolve as resolve12, sep as sep5 } from "node:path";
|
|
48643
48669
|
function getWindowsPaths(...relativePaths) {
|
|
48644
48670
|
const roots = [
|
|
@@ -48915,7 +48941,7 @@ async function isActionPathAllowed(dirPath, projectId) {
|
|
|
48915
48941
|
try {
|
|
48916
48942
|
const encodedPath = projectId.slice("discovered-".length);
|
|
48917
48943
|
const discoveredPath = resolve12(Buffer.from(encodedPath, "base64url").toString("utf-8"));
|
|
48918
|
-
if (discoveredPath === dirPath && (isPathInsideBase(discoveredPath, process.cwd()) || isPathInsideBase(discoveredPath,
|
|
48944
|
+
if (discoveredPath === dirPath && (isPathInsideBase(discoveredPath, process.cwd()) || isPathInsideBase(discoveredPath, homedir13()))) {
|
|
48919
48945
|
return true;
|
|
48920
48946
|
}
|
|
48921
48947
|
} catch {}
|
|
@@ -48927,7 +48953,7 @@ async function isActionPathAllowed(dirPath, projectId) {
|
|
|
48927
48953
|
if (isPathInsideBase(dirPath, process.cwd())) {
|
|
48928
48954
|
return true;
|
|
48929
48955
|
}
|
|
48930
|
-
return isPathInsideBase(dirPath,
|
|
48956
|
+
return isPathInsideBase(dirPath, homedir13());
|
|
48931
48957
|
}
|
|
48932
48958
|
function buildSystemTerminalCommand(dirPath) {
|
|
48933
48959
|
if (isMacOS()) {
|
|
@@ -49266,7 +49292,7 @@ var init_action_routes = __esm(() => {
|
|
|
49266
49292
|
projectId: exports_external.string().min(1).max(256).optional()
|
|
49267
49293
|
}).strict();
|
|
49268
49294
|
WINDOWS_PATHS = {
|
|
49269
|
-
localAppData: process.env.LOCALAPPDATA || join27(
|
|
49295
|
+
localAppData: process.env.LOCALAPPDATA || join27(homedir13(), "AppData", "Local"),
|
|
49270
49296
|
programFiles: process.env.ProgramFiles || "C:\\Program Files",
|
|
49271
49297
|
programFilesX86: process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)"
|
|
49272
49298
|
};
|
|
@@ -49287,7 +49313,7 @@ var init_action_routes = __esm(() => {
|
|
|
49287
49313
|
openMode: "open-directory",
|
|
49288
49314
|
capabilities: ["open-directory", "run-command"],
|
|
49289
49315
|
macAppName: "iTerm",
|
|
49290
|
-
macAppPaths: ["/Applications/iTerm.app", join27(
|
|
49316
|
+
macAppPaths: ["/Applications/iTerm.app", join27(homedir13(), "Applications", "iTerm.app")]
|
|
49291
49317
|
},
|
|
49292
49318
|
{
|
|
49293
49319
|
id: "warp",
|
|
@@ -49298,7 +49324,7 @@ var init_action_routes = __esm(() => {
|
|
|
49298
49324
|
capabilities: ["open-directory", "uri-scheme"],
|
|
49299
49325
|
commands: ["warp"],
|
|
49300
49326
|
macAppName: "Warp",
|
|
49301
|
-
macAppPaths: ["/Applications/Warp.app", join27(
|
|
49327
|
+
macAppPaths: ["/Applications/Warp.app", join27(homedir13(), "Applications", "Warp.app")],
|
|
49302
49328
|
windowsAppPaths: getWindowsPaths("Warp\\Warp.exe"),
|
|
49303
49329
|
linuxAppPaths: ["/usr/bin/warp", "/usr/local/bin/warp"]
|
|
49304
49330
|
},
|
|
@@ -49321,7 +49347,7 @@ var init_action_routes = __esm(() => {
|
|
|
49321
49347
|
capabilities: ["open-directory"],
|
|
49322
49348
|
commands: ["wezterm"],
|
|
49323
49349
|
macAppName: "WezTerm",
|
|
49324
|
-
macAppPaths: ["/Applications/WezTerm.app", join27(
|
|
49350
|
+
macAppPaths: ["/Applications/WezTerm.app", join27(homedir13(), "Applications", "WezTerm.app")],
|
|
49325
49351
|
windowsAppPaths: getWindowsPaths("WezTerm\\wezterm-gui.exe", "WezTerm\\wezterm.exe"),
|
|
49326
49352
|
linuxAppPaths: ["/usr/bin/wezterm", "/usr/local/bin/wezterm"]
|
|
49327
49353
|
},
|
|
@@ -49334,7 +49360,7 @@ var init_action_routes = __esm(() => {
|
|
|
49334
49360
|
capabilities: ["open-directory"],
|
|
49335
49361
|
commands: ["kitty"],
|
|
49336
49362
|
macAppName: "kitty",
|
|
49337
|
-
macAppPaths: ["/Applications/kitty.app", join27(
|
|
49363
|
+
macAppPaths: ["/Applications/kitty.app", join27(homedir13(), "Applications", "kitty.app")],
|
|
49338
49364
|
windowsAppPaths: getWindowsPaths("kitty\\kitty.exe"),
|
|
49339
49365
|
linuxAppPaths: ["/usr/bin/kitty", "/usr/local/bin/kitty"]
|
|
49340
49366
|
},
|
|
@@ -49347,7 +49373,7 @@ var init_action_routes = __esm(() => {
|
|
|
49347
49373
|
capabilities: ["open-directory"],
|
|
49348
49374
|
commands: ["alacritty"],
|
|
49349
49375
|
macAppName: "Alacritty",
|
|
49350
|
-
macAppPaths: ["/Applications/Alacritty.app", join27(
|
|
49376
|
+
macAppPaths: ["/Applications/Alacritty.app", join27(homedir13(), "Applications", "Alacritty.app")],
|
|
49351
49377
|
windowsAppPaths: getWindowsPaths("Alacritty\\alacritty.exe"),
|
|
49352
49378
|
linuxAppPaths: ["/usr/bin/alacritty", "/usr/local/bin/alacritty"]
|
|
49353
49379
|
},
|
|
@@ -49420,7 +49446,7 @@ var init_action_routes = __esm(() => {
|
|
|
49420
49446
|
capabilities: ["open-app"],
|
|
49421
49447
|
commands: ["termius"],
|
|
49422
49448
|
macAppName: "Termius",
|
|
49423
|
-
macAppPaths: ["/Applications/Termius.app", join27(
|
|
49449
|
+
macAppPaths: ["/Applications/Termius.app", join27(homedir13(), "Applications", "Termius.app")],
|
|
49424
49450
|
windowsAppPaths: getWindowsPaths("Termius\\Termius.exe"),
|
|
49425
49451
|
linuxAppPaths: ["/usr/bin/termius"]
|
|
49426
49452
|
},
|
|
@@ -49443,7 +49469,7 @@ var init_action_routes = __esm(() => {
|
|
|
49443
49469
|
macAppName: "Visual Studio Code",
|
|
49444
49470
|
macAppPaths: [
|
|
49445
49471
|
"/Applications/Visual Studio Code.app",
|
|
49446
|
-
join27(
|
|
49472
|
+
join27(homedir13(), "Applications", "Visual Studio Code.app")
|
|
49447
49473
|
],
|
|
49448
49474
|
windowsAppPaths: getWindowsPaths("Programs\\Microsoft VS Code\\Code.exe", "Microsoft VS Code\\Code.exe"),
|
|
49449
49475
|
linuxAppPaths: ["/usr/bin/code", "/snap/bin/code"]
|
|
@@ -49457,7 +49483,7 @@ var init_action_routes = __esm(() => {
|
|
|
49457
49483
|
capabilities: ["open-directory"],
|
|
49458
49484
|
commands: ["cursor"],
|
|
49459
49485
|
macAppName: "Cursor",
|
|
49460
|
-
macAppPaths: ["/Applications/Cursor.app", join27(
|
|
49486
|
+
macAppPaths: ["/Applications/Cursor.app", join27(homedir13(), "Applications", "Cursor.app")],
|
|
49461
49487
|
windowsAppPaths: getWindowsPaths("Programs\\Cursor\\Cursor.exe", "Cursor\\Cursor.exe"),
|
|
49462
49488
|
linuxAppPaths: ["/usr/bin/cursor"]
|
|
49463
49489
|
},
|
|
@@ -49470,7 +49496,7 @@ var init_action_routes = __esm(() => {
|
|
|
49470
49496
|
capabilities: ["open-directory"],
|
|
49471
49497
|
commands: ["windsurf"],
|
|
49472
49498
|
macAppName: "Windsurf",
|
|
49473
|
-
macAppPaths: ["/Applications/Windsurf.app", join27(
|
|
49499
|
+
macAppPaths: ["/Applications/Windsurf.app", join27(homedir13(), "Applications", "Windsurf.app")],
|
|
49474
49500
|
windowsAppPaths: getWindowsPaths("Programs\\Windsurf\\Windsurf.exe", "Windsurf\\Windsurf.exe"),
|
|
49475
49501
|
linuxAppPaths: ["/usr/bin/windsurf"]
|
|
49476
49502
|
},
|
|
@@ -49485,11 +49511,11 @@ var init_action_routes = __esm(() => {
|
|
|
49485
49511
|
macAppName: "Antigravity",
|
|
49486
49512
|
macAppPaths: [
|
|
49487
49513
|
"/Applications/Antigravity.app",
|
|
49488
|
-
join27(
|
|
49514
|
+
join27(homedir13(), "Applications", "Antigravity.app")
|
|
49489
49515
|
],
|
|
49490
49516
|
windowsAppPaths: getWindowsPaths("Programs\\Antigravity\\Antigravity.exe"),
|
|
49491
49517
|
linuxAppPaths: ["/usr/bin/antigravity"],
|
|
49492
|
-
fallbackDetectionPaths: [join27(
|
|
49518
|
+
fallbackDetectionPaths: [join27(homedir13(), ".gemini", "antigravity")]
|
|
49493
49519
|
},
|
|
49494
49520
|
{
|
|
49495
49521
|
id: "zed",
|
|
@@ -49500,7 +49526,7 @@ var init_action_routes = __esm(() => {
|
|
|
49500
49526
|
capabilities: ["open-directory"],
|
|
49501
49527
|
commands: ["zed"],
|
|
49502
49528
|
macAppName: "Zed",
|
|
49503
|
-
macAppPaths: ["/Applications/Zed.app", join27(
|
|
49529
|
+
macAppPaths: ["/Applications/Zed.app", join27(homedir13(), "Applications", "Zed.app")],
|
|
49504
49530
|
windowsAppPaths: getWindowsPaths("Zed\\Zed.exe"),
|
|
49505
49531
|
linuxAppPaths: ["/usr/bin/zed", "/usr/local/bin/zed"]
|
|
49506
49532
|
},
|
|
@@ -49515,7 +49541,7 @@ var init_action_routes = __esm(() => {
|
|
|
49515
49541
|
macAppName: "Sublime Text",
|
|
49516
49542
|
macAppPaths: [
|
|
49517
49543
|
"/Applications/Sublime Text.app",
|
|
49518
|
-
join27(
|
|
49544
|
+
join27(homedir13(), "Applications", "Sublime Text.app")
|
|
49519
49545
|
],
|
|
49520
49546
|
windowsAppPaths: getWindowsPaths("Sublime Text\\sublime_text.exe"),
|
|
49521
49547
|
linuxAppPaths: ["/usr/bin/subl", "/snap/bin/subl"]
|
|
@@ -49556,7 +49582,7 @@ var init_action_routes = __esm(() => {
|
|
|
49556
49582
|
|
|
49557
49583
|
// src/domains/web-server/routes/agents-routes.ts
|
|
49558
49584
|
import { readdir as readdir7 } from "node:fs/promises";
|
|
49559
|
-
import { homedir as
|
|
49585
|
+
import { homedir as homedir14 } from "node:os";
|
|
49560
49586
|
import { isAbsolute as isAbsolute4, join as join28, relative as relative7 } from "node:path";
|
|
49561
49587
|
function resolveAgentDirs() {
|
|
49562
49588
|
const dirs = [];
|
|
@@ -49601,7 +49627,7 @@ async function scanAgentDir(dirPath, dirLabel) {
|
|
|
49601
49627
|
color: frontmatter.color || null,
|
|
49602
49628
|
skillCount: countSkills(frontmatter.tools),
|
|
49603
49629
|
dirLabel,
|
|
49604
|
-
relativePath: relative7(
|
|
49630
|
+
relativePath: relative7(homedir14(), filePath)
|
|
49605
49631
|
});
|
|
49606
49632
|
} catch {}
|
|
49607
49633
|
}
|
|
@@ -49645,7 +49671,7 @@ function registerAgentsBrowserRoutes(app) {
|
|
|
49645
49671
|
color: frontmatter.color || null,
|
|
49646
49672
|
skillCount: countSkills(frontmatter.tools),
|
|
49647
49673
|
dirLabel: dir.label,
|
|
49648
|
-
relativePath: relative7(
|
|
49674
|
+
relativePath: relative7(homedir14(), filePath),
|
|
49649
49675
|
frontmatter,
|
|
49650
49676
|
body
|
|
49651
49677
|
};
|
|
@@ -49660,7 +49686,7 @@ var home2;
|
|
|
49660
49686
|
var init_agents_routes = __esm(() => {
|
|
49661
49687
|
init_frontmatter_parser();
|
|
49662
49688
|
init_kit_layout();
|
|
49663
|
-
home2 =
|
|
49689
|
+
home2 = homedir14();
|
|
49664
49690
|
});
|
|
49665
49691
|
|
|
49666
49692
|
// src/schemas/ck-config.schema.json
|
|
@@ -50122,6 +50148,16 @@ var init_ck_config_schema = __esm(() => {
|
|
|
50122
50148
|
default: true,
|
|
50123
50149
|
description: "SubagentStart hook - injects context to subagents"
|
|
50124
50150
|
},
|
|
50151
|
+
"session-state": {
|
|
50152
|
+
type: "boolean",
|
|
50153
|
+
default: true,
|
|
50154
|
+
description: "Stop/SubagentStop/PostToolUse hook - persists session state for handoff and statusline context"
|
|
50155
|
+
},
|
|
50156
|
+
"cook-after-plan-reminder": {
|
|
50157
|
+
type: "boolean",
|
|
50158
|
+
default: true,
|
|
50159
|
+
description: "SubagentStop hook - reminds agents to continue implementation after planning"
|
|
50160
|
+
},
|
|
50125
50161
|
"descriptive-name": {
|
|
50126
50162
|
type: "boolean",
|
|
50127
50163
|
default: true,
|
|
@@ -50132,6 +50168,16 @@ var init_ck_config_schema = __esm(() => {
|
|
|
50132
50168
|
default: true,
|
|
50133
50169
|
description: "UserPromptSubmit hook - injects dev rules context"
|
|
50134
50170
|
},
|
|
50171
|
+
"plan-format-kanban": {
|
|
50172
|
+
type: "boolean",
|
|
50173
|
+
default: true,
|
|
50174
|
+
description: "PostToolUse hook - keeps plan kanban metadata synchronized after edits"
|
|
50175
|
+
},
|
|
50176
|
+
"usage-quota-cache-refresh": {
|
|
50177
|
+
type: "boolean",
|
|
50178
|
+
default: true,
|
|
50179
|
+
description: "Lifecycle hook - refreshes cached usage quota information"
|
|
50180
|
+
},
|
|
50135
50181
|
"usage-context-awareness": {
|
|
50136
50182
|
type: "boolean",
|
|
50137
50183
|
default: true,
|
|
@@ -50477,7 +50523,7 @@ var init_ck_config_routes = __esm(() => {
|
|
|
50477
50523
|
// src/domains/web-server/routes/command-routes.ts
|
|
50478
50524
|
import { existsSync as existsSync16 } from "node:fs";
|
|
50479
50525
|
import { readFile as readFile12, readdir as readdir8 } from "node:fs/promises";
|
|
50480
|
-
import { homedir as
|
|
50526
|
+
import { homedir as homedir15 } from "node:os";
|
|
50481
50527
|
import { basename as basename9, isAbsolute as isAbsolute5, join as join30, relative as relative8, resolve as resolve13 } from "node:path";
|
|
50482
50528
|
async function buildCommandTree(dir, baseDir) {
|
|
50483
50529
|
let dirents;
|
|
@@ -50519,7 +50565,7 @@ async function buildCommandTree(dir, baseDir) {
|
|
|
50519
50565
|
}
|
|
50520
50566
|
function registerCommandRoutes(app) {
|
|
50521
50567
|
app.get("/api/commands", async (_req, res) => {
|
|
50522
|
-
const commandsDir = join30(
|
|
50568
|
+
const commandsDir = join30(homedir15(), ".claude", "commands");
|
|
50523
50569
|
if (!existsSync16(commandsDir)) {
|
|
50524
50570
|
res.json({ tree: [] });
|
|
50525
50571
|
return;
|
|
@@ -50542,7 +50588,7 @@ function registerCommandRoutes(app) {
|
|
|
50542
50588
|
res.status(400).json({ error: "Invalid path" });
|
|
50543
50589
|
return;
|
|
50544
50590
|
}
|
|
50545
|
-
const commandsDir = join30(
|
|
50591
|
+
const commandsDir = join30(homedir15(), ".claude", "commands");
|
|
50546
50592
|
const safePath = resolve13(commandsDir, rawPath);
|
|
50547
50593
|
const rel = relative8(commandsDir, safePath);
|
|
50548
50594
|
if (rel.startsWith("..") || isAbsolute5(rel)) {
|
|
@@ -50616,11 +50662,11 @@ var init_types5 = __esm(() => {
|
|
|
50616
50662
|
|
|
50617
50663
|
// src/services/claude-data/history-parser.ts
|
|
50618
50664
|
import { createReadStream, statSync as statSync4 } from "node:fs";
|
|
50619
|
-
import { homedir as
|
|
50665
|
+
import { homedir as homedir16 } from "node:os";
|
|
50620
50666
|
import { join as join31 } from "node:path";
|
|
50621
50667
|
import { createInterface as createInterface2 } from "node:readline";
|
|
50622
50668
|
function getHistoryPath() {
|
|
50623
|
-
return process.env.CLAUDE_HISTORY_PATH ?? join31(
|
|
50669
|
+
return process.env.CLAUDE_HISTORY_PATH ?? join31(homedir16(), ".claude", "history.jsonl");
|
|
50624
50670
|
}
|
|
50625
50671
|
function emptyResult(parseTimeMs, error) {
|
|
50626
50672
|
return { projects: [], totalEntries: 0, errorCount: 0, parseTimeMs, error };
|
|
@@ -50818,10 +50864,10 @@ var init_session_parser = () => {};
|
|
|
50818
50864
|
// src/services/claude-data/skill-scanner.ts
|
|
50819
50865
|
import { existsSync as existsSync18 } from "node:fs";
|
|
50820
50866
|
import { readFile as readFile14, readdir as readdir10, stat as stat6 } from "node:fs/promises";
|
|
50821
|
-
import { homedir as
|
|
50867
|
+
import { homedir as homedir17 } from "node:os";
|
|
50822
50868
|
import { join as join33 } from "node:path";
|
|
50823
50869
|
async function getCkSkillMetadata(scope) {
|
|
50824
|
-
const metaPath = scope === "global" ? join33(
|
|
50870
|
+
const metaPath = scope === "global" ? join33(homedir17(), ".claude", "metadata.json") : join33(process.cwd(), ".claude", "metadata.json");
|
|
50825
50871
|
if (!existsSync18(metaPath))
|
|
50826
50872
|
return null;
|
|
50827
50873
|
const result = new Map;
|
|
@@ -50951,14 +50997,14 @@ async function scanSkills() {
|
|
|
50951
50997
|
var import_gray_matter4, skillsDir, SKIP_DIRS2;
|
|
50952
50998
|
var init_skill_scanner = __esm(() => {
|
|
50953
50999
|
import_gray_matter4 = __toESM(require_gray_matter(), 1);
|
|
50954
|
-
skillsDir = join33(
|
|
51000
|
+
skillsDir = join33(homedir17(), ".claude", "skills");
|
|
50955
51001
|
SKIP_DIRS2 = [".venv", "scripts", "__pycache__", "node_modules", ".git", "common"];
|
|
50956
51002
|
});
|
|
50957
51003
|
|
|
50958
51004
|
// src/services/claude-data/settings-reader.ts
|
|
50959
51005
|
import { existsSync as existsSync19 } from "node:fs";
|
|
50960
51006
|
import { copyFile as copyFile2, mkdir as mkdir9, readFile as readFile15, rename as rename5, rm as rm4, writeFile as writeFile10 } from "node:fs/promises";
|
|
50961
|
-
import { homedir as
|
|
51007
|
+
import { homedir as homedir18 } from "node:os";
|
|
50962
51008
|
import { join as join34 } from "node:path";
|
|
50963
51009
|
function getSettingsPath() {
|
|
50964
51010
|
return join34(claudeDir, settingsFilename);
|
|
@@ -51020,7 +51066,7 @@ function countMcpServers(settings) {
|
|
|
51020
51066
|
}
|
|
51021
51067
|
var claudeDir, settingsFilename = "settings.json", settingsBackupDir;
|
|
51022
51068
|
var init_settings_reader = __esm(() => {
|
|
51023
|
-
claudeDir = join34(
|
|
51069
|
+
claudeDir = join34(homedir18(), ".claude");
|
|
51024
51070
|
settingsBackupDir = join34(claudeDir, ".ck-backups", "settings");
|
|
51025
51071
|
});
|
|
51026
51072
|
|
|
@@ -51188,7 +51234,7 @@ var init_hook_log_reader = __esm(() => {
|
|
|
51188
51234
|
});
|
|
51189
51235
|
|
|
51190
51236
|
// src/services/claude-data/project-scanner.ts
|
|
51191
|
-
import { homedir as
|
|
51237
|
+
import { homedir as homedir19 } from "node:os";
|
|
51192
51238
|
import { basename as basename10, join as join36, normalize as normalize4 } from "node:path";
|
|
51193
51239
|
function decodePath(encoded) {
|
|
51194
51240
|
const decoded = encoded.replace(/^-/, "/").replace(/-/g, "/");
|
|
@@ -51203,7 +51249,7 @@ function encodePath(path4) {
|
|
|
51203
51249
|
}
|
|
51204
51250
|
var projectsDir;
|
|
51205
51251
|
var init_project_scanner = __esm(() => {
|
|
51206
|
-
projectsDir = join36(
|
|
51252
|
+
projectsDir = join36(homedir19(), ".claude", "projects");
|
|
51207
51253
|
});
|
|
51208
51254
|
|
|
51209
51255
|
// src/services/claude-data/project-discovery.ts
|
|
@@ -51298,10 +51344,10 @@ var init_project_discovery = __esm(() => {
|
|
|
51298
51344
|
|
|
51299
51345
|
// src/services/claude-data/user-preferences.ts
|
|
51300
51346
|
import { readFile as readFile16, stat as stat7 } from "node:fs/promises";
|
|
51301
|
-
import { homedir as
|
|
51347
|
+
import { homedir as homedir20 } from "node:os";
|
|
51302
51348
|
import { join as join37 } from "node:path";
|
|
51303
51349
|
function getPreferencesPath() {
|
|
51304
|
-
return join37(
|
|
51350
|
+
return join37(homedir20(), ".claude.json");
|
|
51305
51351
|
}
|
|
51306
51352
|
async function readUserPreferences(filePath) {
|
|
51307
51353
|
const path4 = filePath ?? getPreferencesPath();
|
|
@@ -51392,7 +51438,7 @@ var init_claude_data = __esm(() => {
|
|
|
51392
51438
|
// src/domains/web-server/routes/dashboard-routes.ts
|
|
51393
51439
|
import { existsSync as existsSync20 } from "node:fs";
|
|
51394
51440
|
import { readFile as readFile17, readdir as readdir11 } from "node:fs/promises";
|
|
51395
|
-
import { homedir as
|
|
51441
|
+
import { homedir as homedir21 } from "node:os";
|
|
51396
51442
|
import { join as join38 } from "node:path";
|
|
51397
51443
|
async function readAgents() {
|
|
51398
51444
|
const agentsDir = join38(claudeDir2, "agents");
|
|
@@ -51462,7 +51508,7 @@ async function countAllMcpServers() {
|
|
|
51462
51508
|
}
|
|
51463
51509
|
let claudeJsonCount = 0;
|
|
51464
51510
|
try {
|
|
51465
|
-
const claudeJsonPath = join38(
|
|
51511
|
+
const claudeJsonPath = join38(homedir21(), ".claude.json");
|
|
51466
51512
|
if (existsSync20(claudeJsonPath)) {
|
|
51467
51513
|
const content = await readFile17(claudeJsonPath, "utf-8");
|
|
51468
51514
|
const data = JSON.parse(content);
|
|
@@ -51589,7 +51635,7 @@ var claudeDir2;
|
|
|
51589
51635
|
var init_dashboard_routes = __esm(() => {
|
|
51590
51636
|
init_frontmatter_parser();
|
|
51591
51637
|
init_claude_data();
|
|
51592
|
-
claudeDir2 = join38(
|
|
51638
|
+
claudeDir2 = join38(homedir21(), ".claude");
|
|
51593
51639
|
});
|
|
51594
51640
|
|
|
51595
51641
|
// src/domains/web-server/routes/health-routes.ts
|
|
@@ -51663,7 +51709,7 @@ var init_hook_log_routes = __esm(() => {
|
|
|
51663
51709
|
// src/domains/web-server/routes/mcp-routes.ts
|
|
51664
51710
|
import { existsSync as existsSync21 } from "node:fs";
|
|
51665
51711
|
import { readFile as readFile18 } from "node:fs/promises";
|
|
51666
|
-
import { homedir as
|
|
51712
|
+
import { homedir as homedir22 } from "node:os";
|
|
51667
51713
|
import { basename as basename12, join as join39, resolve as resolve14 } from "node:path";
|
|
51668
51714
|
function parseMcpServers(raw, source, sourceLabel) {
|
|
51669
51715
|
const entries = [];
|
|
@@ -51712,7 +51758,7 @@ function mergeServers(lists) {
|
|
|
51712
51758
|
function isSafeProjectPath(projectPath) {
|
|
51713
51759
|
if (projectPath.includes(".."))
|
|
51714
51760
|
return false;
|
|
51715
|
-
const home3 =
|
|
51761
|
+
const home3 = homedir22();
|
|
51716
51762
|
try {
|
|
51717
51763
|
const resolved = resolve14(projectPath);
|
|
51718
51764
|
if (!resolved.startsWith(home3))
|
|
@@ -51725,7 +51771,7 @@ function isSafeProjectPath(projectPath) {
|
|
|
51725
51771
|
function registerMcpRoutes(app) {
|
|
51726
51772
|
app.get("/api/mcp-servers", async (_req, res) => {
|
|
51727
51773
|
try {
|
|
51728
|
-
const claudeDir3 = join39(
|
|
51774
|
+
const claudeDir3 = join39(homedir22(), ".claude");
|
|
51729
51775
|
const allLists = [];
|
|
51730
51776
|
try {
|
|
51731
51777
|
const settings = await readSettings();
|
|
@@ -51735,7 +51781,7 @@ function registerMcpRoutes(app) {
|
|
|
51735
51781
|
}
|
|
51736
51782
|
} catch {}
|
|
51737
51783
|
try {
|
|
51738
|
-
const claudeJsonPath = join39(
|
|
51784
|
+
const claudeJsonPath = join39(homedir22(), ".claude.json");
|
|
51739
51785
|
if (existsSync21(claudeJsonPath)) {
|
|
51740
51786
|
const content = await readFile18(claudeJsonPath, "utf-8");
|
|
51741
51787
|
const parsed = JSON.parse(content);
|
|
@@ -51996,7 +52042,7 @@ var init_skill_directory_installer = __esm(() => {
|
|
|
51996
52042
|
// src/commands/portable/config-discovery.ts
|
|
51997
52043
|
import { existsSync as existsSync23, readFileSync as readFileSync6 } from "node:fs";
|
|
51998
52044
|
import { cp as cp2, mkdir as mkdir11, readFile as readFile19, readdir as readdir12, stat as stat8 } from "node:fs/promises";
|
|
51999
|
-
import { homedir as
|
|
52045
|
+
import { homedir as homedir23 } from "node:os";
|
|
52000
52046
|
import { basename as basename13, dirname as dirname12, extname as extname3, join as join41, relative as relative9, resolve as resolve16, sep as sep6 } from "node:path";
|
|
52001
52047
|
async function copyHooksCompanionDirs(sourceDir, targetDir) {
|
|
52002
52048
|
const result = {
|
|
@@ -52079,7 +52125,7 @@ async function copyHooksCompanionDirs(sourceDir, targetDir) {
|
|
|
52079
52125
|
function resolveSourceOrigin(sourcePath) {
|
|
52080
52126
|
if (!sourcePath)
|
|
52081
52127
|
return "global";
|
|
52082
|
-
const home3 =
|
|
52128
|
+
const home3 = homedir23();
|
|
52083
52129
|
const cwd2 = process.cwd();
|
|
52084
52130
|
if (cwd2 === home3)
|
|
52085
52131
|
return "global";
|
|
@@ -52094,16 +52140,16 @@ function getConfigSourcePath(globalOnly = false) {
|
|
|
52094
52140
|
return findExistingProjectConfigPath(process.cwd()) ?? getGlobalConfigSourcePath();
|
|
52095
52141
|
}
|
|
52096
52142
|
function getGlobalConfigSourcePath() {
|
|
52097
|
-
return join41(
|
|
52143
|
+
return join41(homedir23(), ".claude", "CLAUDE.md");
|
|
52098
52144
|
}
|
|
52099
52145
|
function getRulesSourcePath(globalOnly = false) {
|
|
52100
|
-
const globalPath = join41(
|
|
52146
|
+
const globalPath = join41(homedir23(), ".claude", "rules");
|
|
52101
52147
|
if (globalOnly)
|
|
52102
52148
|
return globalPath;
|
|
52103
52149
|
return findExistingProjectLayoutPath(process.cwd(), "rules") ?? globalPath;
|
|
52104
52150
|
}
|
|
52105
52151
|
function getHooksSourcePath(globalOnly = false) {
|
|
52106
|
-
const globalPath = join41(
|
|
52152
|
+
const globalPath = join41(homedir23(), ".claude", "hooks");
|
|
52107
52153
|
if (globalOnly)
|
|
52108
52154
|
return globalPath;
|
|
52109
52155
|
return findExistingProjectLayoutPath(process.cwd(), "hooks") ?? globalPath;
|
|
@@ -54292,7 +54338,7 @@ var init_codex_capabilities = __esm(() => {
|
|
|
54292
54338
|
// src/commands/portable/codex-path-safety.ts
|
|
54293
54339
|
import { existsSync as existsSync24 } from "node:fs";
|
|
54294
54340
|
import { mkdir as mkdir12, realpath as realpath7 } from "node:fs/promises";
|
|
54295
|
-
import { homedir as
|
|
54341
|
+
import { homedir as homedir24 } from "node:os";
|
|
54296
54342
|
import { dirname as dirname13, join as join42, resolve as resolve17, sep as sep7 } from "node:path";
|
|
54297
54343
|
function isPathWithinBoundary3(targetPath, boundaryPath) {
|
|
54298
54344
|
const resolvedTarget = resolve17(targetPath);
|
|
@@ -54339,7 +54385,7 @@ async function withCodexTargetLock2(targetFilePath, operation) {
|
|
|
54339
54385
|
}
|
|
54340
54386
|
}
|
|
54341
54387
|
function getCodexGlobalBoundary() {
|
|
54342
|
-
return join42(
|
|
54388
|
+
return join42(homedir24(), ".codex");
|
|
54343
54389
|
}
|
|
54344
54390
|
var import_proper_lockfile6;
|
|
54345
54391
|
var init_codex_path_safety = __esm(() => {
|
|
@@ -54734,7 +54780,7 @@ var init_codex_hook_wrapper = __esm(() => {
|
|
|
54734
54780
|
});
|
|
54735
54781
|
|
|
54736
54782
|
// src/commands/portable/converters/claude-to-codex-hooks.ts
|
|
54737
|
-
import { homedir as
|
|
54783
|
+
import { homedir as homedir25 } from "node:os";
|
|
54738
54784
|
function convertClaudeHooksToCodex(sourceHooks, capabilities, pathRewrite) {
|
|
54739
54785
|
const result = {};
|
|
54740
54786
|
for (const [event, groups] of Object.entries(sourceHooks)) {
|
|
@@ -54792,7 +54838,7 @@ function rewriteCommandPath(command, pathRewrite) {
|
|
|
54792
54838
|
const normalizeSlashes = (s) => s.replace(/\\/g, "/");
|
|
54793
54839
|
let rewritten = command;
|
|
54794
54840
|
if (pathRewrite.commandSubstitutions && pathRewrite.commandSubstitutions.size > 0) {
|
|
54795
|
-
const home3 =
|
|
54841
|
+
const home3 = homedir25();
|
|
54796
54842
|
const homeForward = normalizeSlashes(home3);
|
|
54797
54843
|
for (const [originalAbsPath, wrapperAbsPath] of pathRewrite.commandSubstitutions) {
|
|
54798
54844
|
const originalAbsForward = normalizeSlashes(originalAbsPath);
|
|
@@ -54895,7 +54941,7 @@ var init_gemini_hook_event_map = __esm(() => {
|
|
|
54895
54941
|
// src/commands/portable/hooks-settings-merger.ts
|
|
54896
54942
|
import { existsSync as existsSync26 } from "node:fs";
|
|
54897
54943
|
import { mkdir as mkdir13, readFile as readFile21, rename as rename8, rm as rm6, writeFile as writeFile12 } from "node:fs/promises";
|
|
54898
|
-
import { homedir as
|
|
54944
|
+
import { homedir as homedir26 } from "node:os";
|
|
54899
54945
|
import { basename as basename14, dirname as dirname16, extname as extname4, join as join44, resolve as resolve20 } from "node:path";
|
|
54900
54946
|
function isCodexWrappableHookPath(filePath) {
|
|
54901
54947
|
return hookAssetBasename(filePath) !== "node-hook-runner.sh" && CODEX_WRAPPABLE_HOOK_EXTENSIONS.has(extname4(filePath).toLowerCase());
|
|
@@ -54978,7 +55024,7 @@ function normalizeDirPattern(value) {
|
|
|
54978
55024
|
}
|
|
54979
55025
|
function homeRelativeDir(value) {
|
|
54980
55026
|
const normalized = normalizeDirPattern(value);
|
|
54981
|
-
const home3 = normalizeDirPattern(
|
|
55027
|
+
const home3 = normalizeDirPattern(homedir26());
|
|
54982
55028
|
return normalized.startsWith(`${home3}/`) ? normalized.slice(home3.length + 1) : normalized;
|
|
54983
55029
|
}
|
|
54984
55030
|
function buildHookDirRewritePairs(sourceHooksDir, targetHooksDir) {
|
|
@@ -55535,7 +55581,7 @@ async function migrateHooksSettingsForCodex(options2) {
|
|
|
55535
55581
|
}
|
|
55536
55582
|
let featureFlagWritten = false;
|
|
55537
55583
|
if (capabilities.requiresFeatureFlag) {
|
|
55538
|
-
const configTomlPath = isGlobal ? join44(
|
|
55584
|
+
const configTomlPath = isGlobal ? join44(homedir26(), ".codex", "config.toml") : join44(process.cwd(), ".codex", "config.toml");
|
|
55539
55585
|
const flagResult = await ensureCodexHooksFeatureFlag(configTomlPath, isGlobal);
|
|
55540
55586
|
featureFlagWritten = flagResult.status === "written" || flagResult.status === "updated";
|
|
55541
55587
|
}
|
|
@@ -56940,10 +56986,10 @@ __export(exports_skills_discovery, {
|
|
|
56940
56986
|
discoverSkills: () => discoverSkills
|
|
56941
56987
|
});
|
|
56942
56988
|
import { readFile as readFile25, readdir as readdir13, stat as stat9 } from "node:fs/promises";
|
|
56943
|
-
import { homedir as
|
|
56989
|
+
import { homedir as homedir27 } from "node:os";
|
|
56944
56990
|
import { dirname as dirname17, join as join45 } from "node:path";
|
|
56945
56991
|
function getSkillSourcePath(globalOnly = false) {
|
|
56946
|
-
const globalPath = join45(
|
|
56992
|
+
const globalPath = join45(homedir27(), ".claude/skills");
|
|
56947
56993
|
if (globalOnly) {
|
|
56948
56994
|
return findFirstExistingPath([globalPath]);
|
|
56949
56995
|
}
|
|
@@ -57184,7 +57230,7 @@ var init_migration_result_utils = __esm(() => {
|
|
|
57184
57230
|
// src/domains/web-server/routes/migration-routes.ts
|
|
57185
57231
|
import { existsSync as existsSync30 } from "node:fs";
|
|
57186
57232
|
import { readFile as readFile26, rm as rm8 } from "node:fs/promises";
|
|
57187
|
-
import { homedir as
|
|
57233
|
+
import { homedir as homedir28 } from "node:os";
|
|
57188
57234
|
import { basename as basename17, join as join46, resolve as resolve23 } from "node:path";
|
|
57189
57235
|
function resolveRegistryDeps(deps) {
|
|
57190
57236
|
return {
|
|
@@ -57863,7 +57909,7 @@ function registerMigrationRoutes(app, deps) {
|
|
|
57863
57909
|
};
|
|
57864
57910
|
const discovered = await discoverMigrationItems(includeAll);
|
|
57865
57911
|
const cwd2 = process.cwd();
|
|
57866
|
-
const home3 =
|
|
57912
|
+
const home3 = homedir28();
|
|
57867
57913
|
res.status(200).json({
|
|
57868
57914
|
cwd: cwd2,
|
|
57869
57915
|
targetPaths: {
|
|
@@ -59379,7 +59425,7 @@ function scanPlanDir(dir) {
|
|
|
59379
59425
|
var init_plan_scanner = () => {};
|
|
59380
59426
|
|
|
59381
59427
|
// src/domains/plan-parser/plan-scope.ts
|
|
59382
|
-
import { homedir as
|
|
59428
|
+
import { homedir as homedir29 } from "node:os";
|
|
59383
59429
|
import { isAbsolute as isAbsolute8, join as join49, relative as relative12, resolve as resolve25 } from "node:path";
|
|
59384
59430
|
function resolveConfiguredDir(configuredPath, baseDir) {
|
|
59385
59431
|
const trimmed = configuredPath?.trim();
|
|
@@ -59392,7 +59438,7 @@ function resolveProjectPlansDir(projectRoot, config) {
|
|
|
59392
59438
|
return resolveConfiguredDir(config?.paths?.plans, projectRoot);
|
|
59393
59439
|
}
|
|
59394
59440
|
function resolveGlobalPlansDir(config) {
|
|
59395
|
-
return resolveConfiguredDir(config?.paths?.globalPlans, join49(
|
|
59441
|
+
return resolveConfiguredDir(config?.paths?.globalPlans, join49(homedir29(), ".claude"));
|
|
59396
59442
|
}
|
|
59397
59443
|
function resolvePlanDirForScope(scope, projectRoot, config) {
|
|
59398
59444
|
return scope === "global" ? resolveGlobalPlansDir(config) : resolveProjectPlansDir(projectRoot, config);
|
|
@@ -60664,7 +60710,7 @@ var init_p_limit = __esm(() => {
|
|
|
60664
60710
|
|
|
60665
60711
|
// src/domains/web-server/routes/plan-routes.ts
|
|
60666
60712
|
import { existsSync as existsSync36, readFileSync as readFileSync12, realpathSync as realpathSync2 } from "node:fs";
|
|
60667
|
-
import { homedir as
|
|
60713
|
+
import { homedir as homedir30 } from "node:os";
|
|
60668
60714
|
import { basename as basename20, dirname as dirname24, join as join54, relative as relative14, resolve as resolve27, sep as sep8 } from "node:path";
|
|
60669
60715
|
function sanitizeError(err) {
|
|
60670
60716
|
if (err instanceof Error) {
|
|
@@ -60855,7 +60901,7 @@ function withTimeout(promiseFactory, timeoutMs, label) {
|
|
|
60855
60901
|
function isCurrentProjectFallbackCandidate(currentPath, globalProjectKey) {
|
|
60856
60902
|
if (toProjectPathKey(currentPath) === globalProjectKey)
|
|
60857
60903
|
return false;
|
|
60858
|
-
if (toProjectPathKey(currentPath) === toProjectPathKey(
|
|
60904
|
+
if (toProjectPathKey(currentPath) === toProjectPathKey(homedir30()))
|
|
60859
60905
|
return false;
|
|
60860
60906
|
return existsSync36(join54(currentPath, ".git")) || existsSync36(CkConfigManager.getProjectConfigPath(currentPath)) || existsSync36(join54(currentPath, "plans"));
|
|
60861
60907
|
}
|
|
@@ -60920,7 +60966,7 @@ function registerPlanRoutes(app) {
|
|
|
60920
60966
|
});
|
|
60921
60967
|
app.get("/api/plan/list-all", async (_req, res) => {
|
|
60922
60968
|
try {
|
|
60923
|
-
const globalProjectKey = toProjectPathKey(join54(
|
|
60969
|
+
const globalProjectKey = toProjectPathKey(join54(homedir30(), ".claude"));
|
|
60924
60970
|
const seenProjectKeys = new Set;
|
|
60925
60971
|
const scanTargets = [];
|
|
60926
60972
|
for (const project of await ProjectsRegistryManager.listProjects()) {
|
|
@@ -61167,7 +61213,7 @@ var init_project_plan_data = __esm(() => {
|
|
|
61167
61213
|
// src/domains/web-server/routes/project-routes.ts
|
|
61168
61214
|
import { existsSync as existsSync37 } from "node:fs";
|
|
61169
61215
|
import { readFile as readFile27 } from "node:fs/promises";
|
|
61170
|
-
import { homedir as
|
|
61216
|
+
import { homedir as homedir31 } from "node:os";
|
|
61171
61217
|
import { basename as basename21, join as join55, resolve as resolve28 } from "node:path";
|
|
61172
61218
|
function registerProjectRoutes(app) {
|
|
61173
61219
|
app.get("/api/projects", async (req, res) => {
|
|
@@ -61188,7 +61234,7 @@ function registerProjectRoutes(app) {
|
|
|
61188
61234
|
for (const discovered of discoveredProjects) {
|
|
61189
61235
|
if (registeredPaths.has(discovered.path))
|
|
61190
61236
|
continue;
|
|
61191
|
-
if (discovered.path === join55(
|
|
61237
|
+
if (discovered.path === join55(homedir31(), ".claude"))
|
|
61192
61238
|
continue;
|
|
61193
61239
|
const projectInfo = await detectAndBuildProjectInfo(discovered.path, `discovered-${discovered.path}`, cachedSettings, cachedSkills, false);
|
|
61194
61240
|
if (projectInfo) {
|
|
@@ -61204,7 +61250,7 @@ function registerProjectRoutes(app) {
|
|
|
61204
61250
|
if (cwdProject) {
|
|
61205
61251
|
projects.push(cwdProject);
|
|
61206
61252
|
}
|
|
61207
|
-
const globalDir = join55(
|
|
61253
|
+
const globalDir = join55(homedir31(), ".claude");
|
|
61208
61254
|
const globalProject = await detectAndBuildProjectInfo(globalDir, "global", undefined, undefined, false);
|
|
61209
61255
|
if (globalProject) {
|
|
61210
61256
|
projects.push(globalProject);
|
|
@@ -61276,12 +61322,12 @@ function registerProjectRoutes(app) {
|
|
|
61276
61322
|
const body = validation.data;
|
|
61277
61323
|
let projectPath = body.path;
|
|
61278
61324
|
if (projectPath.startsWith("~/") || projectPath === "~") {
|
|
61279
|
-
projectPath = join55(
|
|
61325
|
+
projectPath = join55(homedir31(), projectPath.slice(1));
|
|
61280
61326
|
} else if (projectPath.startsWith("~\\")) {
|
|
61281
|
-
projectPath = join55(
|
|
61327
|
+
projectPath = join55(homedir31(), projectPath.slice(1));
|
|
61282
61328
|
}
|
|
61283
61329
|
projectPath = resolve28(projectPath);
|
|
61284
|
-
const homeDir =
|
|
61330
|
+
const homeDir = homedir31();
|
|
61285
61331
|
if (projectPath.includes("..") || !projectPath.startsWith(homeDir)) {
|
|
61286
61332
|
res.status(400).json({ error: "Invalid path after expansion" });
|
|
61287
61333
|
return;
|
|
@@ -61338,7 +61384,7 @@ function registerProjectRoutes(app) {
|
|
|
61338
61384
|
if (id === "current") {
|
|
61339
61385
|
projectPath = process.cwd();
|
|
61340
61386
|
} else if (id === "global") {
|
|
61341
|
-
projectPath = join55(
|
|
61387
|
+
projectPath = join55(homedir31(), ".claude");
|
|
61342
61388
|
} else {
|
|
61343
61389
|
res.status(404).json({ error: "Project not found" });
|
|
61344
61390
|
return;
|
|
@@ -61418,7 +61464,7 @@ async function buildProjectInfoFromRegistry(registered, cachedSettings, cachedSk
|
|
|
61418
61464
|
const hasLocalConfig = hasClaudeDir && CkConfigManager.projectConfigExists(registered.path, false);
|
|
61419
61465
|
const settings = cachedSettings !== undefined ? cachedSettings : await readSettings();
|
|
61420
61466
|
const skills = cachedSkills !== undefined ? cachedSkills : await scanSkills();
|
|
61421
|
-
const settingsPath = join55(
|
|
61467
|
+
const settingsPath = join55(homedir31(), ".claude", "settings.json");
|
|
61422
61468
|
const health = existsSync37(settingsPath) ? "healthy" : "warning";
|
|
61423
61469
|
const model = getCurrentModel() || settings?.model || "claude-sonnet-4";
|
|
61424
61470
|
const planData = includePlanData ? await buildProjectPlanData(registered.path, "project") : null;
|
|
@@ -61460,7 +61506,7 @@ async function detectAndBuildProjectInfo(path6, id, cachedSettings, cachedSkills
|
|
|
61460
61506
|
const hasLocalConfig = CkConfigManager.projectConfigExists(path6, id === "global");
|
|
61461
61507
|
const settings = cachedSettings !== undefined ? cachedSettings : await readSettings();
|
|
61462
61508
|
const skills = cachedSkills !== undefined ? cachedSkills : await scanSkills();
|
|
61463
|
-
const settingsPath = join55(
|
|
61509
|
+
const settingsPath = join55(homedir31(), ".claude", "settings.json");
|
|
61464
61510
|
const health = existsSync37(settingsPath) ? "healthy" : "warning";
|
|
61465
61511
|
const model = getCurrentModel() || settings?.model || "claude-sonnet-4";
|
|
61466
61512
|
const scope = id === "global" ? "global" : "project";
|
|
@@ -61508,7 +61554,7 @@ var init_project_routes = __esm(() => {
|
|
|
61508
61554
|
// src/domains/web-server/routes/session-routes.ts
|
|
61509
61555
|
import { existsSync as existsSync38 } from "node:fs";
|
|
61510
61556
|
import { readFile as readFile28, readdir as readdir14, stat as stat10 } from "node:fs/promises";
|
|
61511
|
-
import { homedir as
|
|
61557
|
+
import { homedir as homedir32 } from "node:os";
|
|
61512
61558
|
import { basename as basename22, join as join56 } from "node:path";
|
|
61513
61559
|
function toDateStr(d3) {
|
|
61514
61560
|
const y3 = d3.getFullYear();
|
|
@@ -61517,7 +61563,7 @@ function toDateStr(d3) {
|
|
|
61517
61563
|
return `${y3}-${m2}-${day}`;
|
|
61518
61564
|
}
|
|
61519
61565
|
async function scanActivityMetrics(periodDays) {
|
|
61520
|
-
const home3 =
|
|
61566
|
+
const home3 = homedir32();
|
|
61521
61567
|
const projectsDir2 = join56(home3, ".claude", "projects");
|
|
61522
61568
|
const cutoff = new Date;
|
|
61523
61569
|
cutoff.setDate(cutoff.getDate() - periodDays);
|
|
@@ -61588,7 +61634,7 @@ async function scanActivityMetrics(periodDays) {
|
|
|
61588
61634
|
return { totalSessions, projects: projectActivities, dailyCounts };
|
|
61589
61635
|
}
|
|
61590
61636
|
async function resolveSessionDir(projectId) {
|
|
61591
|
-
const home3 =
|
|
61637
|
+
const home3 = homedir32();
|
|
61592
61638
|
if (projectId.startsWith("discovered-")) {
|
|
61593
61639
|
try {
|
|
61594
61640
|
const encodedPathB64 = projectId.slice("discovered-".length);
|
|
@@ -61762,7 +61808,7 @@ async function parseSessionDetail(filePath, limit, offset) {
|
|
|
61762
61808
|
}
|
|
61763
61809
|
function registerSessionRoutes(app) {
|
|
61764
61810
|
app.get("/api/sessions", async (_req, res) => {
|
|
61765
|
-
const home3 =
|
|
61811
|
+
const home3 = homedir32();
|
|
61766
61812
|
const projectsDir2 = join56(home3, ".claude", "projects");
|
|
61767
61813
|
if (!existsSync38(projectsDir2)) {
|
|
61768
61814
|
res.json({ projects: [] });
|
|
@@ -61831,7 +61877,7 @@ function registerSessionRoutes(app) {
|
|
|
61831
61877
|
res.status(404).json({ error: "Project not found" });
|
|
61832
61878
|
return;
|
|
61833
61879
|
}
|
|
61834
|
-
const allowedBase = join56(
|
|
61880
|
+
const allowedBase = join56(homedir32(), ".claude", "projects");
|
|
61835
61881
|
if (!projectDir.startsWith(allowedBase)) {
|
|
61836
61882
|
res.status(403).json({ error: "Access denied" });
|
|
61837
61883
|
return;
|
|
@@ -61861,7 +61907,7 @@ function registerSessionRoutes(app) {
|
|
|
61861
61907
|
res.status(404).json({ error: "Project not found" });
|
|
61862
61908
|
return;
|
|
61863
61909
|
}
|
|
61864
|
-
const allowedBase = join56(
|
|
61910
|
+
const allowedBase = join56(homedir32(), ".claude", "projects");
|
|
61865
61911
|
if (!projectDir.startsWith(allowedBase)) {
|
|
61866
61912
|
res.status(403).json({ error: "Access denied" });
|
|
61867
61913
|
return;
|
|
@@ -61895,7 +61941,7 @@ var init_session_routes = __esm(() => {
|
|
|
61895
61941
|
});
|
|
61896
61942
|
|
|
61897
61943
|
// src/domains/web-server/routes/settings-routes.ts
|
|
61898
|
-
import { homedir as
|
|
61944
|
+
import { homedir as homedir33 } from "node:os";
|
|
61899
61945
|
function registerSettingsRoutes(app) {
|
|
61900
61946
|
app.get("/api/settings", async (_req, res) => {
|
|
61901
61947
|
try {
|
|
@@ -61951,7 +61997,7 @@ function registerSettingsRoutes(app) {
|
|
|
61951
61997
|
res.json({
|
|
61952
61998
|
success: true,
|
|
61953
61999
|
path: "~/.claude/settings.json",
|
|
61954
|
-
backupPath: saveResult.backupPath ? saveResult.backupPath.replace(
|
|
62000
|
+
backupPath: saveResult.backupPath ? saveResult.backupPath.replace(homedir33(), "~") : null,
|
|
61955
62001
|
absolutePath: getSettingsPath()
|
|
61956
62002
|
});
|
|
61957
62003
|
} catch (error) {
|
|
@@ -61985,7 +62031,7 @@ var init_settings_routes = __esm(() => {
|
|
|
61985
62031
|
|
|
61986
62032
|
// src/domains/skills/skill-catalog-generator.ts
|
|
61987
62033
|
import { mkdir as mkdir14, readFile as readFile29, readdir as readdir15, rename as rename10, stat as stat11, writeFile as writeFile14 } from "node:fs/promises";
|
|
61988
|
-
import { homedir as
|
|
62034
|
+
import { homedir as homedir34 } from "node:os";
|
|
61989
62035
|
import { dirname as dirname25, join as join57, relative as relative15 } from "node:path";
|
|
61990
62036
|
async function hasScripts(skillPath) {
|
|
61991
62037
|
try {
|
|
@@ -62128,7 +62174,7 @@ var CATALOG_PATH, CATALOG_VERSION = "1.0.0", SKIP_DIRS4, skillCatalogGenerator;
|
|
|
62128
62174
|
var init_skill_catalog_generator = __esm(() => {
|
|
62129
62175
|
init_skills_discovery();
|
|
62130
62176
|
init_logger();
|
|
62131
|
-
CATALOG_PATH = join57(
|
|
62177
|
+
CATALOG_PATH = join57(homedir34(), ".claude", ".skills-catalog.json");
|
|
62132
62178
|
SKIP_DIRS4 = [".venv", "__pycache__", "node_modules", ".git"];
|
|
62133
62179
|
skillCatalogGenerator = new SkillCatalogGenerator;
|
|
62134
62180
|
});
|
|
@@ -62418,7 +62464,7 @@ var init_skill_browser_routes = __esm(() => {
|
|
|
62418
62464
|
|
|
62419
62465
|
// src/commands/skills/agents.ts
|
|
62420
62466
|
import { existsSync as existsSync39, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
|
|
62421
|
-
import { homedir as
|
|
62467
|
+
import { homedir as homedir36, platform as platform5 } from "node:os";
|
|
62422
62468
|
import { join as join59 } from "node:path";
|
|
62423
62469
|
function hasInstallSignal2(path7) {
|
|
62424
62470
|
if (!path7 || !existsSync39(path7)) {
|
|
@@ -62475,7 +62521,7 @@ function isSkillInstalled(skillName, agent, options2) {
|
|
|
62475
62521
|
}
|
|
62476
62522
|
var home3, OPENCODE_BINARY_NAME2, agents;
|
|
62477
62523
|
var init_agents = __esm(() => {
|
|
62478
|
-
home3 =
|
|
62524
|
+
home3 = homedir36();
|
|
62479
62525
|
OPENCODE_BINARY_NAME2 = platform5() === "win32" ? "opencode.exe" : "opencode";
|
|
62480
62526
|
agents = {
|
|
62481
62527
|
"claude-code": {
|
|
@@ -62582,7 +62628,7 @@ var init_agents = __esm(() => {
|
|
|
62582
62628
|
// src/commands/skills/skills-registry.ts
|
|
62583
62629
|
import { existsSync as existsSync40 } from "node:fs";
|
|
62584
62630
|
import { mkdir as mkdir15, readFile as readFile31, writeFile as writeFile15 } from "node:fs/promises";
|
|
62585
|
-
import { homedir as
|
|
62631
|
+
import { homedir as homedir37 } from "node:os";
|
|
62586
62632
|
import { dirname as dirname26, join as join60, sep as sep10 } from "node:path";
|
|
62587
62633
|
function getCliVersion3() {
|
|
62588
62634
|
try {
|
|
@@ -62694,7 +62740,7 @@ async function syncRegistry() {
|
|
|
62694
62740
|
var home4, REGISTRY_PATH, SkillInstallationSchema, SkillRegistrySchema, REGISTRY_PATH_MIGRATIONS;
|
|
62695
62741
|
var init_skills_registry = __esm(() => {
|
|
62696
62742
|
init_zod();
|
|
62697
|
-
home4 =
|
|
62743
|
+
home4 = homedir37();
|
|
62698
62744
|
REGISTRY_PATH = join60(home4, ".claudekit", "skill-registry.json");
|
|
62699
62745
|
SkillInstallationSchema = exports_external.object({
|
|
62700
62746
|
skill: exports_external.string(),
|
|
@@ -62726,7 +62772,7 @@ var init_skills_registry = __esm(() => {
|
|
|
62726
62772
|
// src/commands/skills/skills-installer.ts
|
|
62727
62773
|
import { existsSync as existsSync41 } from "node:fs";
|
|
62728
62774
|
import { cp as cp3, mkdir as mkdir16, rm as rm9, stat as stat12 } from "node:fs/promises";
|
|
62729
|
-
import { homedir as
|
|
62775
|
+
import { homedir as homedir38 } from "node:os";
|
|
62730
62776
|
import { dirname as dirname27, join as join61, resolve as resolve30 } from "node:path";
|
|
62731
62777
|
function isSamePath2(path1, path22) {
|
|
62732
62778
|
try {
|
|
@@ -62857,7 +62903,7 @@ var init_skills_installer = __esm(() => {
|
|
|
62857
62903
|
LEGACY_SKILL_PATHS = {
|
|
62858
62904
|
"gemini-cli": {
|
|
62859
62905
|
project: ".gemini/skills",
|
|
62860
|
-
global: join61(
|
|
62906
|
+
global: join61(homedir38(), ".gemini/skills")
|
|
62861
62907
|
}
|
|
62862
62908
|
};
|
|
62863
62909
|
});
|
|
@@ -63806,7 +63852,7 @@ var package_default;
|
|
|
63806
63852
|
var init_package = __esm(() => {
|
|
63807
63853
|
package_default = {
|
|
63808
63854
|
name: "claudekit-cli",
|
|
63809
|
-
version: "4.3.1-dev.
|
|
63855
|
+
version: "4.3.1-dev.18",
|
|
63810
63856
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
63811
63857
|
type: "module",
|
|
63812
63858
|
repository: {
|
|
@@ -64288,10 +64334,11 @@ var init_package_manager_runner = __esm(() => {
|
|
|
64288
64334
|
|
|
64289
64335
|
// src/domains/installation/merger/zombie-wirings-pruner.ts
|
|
64290
64336
|
import { existsSync as existsSync44, readdirSync as readdirSync7 } from "node:fs";
|
|
64291
|
-
import { homedir as
|
|
64337
|
+
import { homedir as homedir39 } from "node:os";
|
|
64292
64338
|
import { basename as basename23, dirname as dirname28, isAbsolute as isAbsolute10, resolve as resolve32, sep as sep11 } from "node:path";
|
|
64293
|
-
function pruneZombieEngineerWirings(settings, hookDir) {
|
|
64339
|
+
function pruneZombieEngineerWirings(settings, hookDir, preserveCommands = new Set) {
|
|
64294
64340
|
const pruned = [];
|
|
64341
|
+
const normalizedPreserveCommands = new Set(Array.from(preserveCommands).map((command) => normalizeCommand(command)));
|
|
64295
64342
|
if (!existsSync44(hookDir)) {
|
|
64296
64343
|
return { settings, pruned };
|
|
64297
64344
|
}
|
|
@@ -64311,14 +64358,14 @@ function pruneZombieEngineerWirings(settings, hookDir) {
|
|
|
64311
64358
|
for (const group of groups) {
|
|
64312
64359
|
if (!("hooks" in group) || !Array.isArray(group.hooks)) {
|
|
64313
64360
|
const entry = group;
|
|
64314
|
-
if (shouldPruneEntry(entry, hookDir, pruned)) {
|
|
64361
|
+
if (shouldPruneEntry(entry, hookDir, pruned, normalizedPreserveCommands)) {
|
|
64315
64362
|
continue;
|
|
64316
64363
|
}
|
|
64317
64364
|
keptGroups.push(group);
|
|
64318
64365
|
continue;
|
|
64319
64366
|
}
|
|
64320
64367
|
const keptHooks = group.hooks.filter((h2) => {
|
|
64321
|
-
return !shouldPruneEntry(h2, hookDir, pruned);
|
|
64368
|
+
return !shouldPruneEntry(h2, hookDir, pruned, normalizedPreserveCommands);
|
|
64322
64369
|
});
|
|
64323
64370
|
if (keptHooks.length > 0) {
|
|
64324
64371
|
keptGroups.push({ ...group, hooks: keptHooks });
|
|
@@ -64335,13 +64382,16 @@ function pruneZombieEngineerWirings(settings, hookDir) {
|
|
|
64335
64382
|
}
|
|
64336
64383
|
return { settings, pruned };
|
|
64337
64384
|
}
|
|
64338
|
-
function shouldPruneEntry(entry, hookDir, pruned) {
|
|
64385
|
+
function shouldPruneEntry(entry, hookDir, pruned, preserveCommands) {
|
|
64339
64386
|
if (isLegacyDescriptiveNamePrompt(entry)) {
|
|
64340
64387
|
pruned.push("legacy-descriptive-name-prompt");
|
|
64341
64388
|
return true;
|
|
64342
64389
|
}
|
|
64343
64390
|
if (entry._origin !== "engineer")
|
|
64344
64391
|
return false;
|
|
64392
|
+
if (entry.command && preserveCommands.has(normalizeCommand(entry.command))) {
|
|
64393
|
+
return false;
|
|
64394
|
+
}
|
|
64345
64395
|
const filePath = extractHookFilePath(entry.command, hookDir);
|
|
64346
64396
|
if (!filePath)
|
|
64347
64397
|
return false;
|
|
@@ -64364,7 +64414,7 @@ function extractHookFilePath(command, hookDir) {
|
|
|
64364
64414
|
return null;
|
|
64365
64415
|
if (/&&|\|\||;|(?<!["|'])\|(?!["|'])/.test(command))
|
|
64366
64416
|
return null;
|
|
64367
|
-
const home5 =
|
|
64417
|
+
const home5 = homedir39().replace(/\\/g, "/");
|
|
64368
64418
|
const hookDirNorm = hookDir.replace(/\\/g, "/");
|
|
64369
64419
|
function resolveEnvPath(prefix, rest) {
|
|
64370
64420
|
const normRest = rest.replace(/\\/g, "/");
|
|
@@ -64426,7 +64476,9 @@ function extractHookFilePath(command, hookDir) {
|
|
|
64426
64476
|
}
|
|
64427
64477
|
return null;
|
|
64428
64478
|
}
|
|
64429
|
-
var init_zombie_wirings_pruner = () => {
|
|
64479
|
+
var init_zombie_wirings_pruner = __esm(() => {
|
|
64480
|
+
init_command_normalizer();
|
|
64481
|
+
});
|
|
64430
64482
|
|
|
64431
64483
|
// src/domains/health-checks/checkers/shared.ts
|
|
64432
64484
|
function shouldSkipExpensiveOperations2() {
|
|
@@ -64442,7 +64494,7 @@ var init_shared2 = __esm(() => {
|
|
|
64442
64494
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
64443
64495
|
import { existsSync as existsSync45, readFileSync as readFileSync13, readdirSync as readdirSync8, statSync as statSync9, writeFileSync as writeFileSync5 } from "node:fs";
|
|
64444
64496
|
import { readdir as readdir17 } from "node:fs/promises";
|
|
64445
|
-
import { homedir as
|
|
64497
|
+
import { homedir as homedir40, tmpdir } from "node:os";
|
|
64446
64498
|
import { join as join64, resolve as resolve33 } from "node:path";
|
|
64447
64499
|
function resolveDoctorCkExecutable(platformName = process.platform) {
|
|
64448
64500
|
return platformName === "win32" ? "ck.cmd" : "ck";
|
|
@@ -64472,12 +64524,12 @@ function isPathWithin2(filePath, parentDir) {
|
|
|
64472
64524
|
}
|
|
64473
64525
|
function getCanonicalGlobalCommandRoot() {
|
|
64474
64526
|
const configuredGlobalDir = PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "");
|
|
64475
|
-
const defaultGlobalDir = join64(
|
|
64527
|
+
const defaultGlobalDir = join64(homedir40(), ".claude").replace(/\\/g, "/");
|
|
64476
64528
|
return configuredGlobalDir === defaultGlobalDir ? "$HOME" : configuredGlobalDir;
|
|
64477
64529
|
}
|
|
64478
64530
|
function getClaudeSettingsFiles(projectDir) {
|
|
64479
64531
|
const globalClaudeDir = PathResolver.getGlobalKitDir();
|
|
64480
|
-
const ccsSettingsDir = join64(process.env.CK_TEST_HOME ??
|
|
64532
|
+
const ccsSettingsDir = join64(process.env.CK_TEST_HOME ?? homedir40(), ".ccs");
|
|
64481
64533
|
const candidates = [
|
|
64482
64534
|
{
|
|
64483
64535
|
path: resolve33(projectDir, ".claude", "settings.json"),
|
|
@@ -65176,7 +65228,7 @@ function extractHookReferencePaths(cmd) {
|
|
|
65176
65228
|
}
|
|
65177
65229
|
function resolveHookScriptPath(scriptPath, projectDir) {
|
|
65178
65230
|
let resolved = scriptPath.replace(/\\/g, "/");
|
|
65179
|
-
const home5 =
|
|
65231
|
+
const home5 = homedir40();
|
|
65180
65232
|
resolved = resolved.replace(/^\$\{?HOME\}?/, home5);
|
|
65181
65233
|
resolved = resolved.replace(/^\$\{?CLAUDE_PROJECT_DIR\}?/, projectDir);
|
|
65182
65234
|
resolved = resolved.replace(/^%USERPROFILE%/, home5);
|
|
@@ -67391,7 +67443,62 @@ async function readMetadataFile(claudeDir3) {
|
|
|
67391
67443
|
return null;
|
|
67392
67444
|
}
|
|
67393
67445
|
}
|
|
67394
|
-
function
|
|
67446
|
+
function extractCkHookName(command) {
|
|
67447
|
+
if (!command.trim().startsWith("node "))
|
|
67448
|
+
return null;
|
|
67449
|
+
const normalized = command.replace(/\\/g, "/");
|
|
67450
|
+
const match = normalized.match(/\/hooks\/([^/"'\s]+)\.(?:cjs|mjs|js)(?:["'\s]|$)/);
|
|
67451
|
+
return match?.[1] ?? null;
|
|
67452
|
+
}
|
|
67453
|
+
function collectSettingsHookCommands(settings) {
|
|
67454
|
+
const commands = new Set;
|
|
67455
|
+
for (const entries of Object.values(settings.hooks ?? {})) {
|
|
67456
|
+
for (const entry of entries) {
|
|
67457
|
+
if (typeof entry.command === "string") {
|
|
67458
|
+
commands.add(normalizeCommand(entry.command));
|
|
67459
|
+
}
|
|
67460
|
+
for (const hook of entry.hooks ?? []) {
|
|
67461
|
+
if (typeof hook.command === "string") {
|
|
67462
|
+
commands.add(normalizeCommand(hook.command));
|
|
67463
|
+
}
|
|
67464
|
+
}
|
|
67465
|
+
}
|
|
67466
|
+
}
|
|
67467
|
+
return commands;
|
|
67468
|
+
}
|
|
67469
|
+
function getInstalledHookCommands(config, kit) {
|
|
67470
|
+
const kits = Object.entries(config.kits ?? {});
|
|
67471
|
+
if (kits.length === 0)
|
|
67472
|
+
return [];
|
|
67473
|
+
const kitKey = kit?.toLowerCase();
|
|
67474
|
+
const preferred = kitKey ? kits.filter(([name]) => {
|
|
67475
|
+
const normalizedName = name.toLowerCase();
|
|
67476
|
+
return normalizedName === kitKey || normalizedName.includes(kitKey);
|
|
67477
|
+
}) : [];
|
|
67478
|
+
const candidates = preferred.length > 0 ? preferred : kits;
|
|
67479
|
+
return candidates.flatMap(([, entry]) => entry.installedSettings?.hooks ?? []);
|
|
67480
|
+
}
|
|
67481
|
+
async function countMissingCkHookRegistrations(claudeDir3, kit) {
|
|
67482
|
+
const settingsPath = join68(claudeDir3, "settings.json");
|
|
67483
|
+
const configPath = join68(claudeDir3, ".ck.json");
|
|
67484
|
+
if (!existsSync47(settingsPath) || !existsSync47(configPath))
|
|
67485
|
+
return 0;
|
|
67486
|
+
const settings = parseJsonContent(await import_fs_extra8.readFile(settingsPath, "utf-8"));
|
|
67487
|
+
const config = parseJsonContent(await import_fs_extra8.readFile(configPath, "utf-8"));
|
|
67488
|
+
const existingCommands = collectSettingsHookCommands(settings);
|
|
67489
|
+
const disabledHooks = new Set(Object.entries(config.hooks ?? {}).filter(([, enabled]) => enabled === false).map(([name]) => name));
|
|
67490
|
+
let missing = 0;
|
|
67491
|
+
for (const command of getInstalledHookCommands(config, kit)) {
|
|
67492
|
+
const hookName = extractCkHookName(command);
|
|
67493
|
+
if (hookName && disabledHooks.has(hookName))
|
|
67494
|
+
continue;
|
|
67495
|
+
if (!existingCommands.has(normalizeCommand(command))) {
|
|
67496
|
+
missing++;
|
|
67497
|
+
}
|
|
67498
|
+
}
|
|
67499
|
+
return missing;
|
|
67500
|
+
}
|
|
67501
|
+
function buildInitCommand(isGlobal, kit, beta, yes, restoreCkHooks) {
|
|
67395
67502
|
const parts = ["ck init"];
|
|
67396
67503
|
if (isGlobal)
|
|
67397
67504
|
parts.push("-g");
|
|
@@ -67399,6 +67506,8 @@ function buildInitCommand(isGlobal, kit, beta, yes) {
|
|
|
67399
67506
|
parts.push(`--kit ${kit}`);
|
|
67400
67507
|
if (yes)
|
|
67401
67508
|
parts.push("--yes");
|
|
67509
|
+
if (restoreCkHooks)
|
|
67510
|
+
parts.push("--restore-ck-hooks");
|
|
67402
67511
|
parts.push("--install-skills");
|
|
67403
67512
|
if (beta)
|
|
67404
67513
|
parts.push("--beta");
|
|
@@ -67480,6 +67589,57 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
67480
67589
|
logger.verbose("No ClaudeKit installations detected, skipping kit update prompt");
|
|
67481
67590
|
return;
|
|
67482
67591
|
}
|
|
67592
|
+
let forceKitReinstall = false;
|
|
67593
|
+
if (hasLocal && setup.project.path) {
|
|
67594
|
+
try {
|
|
67595
|
+
const missingHookDeps = await findMissingHookDepsFn(setup.project.path);
|
|
67596
|
+
if (missingHookDeps.length > 0) {
|
|
67597
|
+
logger.warning(`Detected ${missingHookDeps.length} local missing hook dependency(ies); reinstalling local kit content`);
|
|
67598
|
+
forceKitReinstall = true;
|
|
67599
|
+
}
|
|
67600
|
+
} catch (error) {
|
|
67601
|
+
logger.verbose(`Local hook dependency self-heal check skipped: ${error instanceof Error ? error.message : "unknown"}`);
|
|
67602
|
+
}
|
|
67603
|
+
try {
|
|
67604
|
+
const countMissingHookRefsFn = deps?.countMissingHookFileReferencesFn ?? countMissingHookFileReferences;
|
|
67605
|
+
const missingHookRefs = await countMissingHookRefsFn(dirname29(setup.project.path));
|
|
67606
|
+
if (missingHookRefs > 0) {
|
|
67607
|
+
logger.warning(`Detected ${missingHookRefs} local broken hook registration(s); reinstalling local kit content`);
|
|
67608
|
+
forceKitReinstall = true;
|
|
67609
|
+
}
|
|
67610
|
+
} catch (error) {
|
|
67611
|
+
logger.verbose(`Local hook registration self-heal check skipped: ${error instanceof Error ? error.message : "unknown"}`);
|
|
67612
|
+
}
|
|
67613
|
+
if (forceKitReinstall && selection.isGlobal) {
|
|
67614
|
+
const kit = localKits[0] || selection.kit;
|
|
67615
|
+
selection = {
|
|
67616
|
+
isGlobal: false,
|
|
67617
|
+
kit,
|
|
67618
|
+
promptMessage: `Update local project ClaudeKit content${kit ? ` (${kit})` : ""}?`
|
|
67619
|
+
};
|
|
67620
|
+
}
|
|
67621
|
+
}
|
|
67622
|
+
const selectedClaudeDir = selection.isGlobal ? setup.global.path : setup.project.path;
|
|
67623
|
+
if (selectedClaudeDir) {
|
|
67624
|
+
try {
|
|
67625
|
+
const missingHookDeps = await findMissingHookDepsFn(selectedClaudeDir);
|
|
67626
|
+
if (missingHookDeps.length > 0) {
|
|
67627
|
+
logger.warning(`Detected ${missingHookDeps.length} ${selection.isGlobal ? "global" : "local"} missing hook dependency(ies); reinstalling kit content`);
|
|
67628
|
+
forceKitReinstall = true;
|
|
67629
|
+
}
|
|
67630
|
+
} catch (error) {
|
|
67631
|
+
logger.verbose(`Selected hook dependency self-heal check skipped: ${error instanceof Error ? error.message : "unknown"}`);
|
|
67632
|
+
}
|
|
67633
|
+
try {
|
|
67634
|
+
const missingHookRegistrations = await countMissingCkHookRegistrations(selectedClaudeDir, selection.kit);
|
|
67635
|
+
if (missingHookRegistrations > 0) {
|
|
67636
|
+
logger.warning(`Detected ${missingHookRegistrations} ${selection.isGlobal ? "global" : "local"} missing hook registration(s); reinstalling kit content`);
|
|
67637
|
+
forceKitReinstall = true;
|
|
67638
|
+
}
|
|
67639
|
+
} catch (error) {
|
|
67640
|
+
logger.verbose(`Selected hook registration self-heal check skipped: ${error instanceof Error ? error.message : "unknown"}`);
|
|
67641
|
+
}
|
|
67642
|
+
}
|
|
67483
67643
|
let kitVersion = selection.kit ? selection.isGlobal ? globalMetadata?.kits?.[selection.kit]?.version : localMetadata?.kits?.[selection.kit]?.version : undefined;
|
|
67484
67644
|
const isBetaInstalled = isBetaVersion(kitVersion);
|
|
67485
67645
|
const promptMessage = selection.promptMessage;
|
|
@@ -67487,7 +67647,7 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
67487
67647
|
logger.info(`Current kit version: ${selection.kit}@${kitVersion}`);
|
|
67488
67648
|
}
|
|
67489
67649
|
let alreadyAtLatest = false;
|
|
67490
|
-
if (yes && selection.kit && kitVersion) {
|
|
67650
|
+
if (yes && selection.kit && kitVersion && !forceKitReinstall) {
|
|
67491
67651
|
const getTagFn = deps?.getLatestReleaseTagFn ?? fetchLatestReleaseTag;
|
|
67492
67652
|
const latestTag = await getTagFn(selection.kit, beta || isBetaInstalled);
|
|
67493
67653
|
if (latestTag && versionsMatch(kitVersion, latestTag)) {
|
|
@@ -67503,6 +67663,7 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
67503
67663
|
if (missingHookDeps.length > 0) {
|
|
67504
67664
|
logger.warning(`Detected ${missingHookDeps.length} missing hook dependency(ies); reinstalling kit content`);
|
|
67505
67665
|
alreadyAtLatest = false;
|
|
67666
|
+
forceKitReinstall = true;
|
|
67506
67667
|
}
|
|
67507
67668
|
} catch (error) {
|
|
67508
67669
|
logger.verbose(`Hook dependency self-heal check skipped: ${error instanceof Error ? error.message : "unknown"}`);
|
|
@@ -67516,6 +67677,7 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
67516
67677
|
if (missingHookRefs > 0) {
|
|
67517
67678
|
logger.warning(`Detected ${missingHookRefs} broken hook registration(s); reinstalling kit content`);
|
|
67518
67679
|
alreadyAtLatest = false;
|
|
67680
|
+
forceKitReinstall = true;
|
|
67519
67681
|
if (setup.project.path && selection.isGlobal) {
|
|
67520
67682
|
selection = {
|
|
67521
67683
|
isGlobal: false,
|
|
@@ -67552,7 +67714,7 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
67552
67714
|
}
|
|
67553
67715
|
const useBeta = beta || isBetaInstalled;
|
|
67554
67716
|
if (yes) {
|
|
67555
|
-
const initCmd = buildInitCommand(selection.isGlobal, selection.kit, useBeta, true);
|
|
67717
|
+
const initCmd = buildInitCommand(selection.isGlobal, selection.kit, useBeta, true, forceKitReinstall);
|
|
67556
67718
|
logger.info(`Running: ${initCmd}`);
|
|
67557
67719
|
const s = (deps?.spinnerFn ?? de)();
|
|
67558
67720
|
s.start("Updating ClaudeKit content...");
|
|
@@ -67585,6 +67747,8 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
67585
67747
|
const args = ["init"];
|
|
67586
67748
|
if (selection.isGlobal)
|
|
67587
67749
|
args.push("-g");
|
|
67750
|
+
if (forceKitReinstall)
|
|
67751
|
+
args.push("--restore-ck-hooks");
|
|
67588
67752
|
args.push("--install-skills");
|
|
67589
67753
|
if (useBeta)
|
|
67590
67754
|
args.push("--beta");
|
|
@@ -67654,17 +67818,19 @@ async function promptMigrateUpdate(deps) {
|
|
|
67654
67818
|
} catch {}
|
|
67655
67819
|
try {
|
|
67656
67820
|
const cleanupFn = deps?.cleanupMigratedHooksFn ?? (await Promise.resolve().then(() => (init_migrated_hooks_cleanup(), exports_migrated_hooks_cleanup))).cleanupMigratedHooksForProviders;
|
|
67657
|
-
const cleanupProviders = allProviders.filter((p) => SAFE_PROVIDER_NAME.test(p));
|
|
67658
|
-
|
|
67659
|
-
|
|
67660
|
-
|
|
67661
|
-
|
|
67821
|
+
const cleanupProviders = allProviders.filter((p) => p !== "claude-code" && SAFE_PROVIDER_NAME.test(p));
|
|
67822
|
+
if (cleanupProviders.length > 0) {
|
|
67823
|
+
const cleanupResults = await cleanupFn(cleanupProviders, { global: isGlobal });
|
|
67824
|
+
const cleanupCount = cleanupResults.reduce((total, result) => total + result.hooksPruned + result.filesRemoved + result.registryEntriesRemoved, 0);
|
|
67825
|
+
if (cleanupCount > 0) {
|
|
67826
|
+
logger.info(`Cleaned up ${cleanupCount} generated-context hook artifact(s)`);
|
|
67827
|
+
}
|
|
67828
|
+
await repairLegacyHookPromptsSafely();
|
|
67829
|
+
await repairHookFileReferencesSafely();
|
|
67662
67830
|
}
|
|
67663
67831
|
} catch (error) {
|
|
67664
67832
|
logger.verbose(`Migrated hook cleanup skipped: ${error instanceof Error ? error.message : "unknown"}`);
|
|
67665
67833
|
}
|
|
67666
|
-
await repairLegacyHookPromptsSafely();
|
|
67667
|
-
await repairHookFileReferencesSafely();
|
|
67668
67834
|
const targets = allProviders.filter((p) => p !== "claude-code");
|
|
67669
67835
|
if (targets.length === 0) {
|
|
67670
67836
|
logger.verbose("No migration targets detected, skipping migrate step");
|
|
@@ -67743,6 +67909,7 @@ var init_post_update_handler = __esm(() => {
|
|
|
67743
67909
|
init_metadata_migration();
|
|
67744
67910
|
init_version_utils();
|
|
67745
67911
|
init_claudekit_scanner();
|
|
67912
|
+
init_command_normalizer();
|
|
67746
67913
|
init_logger();
|
|
67747
67914
|
init_safe_prompts();
|
|
67748
67915
|
init_types3();
|
|
@@ -68148,7 +68315,7 @@ import { spawn as spawn3 } from "node:child_process";
|
|
|
68148
68315
|
import { execFile as execFile8 } from "node:child_process";
|
|
68149
68316
|
import { existsSync as existsSync48 } from "node:fs";
|
|
68150
68317
|
import { readFile as readFile38 } from "node:fs/promises";
|
|
68151
|
-
import { cpus, homedir as
|
|
68318
|
+
import { cpus, homedir as homedir41, totalmem } from "node:os";
|
|
68152
68319
|
import { join as join70 } from "node:path";
|
|
68153
68320
|
function runCommand(cmd, args, fallback2) {
|
|
68154
68321
|
return new Promise((resolve34) => {
|
|
@@ -68314,7 +68481,7 @@ function registerSystemRoutes(app) {
|
|
|
68314
68481
|
gitVersion,
|
|
68315
68482
|
ghVersion,
|
|
68316
68483
|
shell: process.env.SHELL ?? process.env.ComSpec ?? "unknown",
|
|
68317
|
-
homeDir:
|
|
68484
|
+
homeDir: homedir41(),
|
|
68318
68485
|
cpuCores: cpus().length,
|
|
68319
68486
|
totalMemoryGb: (totalmem() / 1024 ** 3).toFixed(1)
|
|
68320
68487
|
};
|
|
@@ -74276,10 +74443,10 @@ var init_config_manager2 = __esm(() => {
|
|
|
74276
74443
|
|
|
74277
74444
|
// src/services/package-installer/gemini-mcp/validation.ts
|
|
74278
74445
|
import { existsSync as existsSync63, lstatSync, readlinkSync } from "node:fs";
|
|
74279
|
-
import { homedir as
|
|
74446
|
+
import { homedir as homedir44 } from "node:os";
|
|
74280
74447
|
import { join as join93 } from "node:path";
|
|
74281
74448
|
function getGlobalMcpConfigPath() {
|
|
74282
|
-
return join93(
|
|
74449
|
+
return join93(homedir44(), ".claude", ".mcp.json");
|
|
74283
74450
|
}
|
|
74284
74451
|
function getLocalMcpConfigPath(projectDir) {
|
|
74285
74452
|
return join93(projectDir, ".mcp.json");
|
|
@@ -74300,7 +74467,7 @@ function findMcpConfigPath(projectDir) {
|
|
|
74300
74467
|
}
|
|
74301
74468
|
function getGeminiSettingsPath(projectDir, isGlobal) {
|
|
74302
74469
|
if (isGlobal) {
|
|
74303
|
-
return join93(
|
|
74470
|
+
return join93(homedir44(), ".gemini", "settings.json");
|
|
74304
74471
|
}
|
|
74305
74472
|
return join93(projectDir, ".gemini", "settings.json");
|
|
74306
74473
|
}
|
|
@@ -76928,7 +77095,7 @@ var init_content_validator = __esm(() => {
|
|
|
76928
77095
|
import { createHash as createHash9 } from "node:crypto";
|
|
76929
77096
|
import { existsSync as existsSync79, mkdirSync as mkdirSync5, readFileSync as readFileSync19, readdirSync as readdirSync13, statSync as statSync14 } from "node:fs";
|
|
76930
77097
|
import { rename as rename16, writeFile as writeFile40 } from "node:fs/promises";
|
|
76931
|
-
import { homedir as
|
|
77098
|
+
import { homedir as homedir54 } from "node:os";
|
|
76932
77099
|
import { basename as basename34, join as join160 } from "node:path";
|
|
76933
77100
|
function getCachedContext(repoPath) {
|
|
76934
77101
|
const cachePath = getCacheFilePath(repoPath);
|
|
@@ -77003,7 +77170,7 @@ function getCacheFilePath(repoPath) {
|
|
|
77003
77170
|
}
|
|
77004
77171
|
var CACHE_DIR, CACHE_TTL_MS5;
|
|
77005
77172
|
var init_context_cache_manager = __esm(() => {
|
|
77006
|
-
CACHE_DIR = join160(
|
|
77173
|
+
CACHE_DIR = join160(homedir54(), ".claudekit", "cache");
|
|
77007
77174
|
CACHE_TTL_MS5 = 24 * 60 * 60 * 1000;
|
|
77008
77175
|
});
|
|
77009
77176
|
|
|
@@ -77457,10 +77624,10 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
|
|
|
77457
77624
|
// src/commands/content/phases/photo-generator.ts
|
|
77458
77625
|
import { execSync as execSync8 } from "node:child_process";
|
|
77459
77626
|
import { existsSync as existsSync81, mkdirSync as mkdirSync6, readdirSync as readdirSync15 } from "node:fs";
|
|
77460
|
-
import { homedir as
|
|
77627
|
+
import { homedir as homedir55 } from "node:os";
|
|
77461
77628
|
import { join as join162 } from "node:path";
|
|
77462
77629
|
async function generatePhoto(_content, context, config, platform18, contentId, contentLogger) {
|
|
77463
|
-
const mediaDir = join162(config.contentDir.replace(/^~/,
|
|
77630
|
+
const mediaDir = join162(config.contentDir.replace(/^~/, homedir55()), "media", String(contentId));
|
|
77464
77631
|
if (!existsSync81(mediaDir)) {
|
|
77465
77632
|
mkdirSync6(mediaDir, { recursive: true });
|
|
77466
77633
|
}
|
|
@@ -77574,7 +77741,7 @@ var init_content_creator = __esm(() => {
|
|
|
77574
77741
|
|
|
77575
77742
|
// src/commands/content/phases/content-logger.ts
|
|
77576
77743
|
import { createWriteStream as createWriteStream4, existsSync as existsSync82, mkdirSync as mkdirSync7, statSync as statSync15 } from "node:fs";
|
|
77577
|
-
import { homedir as
|
|
77744
|
+
import { homedir as homedir56 } from "node:os";
|
|
77578
77745
|
import { join as join163 } from "node:path";
|
|
77579
77746
|
|
|
77580
77747
|
class ContentLogger {
|
|
@@ -77583,7 +77750,7 @@ class ContentLogger {
|
|
|
77583
77750
|
logDir;
|
|
77584
77751
|
maxBytes;
|
|
77585
77752
|
constructor(maxBytes = 0) {
|
|
77586
|
-
this.logDir = join163(
|
|
77753
|
+
this.logDir = join163(homedir56(), ".claudekit", "logs");
|
|
77587
77754
|
this.maxBytes = maxBytes;
|
|
77588
77755
|
}
|
|
77589
77756
|
init() {
|
|
@@ -79194,11 +79361,11 @@ var init_setup_wizard = __esm(() => {
|
|
|
79194
79361
|
|
|
79195
79362
|
// src/commands/content/content-review-commands.ts
|
|
79196
79363
|
import { existsSync as existsSync86 } from "node:fs";
|
|
79197
|
-
import { homedir as
|
|
79364
|
+
import { homedir as homedir57 } from "node:os";
|
|
79198
79365
|
async function queueContent() {
|
|
79199
79366
|
const cwd2 = process.cwd();
|
|
79200
79367
|
const config = await loadContentConfig(cwd2);
|
|
79201
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
79368
|
+
const dbPath = config.dbPath.replace(/^~/, homedir57());
|
|
79202
79369
|
if (!existsSync86(dbPath)) {
|
|
79203
79370
|
logger.info("No content database found. Run 'ck content setup' first.");
|
|
79204
79371
|
return;
|
|
@@ -79225,7 +79392,7 @@ async function queueContent() {
|
|
|
79225
79392
|
async function approveContentCmd(id) {
|
|
79226
79393
|
const cwd2 = process.cwd();
|
|
79227
79394
|
const config = await loadContentConfig(cwd2);
|
|
79228
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
79395
|
+
const dbPath = config.dbPath.replace(/^~/, homedir57());
|
|
79229
79396
|
const db = initDatabase(dbPath);
|
|
79230
79397
|
try {
|
|
79231
79398
|
approveContent(db, Number.parseInt(id, 10));
|
|
@@ -79237,7 +79404,7 @@ async function approveContentCmd(id) {
|
|
|
79237
79404
|
async function rejectContentCmd(id, reason) {
|
|
79238
79405
|
const cwd2 = process.cwd();
|
|
79239
79406
|
const config = await loadContentConfig(cwd2);
|
|
79240
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
79407
|
+
const dbPath = config.dbPath.replace(/^~/, homedir57());
|
|
79241
79408
|
const db = initDatabase(dbPath);
|
|
79242
79409
|
try {
|
|
79243
79410
|
rejectContent(db, Number.parseInt(id, 10), reason);
|
|
@@ -79268,7 +79435,7 @@ __export(exports_content_subcommands, {
|
|
|
79268
79435
|
approveContentCmd: () => approveContentCmd
|
|
79269
79436
|
});
|
|
79270
79437
|
import { existsSync as existsSync87, readFileSync as readFileSync22, unlinkSync as unlinkSync6 } from "node:fs";
|
|
79271
|
-
import { homedir as
|
|
79438
|
+
import { homedir as homedir58 } from "node:os";
|
|
79272
79439
|
import { join as join168 } from "node:path";
|
|
79273
79440
|
function isDaemonRunning() {
|
|
79274
79441
|
const lockFile = join168(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
@@ -79342,7 +79509,7 @@ async function statusContent() {
|
|
|
79342
79509
|
} catch {}
|
|
79343
79510
|
}
|
|
79344
79511
|
async function logsContent(options2) {
|
|
79345
|
-
const logDir = join168(
|
|
79512
|
+
const logDir = join168(homedir58(), ".claudekit", "logs");
|
|
79346
79513
|
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
79347
79514
|
const logPath = join168(logDir, `content-${dateStr}.log`);
|
|
79348
79515
|
if (!existsSync87(logPath)) {
|
|
@@ -79376,12 +79543,12 @@ var init_content_subcommands = __esm(() => {
|
|
|
79376
79543
|
init_setup_wizard();
|
|
79377
79544
|
init_state_manager();
|
|
79378
79545
|
init_content_review_commands();
|
|
79379
|
-
LOCK_DIR = join168(
|
|
79546
|
+
LOCK_DIR = join168(homedir58(), ".claudekit", "locks");
|
|
79380
79547
|
});
|
|
79381
79548
|
|
|
79382
79549
|
// src/commands/content/content-command.ts
|
|
79383
79550
|
import { existsSync as existsSync88, mkdirSync as mkdirSync9, unlinkSync as unlinkSync7, writeFileSync as writeFileSync7 } from "node:fs";
|
|
79384
|
-
import { homedir as
|
|
79551
|
+
import { homedir as homedir59 } from "node:os";
|
|
79385
79552
|
import { join as join169 } from "node:path";
|
|
79386
79553
|
async function contentCommand(options2) {
|
|
79387
79554
|
const cwd2 = process.cwd();
|
|
@@ -79414,7 +79581,7 @@ async function contentCommand(options2) {
|
|
|
79414
79581
|
if (!existsSync88(LOCK_DIR2))
|
|
79415
79582
|
mkdirSync9(LOCK_DIR2, { recursive: true });
|
|
79416
79583
|
writeFileSync7(LOCK_FILE, String(process.pid), "utf-8");
|
|
79417
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
79584
|
+
const dbPath = config.dbPath.replace(/^~/, homedir59());
|
|
79418
79585
|
const db = initDatabase(dbPath);
|
|
79419
79586
|
contentLogger.info(`Database initialised at ${dbPath}`);
|
|
79420
79587
|
const adapters = initializeAdapters(config);
|
|
@@ -79560,7 +79727,7 @@ var init_content_command = __esm(() => {
|
|
|
79560
79727
|
init_publisher();
|
|
79561
79728
|
init_review_manager();
|
|
79562
79729
|
init_state_manager();
|
|
79563
|
-
LOCK_DIR2 = join169(
|
|
79730
|
+
LOCK_DIR2 = join169(homedir59(), ".claudekit", "locks");
|
|
79564
79731
|
LOCK_FILE = join169(LOCK_DIR2, "ck-content.lock");
|
|
79565
79732
|
});
|
|
79566
79733
|
|
|
@@ -80723,6 +80890,10 @@ var init_init_command_help = __esm(() => {
|
|
|
80723
80890
|
{
|
|
80724
80891
|
flags: "--force-overwrite-settings",
|
|
80725
80892
|
description: "Fully replace settings.json instead of selective merge"
|
|
80893
|
+
},
|
|
80894
|
+
{
|
|
80895
|
+
flags: "--restore-ck-hooks",
|
|
80896
|
+
description: "Restore CK-managed hook registrations during update self-heal"
|
|
80726
80897
|
}
|
|
80727
80898
|
]
|
|
80728
80899
|
},
|
|
@@ -82777,9 +82948,9 @@ var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
|
82777
82948
|
init_fm_to_json();
|
|
82778
82949
|
init_portable_registry();
|
|
82779
82950
|
init_provider_registry();
|
|
82780
|
-
import { existsSync as
|
|
82951
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
82781
82952
|
import { readFile as readFile6, rm, writeFile as writeFile4 } from "node:fs/promises";
|
|
82782
|
-
import { dirname as dirname4, join as
|
|
82953
|
+
import { dirname as dirname4, join as join8 } from "node:path";
|
|
82783
82954
|
function toSlug3(name) {
|
|
82784
82955
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
82785
82956
|
}
|
|
@@ -82899,7 +83070,7 @@ async function removeFromJsonMerge(agentName, filePath) {
|
|
|
82899
83070
|
const rulesDir = dirname4(filePath);
|
|
82900
83071
|
const ruleNames = new Set([`${agentName}.md`, `${slug}.md`]);
|
|
82901
83072
|
for (const ruleName of ruleNames) {
|
|
82902
|
-
await rm(
|
|
83073
|
+
await rm(join8(rulesDir, ruleName), { force: true });
|
|
82903
83074
|
}
|
|
82904
83075
|
if (filtered.length === 0) {
|
|
82905
83076
|
await rm(filePath, { force: true });
|
|
@@ -82929,7 +83100,7 @@ async function uninstallAgentFromProvider(agentName, provider, global2) {
|
|
|
82929
83100
|
};
|
|
82930
83101
|
}
|
|
82931
83102
|
const installation = installations[0];
|
|
82932
|
-
const fileExists =
|
|
83103
|
+
const fileExists = existsSync7(installation.path);
|
|
82933
83104
|
try {
|
|
82934
83105
|
const config = providers[provider];
|
|
82935
83106
|
const pathConfig = config.agents;
|
|
@@ -83018,8 +83189,8 @@ async function forceUninstallAgentFromProvider(agentName, provider, global2) {
|
|
|
83018
83189
|
};
|
|
83019
83190
|
}
|
|
83020
83191
|
const writeStrategy = pathConfig.writeStrategy;
|
|
83021
|
-
const targetPath = writeStrategy === "json-merge" ?
|
|
83022
|
-
const fileExists =
|
|
83192
|
+
const targetPath = writeStrategy === "json-merge" ? join8(basePath, "cline_custom_modes.json") : writeStrategy === "merge-single" || writeStrategy === "yaml-merge" || writeStrategy === "single-file" ? basePath : join8(basePath, `${agentName}${pathConfig.fileExtension}`);
|
|
83193
|
+
const fileExists = existsSync7(targetPath);
|
|
83023
83194
|
try {
|
|
83024
83195
|
if (!fileExists) {
|
|
83025
83196
|
return {
|
|
@@ -83538,7 +83709,7 @@ var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
|
83538
83709
|
|
|
83539
83710
|
// src/domains/claudekit-api/index.ts
|
|
83540
83711
|
import { homedir as homedir7 } from "node:os";
|
|
83541
|
-
import { join as
|
|
83712
|
+
import { join as join10 } from "node:path";
|
|
83542
83713
|
|
|
83543
83714
|
// src/domains/api-key/validator.ts
|
|
83544
83715
|
var API_BASE_URL = "https://claudekit.cc/api";
|
|
@@ -83585,20 +83756,20 @@ function isValidKeyFormat(key) {
|
|
|
83585
83756
|
return /^ck_live_[A-Za-z0-9_-]{32}$/.test(key);
|
|
83586
83757
|
}
|
|
83587
83758
|
// src/domains/api-key/storage.ts
|
|
83588
|
-
import { existsSync as
|
|
83589
|
-
import { join as
|
|
83759
|
+
import { existsSync as existsSync8, readFileSync as readFileSync4, writeFileSync } from "node:fs";
|
|
83760
|
+
import { join as join9 } from "node:path";
|
|
83590
83761
|
var ENV_FILE = ".env";
|
|
83591
83762
|
var API_KEY_VAR = "CLAUDEKIT_API_KEY";
|
|
83592
83763
|
function getEnvFilePath(claudeDir) {
|
|
83593
|
-
return
|
|
83764
|
+
return join9(claudeDir, ENV_FILE);
|
|
83594
83765
|
}
|
|
83595
83766
|
function readExistingApiKey(claudeDir) {
|
|
83596
83767
|
const envPath = getEnvFilePath(claudeDir);
|
|
83597
|
-
if (!
|
|
83768
|
+
if (!existsSync8(envPath)) {
|
|
83598
83769
|
return null;
|
|
83599
83770
|
}
|
|
83600
83771
|
try {
|
|
83601
|
-
const content =
|
|
83772
|
+
const content = readFileSync4(envPath, "utf-8");
|
|
83602
83773
|
const match = content.match(new RegExp(`^${API_KEY_VAR}=(.+)$`, "m"));
|
|
83603
83774
|
return match?.[1]?.trim() ?? null;
|
|
83604
83775
|
} catch {
|
|
@@ -83608,8 +83779,8 @@ function readExistingApiKey(claudeDir) {
|
|
|
83608
83779
|
function saveApiKey(claudeDir, apiKey) {
|
|
83609
83780
|
const envPath = getEnvFilePath(claudeDir);
|
|
83610
83781
|
let content = "";
|
|
83611
|
-
if (
|
|
83612
|
-
content =
|
|
83782
|
+
if (existsSync8(envPath)) {
|
|
83783
|
+
content = readFileSync4(envPath, "utf-8");
|
|
83613
83784
|
if (content.includes(`${API_KEY_VAR}=`)) {
|
|
83614
83785
|
content = content.replace(new RegExp(`^${API_KEY_VAR}=.*$`, "m"), `${API_KEY_VAR}=${apiKey}`);
|
|
83615
83786
|
} else {
|
|
@@ -83765,7 +83936,7 @@ class ClaudekitHttpClient {
|
|
|
83765
83936
|
} catch (error) {
|
|
83766
83937
|
if (error instanceof CkApiError && error.code === "RATE_LIMIT_EXCEEDED" && error.retryAfter) {
|
|
83767
83938
|
const delayMs = error.retryAfter * 1000;
|
|
83768
|
-
await new Promise((
|
|
83939
|
+
await new Promise((resolve5) => setTimeout(resolve5, delayMs));
|
|
83769
83940
|
return fn();
|
|
83770
83941
|
}
|
|
83771
83942
|
throw error;
|
|
@@ -83775,7 +83946,7 @@ class ClaudekitHttpClient {
|
|
|
83775
83946
|
|
|
83776
83947
|
// src/domains/claudekit-api/index.ts
|
|
83777
83948
|
function createApiClient(claudeDir) {
|
|
83778
|
-
const dir = claudeDir ??
|
|
83949
|
+
const dir = claudeDir ?? join10(homedir7(), ".claude");
|
|
83779
83950
|
const apiKey = readExistingApiKey(dir);
|
|
83780
83951
|
if (!apiKey) {
|
|
83781
83952
|
throw new CkApiError("MISSING_API_KEY", "No API key found. Run `ck api setup` to configure your ClaudeKit API key.", 401);
|
|
@@ -84206,13 +84377,13 @@ async function handleApiServices(options2) {
|
|
|
84206
84377
|
|
|
84207
84378
|
// src/commands/api/subcommands/api-setup-handler.ts
|
|
84208
84379
|
import { homedir as homedir8 } from "node:os";
|
|
84209
|
-
import { join as
|
|
84380
|
+
import { join as join11 } from "node:path";
|
|
84210
84381
|
init_logger();
|
|
84211
84382
|
init_dist2();
|
|
84212
84383
|
var DASHBOARD_URL = "https://claudekit.cc/api-keys";
|
|
84213
84384
|
var MAX_ATTEMPTS = 3;
|
|
84214
84385
|
async function handleApiSetup(options2) {
|
|
84215
|
-
const claudeDir =
|
|
84386
|
+
const claudeDir = join11(homedir8(), ".claude");
|
|
84216
84387
|
const existing = readExistingApiKey(claudeDir);
|
|
84217
84388
|
if (existing && !options2.force) {
|
|
84218
84389
|
const masked = `${existing.slice(0, 15)}...`;
|
|
@@ -88196,7 +88367,7 @@ init_logger();
|
|
|
88196
88367
|
init_path_resolver();
|
|
88197
88368
|
import { existsSync as existsSync58 } from "node:fs";
|
|
88198
88369
|
import { readFile as readFile42 } from "node:fs/promises";
|
|
88199
|
-
import { homedir as
|
|
88370
|
+
import { homedir as homedir42 } from "node:os";
|
|
88200
88371
|
import { dirname as dirname31, join as join80, normalize as normalize6, resolve as resolve36 } from "node:path";
|
|
88201
88372
|
async function checkPathRefsValid(projectDir) {
|
|
88202
88373
|
const globalClaudeMd = join80(PathResolver.getGlobalKitDir(), "CLAUDE.md");
|
|
@@ -88229,7 +88400,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
88229
88400
|
};
|
|
88230
88401
|
}
|
|
88231
88402
|
const baseDir = dirname31(claudeMdPath);
|
|
88232
|
-
const home5 =
|
|
88403
|
+
const home5 = homedir42();
|
|
88233
88404
|
const broken = [];
|
|
88234
88405
|
for (const ref of refs) {
|
|
88235
88406
|
let refPath;
|
|
@@ -89233,7 +89404,7 @@ import { platform as platform8 } from "node:os";
|
|
|
89233
89404
|
init_environment();
|
|
89234
89405
|
init_path_resolver();
|
|
89235
89406
|
import { constants as constants3, access as access4, mkdir as mkdir21, readFile as readFile44, unlink as unlink11, writeFile as writeFile21 } from "node:fs/promises";
|
|
89236
|
-
import { arch as arch2, homedir as
|
|
89407
|
+
import { arch as arch2, homedir as homedir43, platform as platform7 } from "node:os";
|
|
89237
89408
|
import { join as join85, normalize as normalize7 } from "node:path";
|
|
89238
89409
|
function shouldSkipExpensiveOperations4() {
|
|
89239
89410
|
return shouldSkipExpensiveOperations();
|
|
@@ -89256,7 +89427,7 @@ async function checkPlatformDetect() {
|
|
|
89256
89427
|
};
|
|
89257
89428
|
}
|
|
89258
89429
|
async function checkHomeDirResolution() {
|
|
89259
|
-
const nodeHome = normalize7(
|
|
89430
|
+
const nodeHome = normalize7(homedir43());
|
|
89260
89431
|
const rawEnvHome = getHomeDirectoryFromEnv(platform7());
|
|
89261
89432
|
const envHome = rawEnvHome ? normalize7(rawEnvHome) : "";
|
|
89262
89433
|
const match = nodeHome === envHome && envHome !== "";
|
|
@@ -103341,7 +103512,7 @@ class FileScanner {
|
|
|
103341
103512
|
|
|
103342
103513
|
// src/domains/installation/merger/settings-processor.ts
|
|
103343
103514
|
import { execSync as execSync5 } from "node:child_process";
|
|
103344
|
-
import { homedir as
|
|
103515
|
+
import { homedir as homedir45 } from "node:os";
|
|
103345
103516
|
import { dirname as dirname39, join as join109 } from "node:path";
|
|
103346
103517
|
|
|
103347
103518
|
// src/domains/config/installed-settings-tracker.ts
|
|
@@ -103373,7 +103544,7 @@ class InstalledSettingsTracker {
|
|
|
103373
103544
|
}
|
|
103374
103545
|
try {
|
|
103375
103546
|
const content = await readFile50(ckJsonPath, "utf-8");
|
|
103376
|
-
const data =
|
|
103547
|
+
const data = parseJsonContent(content);
|
|
103377
103548
|
const installed = data.kits?.[this.kitName]?.installedSettings;
|
|
103378
103549
|
if (installed) {
|
|
103379
103550
|
return installed;
|
|
@@ -103390,7 +103561,7 @@ class InstalledSettingsTracker {
|
|
|
103390
103561
|
let data = {};
|
|
103391
103562
|
if (existsSync66(ckJsonPath)) {
|
|
103392
103563
|
const content = await readFile50(ckJsonPath, "utf-8");
|
|
103393
|
-
data =
|
|
103564
|
+
data = parseJsonContent(content);
|
|
103394
103565
|
}
|
|
103395
103566
|
if (!data.kits) {
|
|
103396
103567
|
data.kits = {};
|
|
@@ -103456,6 +103627,7 @@ class SettingsProcessor {
|
|
|
103456
103627
|
installingKit;
|
|
103457
103628
|
cachedVersion = undefined;
|
|
103458
103629
|
deletionPatterns = [];
|
|
103630
|
+
restoreCkHooks = false;
|
|
103459
103631
|
zombiePrunerHookDir = null;
|
|
103460
103632
|
setGlobalFlag(isGlobal) {
|
|
103461
103633
|
this.isGlobal = isGlobal;
|
|
@@ -103463,6 +103635,9 @@ class SettingsProcessor {
|
|
|
103463
103635
|
setForceOverwriteSettings(force) {
|
|
103464
103636
|
this.forceOverwriteSettings = force;
|
|
103465
103637
|
}
|
|
103638
|
+
setRestoreCkHooks(restore) {
|
|
103639
|
+
this.restoreCkHooks = restore;
|
|
103640
|
+
}
|
|
103466
103641
|
setProjectDir(dir) {
|
|
103467
103642
|
this.projectDir = dir;
|
|
103468
103643
|
this.initTracker();
|
|
@@ -103507,6 +103682,7 @@ class SettingsProcessor {
|
|
|
103507
103682
|
} else {
|
|
103508
103683
|
try {
|
|
103509
103684
|
const parsedSettings = JSON.parse(transformedSource);
|
|
103685
|
+
await this.applyDisabledHookConfig(parsedSettings);
|
|
103510
103686
|
this.logHookCommandRepair(this.fixHookCommandPaths(parsedSettings), "fresh install");
|
|
103511
103687
|
await SettingsMerger.writeSettingsFile(destFile, parsedSettings);
|
|
103512
103688
|
try {
|
|
@@ -103536,6 +103712,7 @@ class SettingsProcessor {
|
|
|
103536
103712
|
let sourceSettings;
|
|
103537
103713
|
try {
|
|
103538
103714
|
sourceSettings = JSON.parse(transformedSourceContent);
|
|
103715
|
+
await this.applyDisabledHookConfig(sourceSettings);
|
|
103539
103716
|
} catch {
|
|
103540
103717
|
logger.warning("Failed to parse source settings.json, falling back to overwrite");
|
|
103541
103718
|
const formattedContent = this.formatJsonContent(transformedSourceContent);
|
|
@@ -103558,10 +103735,15 @@ class SettingsProcessor {
|
|
|
103558
103735
|
if (this.tracker) {
|
|
103559
103736
|
installedSettings = await this.tracker.loadInstalledSettings();
|
|
103560
103737
|
}
|
|
103738
|
+
const mergeInstalledSettings = this.restoreCkHooks ? { ...installedSettings, hooks: [] } : installedSettings;
|
|
103561
103739
|
const mergeResult = SettingsMerger.merge(sourceSettings, destSettings, {
|
|
103562
|
-
installedSettings,
|
|
103740
|
+
installedSettings: mergeInstalledSettings,
|
|
103563
103741
|
sourceKit: this.installingKit
|
|
103564
103742
|
});
|
|
103743
|
+
await this.applyDisabledHookConfig(mergeResult.merged);
|
|
103744
|
+
if (this.restoreCkHooks) {
|
|
103745
|
+
logger.info("Restored CK hook registrations while respecting .ck.json hook disables");
|
|
103746
|
+
}
|
|
103565
103747
|
logger.verbose("Settings merge details", {
|
|
103566
103748
|
hooksAdded: mergeResult.hooksAdded,
|
|
103567
103749
|
hooksPreserved: mergeResult.hooksPreserved,
|
|
@@ -103591,7 +103773,8 @@ class SettingsProcessor {
|
|
|
103591
103773
|
logger.info(`Pruned ${hooksPruned} stale hook(s) referencing deleted files`);
|
|
103592
103774
|
}
|
|
103593
103775
|
if (this.zombiePrunerHookDir) {
|
|
103594
|
-
const
|
|
103776
|
+
const sourceHookCommands = this.collectHookCommands(sourceSettings);
|
|
103777
|
+
const { pruned: zombiePruned } = pruneZombieEngineerWirings(mergeResult.merged, this.zombiePrunerHookDir, sourceHookCommands);
|
|
103595
103778
|
if (zombiePruned.length > 0) {
|
|
103596
103779
|
logger.info(`Pruned ${zombiePruned.length} zombie hook entries: ${zombiePruned.join(", ")}`);
|
|
103597
103780
|
}
|
|
@@ -103600,6 +103783,111 @@ class SettingsProcessor {
|
|
|
103600
103783
|
logger.success("Merged settings.json (user customizations preserved)");
|
|
103601
103784
|
await this.injectTeamHooksIfSupported(destFile, mergeResult.merged);
|
|
103602
103785
|
}
|
|
103786
|
+
async getDisabledHookNames() {
|
|
103787
|
+
if (!this.projectDir) {
|
|
103788
|
+
return new Set;
|
|
103789
|
+
}
|
|
103790
|
+
const disabled = new Set;
|
|
103791
|
+
const addFromConfig = async (configPath) => {
|
|
103792
|
+
const names = await this.readDisabledHookNamesFromConfig(configPath);
|
|
103793
|
+
for (const name2 of names)
|
|
103794
|
+
disabled.add(name2);
|
|
103795
|
+
};
|
|
103796
|
+
try {
|
|
103797
|
+
if (this.isGlobal) {
|
|
103798
|
+
await addFromConfig(join109(this.projectDir, ".ck.json"));
|
|
103799
|
+
} else {
|
|
103800
|
+
await addFromConfig(join109(PathResolver.getGlobalKitDir(), ".ck.json"));
|
|
103801
|
+
await addFromConfig(join109(this.projectDir, ".claude", ".ck.json"));
|
|
103802
|
+
}
|
|
103803
|
+
} catch (error) {
|
|
103804
|
+
logger.debug(`Failed to load .ck.json hook preferences: ${error instanceof Error ? error.message : "unknown"}`);
|
|
103805
|
+
}
|
|
103806
|
+
return disabled;
|
|
103807
|
+
}
|
|
103808
|
+
async readDisabledHookNamesFromConfig(configPath) {
|
|
103809
|
+
if (!await import_fs_extra14.pathExists(configPath))
|
|
103810
|
+
return new Set;
|
|
103811
|
+
const raw2 = parseJsonContent(await import_fs_extra14.readFile(configPath, "utf-8"));
|
|
103812
|
+
const hooks = raw2.hooks;
|
|
103813
|
+
if (!hooks || typeof hooks !== "object")
|
|
103814
|
+
return new Set;
|
|
103815
|
+
return new Set(Object.entries(hooks).filter(([, enabled]) => enabled === false).map(([name2]) => name2));
|
|
103816
|
+
}
|
|
103817
|
+
async applyDisabledHookConfig(settings) {
|
|
103818
|
+
const disabledHooks = await this.getDisabledHookNames();
|
|
103819
|
+
if (disabledHooks.size === 0 || !settings.hooks)
|
|
103820
|
+
return 0;
|
|
103821
|
+
let removed = 0;
|
|
103822
|
+
const hooksRecord = settings.hooks;
|
|
103823
|
+
for (const [eventName, entries] of Object.entries(hooksRecord)) {
|
|
103824
|
+
const filteredEntries = [];
|
|
103825
|
+
for (const entry of entries) {
|
|
103826
|
+
if (Array.isArray(entry.hooks)) {
|
|
103827
|
+
const keptHooks = entry.hooks.filter((hook) => {
|
|
103828
|
+
const command = typeof hook.command === "string" ? hook.command : "";
|
|
103829
|
+
const hookName = this.extractCkHookName(command);
|
|
103830
|
+
if (hookName && disabledHooks.has(hookName)) {
|
|
103831
|
+
removed++;
|
|
103832
|
+
return false;
|
|
103833
|
+
}
|
|
103834
|
+
return true;
|
|
103835
|
+
});
|
|
103836
|
+
if (keptHooks.length > 0) {
|
|
103837
|
+
filteredEntries.push({ ...entry, hooks: keptHooks });
|
|
103838
|
+
}
|
|
103839
|
+
} else {
|
|
103840
|
+
const command = typeof entry.command === "string" ? entry.command : "";
|
|
103841
|
+
const hookName = this.extractCkHookName(command);
|
|
103842
|
+
if (hookName && disabledHooks.has(hookName)) {
|
|
103843
|
+
removed++;
|
|
103844
|
+
continue;
|
|
103845
|
+
}
|
|
103846
|
+
filteredEntries.push(entry);
|
|
103847
|
+
}
|
|
103848
|
+
}
|
|
103849
|
+
if (filteredEntries.length > 0) {
|
|
103850
|
+
hooksRecord[eventName] = filteredEntries;
|
|
103851
|
+
} else {
|
|
103852
|
+
delete hooksRecord[eventName];
|
|
103853
|
+
}
|
|
103854
|
+
}
|
|
103855
|
+
if (Object.keys(hooksRecord).length === 0) {
|
|
103856
|
+
settings.hooks = undefined;
|
|
103857
|
+
}
|
|
103858
|
+
if (removed > 0) {
|
|
103859
|
+
logger.info(`Skipped ${removed} hook registration(s) disabled in .ck.json`);
|
|
103860
|
+
}
|
|
103861
|
+
return removed;
|
|
103862
|
+
}
|
|
103863
|
+
collectHookCommands(settings) {
|
|
103864
|
+
const commands = new Set;
|
|
103865
|
+
if (!settings.hooks)
|
|
103866
|
+
return commands;
|
|
103867
|
+
for (const entries of Object.values(settings.hooks)) {
|
|
103868
|
+
for (const entry of entries) {
|
|
103869
|
+
if ("hooks" in entry && Array.isArray(entry.hooks)) {
|
|
103870
|
+
for (const hook of entry.hooks) {
|
|
103871
|
+
if (typeof hook.command === "string") {
|
|
103872
|
+
commands.add(hook.command);
|
|
103873
|
+
}
|
|
103874
|
+
}
|
|
103875
|
+
continue;
|
|
103876
|
+
}
|
|
103877
|
+
if ("command" in entry && typeof entry.command === "string") {
|
|
103878
|
+
commands.add(entry.command);
|
|
103879
|
+
}
|
|
103880
|
+
}
|
|
103881
|
+
}
|
|
103882
|
+
return commands;
|
|
103883
|
+
}
|
|
103884
|
+
extractCkHookName(command) {
|
|
103885
|
+
if (!command.trim().startsWith("node "))
|
|
103886
|
+
return null;
|
|
103887
|
+
const normalized = command.replace(/\\/g, "/");
|
|
103888
|
+
const match2 = normalized.match(/\/hooks\/([^/"'\s]+)\.(?:cjs|mjs|js)(?:["'\s]|$)/);
|
|
103889
|
+
return match2?.[1] ?? null;
|
|
103890
|
+
}
|
|
103603
103891
|
migrateDeprecatedMatchers(destSettings, sourceSettings) {
|
|
103604
103892
|
if (!destSettings.hooks || !sourceSettings.hooks)
|
|
103605
103893
|
return;
|
|
@@ -103841,7 +104129,7 @@ class SettingsProcessor {
|
|
|
103841
104129
|
return false;
|
|
103842
104130
|
}
|
|
103843
104131
|
const configuredGlobalDir = PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "");
|
|
103844
|
-
const defaultGlobalDir = join109(
|
|
104132
|
+
const defaultGlobalDir = join109(homedir45(), ".claude").replace(/\\/g, "/");
|
|
103845
104133
|
return configuredGlobalDir !== defaultGlobalDir;
|
|
103846
104134
|
}
|
|
103847
104135
|
getClaudeCommandRoot() {
|
|
@@ -103992,6 +104280,9 @@ class CopyExecutor {
|
|
|
103992
104280
|
setForceOverwriteSettings(force) {
|
|
103993
104281
|
this.settingsProcessor.setForceOverwriteSettings(force);
|
|
103994
104282
|
}
|
|
104283
|
+
setRestoreCkHooks(restore) {
|
|
104284
|
+
this.settingsProcessor.setRestoreCkHooks(restore);
|
|
104285
|
+
}
|
|
103995
104286
|
setDeletions(deletions) {
|
|
103996
104287
|
this.settingsProcessor.setDeletions(deletions);
|
|
103997
104288
|
}
|
|
@@ -104164,6 +104455,9 @@ class FileMerger {
|
|
|
104164
104455
|
setForceOverwriteSettings(force) {
|
|
104165
104456
|
this.copyExecutor.setForceOverwriteSettings(force);
|
|
104166
104457
|
}
|
|
104458
|
+
setRestoreCkHooks(restore) {
|
|
104459
|
+
this.copyExecutor.setRestoreCkHooks(restore);
|
|
104460
|
+
}
|
|
104167
104461
|
setProjectDir(dir) {
|
|
104168
104462
|
this.copyExecutor.setProjectDir(dir);
|
|
104169
104463
|
}
|
|
@@ -105487,6 +105781,7 @@ async function handleMerge(ctx) {
|
|
|
105487
105781
|
}
|
|
105488
105782
|
merger.setGlobalFlag(ctx.options.global);
|
|
105489
105783
|
merger.setForceOverwriteSettings(ctx.options.forceOverwriteSettings);
|
|
105784
|
+
merger.setRestoreCkHooks(ctx.options.restoreCkHooks);
|
|
105490
105785
|
merger.setProjectDir(ctx.resolvedDir);
|
|
105491
105786
|
merger.setKitName(ctx.kit.name);
|
|
105492
105787
|
merger.setZombiePrunerHookDir(join120(ctx.claudeDir, "hooks"));
|
|
@@ -106974,6 +107269,7 @@ async function resolveOptions(ctx) {
|
|
|
106974
107269
|
skipSetup: parsed.skipSetup ?? false,
|
|
106975
107270
|
forceOverwrite: parsed.forceOverwrite ?? false,
|
|
106976
107271
|
forceOverwriteSettings: parsed.forceOverwriteSettings ?? false,
|
|
107272
|
+
restoreCkHooks: parsed.restoreCkHooks ?? false,
|
|
106977
107273
|
dryRun: parsed.dryRun ?? false,
|
|
106978
107274
|
prefix: parsed.prefix ?? false,
|
|
106979
107275
|
sync: parsed.sync ?? false,
|
|
@@ -107530,7 +107826,7 @@ async function handleFreshInstallation(claudeDir3, prompts) {
|
|
|
107530
107826
|
// src/domains/installation/global-kit-legacy-repair.ts
|
|
107531
107827
|
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
107532
107828
|
import { cp as cp5, mkdir as mkdir35, readdir as readdir42, rename as rename11, rm as rm16, stat as stat22 } from "node:fs/promises";
|
|
107533
|
-
import { homedir as
|
|
107829
|
+
import { homedir as homedir46 } from "node:os";
|
|
107534
107830
|
import { dirname as dirname42, join as join133, normalize as normalize11, resolve as resolve46 } from "node:path";
|
|
107535
107831
|
var LEGACY_KIT_MARKERS = [
|
|
107536
107832
|
"metadata.json",
|
|
@@ -107565,7 +107861,7 @@ function uniqueNormalizedPaths(paths) {
|
|
|
107565
107861
|
}
|
|
107566
107862
|
return result;
|
|
107567
107863
|
}
|
|
107568
|
-
function getLegacyWindowsGlobalKitDirCandidates(env2 = process.env, homeDir =
|
|
107864
|
+
function getLegacyWindowsGlobalKitDirCandidates(env2 = process.env, homeDir = homedir46()) {
|
|
107569
107865
|
const candidates = [];
|
|
107570
107866
|
const localAppData = safeEnvPath(env2.LOCALAPPDATA);
|
|
107571
107867
|
const appData = safeEnvPath(env2.APPDATA);
|
|
@@ -108016,7 +108312,7 @@ async function handleSelection(ctx) {
|
|
|
108016
108312
|
logger.info("--force has no effect without --yes (the version-match skip only applies in non-interactive mode)");
|
|
108017
108313
|
}
|
|
108018
108314
|
const releaseTag = release?.tag_name;
|
|
108019
|
-
if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode && !pendingKits?.length) {
|
|
108315
|
+
if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && !ctx.options.restoreCkHooks && releaseTag && !isOfflineMode && !pendingKits?.length) {
|
|
108020
108316
|
try {
|
|
108021
108317
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
108022
108318
|
const claudeDir3 = prefix ? join134(resolvedDir, prefix) : resolvedDir;
|
|
@@ -108698,7 +108994,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
108698
108994
|
// src/services/transformers/global-path-transformer.ts
|
|
108699
108995
|
init_logger();
|
|
108700
108996
|
import { readFile as readFile61, readdir as readdir44, writeFile as writeFile35 } from "node:fs/promises";
|
|
108701
|
-
import { homedir as
|
|
108997
|
+
import { homedir as homedir47, platform as platform15 } from "node:os";
|
|
108702
108998
|
import { extname as extname7, join as join138 } from "node:path";
|
|
108703
108999
|
var IS_WINDOWS3 = platform15() === "win32";
|
|
108704
109000
|
var HOME_PREFIX = "$HOME";
|
|
@@ -108709,7 +109005,7 @@ function normalizeInstallPath(path17) {
|
|
|
108709
109005
|
return path17.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
108710
109006
|
}
|
|
108711
109007
|
function getDefaultGlobalClaudeDir() {
|
|
108712
|
-
return normalizeInstallPath(join138(
|
|
109008
|
+
return normalizeInstallPath(join138(homedir47(), ".claude"));
|
|
108713
109009
|
}
|
|
108714
109010
|
function getCustomGlobalClaudeDir(targetClaudeDir) {
|
|
108715
109011
|
if (!targetClaudeDir)
|
|
@@ -108990,6 +109286,7 @@ function createInitContext(rawOptions, prompts) {
|
|
|
108990
109286
|
skipSetup: false,
|
|
108991
109287
|
forceOverwrite: false,
|
|
108992
109288
|
forceOverwriteSettings: false,
|
|
109289
|
+
restoreCkHooks: false,
|
|
108993
109290
|
dryRun: false,
|
|
108994
109291
|
prefix: false,
|
|
108995
109292
|
sync: false,
|
|
@@ -109140,13 +109437,13 @@ init_dist2();
|
|
|
109140
109437
|
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
109141
109438
|
import { existsSync as existsSync68 } from "node:fs";
|
|
109142
109439
|
import { readFile as readFile65, rm as rm18, unlink as unlink14 } from "node:fs/promises";
|
|
109143
|
-
import { homedir as
|
|
109440
|
+
import { homedir as homedir52 } from "node:os";
|
|
109144
109441
|
import { basename as basename30, join as join143, resolve as resolve50 } from "node:path";
|
|
109145
109442
|
init_logger();
|
|
109146
109443
|
|
|
109147
109444
|
// src/ui/ck-cli-design/tokens.ts
|
|
109148
109445
|
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
109149
|
-
import { homedir as
|
|
109446
|
+
import { homedir as homedir48, platform as platform16 } from "node:os";
|
|
109150
109447
|
import { resolve as resolve49, win32 as win322 } from "node:path";
|
|
109151
109448
|
var PANEL_MIN_WIDTH = 60;
|
|
109152
109449
|
var PANEL_MAX_WIDTH = 72;
|
|
@@ -109304,7 +109601,7 @@ function wrapText(value, width) {
|
|
|
109304
109601
|
}
|
|
109305
109602
|
function formatDisplayPath(value) {
|
|
109306
109603
|
const normalized = value.replace(/\\/g, "/");
|
|
109307
|
-
const home5 =
|
|
109604
|
+
const home5 = homedir48().replace(/\\/g, "/");
|
|
109308
109605
|
if (normalized === home5)
|
|
109309
109606
|
return "~";
|
|
109310
109607
|
if (normalized.startsWith(`${home5}/`)) {
|
|
@@ -109618,13 +109915,13 @@ init_logger();
|
|
|
109618
109915
|
init_dist2();
|
|
109619
109916
|
init_model_taxonomy();
|
|
109620
109917
|
import { mkdir as mkdir39, readFile as readFile64, writeFile as writeFile37 } from "node:fs/promises";
|
|
109621
|
-
import { homedir as
|
|
109918
|
+
import { homedir as homedir51 } from "node:os";
|
|
109622
109919
|
import { dirname as dirname44, join as join142 } from "node:path";
|
|
109623
109920
|
|
|
109624
109921
|
// src/commands/portable/models-dev-cache.ts
|
|
109625
109922
|
init_logger();
|
|
109626
109923
|
import { mkdir as mkdir38, readFile as readFile62, rename as rename14, writeFile as writeFile36 } from "node:fs/promises";
|
|
109627
|
-
import { homedir as
|
|
109924
|
+
import { homedir as homedir49 } from "node:os";
|
|
109628
109925
|
import { join as join140 } from "node:path";
|
|
109629
109926
|
|
|
109630
109927
|
class ModelsDevUnavailableError extends Error {
|
|
@@ -109637,7 +109934,7 @@ var MODELS_DEV_URL = "https://models.dev/api.json";
|
|
|
109637
109934
|
var CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
|
|
109638
109935
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
109639
109936
|
function defaultCacheDir() {
|
|
109640
|
-
return join140(
|
|
109937
|
+
return join140(homedir49(), ".config", "claudekit", "cache");
|
|
109641
109938
|
}
|
|
109642
109939
|
function cacheFilePath(cacheDir) {
|
|
109643
109940
|
return join140(cacheDir, "models-dev.json");
|
|
@@ -109717,7 +110014,7 @@ async function getModelsDevCatalog(opts = {}) {
|
|
|
109717
110014
|
// src/commands/portable/opencode-model-discovery.ts
|
|
109718
110015
|
init_logger();
|
|
109719
110016
|
import { readFile as readFile63 } from "node:fs/promises";
|
|
109720
|
-
import { homedir as
|
|
110017
|
+
import { homedir as homedir50, platform as platform17 } from "node:os";
|
|
109721
110018
|
import { join as join141 } from "node:path";
|
|
109722
110019
|
function resolveOpenCodeAuthPath(homeDir) {
|
|
109723
110020
|
if (platform17() === "win32") {
|
|
@@ -109763,7 +110060,7 @@ function pickGenericModel(models) {
|
|
|
109763
110060
|
return sorted[0] ?? null;
|
|
109764
110061
|
}
|
|
109765
110062
|
async function resolveOpenCodeDefaultModel(opts = {}) {
|
|
109766
|
-
const home5 = opts.homeDir ??
|
|
110063
|
+
const home5 = opts.homeDir ?? homedir50();
|
|
109767
110064
|
const authedProviders = await readAuthedProviders(home5);
|
|
109768
110065
|
if (authedProviders.length === 0) {
|
|
109769
110066
|
return { ok: false, reason: "no-auth", authedProviders: [] };
|
|
@@ -109827,7 +110124,7 @@ function messageForReason(reason) {
|
|
|
109827
110124
|
}
|
|
109828
110125
|
function getOpenCodeConfigPath(options2) {
|
|
109829
110126
|
if (options2.global) {
|
|
109830
|
-
return join142(options2.homeDir ??
|
|
110127
|
+
return join142(options2.homeDir ?? homedir51(), ".config", "opencode", "opencode.json");
|
|
109831
110128
|
}
|
|
109832
110129
|
return join142(options2.cwd ?? process.cwd(), "opencode.json");
|
|
109833
110130
|
}
|
|
@@ -110834,7 +111131,7 @@ async function processMetadataDeletions(skillSourcePath, installGlobally) {
|
|
|
110834
111131
|
}
|
|
110835
111132
|
if (!sourceMetadata.deletions || sourceMetadata.deletions.length === 0)
|
|
110836
111133
|
return;
|
|
110837
|
-
const claudeDir3 = installGlobally ? join143(
|
|
111134
|
+
const claudeDir3 = installGlobally ? join143(homedir52(), ".claude") : join143(process.cwd(), ".claude");
|
|
110838
111135
|
if (!existsSync68(claudeDir3))
|
|
110839
111136
|
return;
|
|
110840
111137
|
try {
|
|
@@ -110963,7 +111260,7 @@ async function migrateCommand(options2) {
|
|
|
110963
111260
|
let installGlobally = requestedGlobal;
|
|
110964
111261
|
if (options2.global === undefined && !options2.yes) {
|
|
110965
111262
|
const projectTarget = join143(process.cwd(), ".claude");
|
|
110966
|
-
const globalTarget = join143(
|
|
111263
|
+
const globalTarget = join143(homedir52(), ".claude");
|
|
110967
111264
|
const scopeChoice = await ie({
|
|
110968
111265
|
message: "Installation scope",
|
|
110969
111266
|
options: [
|
|
@@ -111036,7 +111333,7 @@ async function migrateCommand(options2) {
|
|
|
111036
111333
|
}).join(`
|
|
111037
111334
|
`));
|
|
111038
111335
|
if (sourceGlobalOnly) {
|
|
111039
|
-
f2.info(import_picocolors30.default.dim(` Scope: global (--global / -g) - reading from ${formatDisplayPath(join143(
|
|
111336
|
+
f2.info(import_picocolors30.default.dim(` Scope: global (--global / -g) - reading from ${formatDisplayPath(join143(homedir52(), ".claude"))}`));
|
|
111040
111337
|
} else {
|
|
111041
111338
|
f2.info(import_picocolors30.default.dim(` CWD: ${process.cwd()}`));
|
|
111042
111339
|
}
|
|
@@ -113083,6 +113380,7 @@ async function handleKitSelection(ctx) {
|
|
|
113083
113380
|
dryRun: false,
|
|
113084
113381
|
forceOverwrite: false,
|
|
113085
113382
|
forceOverwriteSettings: false,
|
|
113383
|
+
restoreCkHooks: false,
|
|
113086
113384
|
skipSetup: true,
|
|
113087
113385
|
refresh: false,
|
|
113088
113386
|
sync: false,
|
|
@@ -116064,7 +116362,7 @@ async function scanForRepos(parentDir) {
|
|
|
116064
116362
|
init_logger();
|
|
116065
116363
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
116066
116364
|
import { existsSync as existsSync76 } from "node:fs";
|
|
116067
|
-
import { homedir as
|
|
116365
|
+
import { homedir as homedir53 } from "node:os";
|
|
116068
116366
|
import { join as join157 } from "node:path";
|
|
116069
116367
|
async function validateSetup(cwd2) {
|
|
116070
116368
|
const workDir = cwd2 ?? process.cwd();
|
|
@@ -116096,7 +116394,7 @@ Run this command from a directory with a GitHub remote.`);
|
|
|
116096
116394
|
} catch {
|
|
116097
116395
|
throw new Error(`Failed to parse repository info: ${ghRepo.stdout}`);
|
|
116098
116396
|
}
|
|
116099
|
-
const skillsPath = join157(
|
|
116397
|
+
const skillsPath = join157(homedir53(), ".claude", "skills");
|
|
116100
116398
|
const skillsAvailable = existsSync76(skillsPath);
|
|
116101
116399
|
if (!skillsAvailable) {
|
|
116102
116400
|
logger.warning(`ClaudeKit Engineer skills not found at ${skillsPath}`);
|
|
@@ -116437,7 +116735,7 @@ function registerCommands(cli) {
|
|
|
116437
116735
|
}
|
|
116438
116736
|
await newCommand(options2);
|
|
116439
116737
|
});
|
|
116440
|
-
cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use: engineer, marketing, all, or comma-separated").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove CK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").action(async (options2) => {
|
|
116738
|
+
cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use: engineer, marketing, all, or comma-separated").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove CK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--restore-ck-hooks", "Restore CK-managed hook registrations during update self-heal").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").action(async (options2) => {
|
|
116441
116739
|
if (options2.exclude && !Array.isArray(options2.exclude)) {
|
|
116442
116740
|
options2.exclude = [options2.exclude];
|
|
116443
116741
|
}
|