claudekit-cli 4.5.0-dev.3 → 4.5.0-dev.5
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 +2 -2
- package/dist/index.js +609 -179
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -64421,7 +64421,7 @@ var package_default;
|
|
|
64421
64421
|
var init_package = __esm(() => {
|
|
64422
64422
|
package_default = {
|
|
64423
64423
|
name: "claudekit-cli",
|
|
64424
|
-
version: "4.5.0-dev.
|
|
64424
|
+
version: "4.5.0-dev.5",
|
|
64425
64425
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
64426
64426
|
type: "module",
|
|
64427
64427
|
repository: {
|
|
@@ -65083,7 +65083,7 @@ import { spawnSync as spawnSync3 } from "node:child_process";
|
|
|
65083
65083
|
import { existsSync as existsSync46, readFileSync as readFileSync14, readdirSync as readdirSync9, statSync as statSync10, writeFileSync as writeFileSync5 } from "node:fs";
|
|
65084
65084
|
import { readdir as readdir17 } from "node:fs/promises";
|
|
65085
65085
|
import { homedir as homedir40, tmpdir } from "node:os";
|
|
65086
|
-
import { dirname as dirname29, join as join65, resolve as resolve33 } from "node:path";
|
|
65086
|
+
import { dirname as dirname29, join as join65, resolve as resolve33, sep as sep11 } from "node:path";
|
|
65087
65087
|
function resolveDoctorCkExecutable(platformName = process.platform) {
|
|
65088
65088
|
return platformName === "win32" ? "ck.cmd" : "ck";
|
|
65089
65089
|
}
|
|
@@ -66085,6 +66085,21 @@ async function countMissingHookFileReferences(projectDir = process.cwd()) {
|
|
|
66085
66085
|
}
|
|
66086
66086
|
return count;
|
|
66087
66087
|
}
|
|
66088
|
+
async function countMissingHookFileReferencesForClaudeDir(claudeDir3, projectRoot = dirname29(claudeDir3)) {
|
|
66089
|
+
const hooksDirPrefix = `${resolve33(claudeDir3, "hooks")}${sep11}`;
|
|
66090
|
+
let count = 0;
|
|
66091
|
+
for (const fileName of ["settings.json", "settings.local.json"]) {
|
|
66092
|
+
const filePath = resolve33(claudeDir3, fileName);
|
|
66093
|
+
if (!existsSync46(filePath))
|
|
66094
|
+
continue;
|
|
66095
|
+
const settings = await SettingsMerger.readSettingsFile(filePath);
|
|
66096
|
+
if (!settings)
|
|
66097
|
+
continue;
|
|
66098
|
+
const descriptor = { path: filePath, label: fileName, root: "$HOME" };
|
|
66099
|
+
count += collectMissingHookReferences(settings, descriptor, projectRoot).filter((finding) => finding.resolvedPath.startsWith(hooksDirPrefix)).length;
|
|
66100
|
+
}
|
|
66101
|
+
return count;
|
|
66102
|
+
}
|
|
66088
66103
|
async function repairMissingHookFileReferences(projectDir = process.cwd()) {
|
|
66089
66104
|
const result = await checkHookFileReferences(projectDir);
|
|
66090
66105
|
if (result.status !== "fail" || !result.fix) {
|
|
@@ -66589,6 +66604,118 @@ This is a bug. Please open an issue at https://github.com/mrgoonie/claudekit-cli
|
|
|
66589
66604
|
};
|
|
66590
66605
|
});
|
|
66591
66606
|
|
|
66607
|
+
// src/domains/installation/plugin/codex-plugin-installer.ts
|
|
66608
|
+
import { execFile as execFile8 } from "node:child_process";
|
|
66609
|
+
import { promisify as promisify9 } from "node:util";
|
|
66610
|
+
function resolveCodexExecutable(platformName = process.platform) {
|
|
66611
|
+
return platformName === "win32" ? "codex.cmd" : "codex";
|
|
66612
|
+
}
|
|
66613
|
+
function shouldRunCodexInShell(platformName = process.platform) {
|
|
66614
|
+
return platformName === "win32";
|
|
66615
|
+
}
|
|
66616
|
+
|
|
66617
|
+
class CodexPluginInstaller {
|
|
66618
|
+
run;
|
|
66619
|
+
codexHome;
|
|
66620
|
+
constructor(run = defaultCodexRunner, codexHome) {
|
|
66621
|
+
this.run = run;
|
|
66622
|
+
this.codexHome = codexHome;
|
|
66623
|
+
}
|
|
66624
|
+
opts(timeoutMs) {
|
|
66625
|
+
return { codexHome: this.codexHome, timeoutMs };
|
|
66626
|
+
}
|
|
66627
|
+
async isCodexAvailable() {
|
|
66628
|
+
return (await this.run(["--version"], this.opts(15000))).ok;
|
|
66629
|
+
}
|
|
66630
|
+
async isPluginSupported() {
|
|
66631
|
+
const r2 = await this.run(["plugin", "--help"], this.opts(15000));
|
|
66632
|
+
return r2.ok && /marketplace/i.test(r2.stdout + r2.stderr);
|
|
66633
|
+
}
|
|
66634
|
+
async marketplaceAdd(source) {
|
|
66635
|
+
return this.run(["plugin", "marketplace", "add", source], this.opts());
|
|
66636
|
+
}
|
|
66637
|
+
async add() {
|
|
66638
|
+
return this.run(["plugin", "add", `${CK_PLUGIN_NAME}@${CK_MARKETPLACE_NAME}`], this.opts());
|
|
66639
|
+
}
|
|
66640
|
+
async listJson() {
|
|
66641
|
+
return this.run(["plugin", "list", "--json"], this.opts(15000));
|
|
66642
|
+
}
|
|
66643
|
+
async verifyInstalled() {
|
|
66644
|
+
const r2 = await this.listJson();
|
|
66645
|
+
if (!r2.ok)
|
|
66646
|
+
return false;
|
|
66647
|
+
try {
|
|
66648
|
+
const parsed = JSON.parse(r2.stdout);
|
|
66649
|
+
return (parsed.installed ?? []).some((plugin) => plugin.pluginId === `${CK_PLUGIN_NAME}@${CK_MARKETPLACE_NAME}` && plugin.installed === true && plugin.enabled === true);
|
|
66650
|
+
} catch {
|
|
66651
|
+
return false;
|
|
66652
|
+
}
|
|
66653
|
+
}
|
|
66654
|
+
}
|
|
66655
|
+
async function installCodexPlugin(opts) {
|
|
66656
|
+
const installer = opts.installer ?? new CodexPluginInstaller(undefined, opts.codexHome);
|
|
66657
|
+
if (!await installer.isCodexAvailable() || !await installer.isPluginSupported()) {
|
|
66658
|
+
return { action: "skipped-codex-unsupported", pluginVerified: false };
|
|
66659
|
+
}
|
|
66660
|
+
const added = await installer.marketplaceAdd(opts.pluginSourceDir);
|
|
66661
|
+
if (!added.ok) {
|
|
66662
|
+
return {
|
|
66663
|
+
action: "install-failed",
|
|
66664
|
+
pluginVerified: false,
|
|
66665
|
+
error: `codex marketplace add failed: ${added.stderr.trim()}`
|
|
66666
|
+
};
|
|
66667
|
+
}
|
|
66668
|
+
const installed = await installer.add();
|
|
66669
|
+
if (!installed.ok) {
|
|
66670
|
+
return {
|
|
66671
|
+
action: "install-failed",
|
|
66672
|
+
pluginVerified: false,
|
|
66673
|
+
error: `codex plugin add failed: ${installed.stderr.trim()}`
|
|
66674
|
+
};
|
|
66675
|
+
}
|
|
66676
|
+
const verified = await installer.verifyInstalled();
|
|
66677
|
+
if (!verified) {
|
|
66678
|
+
return {
|
|
66679
|
+
action: "install-failed",
|
|
66680
|
+
pluginVerified: false,
|
|
66681
|
+
error: "codex plugin did not verify after install"
|
|
66682
|
+
};
|
|
66683
|
+
}
|
|
66684
|
+
return { action: "installed", pluginVerified: true };
|
|
66685
|
+
}
|
|
66686
|
+
async function shouldRefreshCodexPlugin(installer = new CodexPluginInstaller) {
|
|
66687
|
+
if (!await installer.isCodexAvailable() || !await installer.isPluginSupported()) {
|
|
66688
|
+
return false;
|
|
66689
|
+
}
|
|
66690
|
+
return !await installer.verifyInstalled();
|
|
66691
|
+
}
|
|
66692
|
+
var execFileAsync6, DEFAULT_TIMEOUT_MS2 = 120000, defaultCodexRunner = async (args, opts) => {
|
|
66693
|
+
const env2 = { ...process.env };
|
|
66694
|
+
if (opts?.codexHome)
|
|
66695
|
+
env2.CODEX_HOME = opts.codexHome;
|
|
66696
|
+
try {
|
|
66697
|
+
const { stdout, stderr } = await execFileAsync6(resolveCodexExecutable(), args, {
|
|
66698
|
+
env: env2,
|
|
66699
|
+
shell: shouldRunCodexInShell(),
|
|
66700
|
+
timeout: opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
|
|
66701
|
+
maxBuffer: 10 * 1024 * 1024
|
|
66702
|
+
});
|
|
66703
|
+
return { ok: true, stdout: String(stdout), stderr: String(stderr), code: 0 };
|
|
66704
|
+
} catch (err) {
|
|
66705
|
+
const e2 = err;
|
|
66706
|
+
return {
|
|
66707
|
+
ok: false,
|
|
66708
|
+
stdout: e2.stdout ? String(e2.stdout) : "",
|
|
66709
|
+
stderr: e2.stderr ? String(e2.stderr) : e2.message ?? "",
|
|
66710
|
+
code: typeof e2.code === "number" ? e2.code : null
|
|
66711
|
+
};
|
|
66712
|
+
}
|
|
66713
|
+
};
|
|
66714
|
+
var init_codex_plugin_installer = __esm(() => {
|
|
66715
|
+
init_install_mode_detector();
|
|
66716
|
+
execFileAsync6 = promisify9(execFile8);
|
|
66717
|
+
});
|
|
66718
|
+
|
|
66592
66719
|
// src/domains/migration/metadata-migration.ts
|
|
66593
66720
|
import { join as join66 } from "node:path";
|
|
66594
66721
|
async function detectMetadataFormat(claudeDir3) {
|
|
@@ -68358,7 +68485,7 @@ import { existsSync as existsSync48 } from "node:fs";
|
|
|
68358
68485
|
import { readdir as readdir19 } from "node:fs/promises";
|
|
68359
68486
|
import { builtinModules } from "node:module";
|
|
68360
68487
|
import { dirname as dirname30, join as join69 } from "node:path";
|
|
68361
|
-
import { promisify as
|
|
68488
|
+
import { promisify as promisify10 } from "node:util";
|
|
68362
68489
|
function selectKitForUpdate(params) {
|
|
68363
68490
|
const { hasLocal, hasGlobal, localKits, globalKits } = params;
|
|
68364
68491
|
const hasLocalKit = localKits.length > 0 || hasLocal;
|
|
@@ -68567,6 +68694,7 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
68567
68694
|
const findMissingHookDepsFn = deps?.findMissingHookDependenciesFn ?? findMissingHookDependencies;
|
|
68568
68695
|
const detectInstallModeFn = deps?.detectInstallModeFn ?? detectInstallMode;
|
|
68569
68696
|
const hasTrackedPluginSuppliedLegacyFilesFn = deps?.hasTrackedPluginSuppliedLegacyFilesFn ?? hasTrackedPluginSuppliedLegacyFiles;
|
|
68697
|
+
const shouldRefreshCodexPluginFn = deps?.shouldRefreshCodexPluginFn ?? shouldRefreshCodexPlugin;
|
|
68570
68698
|
const setup = await getSetupFn();
|
|
68571
68699
|
const hasLocal = !!setup.project.metadata;
|
|
68572
68700
|
const hasGlobal = !!setup.global.metadata;
|
|
@@ -68637,6 +68765,10 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
68637
68765
|
logger.warning(`Detected ${installMode.mode} global Engineer install; migrating to plugin format`);
|
|
68638
68766
|
forceKitReinstall = true;
|
|
68639
68767
|
}
|
|
68768
|
+
if (await shouldRefreshCodexPluginFn()) {
|
|
68769
|
+
logger.warning("Detected missing Codex ClaudeKit plugin; reinstalling global Engineer content");
|
|
68770
|
+
forceKitReinstall = true;
|
|
68771
|
+
}
|
|
68640
68772
|
}
|
|
68641
68773
|
} catch (error) {
|
|
68642
68774
|
logger.verbose(`Plugin install-mode self-heal check skipped: ${error instanceof Error ? error.message : "unknown"}`);
|
|
@@ -68927,6 +69059,7 @@ var import_fs_extra8, execAsync2, SAFE_PROVIDER_NAME, HOOK_DEPENDENCY_EXTENSIONS
|
|
|
68927
69059
|
var init_post_update_handler = __esm(() => {
|
|
68928
69060
|
init_ck_config_manager();
|
|
68929
69061
|
init_hook_health_checker();
|
|
69062
|
+
init_codex_plugin_installer();
|
|
68930
69063
|
init_install_mode_detector();
|
|
68931
69064
|
init_metadata_migration();
|
|
68932
69065
|
init_version_utils();
|
|
@@ -68937,7 +69070,7 @@ var init_post_update_handler = __esm(() => {
|
|
|
68937
69070
|
init_codex_sync_notice();
|
|
68938
69071
|
init_version_comparator();
|
|
68939
69072
|
import_fs_extra8 = __toESM(require_lib(), 1);
|
|
68940
|
-
execAsync2 =
|
|
69073
|
+
execAsync2 = promisify10(exec2);
|
|
68941
69074
|
SAFE_PROVIDER_NAME = /^[a-z0-9-]+$/;
|
|
68942
69075
|
HOOK_DEPENDENCY_EXTENSIONS = [".js", ".cjs", ".mjs", ".json"];
|
|
68943
69076
|
});
|
|
@@ -68948,8 +69081,8 @@ function getDefaultUpdateCliCommandDeps() {
|
|
|
68948
69081
|
currentVersion: package_default.version,
|
|
68949
69082
|
execAsyncFn: async (cmd, opts) => {
|
|
68950
69083
|
const { exec: exec3 } = await import("node:child_process");
|
|
68951
|
-
const { promisify:
|
|
68952
|
-
const result = await
|
|
69084
|
+
const { promisify: promisify11 } = await import("node:util");
|
|
69085
|
+
const result = await promisify11(exec3)(cmd, opts);
|
|
68953
69086
|
return { stdout: String(result.stdout ?? ""), stderr: String(result.stderr ?? "") };
|
|
68954
69087
|
},
|
|
68955
69088
|
packageManagerDetector: PackageManagerDetector,
|
|
@@ -69335,14 +69468,14 @@ var init_config_version_checker = __esm(() => {
|
|
|
69335
69468
|
|
|
69336
69469
|
// src/domains/web-server/routes/system-routes.ts
|
|
69337
69470
|
import { spawn as spawn3 } from "node:child_process";
|
|
69338
|
-
import { execFile as
|
|
69471
|
+
import { execFile as execFile9 } from "node:child_process";
|
|
69339
69472
|
import { existsSync as existsSync49 } from "node:fs";
|
|
69340
69473
|
import { readFile as readFile40 } from "node:fs/promises";
|
|
69341
69474
|
import { cpus, homedir as homedir42, totalmem } from "node:os";
|
|
69342
69475
|
import { join as join71 } from "node:path";
|
|
69343
69476
|
function runCommand(cmd, args, fallback2) {
|
|
69344
69477
|
return new Promise((resolve35) => {
|
|
69345
|
-
|
|
69478
|
+
execFile9(cmd, args, { timeout: 5000 }, (err, stdout) => {
|
|
69346
69479
|
if (err) {
|
|
69347
69480
|
resolve35(fallback2);
|
|
69348
69481
|
} else {
|
|
@@ -74607,8 +74740,8 @@ var require_picomatch2 = __commonJS((exports, module) => {
|
|
|
74607
74740
|
});
|
|
74608
74741
|
|
|
74609
74742
|
// src/services/package-installer/process-executor.ts
|
|
74610
|
-
import { exec as exec7, execFile as
|
|
74611
|
-
import { promisify as
|
|
74743
|
+
import { exec as exec7, execFile as execFile10, spawn as spawn4 } from "node:child_process";
|
|
74744
|
+
import { promisify as promisify15 } from "node:util";
|
|
74612
74745
|
function executeInteractiveScript(command, args, options2) {
|
|
74613
74746
|
return new Promise((resolve38, reject) => {
|
|
74614
74747
|
const child = spawn4(command, args, {
|
|
@@ -74645,10 +74778,10 @@ function getNpmCommand() {
|
|
|
74645
74778
|
const platform10 = process.platform;
|
|
74646
74779
|
return platform10 === "win32" ? "npm.cmd" : "npm";
|
|
74647
74780
|
}
|
|
74648
|
-
var execAsync7,
|
|
74781
|
+
var execAsync7, execFileAsync7;
|
|
74649
74782
|
var init_process_executor = __esm(() => {
|
|
74650
|
-
execAsync7 =
|
|
74651
|
-
|
|
74783
|
+
execAsync7 = promisify15(exec7);
|
|
74784
|
+
execFileAsync7 = promisify15(execFile10);
|
|
74652
74785
|
});
|
|
74653
74786
|
|
|
74654
74787
|
// src/services/package-installer/validators.ts
|
|
@@ -74879,14 +75012,14 @@ async function installOpenCode() {
|
|
|
74879
75012
|
const tempScriptPath = join90(tmpdir4(), "opencode-install.sh");
|
|
74880
75013
|
try {
|
|
74881
75014
|
logger.info("Downloading OpenCode installation script...");
|
|
74882
|
-
await
|
|
75015
|
+
await execFileAsync7("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
|
|
74883
75016
|
timeout: 30000
|
|
74884
75017
|
});
|
|
74885
|
-
await
|
|
75018
|
+
await execFileAsync7("chmod", ["+x", tempScriptPath], {
|
|
74886
75019
|
timeout: 5000
|
|
74887
75020
|
});
|
|
74888
75021
|
logger.info("Executing OpenCode installation script...");
|
|
74889
|
-
await
|
|
75022
|
+
await execFileAsync7("bash", [tempScriptPath], {
|
|
74890
75023
|
timeout: 120000
|
|
74891
75024
|
});
|
|
74892
75025
|
} finally {
|
|
@@ -75077,8 +75210,8 @@ async function checkNeedsSudoPackages() {
|
|
|
75077
75210
|
return false;
|
|
75078
75211
|
}
|
|
75079
75212
|
const { exec: exec8 } = await import("node:child_process");
|
|
75080
|
-
const { promisify:
|
|
75081
|
-
const execAsync8 =
|
|
75213
|
+
const { promisify: promisify16 } = await import("node:util");
|
|
75214
|
+
const execAsync8 = promisify16(exec8);
|
|
75082
75215
|
try {
|
|
75083
75216
|
await Promise.all([
|
|
75084
75217
|
execAsync8("which ffmpeg", { timeout: WHICH_COMMAND_TIMEOUT_MS }),
|
|
@@ -75649,7 +75782,7 @@ __export(exports_package_installer, {
|
|
|
75649
75782
|
getPackageVersion: () => getPackageVersion,
|
|
75650
75783
|
getNpmCommand: () => getNpmCommand,
|
|
75651
75784
|
executeInteractiveScript: () => executeInteractiveScript,
|
|
75652
|
-
execFileAsync: () =>
|
|
75785
|
+
execFileAsync: () => execFileAsync7,
|
|
75653
75786
|
execAsync: () => execAsync7,
|
|
75654
75787
|
PARTIAL_INSTALL_VERSION: () => PARTIAL_INSTALL_VERSION,
|
|
75655
75788
|
EXIT_CODE_PARTIAL_SUCCESS: () => EXIT_CODE_PARTIAL_SUCCESS,
|
|
@@ -77576,11 +77709,11 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
77576
77709
|
var { createWriteStream: createWriteStream3, promises: fs19 } = __require("fs");
|
|
77577
77710
|
var getStream = require_get_stream();
|
|
77578
77711
|
var path15 = __require("path");
|
|
77579
|
-
var { promisify:
|
|
77712
|
+
var { promisify: promisify16 } = __require("util");
|
|
77580
77713
|
var stream = __require("stream");
|
|
77581
77714
|
var yauzl = require_yauzl();
|
|
77582
|
-
var openZip =
|
|
77583
|
-
var pipeline =
|
|
77715
|
+
var openZip = promisify16(yauzl.open);
|
|
77716
|
+
var pipeline = promisify16(stream.pipeline);
|
|
77584
77717
|
|
|
77585
77718
|
class Extractor {
|
|
77586
77719
|
constructor(zipPath, opts) {
|
|
@@ -77665,7 +77798,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
77665
77798
|
if (isDir2)
|
|
77666
77799
|
return;
|
|
77667
77800
|
debug("opening read stream", dest);
|
|
77668
|
-
const readStream = await
|
|
77801
|
+
const readStream = await promisify16(this.zipfile.openReadStream.bind(this.zipfile))(entry);
|
|
77669
77802
|
if (symlink4) {
|
|
77670
77803
|
const link = await getStream(readStream);
|
|
77671
77804
|
debug("creating symlink", link, dest);
|
|
@@ -77950,10 +78083,10 @@ __export(exports_worktree_manager, {
|
|
|
77950
78083
|
cleanupAllWorktrees: () => cleanupAllWorktrees
|
|
77951
78084
|
});
|
|
77952
78085
|
import { existsSync as existsSync77 } from "node:fs";
|
|
77953
|
-
import { readFile as
|
|
77954
|
-
import { join as
|
|
78086
|
+
import { readFile as readFile70, writeFile as writeFile41 } from "node:fs/promises";
|
|
78087
|
+
import { join as join159 } from "node:path";
|
|
77955
78088
|
async function createWorktree(projectDir, issueNumber, baseBranch) {
|
|
77956
|
-
const worktreePath =
|
|
78089
|
+
const worktreePath = join159(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
|
|
77957
78090
|
const branchName = `ck-watch/issue-${issueNumber}`;
|
|
77958
78091
|
await spawnAndCollect("git", ["fetch", "origin", baseBranch], projectDir).catch(() => {
|
|
77959
78092
|
logger.warning(`[worktree] Could not fetch origin/${baseBranch}, using local`);
|
|
@@ -77971,7 +78104,7 @@ async function createWorktree(projectDir, issueNumber, baseBranch) {
|
|
|
77971
78104
|
return worktreePath;
|
|
77972
78105
|
}
|
|
77973
78106
|
async function removeWorktree(projectDir, issueNumber) {
|
|
77974
|
-
const worktreePath =
|
|
78107
|
+
const worktreePath = join159(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
|
|
77975
78108
|
const branchName = `ck-watch/issue-${issueNumber}`;
|
|
77976
78109
|
try {
|
|
77977
78110
|
await spawnAndCollect("git", ["worktree", "remove", worktreePath, "--force"], projectDir);
|
|
@@ -77985,7 +78118,7 @@ async function listActiveWorktrees(projectDir) {
|
|
|
77985
78118
|
try {
|
|
77986
78119
|
const output2 = await spawnAndCollect("git", ["worktree", "list", "--porcelain"], projectDir);
|
|
77987
78120
|
const issueNumbers = [];
|
|
77988
|
-
const worktreePrefix =
|
|
78121
|
+
const worktreePrefix = join159(projectDir, WORKTREE_DIR, "issue-").replace(/\\/g, "/");
|
|
77989
78122
|
for (const line of output2.split(`
|
|
77990
78123
|
`)) {
|
|
77991
78124
|
if (line.startsWith("worktree ")) {
|
|
@@ -78013,16 +78146,16 @@ async function cleanupAllWorktrees(projectDir) {
|
|
|
78013
78146
|
await spawnAndCollect("git", ["worktree", "prune"], projectDir).catch(() => {});
|
|
78014
78147
|
}
|
|
78015
78148
|
async function ensureGitignore(projectDir) {
|
|
78016
|
-
const gitignorePath =
|
|
78149
|
+
const gitignorePath = join159(projectDir, ".gitignore");
|
|
78017
78150
|
try {
|
|
78018
|
-
const content = existsSync77(gitignorePath) ? await
|
|
78151
|
+
const content = existsSync77(gitignorePath) ? await readFile70(gitignorePath, "utf-8") : "";
|
|
78019
78152
|
if (!content.includes(".worktrees")) {
|
|
78020
78153
|
const newContent = content.endsWith(`
|
|
78021
78154
|
`) ? `${content}.worktrees/
|
|
78022
78155
|
` : `${content}
|
|
78023
78156
|
.worktrees/
|
|
78024
78157
|
`;
|
|
78025
|
-
await
|
|
78158
|
+
await writeFile41(gitignorePath, newContent, "utf-8");
|
|
78026
78159
|
logger.info("[worktree] Added .worktrees/ to .gitignore");
|
|
78027
78160
|
}
|
|
78028
78161
|
} catch (err) {
|
|
@@ -78117,16 +78250,16 @@ var init_content_validator = __esm(() => {
|
|
|
78117
78250
|
|
|
78118
78251
|
// src/commands/content/phases/context-cache-manager.ts
|
|
78119
78252
|
import { createHash as createHash9 } from "node:crypto";
|
|
78120
|
-
import { existsSync as existsSync83, mkdirSync as mkdirSync7, readFileSync as
|
|
78121
|
-
import { rename as rename16, writeFile as
|
|
78253
|
+
import { existsSync as existsSync83, mkdirSync as mkdirSync7, readFileSync as readFileSync22, readdirSync as readdirSync14, statSync as statSync15 } from "node:fs";
|
|
78254
|
+
import { rename as rename16, writeFile as writeFile43 } from "node:fs/promises";
|
|
78122
78255
|
import { homedir as homedir54 } from "node:os";
|
|
78123
|
-
import { basename as basename34, join as
|
|
78256
|
+
import { basename as basename34, join as join166 } from "node:path";
|
|
78124
78257
|
function getCachedContext(repoPath) {
|
|
78125
78258
|
const cachePath = getCacheFilePath(repoPath);
|
|
78126
78259
|
if (!existsSync83(cachePath))
|
|
78127
78260
|
return null;
|
|
78128
78261
|
try {
|
|
78129
|
-
const raw2 =
|
|
78262
|
+
const raw2 = readFileSync22(cachePath, "utf-8");
|
|
78130
78263
|
const cache5 = JSON.parse(raw2);
|
|
78131
78264
|
const age = Date.now() - new Date(cache5.createdAt).getTime();
|
|
78132
78265
|
if (age >= CACHE_TTL_MS5)
|
|
@@ -78145,7 +78278,7 @@ async function saveCachedContext(repoPath, cache5) {
|
|
|
78145
78278
|
}
|
|
78146
78279
|
const cachePath = getCacheFilePath(repoPath);
|
|
78147
78280
|
const tmpPath = `${cachePath}.tmp`;
|
|
78148
|
-
await
|
|
78281
|
+
await writeFile43(tmpPath, JSON.stringify(cache5, null, 2), "utf-8");
|
|
78149
78282
|
await rename16(tmpPath, cachePath);
|
|
78150
78283
|
}
|
|
78151
78284
|
function computeSourceHash(repoPath) {
|
|
@@ -78163,25 +78296,25 @@ function computeSourceHash(repoPath) {
|
|
|
78163
78296
|
}
|
|
78164
78297
|
function getDocSourcePaths(repoPath) {
|
|
78165
78298
|
const paths = [];
|
|
78166
|
-
const docsDir =
|
|
78299
|
+
const docsDir = join166(repoPath, "docs");
|
|
78167
78300
|
if (existsSync83(docsDir)) {
|
|
78168
78301
|
try {
|
|
78169
78302
|
const files = readdirSync14(docsDir);
|
|
78170
78303
|
for (const f3 of files) {
|
|
78171
78304
|
if (f3.endsWith(".md"))
|
|
78172
|
-
paths.push(
|
|
78305
|
+
paths.push(join166(docsDir, f3));
|
|
78173
78306
|
}
|
|
78174
78307
|
} catch {}
|
|
78175
78308
|
}
|
|
78176
|
-
const readme =
|
|
78309
|
+
const readme = join166(repoPath, "README.md");
|
|
78177
78310
|
if (existsSync83(readme))
|
|
78178
78311
|
paths.push(readme);
|
|
78179
|
-
const stylesDir =
|
|
78312
|
+
const stylesDir = join166(repoPath, "assets", "writing-styles");
|
|
78180
78313
|
if (existsSync83(stylesDir)) {
|
|
78181
78314
|
try {
|
|
78182
78315
|
const files = readdirSync14(stylesDir);
|
|
78183
78316
|
for (const f3 of files) {
|
|
78184
|
-
paths.push(
|
|
78317
|
+
paths.push(join166(stylesDir, f3));
|
|
78185
78318
|
}
|
|
78186
78319
|
} catch {}
|
|
78187
78320
|
}
|
|
@@ -78190,11 +78323,11 @@ function getDocSourcePaths(repoPath) {
|
|
|
78190
78323
|
function getCacheFilePath(repoPath) {
|
|
78191
78324
|
const repoName = basename34(repoPath).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
78192
78325
|
const pathHash = createHash9("sha256").update(repoPath).digest("hex").slice(0, 8);
|
|
78193
|
-
return
|
|
78326
|
+
return join166(CACHE_DIR, `${repoName}-${pathHash}-context-cache.json`);
|
|
78194
78327
|
}
|
|
78195
78328
|
var CACHE_DIR, CACHE_TTL_MS5;
|
|
78196
78329
|
var init_context_cache_manager = __esm(() => {
|
|
78197
|
-
CACHE_DIR =
|
|
78330
|
+
CACHE_DIR = join166(homedir54(), ".claudekit", "cache");
|
|
78198
78331
|
CACHE_TTL_MS5 = 24 * 60 * 60 * 1000;
|
|
78199
78332
|
});
|
|
78200
78333
|
|
|
@@ -78374,8 +78507,8 @@ function extractContentFromResponse(response) {
|
|
|
78374
78507
|
|
|
78375
78508
|
// src/commands/content/phases/docs-summarizer.ts
|
|
78376
78509
|
import { execSync as execSync7 } from "node:child_process";
|
|
78377
|
-
import { existsSync as existsSync84, readFileSync as
|
|
78378
|
-
import { join as
|
|
78510
|
+
import { existsSync as existsSync84, readFileSync as readFileSync23, readdirSync as readdirSync15 } from "node:fs";
|
|
78511
|
+
import { join as join167 } from "node:path";
|
|
78379
78512
|
async function summarizeProjectDocs(repoPath, contentLogger) {
|
|
78380
78513
|
const rawContent = collectRawDocs(repoPath);
|
|
78381
78514
|
if (rawContent.total.length < 200) {
|
|
@@ -78423,18 +78556,18 @@ function collectRawDocs(repoPath) {
|
|
|
78423
78556
|
return "";
|
|
78424
78557
|
if (totalChars >= MAX_RAW_CONTENT_CHARS)
|
|
78425
78558
|
return "";
|
|
78426
|
-
const content =
|
|
78559
|
+
const content = readFileSync23(filePath, "utf-8");
|
|
78427
78560
|
const capped = content.slice(0, Math.min(maxChars, MAX_RAW_CONTENT_CHARS - totalChars));
|
|
78428
78561
|
totalChars += capped.length;
|
|
78429
78562
|
return capped;
|
|
78430
78563
|
};
|
|
78431
78564
|
const docsContent = [];
|
|
78432
|
-
const docsDir =
|
|
78565
|
+
const docsDir = join167(repoPath, "docs");
|
|
78433
78566
|
if (existsSync84(docsDir)) {
|
|
78434
78567
|
try {
|
|
78435
78568
|
const files = readdirSync15(docsDir).filter((f3) => f3.endsWith(".md")).sort();
|
|
78436
78569
|
for (const f3 of files) {
|
|
78437
|
-
const content = readCapped(
|
|
78570
|
+
const content = readCapped(join167(docsDir, f3), 5000);
|
|
78438
78571
|
if (content) {
|
|
78439
78572
|
docsContent.push(`### ${f3}
|
|
78440
78573
|
${content}`);
|
|
@@ -78448,21 +78581,21 @@ ${content}`);
|
|
|
78448
78581
|
let brand = "";
|
|
78449
78582
|
const brandCandidates = ["docs/brand-guidelines.md", "docs/design-guidelines.md"];
|
|
78450
78583
|
for (const p of brandCandidates) {
|
|
78451
|
-
brand = readCapped(
|
|
78584
|
+
brand = readCapped(join167(repoPath, p), 3000);
|
|
78452
78585
|
if (brand)
|
|
78453
78586
|
break;
|
|
78454
78587
|
}
|
|
78455
78588
|
let styles3 = "";
|
|
78456
|
-
const stylesDir =
|
|
78589
|
+
const stylesDir = join167(repoPath, "assets", "writing-styles");
|
|
78457
78590
|
if (existsSync84(stylesDir)) {
|
|
78458
78591
|
try {
|
|
78459
78592
|
const files = readdirSync15(stylesDir).slice(0, 3);
|
|
78460
|
-
styles3 = files.map((f3) => readCapped(
|
|
78593
|
+
styles3 = files.map((f3) => readCapped(join167(stylesDir, f3), 1000)).filter(Boolean).join(`
|
|
78461
78594
|
|
|
78462
78595
|
`);
|
|
78463
78596
|
} catch {}
|
|
78464
78597
|
}
|
|
78465
|
-
const readme = readCapped(
|
|
78598
|
+
const readme = readCapped(join167(repoPath, "README.md"), 3000);
|
|
78466
78599
|
const total = [docs, brand, styles3, readme].join(`
|
|
78467
78600
|
`);
|
|
78468
78601
|
return { docs, brand, styles: styles3, readme, total };
|
|
@@ -78649,9 +78782,9 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
|
|
|
78649
78782
|
import { execSync as execSync8 } from "node:child_process";
|
|
78650
78783
|
import { existsSync as existsSync85, mkdirSync as mkdirSync8, readdirSync as readdirSync16 } from "node:fs";
|
|
78651
78784
|
import { homedir as homedir55 } from "node:os";
|
|
78652
|
-
import { join as
|
|
78785
|
+
import { join as join168 } from "node:path";
|
|
78653
78786
|
async function generatePhoto(_content, context, config, platform18, contentId, contentLogger) {
|
|
78654
|
-
const mediaDir =
|
|
78787
|
+
const mediaDir = join168(config.contentDir.replace(/^~/, homedir55()), "media", String(contentId));
|
|
78655
78788
|
if (!existsSync85(mediaDir)) {
|
|
78656
78789
|
mkdirSync8(mediaDir, { recursive: true });
|
|
78657
78790
|
}
|
|
@@ -78676,7 +78809,7 @@ async function generatePhoto(_content, context, config, platform18, contentId, c
|
|
|
78676
78809
|
const imageFile = files.find((f3) => /\.(png|jpg|jpeg|webp)$/i.test(f3));
|
|
78677
78810
|
if (imageFile) {
|
|
78678
78811
|
const ext2 = imageFile.split(".").pop() ?? "png";
|
|
78679
|
-
return { path:
|
|
78812
|
+
return { path: join168(mediaDir, imageFile), ...dimensions, format: ext2 };
|
|
78680
78813
|
}
|
|
78681
78814
|
contentLogger.warn(`Photo generation produced no image for content ${contentId}`);
|
|
78682
78815
|
return null;
|
|
@@ -78766,7 +78899,7 @@ var init_content_creator = __esm(() => {
|
|
|
78766
78899
|
// src/commands/content/phases/content-logger.ts
|
|
78767
78900
|
import { createWriteStream as createWriteStream4, existsSync as existsSync86, mkdirSync as mkdirSync9, statSync as statSync16 } from "node:fs";
|
|
78768
78901
|
import { homedir as homedir56 } from "node:os";
|
|
78769
|
-
import { join as
|
|
78902
|
+
import { join as join169 } from "node:path";
|
|
78770
78903
|
|
|
78771
78904
|
class ContentLogger {
|
|
78772
78905
|
stream = null;
|
|
@@ -78774,7 +78907,7 @@ class ContentLogger {
|
|
|
78774
78907
|
logDir;
|
|
78775
78908
|
maxBytes;
|
|
78776
78909
|
constructor(maxBytes = 0) {
|
|
78777
|
-
this.logDir =
|
|
78910
|
+
this.logDir = join169(homedir56(), ".claudekit", "logs");
|
|
78778
78911
|
this.maxBytes = maxBytes;
|
|
78779
78912
|
}
|
|
78780
78913
|
init() {
|
|
@@ -78806,7 +78939,7 @@ class ContentLogger {
|
|
|
78806
78939
|
}
|
|
78807
78940
|
}
|
|
78808
78941
|
getLogPath() {
|
|
78809
|
-
return
|
|
78942
|
+
return join169(this.logDir, `content-${this.getDateStr()}.log`);
|
|
78810
78943
|
}
|
|
78811
78944
|
write(level, message) {
|
|
78812
78945
|
this.rotateIfNeeded();
|
|
@@ -78823,18 +78956,18 @@ class ContentLogger {
|
|
|
78823
78956
|
if (dateStr !== this.currentDate) {
|
|
78824
78957
|
this.close();
|
|
78825
78958
|
this.currentDate = dateStr;
|
|
78826
|
-
const logPath =
|
|
78959
|
+
const logPath = join169(this.logDir, `content-${dateStr}.log`);
|
|
78827
78960
|
this.stream = createWriteStream4(logPath, { flags: "a", mode: 384 });
|
|
78828
78961
|
return;
|
|
78829
78962
|
}
|
|
78830
78963
|
if (this.maxBytes > 0 && this.stream) {
|
|
78831
|
-
const logPath =
|
|
78964
|
+
const logPath = join169(this.logDir, `content-${this.currentDate}.log`);
|
|
78832
78965
|
try {
|
|
78833
78966
|
const stat26 = statSync16(logPath);
|
|
78834
78967
|
if (stat26.size >= this.maxBytes) {
|
|
78835
78968
|
this.close();
|
|
78836
78969
|
const suffix = Date.now();
|
|
78837
|
-
const rotatedPath =
|
|
78970
|
+
const rotatedPath = join169(this.logDir, `content-${this.currentDate}-${suffix}.log`);
|
|
78838
78971
|
import("node:fs/promises").then(({ rename: rename17 }) => rename17(logPath, rotatedPath).catch(() => {}));
|
|
78839
78972
|
this.stream = createWriteStream4(logPath, { flags: "w", mode: 384 });
|
|
78840
78973
|
}
|
|
@@ -79104,8 +79237,8 @@ function isNoiseCommit(title, author) {
|
|
|
79104
79237
|
|
|
79105
79238
|
// src/commands/content/phases/change-detector.ts
|
|
79106
79239
|
import { execSync as execSync10, spawnSync as spawnSync9 } from "node:child_process";
|
|
79107
|
-
import { existsSync as existsSync88, readFileSync as
|
|
79108
|
-
import { join as
|
|
79240
|
+
import { existsSync as existsSync88, readFileSync as readFileSync24, readdirSync as readdirSync17, statSync as statSync17 } from "node:fs";
|
|
79241
|
+
import { join as join170 } from "node:path";
|
|
79109
79242
|
function detectCommits(repo, since) {
|
|
79110
79243
|
try {
|
|
79111
79244
|
const fetchUrl = sshToHttps(repo.remoteUrl);
|
|
@@ -79214,7 +79347,7 @@ function detectTags(repo, since) {
|
|
|
79214
79347
|
}
|
|
79215
79348
|
}
|
|
79216
79349
|
function detectCompletedPlans(repo, since) {
|
|
79217
|
-
const plansDir =
|
|
79350
|
+
const plansDir = join170(repo.path, "plans");
|
|
79218
79351
|
if (!existsSync88(plansDir))
|
|
79219
79352
|
return [];
|
|
79220
79353
|
const sinceMs = new Date(since).getTime();
|
|
@@ -79224,14 +79357,14 @@ function detectCompletedPlans(repo, since) {
|
|
|
79224
79357
|
for (const entry of entries) {
|
|
79225
79358
|
if (!entry.isDirectory())
|
|
79226
79359
|
continue;
|
|
79227
|
-
const planFile =
|
|
79360
|
+
const planFile = join170(plansDir, entry.name, "plan.md");
|
|
79228
79361
|
if (!existsSync88(planFile))
|
|
79229
79362
|
continue;
|
|
79230
79363
|
try {
|
|
79231
79364
|
const stat26 = statSync17(planFile);
|
|
79232
79365
|
if (stat26.mtimeMs < sinceMs)
|
|
79233
79366
|
continue;
|
|
79234
|
-
const content =
|
|
79367
|
+
const content = readFileSync24(planFile, "utf-8");
|
|
79235
79368
|
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
79236
79369
|
if (!frontmatterMatch)
|
|
79237
79370
|
continue;
|
|
@@ -79302,7 +79435,7 @@ function classifyCommit(event) {
|
|
|
79302
79435
|
// src/commands/content/phases/repo-discoverer.ts
|
|
79303
79436
|
import { execSync as execSync11 } from "node:child_process";
|
|
79304
79437
|
import { readdirSync as readdirSync18 } from "node:fs";
|
|
79305
|
-
import { join as
|
|
79438
|
+
import { join as join171 } from "node:path";
|
|
79306
79439
|
function discoverRepos2(cwd2) {
|
|
79307
79440
|
const repos = [];
|
|
79308
79441
|
if (isGitRepoRoot(cwd2)) {
|
|
@@ -79315,7 +79448,7 @@ function discoverRepos2(cwd2) {
|
|
|
79315
79448
|
for (const entry of entries) {
|
|
79316
79449
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
79317
79450
|
continue;
|
|
79318
|
-
const dirPath =
|
|
79451
|
+
const dirPath = join171(cwd2, entry.name);
|
|
79319
79452
|
if (isGitRepoRoot(dirPath)) {
|
|
79320
79453
|
const info = getRepoInfo(dirPath);
|
|
79321
79454
|
if (info)
|
|
@@ -79982,12 +80115,12 @@ var init_types6 = __esm(() => {
|
|
|
79982
80115
|
});
|
|
79983
80116
|
|
|
79984
80117
|
// src/commands/content/phases/state-manager.ts
|
|
79985
|
-
import { readFile as
|
|
79986
|
-
import { join as
|
|
80118
|
+
import { readFile as readFile72, rename as rename17, writeFile as writeFile44 } from "node:fs/promises";
|
|
80119
|
+
import { join as join172 } from "node:path";
|
|
79987
80120
|
async function loadContentConfig(projectDir) {
|
|
79988
|
-
const configPath =
|
|
80121
|
+
const configPath = join172(projectDir, CK_CONFIG_FILE2);
|
|
79989
80122
|
try {
|
|
79990
|
-
const raw2 = await
|
|
80123
|
+
const raw2 = await readFile72(configPath, "utf-8");
|
|
79991
80124
|
const json = JSON.parse(raw2);
|
|
79992
80125
|
return ContentConfigSchema.parse(json.content ?? {});
|
|
79993
80126
|
} catch {
|
|
@@ -79995,15 +80128,15 @@ async function loadContentConfig(projectDir) {
|
|
|
79995
80128
|
}
|
|
79996
80129
|
}
|
|
79997
80130
|
async function saveContentConfig(projectDir, config) {
|
|
79998
|
-
const configPath =
|
|
79999
|
-
const json = await
|
|
80131
|
+
const configPath = join172(projectDir, CK_CONFIG_FILE2);
|
|
80132
|
+
const json = await readJsonSafe4(configPath);
|
|
80000
80133
|
json.content = { ...json.content, ...config };
|
|
80001
80134
|
await atomicWrite3(configPath, json);
|
|
80002
80135
|
}
|
|
80003
80136
|
async function loadContentState(projectDir) {
|
|
80004
|
-
const configPath =
|
|
80137
|
+
const configPath = join172(projectDir, CK_CONFIG_FILE2);
|
|
80005
80138
|
try {
|
|
80006
|
-
const raw2 = await
|
|
80139
|
+
const raw2 = await readFile72(configPath, "utf-8");
|
|
80007
80140
|
const json = JSON.parse(raw2);
|
|
80008
80141
|
const contentBlock = json.content ?? {};
|
|
80009
80142
|
return ContentStateSchema.parse(contentBlock.state ?? {});
|
|
@@ -80012,7 +80145,7 @@ async function loadContentState(projectDir) {
|
|
|
80012
80145
|
}
|
|
80013
80146
|
}
|
|
80014
80147
|
async function saveContentState(projectDir, state) {
|
|
80015
|
-
const configPath =
|
|
80148
|
+
const configPath = join172(projectDir, CK_CONFIG_FILE2);
|
|
80016
80149
|
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
|
|
80017
80150
|
for (const key of Object.keys(state.dailyPostCounts)) {
|
|
80018
80151
|
const dateStr = key.slice(-10);
|
|
@@ -80021,16 +80154,16 @@ async function saveContentState(projectDir, state) {
|
|
|
80021
80154
|
}
|
|
80022
80155
|
}
|
|
80023
80156
|
ContentStateSchema.parse(state);
|
|
80024
|
-
const json = await
|
|
80157
|
+
const json = await readJsonSafe4(configPath);
|
|
80025
80158
|
if (!json.content || typeof json.content !== "object") {
|
|
80026
80159
|
json.content = {};
|
|
80027
80160
|
}
|
|
80028
80161
|
json.content.state = state;
|
|
80029
80162
|
await atomicWrite3(configPath, json);
|
|
80030
80163
|
}
|
|
80031
|
-
async function
|
|
80164
|
+
async function readJsonSafe4(filePath) {
|
|
80032
80165
|
try {
|
|
80033
|
-
const raw2 = await
|
|
80166
|
+
const raw2 = await readFile72(filePath, "utf-8");
|
|
80034
80167
|
return JSON.parse(raw2);
|
|
80035
80168
|
} catch {
|
|
80036
80169
|
return {};
|
|
@@ -80038,7 +80171,7 @@ async function readJsonSafe3(filePath) {
|
|
|
80038
80171
|
}
|
|
80039
80172
|
async function atomicWrite3(filePath, data) {
|
|
80040
80173
|
const tmpPath = `${filePath}.tmp`;
|
|
80041
|
-
await
|
|
80174
|
+
await writeFile44(tmpPath, JSON.stringify(data, null, 2), "utf-8");
|
|
80042
80175
|
await rename17(tmpPath, filePath);
|
|
80043
80176
|
}
|
|
80044
80177
|
var CK_CONFIG_FILE2 = ".ck.json";
|
|
@@ -80294,7 +80427,7 @@ var init_platform_setup_x = __esm(() => {
|
|
|
80294
80427
|
|
|
80295
80428
|
// src/commands/content/phases/setup-wizard.ts
|
|
80296
80429
|
import { existsSync as existsSync89 } from "node:fs";
|
|
80297
|
-
import { join as
|
|
80430
|
+
import { join as join173 } from "node:path";
|
|
80298
80431
|
async function runSetupWizard2(cwd2, contentLogger) {
|
|
80299
80432
|
console.log();
|
|
80300
80433
|
oe(import_picocolors43.default.bgCyan(import_picocolors43.default.white(" CK Content — Multi-Channel Content Engine ")));
|
|
@@ -80362,8 +80495,8 @@ async function showRepoSummary(cwd2) {
|
|
|
80362
80495
|
function detectBrandAssets(cwd2, contentLogger) {
|
|
80363
80496
|
const repos = discoverRepos2(cwd2);
|
|
80364
80497
|
for (const repo of repos) {
|
|
80365
|
-
const hasGuidelines = existsSync89(
|
|
80366
|
-
const hasStyles = existsSync89(
|
|
80498
|
+
const hasGuidelines = existsSync89(join173(repo.path, "docs", "brand-guidelines.md"));
|
|
80499
|
+
const hasStyles = existsSync89(join173(repo.path, "assets", "writing-styles"));
|
|
80367
80500
|
if (!hasGuidelines) {
|
|
80368
80501
|
f2.warning(`${repo.name}: No docs/brand-guidelines.md — content will use generic tone.`);
|
|
80369
80502
|
contentLogger.warn(`${repo.name}: missing docs/brand-guidelines.md`);
|
|
@@ -80503,15 +80636,15 @@ __export(exports_content_subcommands, {
|
|
|
80503
80636
|
logsContent: () => logsContent,
|
|
80504
80637
|
approveContentCmd: () => approveContentCmd
|
|
80505
80638
|
});
|
|
80506
|
-
import { existsSync as existsSync91, readFileSync as
|
|
80639
|
+
import { existsSync as existsSync91, readFileSync as readFileSync25, unlinkSync as unlinkSync6 } from "node:fs";
|
|
80507
80640
|
import { homedir as homedir58 } from "node:os";
|
|
80508
|
-
import { join as
|
|
80641
|
+
import { join as join174 } from "node:path";
|
|
80509
80642
|
function isDaemonRunning() {
|
|
80510
|
-
const lockFile =
|
|
80643
|
+
const lockFile = join174(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
80511
80644
|
if (!existsSync91(lockFile))
|
|
80512
80645
|
return { running: false, pid: null };
|
|
80513
80646
|
try {
|
|
80514
|
-
const pidStr =
|
|
80647
|
+
const pidStr = readFileSync25(lockFile, "utf-8").trim();
|
|
80515
80648
|
const pid = Number.parseInt(pidStr, 10);
|
|
80516
80649
|
if (Number.isNaN(pid)) {
|
|
80517
80650
|
unlinkSync6(lockFile);
|
|
@@ -80539,13 +80672,13 @@ async function startContent(options2) {
|
|
|
80539
80672
|
await contentCommand(options2);
|
|
80540
80673
|
}
|
|
80541
80674
|
async function stopContent() {
|
|
80542
|
-
const lockFile =
|
|
80675
|
+
const lockFile = join174(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
80543
80676
|
if (!existsSync91(lockFile)) {
|
|
80544
80677
|
logger.info("Content daemon is not running.");
|
|
80545
80678
|
return;
|
|
80546
80679
|
}
|
|
80547
80680
|
try {
|
|
80548
|
-
const pidStr =
|
|
80681
|
+
const pidStr = readFileSync25(lockFile, "utf-8").trim();
|
|
80549
80682
|
const pid = Number.parseInt(pidStr, 10);
|
|
80550
80683
|
if (!Number.isNaN(pid)) {
|
|
80551
80684
|
process.kill(pid, "SIGTERM");
|
|
@@ -80578,9 +80711,9 @@ async function statusContent() {
|
|
|
80578
80711
|
} catch {}
|
|
80579
80712
|
}
|
|
80580
80713
|
async function logsContent(options2) {
|
|
80581
|
-
const logDir =
|
|
80714
|
+
const logDir = join174(homedir58(), ".claudekit", "logs");
|
|
80582
80715
|
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
80583
|
-
const logPath =
|
|
80716
|
+
const logPath = join174(logDir, `content-${dateStr}.log`);
|
|
80584
80717
|
if (!existsSync91(logPath)) {
|
|
80585
80718
|
logger.info("No content logs found for today.");
|
|
80586
80719
|
return;
|
|
@@ -80593,7 +80726,7 @@ async function logsContent(options2) {
|
|
|
80593
80726
|
process.exit(0);
|
|
80594
80727
|
});
|
|
80595
80728
|
} else {
|
|
80596
|
-
const content =
|
|
80729
|
+
const content = readFileSync25(logPath, "utf-8");
|
|
80597
80730
|
console.log(content);
|
|
80598
80731
|
}
|
|
80599
80732
|
}
|
|
@@ -80612,13 +80745,13 @@ var init_content_subcommands = __esm(() => {
|
|
|
80612
80745
|
init_setup_wizard();
|
|
80613
80746
|
init_state_manager();
|
|
80614
80747
|
init_content_review_commands();
|
|
80615
|
-
LOCK_DIR =
|
|
80748
|
+
LOCK_DIR = join174(homedir58(), ".claudekit", "locks");
|
|
80616
80749
|
});
|
|
80617
80750
|
|
|
80618
80751
|
// src/commands/content/content-command.ts
|
|
80619
80752
|
import { existsSync as existsSync92, mkdirSync as mkdirSync11, unlinkSync as unlinkSync7, writeFileSync as writeFileSync9 } from "node:fs";
|
|
80620
80753
|
import { homedir as homedir59 } from "node:os";
|
|
80621
|
-
import { join as
|
|
80754
|
+
import { join as join175 } from "node:path";
|
|
80622
80755
|
async function contentCommand(options2) {
|
|
80623
80756
|
const cwd2 = process.cwd();
|
|
80624
80757
|
const contentLogger = new ContentLogger;
|
|
@@ -80796,8 +80929,8 @@ var init_content_command = __esm(() => {
|
|
|
80796
80929
|
init_publisher();
|
|
80797
80930
|
init_review_manager();
|
|
80798
80931
|
init_state_manager();
|
|
80799
|
-
LOCK_DIR2 =
|
|
80800
|
-
LOCK_FILE =
|
|
80932
|
+
LOCK_DIR2 = join175(homedir59(), ".claudekit", "locks");
|
|
80933
|
+
LOCK_FILE = join175(LOCK_DIR2, "ck-content.lock");
|
|
80801
80934
|
});
|
|
80802
80935
|
|
|
80803
80936
|
// src/commands/content/index.ts
|
|
@@ -87963,7 +88096,7 @@ class CheckRunner {
|
|
|
87963
88096
|
}
|
|
87964
88097
|
// src/domains/health-checks/system-checker.ts
|
|
87965
88098
|
import { exec as exec6 } from "node:child_process";
|
|
87966
|
-
import { promisify as
|
|
88099
|
+
import { promisify as promisify14 } from "node:util";
|
|
87967
88100
|
|
|
87968
88101
|
// src/domains/github/gh-cli-utils.ts
|
|
87969
88102
|
init_environment();
|
|
@@ -88031,8 +88164,8 @@ function getGhUpgradeInstructions(currentVersion) {
|
|
|
88031
88164
|
init_environment();
|
|
88032
88165
|
init_logger();
|
|
88033
88166
|
import { exec as exec3 } from "node:child_process";
|
|
88034
|
-
import { promisify as
|
|
88035
|
-
var execAsync3 =
|
|
88167
|
+
import { promisify as promisify11 } from "node:util";
|
|
88168
|
+
var execAsync3 = promisify11(exec3);
|
|
88036
88169
|
function getOSInfo() {
|
|
88037
88170
|
const platform8 = process.platform;
|
|
88038
88171
|
const arch2 = process.arch;
|
|
@@ -88253,7 +88386,7 @@ async function checkAllDependencies() {
|
|
|
88253
88386
|
// src/services/package-installer/dependency-installer.ts
|
|
88254
88387
|
init_logger();
|
|
88255
88388
|
import { exec as exec5 } from "node:child_process";
|
|
88256
|
-
import { promisify as
|
|
88389
|
+
import { promisify as promisify13 } from "node:util";
|
|
88257
88390
|
|
|
88258
88391
|
// src/services/package-installer/dependencies/node-installer.ts
|
|
88259
88392
|
var NODEJS_INSTALLERS = [
|
|
@@ -88347,8 +88480,8 @@ var PYTHON_INSTALLERS = [
|
|
|
88347
88480
|
init_logger();
|
|
88348
88481
|
import { exec as exec4 } from "node:child_process";
|
|
88349
88482
|
import * as fs7 from "node:fs";
|
|
88350
|
-
import { promisify as
|
|
88351
|
-
var execAsync4 =
|
|
88483
|
+
import { promisify as promisify12 } from "node:util";
|
|
88484
|
+
var execAsync4 = promisify12(exec4);
|
|
88352
88485
|
async function detectOS() {
|
|
88353
88486
|
const platform8 = process.platform;
|
|
88354
88487
|
const info = { platform: platform8 };
|
|
@@ -88418,7 +88551,7 @@ var CLAUDE_INSTALLERS = [
|
|
|
88418
88551
|
];
|
|
88419
88552
|
|
|
88420
88553
|
// src/services/package-installer/dependency-installer.ts
|
|
88421
|
-
var execAsync5 =
|
|
88554
|
+
var execAsync5 = promisify13(exec5);
|
|
88422
88555
|
function getInstallerMethods(dependency, osInfo) {
|
|
88423
88556
|
let installers = dependency === "claude" ? CLAUDE_INSTALLERS : dependency === "python" || dependency === "pip" ? PYTHON_INSTALLERS : dependency === "nodejs" ? NODEJS_INSTALLERS : [];
|
|
88424
88557
|
installers = installers.filter((m2) => m2.platform === osInfo.platform);
|
|
@@ -88474,7 +88607,7 @@ async function installDependency(dependency, method) {
|
|
|
88474
88607
|
|
|
88475
88608
|
// src/domains/health-checks/system-checker.ts
|
|
88476
88609
|
init_logger();
|
|
88477
|
-
var execAsync6 =
|
|
88610
|
+
var execAsync6 = promisify14(exec6);
|
|
88478
88611
|
|
|
88479
88612
|
class SystemChecker {
|
|
88480
88613
|
group = "system";
|
|
@@ -101939,10 +102072,10 @@ class TarExtractor {
|
|
|
101939
102072
|
// src/domains/installation/extraction/zip-extractor.ts
|
|
101940
102073
|
init_logger();
|
|
101941
102074
|
var import_extract_zip = __toESM(require_extract_zip(), 1);
|
|
101942
|
-
import { execFile as
|
|
102075
|
+
import { execFile as execFile11 } from "node:child_process";
|
|
101943
102076
|
import { copyFile as copyFile5, mkdir as mkdir29, readdir as readdir26, rm as rm12, stat as stat16 } from "node:fs/promises";
|
|
101944
102077
|
import { join as join103 } from "node:path";
|
|
101945
|
-
import { promisify as
|
|
102078
|
+
import { promisify as promisify16 } from "node:util";
|
|
101946
102079
|
|
|
101947
102080
|
// src/domains/installation/extraction/native-zip-commands.ts
|
|
101948
102081
|
var NATIVE_EXTRACT_TIMEOUT_MS = 120000;
|
|
@@ -101981,7 +102114,7 @@ function getNativeZipCommands(archivePath, destDir, platformName = process.platf
|
|
|
101981
102114
|
}
|
|
101982
102115
|
|
|
101983
102116
|
// src/domains/installation/extraction/zip-extractor.ts
|
|
101984
|
-
var
|
|
102117
|
+
var execFileAsync8 = promisify16(execFile11);
|
|
101985
102118
|
|
|
101986
102119
|
class ZipExtractor {
|
|
101987
102120
|
async tryNativeExtraction(archivePath, destDir) {
|
|
@@ -101993,7 +102126,7 @@ class ZipExtractor {
|
|
|
101993
102126
|
try {
|
|
101994
102127
|
await rm12(destDir, { recursive: true, force: true });
|
|
101995
102128
|
await mkdir29(destDir, { recursive: true });
|
|
101996
|
-
await
|
|
102129
|
+
await execFileAsync8(nativeCommand.command, nativeCommand.args, {
|
|
101997
102130
|
timeout: NATIVE_EXTRACT_TIMEOUT_MS,
|
|
101998
102131
|
windowsHide: true
|
|
101999
102132
|
});
|
|
@@ -102631,7 +102764,7 @@ import { join as join122 } from "node:path";
|
|
|
102631
102764
|
|
|
102632
102765
|
// src/domains/installation/deletion-handler.ts
|
|
102633
102766
|
import { existsSync as existsSync66, lstatSync as lstatSync3, readdirSync as readdirSync10, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync4 } from "node:fs";
|
|
102634
|
-
import { dirname as dirname38, join as join107, relative as relative21, resolve as resolve42, sep as
|
|
102767
|
+
import { dirname as dirname38, join as join107, relative as relative21, resolve as resolve42, sep as sep12 } from "node:path";
|
|
102635
102768
|
|
|
102636
102769
|
// src/services/file-operations/manifest/manifest-reader.ts
|
|
102637
102770
|
init_metadata_migration();
|
|
@@ -102878,7 +103011,7 @@ function cleanupEmptyDirectories(filePath, claudeDir3) {
|
|
|
102878
103011
|
function deletePath(fullPath, claudeDir3) {
|
|
102879
103012
|
const normalizedPath = resolve42(fullPath);
|
|
102880
103013
|
const normalizedClaudeDir = resolve42(claudeDir3);
|
|
102881
|
-
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${
|
|
103014
|
+
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep12}`) && normalizedPath !== normalizedClaudeDir) {
|
|
102882
103015
|
throw new Error(`Path traversal detected: ${fullPath}`);
|
|
102883
103016
|
}
|
|
102884
103017
|
try {
|
|
@@ -102952,7 +103085,7 @@ async function handleDeletions(sourceMetadata, claudeDir3, kitType) {
|
|
|
102952
103085
|
const fullPath = join107(claudeDir3, path16);
|
|
102953
103086
|
const normalizedPath = resolve42(fullPath);
|
|
102954
103087
|
const normalizedClaudeDir = resolve42(claudeDir3);
|
|
102955
|
-
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${
|
|
103088
|
+
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep12}`)) {
|
|
102956
103089
|
logger.warning(`Skipping invalid path: ${path16}`);
|
|
102957
103090
|
result.errors.push(path16);
|
|
102958
103091
|
continue;
|
|
@@ -104050,8 +104183,8 @@ var path16 = {
|
|
|
104050
104183
|
win32: { sep: "\\" },
|
|
104051
104184
|
posix: { sep: "/" }
|
|
104052
104185
|
};
|
|
104053
|
-
var
|
|
104054
|
-
minimatch.sep =
|
|
104186
|
+
var sep13 = defaultPlatform === "win32" ? path16.win32.sep : path16.posix.sep;
|
|
104187
|
+
minimatch.sep = sep13;
|
|
104055
104188
|
var GLOBSTAR = Symbol("globstar **");
|
|
104056
104189
|
minimatch.GLOBSTAR = GLOBSTAR;
|
|
104057
104190
|
var qmark2 = "[^/]";
|
|
@@ -108818,7 +108951,8 @@ async function handlePostInstall(ctx) {
|
|
|
108818
108951
|
};
|
|
108819
108952
|
}
|
|
108820
108953
|
// src/commands/init/phases/plugin-install-handler.ts
|
|
108821
|
-
|
|
108954
|
+
init_codex_plugin_installer();
|
|
108955
|
+
import { cpSync as cpSync2, existsSync as existsSync69, mkdirSync as mkdirSync6, readFileSync as readFileSync21, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
108822
108956
|
import { join as join135 } from "node:path";
|
|
108823
108957
|
|
|
108824
108958
|
// src/domains/installation/plugin/migrate-legacy-to-plugin.ts
|
|
@@ -108828,18 +108962,18 @@ import { dirname as dirname43, join as join134 } from "node:path";
|
|
|
108828
108962
|
|
|
108829
108963
|
// src/domains/installation/plugin/plugin-installer.ts
|
|
108830
108964
|
init_install_mode_detector();
|
|
108831
|
-
import { execFile as
|
|
108832
|
-
import { promisify as
|
|
108833
|
-
var
|
|
108834
|
-
var
|
|
108965
|
+
import { execFile as execFile12 } from "node:child_process";
|
|
108966
|
+
import { promisify as promisify17 } from "node:util";
|
|
108967
|
+
var execFileAsync9 = promisify17(execFile12);
|
|
108968
|
+
var DEFAULT_TIMEOUT_MS3 = 120000;
|
|
108835
108969
|
var defaultClaudeRunner = async (args, opts) => {
|
|
108836
108970
|
const env2 = { ...process.env };
|
|
108837
108971
|
if (opts?.configDir)
|
|
108838
108972
|
env2.CLAUDE_CONFIG_DIR = opts.configDir;
|
|
108839
108973
|
try {
|
|
108840
|
-
const { stdout: stdout2, stderr } = await
|
|
108974
|
+
const { stdout: stdout2, stderr } = await execFileAsync9("claude", args, {
|
|
108841
108975
|
env: env2,
|
|
108842
|
-
timeout: opts?.timeoutMs ??
|
|
108976
|
+
timeout: opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS3,
|
|
108843
108977
|
maxBuffer: 10 * 1024 * 1024
|
|
108844
108978
|
});
|
|
108845
108979
|
return { ok: true, stdout: String(stdout2), stderr: String(stderr), code: 0 };
|
|
@@ -109065,12 +109199,23 @@ async function handlePluginInstall(ctx, deps = {}) {
|
|
|
109065
109199
|
return ctx;
|
|
109066
109200
|
}
|
|
109067
109201
|
const migrate = deps.migrate ?? migrateLegacyToPlugin;
|
|
109202
|
+
const installCodex = deps.installCodex ?? installCodexPlugin;
|
|
109068
109203
|
try {
|
|
109069
109204
|
const pluginSourceDir = stagePluginSource(ctx.extractDir, deps.stageBaseDir);
|
|
109070
|
-
|
|
109071
|
-
|
|
109205
|
+
try {
|
|
109206
|
+
const result = await migrate({ pluginSourceDir, claudeDir: ctx.claudeDir });
|
|
109207
|
+
logPluginResult(result);
|
|
109208
|
+
} catch (err) {
|
|
109209
|
+
logger.verbose(`Claude plugin install skipped (legacy copy retained): ${err.message}`);
|
|
109210
|
+
}
|
|
109211
|
+
try {
|
|
109212
|
+
const result = await installCodex({ pluginSourceDir });
|
|
109213
|
+
logCodexPluginResult(result);
|
|
109214
|
+
} catch (err) {
|
|
109215
|
+
logger.verbose(`Codex plugin install skipped: ${err.message}`);
|
|
109216
|
+
}
|
|
109072
109217
|
} catch (err) {
|
|
109073
|
-
logger.verbose(`Plugin
|
|
109218
|
+
logger.verbose(`Plugin staging skipped (legacy copy retained): ${err.message}`);
|
|
109074
109219
|
}
|
|
109075
109220
|
return ctx;
|
|
109076
109221
|
}
|
|
@@ -109082,17 +109227,88 @@ function stagePluginSource(extractDir, stageBaseDir) {
|
|
|
109082
109227
|
}
|
|
109083
109228
|
rmSync4(base2, { recursive: true, force: true });
|
|
109084
109229
|
mkdirSync6(base2, { recursive: true });
|
|
109085
|
-
|
|
109086
|
-
|
|
109230
|
+
const stagedPayload = join135(base2, ".claude");
|
|
109231
|
+
cpSync2(payloadSrc, stagedPayload, { recursive: true });
|
|
109232
|
+
ensureCodexPluginManifest(stagedPayload);
|
|
109233
|
+
const claudeMarketplace = {
|
|
109087
109234
|
name: "claudekit",
|
|
109088
109235
|
owner: { name: "ClaudeKit" },
|
|
109089
109236
|
plugins: [{ name: "ck", source: "./.claude", description: "ClaudeKit Engineer" }]
|
|
109090
109237
|
};
|
|
109091
109238
|
mkdirSync6(join135(base2, ".claude-plugin"), { recursive: true });
|
|
109092
|
-
writeFileSync8(join135(base2, ".claude-plugin", "marketplace.json"), `${JSON.stringify(
|
|
109239
|
+
writeFileSync8(join135(base2, ".claude-plugin", "marketplace.json"), `${JSON.stringify(claudeMarketplace, null, 2)}
|
|
109240
|
+
`, "utf-8");
|
|
109241
|
+
const codexMarketplace = {
|
|
109242
|
+
name: "claudekit",
|
|
109243
|
+
interface: { displayName: "ClaudeKit" },
|
|
109244
|
+
plugins: [
|
|
109245
|
+
{
|
|
109246
|
+
name: "ck",
|
|
109247
|
+
source: { source: "local", path: "./.claude" },
|
|
109248
|
+
policy: { installation: "AVAILABLE", authentication: "ON_INSTALL" },
|
|
109249
|
+
category: "Productivity"
|
|
109250
|
+
}
|
|
109251
|
+
]
|
|
109252
|
+
};
|
|
109253
|
+
mkdirSync6(join135(base2, ".agents", "plugins"), { recursive: true });
|
|
109254
|
+
writeFileSync8(join135(base2, ".agents", "plugins", "marketplace.json"), `${JSON.stringify(codexMarketplace, null, 2)}
|
|
109093
109255
|
`, "utf-8");
|
|
109094
109256
|
return base2;
|
|
109095
109257
|
}
|
|
109258
|
+
function ensureCodexPluginManifest(pluginRoot) {
|
|
109259
|
+
const manifestPath = join135(pluginRoot, ".codex-plugin", "plugin.json");
|
|
109260
|
+
if (existsSync69(manifestPath))
|
|
109261
|
+
return;
|
|
109262
|
+
const claudeManifest = readJsonSafe3(join135(pluginRoot, ".claude-plugin", "plugin.json"));
|
|
109263
|
+
const manifest = pruneUndefined({
|
|
109264
|
+
name: stringField(claudeManifest, "name") ?? "ck",
|
|
109265
|
+
version: stringField(claudeManifest, "version") ?? "0.0.0",
|
|
109266
|
+
description: stringField(claudeManifest, "description") ?? "ClaudeKit Engineer — multi-agent planning, code review, debugging, and workflow skills for Codex.",
|
|
109267
|
+
author: authorField(claudeManifest),
|
|
109268
|
+
homepage: stringField(claudeManifest, "homepage"),
|
|
109269
|
+
repository: stringField(claudeManifest, "repository"),
|
|
109270
|
+
license: stringField(claudeManifest, "license"),
|
|
109271
|
+
keywords: ["claudekit", "codex", "skills", "agents", "workflow"],
|
|
109272
|
+
skills: "./skills/",
|
|
109273
|
+
interface: {
|
|
109274
|
+
displayName: "ClaudeKit Engineer",
|
|
109275
|
+
shortDescription: "ClaudeKit planning, review, debugging, and workflow skills.",
|
|
109276
|
+
longDescription: "ClaudeKit Engineer provides planning, code review, debugging, testing, browser workflow, and implementation skills for Codex.",
|
|
109277
|
+
developerName: "ClaudeKit",
|
|
109278
|
+
category: "Productivity",
|
|
109279
|
+
capabilities: ["Skills"],
|
|
109280
|
+
websiteURL: "https://github.com/claudekit/claudekit-engineer"
|
|
109281
|
+
}
|
|
109282
|
+
});
|
|
109283
|
+
mkdirSync6(join135(pluginRoot, ".codex-plugin"), { recursive: true });
|
|
109284
|
+
writeFileSync8(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
109285
|
+
`, "utf-8");
|
|
109286
|
+
}
|
|
109287
|
+
function readJsonSafe3(filePath) {
|
|
109288
|
+
try {
|
|
109289
|
+
const parsed = JSON.parse(readFileSync21(filePath, "utf-8"));
|
|
109290
|
+
return isRecord3(parsed) ? parsed : null;
|
|
109291
|
+
} catch {
|
|
109292
|
+
return null;
|
|
109293
|
+
}
|
|
109294
|
+
}
|
|
109295
|
+
function stringField(source, key) {
|
|
109296
|
+
const value = source?.[key];
|
|
109297
|
+
return typeof value === "string" && value.trim() !== "" ? value : undefined;
|
|
109298
|
+
}
|
|
109299
|
+
function authorField(source) {
|
|
109300
|
+
const author = source?.author;
|
|
109301
|
+
if (isRecord3(author) && typeof author.name === "string" && author.name.trim() !== "") {
|
|
109302
|
+
return { name: author.name };
|
|
109303
|
+
}
|
|
109304
|
+
return { name: "ClaudeKit" };
|
|
109305
|
+
}
|
|
109306
|
+
function pruneUndefined(value) {
|
|
109307
|
+
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
109308
|
+
}
|
|
109309
|
+
function isRecord3(value) {
|
|
109310
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
109311
|
+
}
|
|
109096
109312
|
function logPluginResult(result) {
|
|
109097
109313
|
switch (result.action) {
|
|
109098
109314
|
case "migrated-from-legacy":
|
|
@@ -109112,6 +109328,19 @@ function logPluginResult(result) {
|
|
|
109112
109328
|
break;
|
|
109113
109329
|
}
|
|
109114
109330
|
}
|
|
109331
|
+
function logCodexPluginResult(result) {
|
|
109332
|
+
switch (result.action) {
|
|
109333
|
+
case "installed":
|
|
109334
|
+
logger.info("Installed ClaudeKit Engineer as a Codex plugin.");
|
|
109335
|
+
break;
|
|
109336
|
+
case "skipped-codex-unsupported":
|
|
109337
|
+
logger.verbose("Codex plugin support unavailable; skipped Codex plugin install.");
|
|
109338
|
+
break;
|
|
109339
|
+
case "install-failed":
|
|
109340
|
+
logger.verbose(`Codex plugin install did not verify. ${result.error ?? ""}`);
|
|
109341
|
+
break;
|
|
109342
|
+
}
|
|
109343
|
+
}
|
|
109115
109344
|
// src/commands/init/phases/selection-handler.ts
|
|
109116
109345
|
init_config_manager();
|
|
109117
109346
|
init_github_client();
|
|
@@ -109187,8 +109416,8 @@ async function detectAccessibleKits() {
|
|
|
109187
109416
|
// src/domains/github/preflight-checker.ts
|
|
109188
109417
|
init_logger();
|
|
109189
109418
|
import { exec as exec8 } from "node:child_process";
|
|
109190
|
-
import { promisify as
|
|
109191
|
-
var execAsync8 =
|
|
109419
|
+
import { promisify as promisify18 } from "node:util";
|
|
109420
|
+
var execAsync8 = promisify18(exec8);
|
|
109192
109421
|
function createSuccessfulPreflightResult() {
|
|
109193
109422
|
return {
|
|
109194
109423
|
success: true,
|
|
@@ -109283,6 +109512,9 @@ async function runPreflightChecks() {
|
|
|
109283
109512
|
return result;
|
|
109284
109513
|
}
|
|
109285
109514
|
|
|
109515
|
+
// src/commands/init/phases/selection-handler.ts
|
|
109516
|
+
init_hook_health_checker();
|
|
109517
|
+
|
|
109286
109518
|
// src/domains/installation/fresh-installer.ts
|
|
109287
109519
|
init_metadata_migration();
|
|
109288
109520
|
import { existsSync as existsSync70, readdirSync as readdirSync11, rmSync as rmSync5, rmdirSync as rmdirSync2, unlinkSync as unlinkSync5 } from "node:fs";
|
|
@@ -110028,8 +110260,13 @@ async function handleSelection(ctx) {
|
|
|
110028
110260
|
const existingMetadata = await readManifest(claudeDir3);
|
|
110029
110261
|
const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
|
|
110030
110262
|
if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
|
|
110031
|
-
|
|
110032
|
-
|
|
110263
|
+
const missingHookFiles = await countMissingHookFileReferencesForClaudeDir(claudeDir3);
|
|
110264
|
+
if (missingHookFiles > 0) {
|
|
110265
|
+
logger.warning(`Detected ${missingHookFiles} registered hook(s) whose script is missing on disk; reinstalling to restore them`);
|
|
110266
|
+
} else {
|
|
110267
|
+
logger.success(`Already at latest version (${kitType}@${installedKitVersion}), skipping reinstall`);
|
|
110268
|
+
return { ...ctx, cancelled: true };
|
|
110269
|
+
}
|
|
110033
110270
|
}
|
|
110034
110271
|
} catch (error) {
|
|
110035
110272
|
logger.verbose(`Metadata read failed, proceeding with installation: ${error instanceof Error ? error.message : "unknown"}`);
|
|
@@ -115778,11 +116015,11 @@ async function detectInstallations() {
|
|
|
115778
116015
|
|
|
115779
116016
|
// src/commands/uninstall/removal-handler.ts
|
|
115780
116017
|
import { readdirSync as readdirSync13, rmSync as rmSync8 } from "node:fs";
|
|
115781
|
-
import { basename as basename33, join as
|
|
116018
|
+
import { basename as basename33, join as join158, resolve as resolve56, sep as sep14 } from "node:path";
|
|
115782
116019
|
init_logger();
|
|
115783
116020
|
init_safe_prompts();
|
|
115784
116021
|
init_safe_spinner();
|
|
115785
|
-
var
|
|
116022
|
+
var import_fs_extra44 = __toESM(require_lib(), 1);
|
|
115786
116023
|
|
|
115787
116024
|
// src/commands/uninstall/analysis-handler.ts
|
|
115788
116025
|
init_metadata_migration();
|
|
@@ -115934,10 +116171,170 @@ function displayDryRunPreview(analysis, installationType) {
|
|
|
115934
116171
|
}
|
|
115935
116172
|
}
|
|
115936
116173
|
|
|
116174
|
+
// src/commands/uninstall/settings-cleanup.ts
|
|
116175
|
+
init_settings_merger();
|
|
116176
|
+
init_command_normalizer();
|
|
116177
|
+
init_logger();
|
|
116178
|
+
var import_fs_extra43 = __toESM(require_lib(), 1);
|
|
116179
|
+
import { join as join157 } from "node:path";
|
|
116180
|
+
var CK_JSON_FILE2 = ".ck.json";
|
|
116181
|
+
var SETTINGS_FILE = "settings.json";
|
|
116182
|
+
var EMPTY_RESULT = {
|
|
116183
|
+
hooksRemoved: 0,
|
|
116184
|
+
mcpServersRemoved: 0,
|
|
116185
|
+
settingsFileRemoved: false,
|
|
116186
|
+
ckJsonRemoved: false
|
|
116187
|
+
};
|
|
116188
|
+
function resolveRemovalTargets(kits, removedKitNames, remainingKits) {
|
|
116189
|
+
const retainedHooks = new Set;
|
|
116190
|
+
const retainedServers = new Set;
|
|
116191
|
+
for (const remainingKit of remainingKits) {
|
|
116192
|
+
const installed = kits[remainingKit]?.installedSettings;
|
|
116193
|
+
for (const command of installed?.hooks ?? []) {
|
|
116194
|
+
const normalized = normalizeCommand(command);
|
|
116195
|
+
if (normalized)
|
|
116196
|
+
retainedHooks.add(normalized);
|
|
116197
|
+
}
|
|
116198
|
+
for (const server of installed?.mcpServers ?? []) {
|
|
116199
|
+
retainedServers.add(server);
|
|
116200
|
+
}
|
|
116201
|
+
}
|
|
116202
|
+
const hooks = new Set;
|
|
116203
|
+
const servers = new Set;
|
|
116204
|
+
for (const kitName of removedKitNames) {
|
|
116205
|
+
const installed = kits[kitName]?.installedSettings;
|
|
116206
|
+
for (const command of installed?.hooks ?? []) {
|
|
116207
|
+
const normalized = normalizeCommand(command);
|
|
116208
|
+
if (normalized && !retainedHooks.has(normalized))
|
|
116209
|
+
hooks.add(normalized);
|
|
116210
|
+
}
|
|
116211
|
+
for (const server of installed?.mcpServers ?? []) {
|
|
116212
|
+
if (!retainedServers.has(server))
|
|
116213
|
+
servers.add(server);
|
|
116214
|
+
}
|
|
116215
|
+
}
|
|
116216
|
+
return { hooks, servers };
|
|
116217
|
+
}
|
|
116218
|
+
function removeHooksFromSettings(settings, normalizedToRemove) {
|
|
116219
|
+
if (!settings.hooks || normalizedToRemove.size === 0)
|
|
116220
|
+
return 0;
|
|
116221
|
+
let removed = 0;
|
|
116222
|
+
const eventKeysToDelete = [];
|
|
116223
|
+
for (const [eventName, entries] of Object.entries(settings.hooks)) {
|
|
116224
|
+
const keptEntries = [];
|
|
116225
|
+
for (const entry of entries) {
|
|
116226
|
+
if (Array.isArray(entry.hooks)) {
|
|
116227
|
+
const keptHooks = entry.hooks.filter((hook) => {
|
|
116228
|
+
if (typeof hook.command === "string" && normalizedToRemove.has(normalizeCommand(hook.command))) {
|
|
116229
|
+
removed++;
|
|
116230
|
+
return false;
|
|
116231
|
+
}
|
|
116232
|
+
return true;
|
|
116233
|
+
});
|
|
116234
|
+
if (keptHooks.length > 0) {
|
|
116235
|
+
keptEntries.push({ ...entry, hooks: keptHooks });
|
|
116236
|
+
}
|
|
116237
|
+
continue;
|
|
116238
|
+
}
|
|
116239
|
+
if (typeof entry.command === "string" && normalizedToRemove.has(normalizeCommand(entry.command))) {
|
|
116240
|
+
removed++;
|
|
116241
|
+
continue;
|
|
116242
|
+
}
|
|
116243
|
+
keptEntries.push(entry);
|
|
116244
|
+
}
|
|
116245
|
+
if (keptEntries.length > 0) {
|
|
116246
|
+
settings.hooks[eventName] = keptEntries;
|
|
116247
|
+
} else {
|
|
116248
|
+
eventKeysToDelete.push(eventName);
|
|
116249
|
+
}
|
|
116250
|
+
}
|
|
116251
|
+
for (const eventName of eventKeysToDelete) {
|
|
116252
|
+
delete settings.hooks[eventName];
|
|
116253
|
+
}
|
|
116254
|
+
if (Object.keys(settings.hooks).length === 0) {
|
|
116255
|
+
Reflect.deleteProperty(settings, "hooks");
|
|
116256
|
+
}
|
|
116257
|
+
return removed;
|
|
116258
|
+
}
|
|
116259
|
+
function removeMcpServersFromSettings(settings, serversToRemove) {
|
|
116260
|
+
const servers = settings.mcp?.servers;
|
|
116261
|
+
if (!servers || serversToRemove.size === 0)
|
|
116262
|
+
return 0;
|
|
116263
|
+
let removed = 0;
|
|
116264
|
+
for (const name2 of serversToRemove) {
|
|
116265
|
+
if (Object.hasOwn(servers, name2)) {
|
|
116266
|
+
delete servers[name2];
|
|
116267
|
+
removed++;
|
|
116268
|
+
}
|
|
116269
|
+
}
|
|
116270
|
+
if (removed > 0 && settings.mcp) {
|
|
116271
|
+
if (Object.keys(servers).length === 0) {
|
|
116272
|
+
Reflect.deleteProperty(settings.mcp, "servers");
|
|
116273
|
+
}
|
|
116274
|
+
if (Object.keys(settings.mcp).length === 0) {
|
|
116275
|
+
Reflect.deleteProperty(settings, "mcp");
|
|
116276
|
+
}
|
|
116277
|
+
}
|
|
116278
|
+
return removed;
|
|
116279
|
+
}
|
|
116280
|
+
async function cleanupCkJson(ckJsonPath, data, removedKitNames, dryRun) {
|
|
116281
|
+
if (!data.kits)
|
|
116282
|
+
return false;
|
|
116283
|
+
for (const kitName of removedKitNames) {
|
|
116284
|
+
delete data.kits[kitName];
|
|
116285
|
+
}
|
|
116286
|
+
const noKitsLeft = Object.keys(data.kits).length === 0;
|
|
116287
|
+
const otherTopLevelKeys = Object.keys(data).filter((key) => key !== "kits");
|
|
116288
|
+
if (dryRun)
|
|
116289
|
+
return noKitsLeft && otherTopLevelKeys.length === 0;
|
|
116290
|
+
if (noKitsLeft && otherTopLevelKeys.length === 0) {
|
|
116291
|
+
await import_fs_extra43.remove(ckJsonPath);
|
|
116292
|
+
return true;
|
|
116293
|
+
}
|
|
116294
|
+
if (noKitsLeft) {
|
|
116295
|
+
Reflect.deleteProperty(data, "kits");
|
|
116296
|
+
}
|
|
116297
|
+
await import_fs_extra43.writeFile(ckJsonPath, JSON.stringify(data, null, 2), "utf-8");
|
|
116298
|
+
return false;
|
|
116299
|
+
}
|
|
116300
|
+
async function cleanupUninstalledSettings(installationPath, options2) {
|
|
116301
|
+
const ckJsonPath = join157(installationPath, CK_JSON_FILE2);
|
|
116302
|
+
if (!await import_fs_extra43.pathExists(ckJsonPath)) {
|
|
116303
|
+
return { ...EMPTY_RESULT };
|
|
116304
|
+
}
|
|
116305
|
+
let data;
|
|
116306
|
+
try {
|
|
116307
|
+
data = parseJsonContent(await import_fs_extra43.readFile(ckJsonPath, "utf-8"));
|
|
116308
|
+
} catch (error) {
|
|
116309
|
+
logger.debug(`Settings cleanup: failed to parse ${ckJsonPath}: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
116310
|
+
return { ...EMPTY_RESULT };
|
|
116311
|
+
}
|
|
116312
|
+
const kits = data.kits ?? {};
|
|
116313
|
+
const removedKitNames = options2.kit ? [options2.kit] : Object.keys(kits);
|
|
116314
|
+
const { hooks, servers } = resolveRemovalTargets(kits, removedKitNames, options2.remainingKits);
|
|
116315
|
+
const result = { ...EMPTY_RESULT };
|
|
116316
|
+
const settingsPath = join157(installationPath, SETTINGS_FILE);
|
|
116317
|
+
const settings = await SettingsMerger.readSettingsFile(settingsPath);
|
|
116318
|
+
if (settings) {
|
|
116319
|
+
result.hooksRemoved = removeHooksFromSettings(settings, hooks);
|
|
116320
|
+
result.mcpServersRemoved = removeMcpServersFromSettings(settings, servers);
|
|
116321
|
+
if (!options2.dryRun && (result.hooksRemoved > 0 || result.mcpServersRemoved > 0)) {
|
|
116322
|
+
if (Object.keys(settings).length === 0) {
|
|
116323
|
+
await import_fs_extra43.remove(settingsPath);
|
|
116324
|
+
result.settingsFileRemoved = true;
|
|
116325
|
+
} else {
|
|
116326
|
+
await SettingsMerger.writeSettingsFile(settingsPath, settings);
|
|
116327
|
+
}
|
|
116328
|
+
}
|
|
116329
|
+
}
|
|
116330
|
+
result.ckJsonRemoved = await cleanupCkJson(ckJsonPath, data, removedKitNames, options2.dryRun ?? false);
|
|
116331
|
+
return result;
|
|
116332
|
+
}
|
|
116333
|
+
|
|
115937
116334
|
// src/commands/uninstall/removal-handler.ts
|
|
115938
116335
|
async function isDirectory2(filePath) {
|
|
115939
116336
|
try {
|
|
115940
|
-
const stats = await
|
|
116337
|
+
const stats = await import_fs_extra44.lstat(filePath);
|
|
115941
116338
|
return stats.isDirectory();
|
|
115942
116339
|
} catch {
|
|
115943
116340
|
logger.debug(`Failed to check if path is directory: ${filePath}`);
|
|
@@ -115945,10 +116342,30 @@ async function isDirectory2(filePath) {
|
|
|
115945
116342
|
}
|
|
115946
116343
|
}
|
|
115947
116344
|
function getUninstallMutatePaths(options2) {
|
|
116345
|
+
const paths = [];
|
|
115948
116346
|
if (options2.retainedManifestPaths.length > 0) {
|
|
115949
|
-
|
|
116347
|
+
paths.push("metadata.json");
|
|
115950
116348
|
}
|
|
115951
|
-
|
|
116349
|
+
if (options2.settingsFileExists) {
|
|
116350
|
+
paths.push("settings.json");
|
|
116351
|
+
}
|
|
116352
|
+
if (options2.ckJsonExists) {
|
|
116353
|
+
paths.push(".ck.json");
|
|
116354
|
+
}
|
|
116355
|
+
return paths;
|
|
116356
|
+
}
|
|
116357
|
+
function logSettingsCleanup(result, dryRun) {
|
|
116358
|
+
if (result.hooksRemoved === 0 && result.mcpServersRemoved === 0)
|
|
116359
|
+
return;
|
|
116360
|
+
const parts = [];
|
|
116361
|
+
if (result.hooksRemoved > 0) {
|
|
116362
|
+
parts.push(`${result.hooksRemoved} hook${result.hooksRemoved === 1 ? "" : "s"}`);
|
|
116363
|
+
}
|
|
116364
|
+
if (result.mcpServersRemoved > 0) {
|
|
116365
|
+
parts.push(`${result.mcpServersRemoved} MCP server${result.mcpServersRemoved === 1 ? "" : "s"}`);
|
|
116366
|
+
}
|
|
116367
|
+
const verb = dryRun ? "Would remove" : "Removed";
|
|
116368
|
+
log.info(`${verb} ${parts.join(" and ")} from settings.json`);
|
|
115952
116369
|
}
|
|
115953
116370
|
async function restoreUninstallBackup(backup) {
|
|
115954
116371
|
const restoreSpinner = createSpinner("Restoring installation from recovery backup...").start();
|
|
@@ -115964,15 +116381,15 @@ async function isPathSafeToRemove(filePath, baseDir) {
|
|
|
115964
116381
|
try {
|
|
115965
116382
|
const resolvedPath = resolve56(filePath);
|
|
115966
116383
|
const resolvedBase = resolve56(baseDir);
|
|
115967
|
-
if (!resolvedPath.startsWith(resolvedBase +
|
|
116384
|
+
if (!resolvedPath.startsWith(resolvedBase + sep14) && resolvedPath !== resolvedBase) {
|
|
115968
116385
|
logger.debug(`Path outside installation directory: ${filePath}`);
|
|
115969
116386
|
return false;
|
|
115970
116387
|
}
|
|
115971
|
-
const stats = await
|
|
116388
|
+
const stats = await import_fs_extra44.lstat(filePath);
|
|
115972
116389
|
if (stats.isSymbolicLink()) {
|
|
115973
|
-
const realPath = await
|
|
116390
|
+
const realPath = await import_fs_extra44.realpath(filePath);
|
|
115974
116391
|
const resolvedReal = resolve56(realPath);
|
|
115975
|
-
if (!resolvedReal.startsWith(resolvedBase +
|
|
116392
|
+
if (!resolvedReal.startsWith(resolvedBase + sep14) && resolvedReal !== resolvedBase) {
|
|
115976
116393
|
logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
|
|
115977
116394
|
return false;
|
|
115978
116395
|
}
|
|
@@ -115994,6 +116411,12 @@ async function removeInstallations(installations, options2) {
|
|
|
115994
116411
|
const label = options2.kit ? `${installation.type} (${options2.kit} kit)` : installation.type;
|
|
115995
116412
|
const legacyLabel2 = !installation.hasMetadata ? " [legacy]" : "";
|
|
115996
116413
|
displayDryRunPreview(analysis, `${label}${legacyLabel2}`);
|
|
116414
|
+
const settingsPreview = await cleanupUninstalledSettings(installation.path, {
|
|
116415
|
+
kit: options2.kit,
|
|
116416
|
+
remainingKits: analysis.remainingKits,
|
|
116417
|
+
dryRun: true
|
|
116418
|
+
});
|
|
116419
|
+
logSettingsCleanup(settingsPreview, true);
|
|
115997
116420
|
if (analysis.remainingKits.length > 0) {
|
|
115998
116421
|
log.info(`Remaining kits after uninstall: ${analysis.remainingKits.join(", ")}`);
|
|
115999
116422
|
}
|
|
@@ -116003,7 +116426,9 @@ async function removeInstallations(installations, options2) {
|
|
|
116003
116426
|
continue;
|
|
116004
116427
|
}
|
|
116005
116428
|
const mutatePaths = getUninstallMutatePaths({
|
|
116006
|
-
retainedManifestPaths: analysis.retainedManifestPaths
|
|
116429
|
+
retainedManifestPaths: analysis.retainedManifestPaths,
|
|
116430
|
+
settingsFileExists: await import_fs_extra44.pathExists(join158(installation.path, "settings.json")),
|
|
116431
|
+
ckJsonExists: await import_fs_extra44.pathExists(join158(installation.path, ".ck.json"))
|
|
116007
116432
|
});
|
|
116008
116433
|
let backup = null;
|
|
116009
116434
|
if (analysis.toDelete.length > 0 || mutatePaths.length > 0) {
|
|
@@ -116031,15 +116456,15 @@ async function removeInstallations(installations, options2) {
|
|
|
116031
116456
|
let removedCount = 0;
|
|
116032
116457
|
let cleanedDirs = 0;
|
|
116033
116458
|
for (const item of analysis.toDelete) {
|
|
116034
|
-
const filePath =
|
|
116035
|
-
if (!await
|
|
116459
|
+
const filePath = join158(installation.path, item.path);
|
|
116460
|
+
if (!await import_fs_extra44.pathExists(filePath))
|
|
116036
116461
|
continue;
|
|
116037
116462
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
116038
116463
|
logger.debug(`Skipping unsafe path: ${item.path}`);
|
|
116039
116464
|
continue;
|
|
116040
116465
|
}
|
|
116041
116466
|
const isDir2 = await isDirectory2(filePath);
|
|
116042
|
-
await
|
|
116467
|
+
await import_fs_extra44.remove(filePath);
|
|
116043
116468
|
removedCount++;
|
|
116044
116469
|
logger.debug(`Removed ${isDir2 ? "directory" : "file"}: ${item.path}`);
|
|
116045
116470
|
if (!isDir2) {
|
|
@@ -116055,6 +116480,11 @@ async function removeInstallations(installations, options2) {
|
|
|
116055
116480
|
throw new Error("Failed to update metadata.json after partial uninstall");
|
|
116056
116481
|
}
|
|
116057
116482
|
}
|
|
116483
|
+
const settingsCleanup = await cleanupUninstalledSettings(installation.path, {
|
|
116484
|
+
kit: options2.kit,
|
|
116485
|
+
remainingKits: analysis.remainingKits
|
|
116486
|
+
});
|
|
116487
|
+
logSettingsCleanup(settingsCleanup, false);
|
|
116058
116488
|
try {
|
|
116059
116489
|
const remaining = readdirSync13(installation.path);
|
|
116060
116490
|
if (remaining.length === 0) {
|
|
@@ -116453,7 +116883,7 @@ ${import_picocolors40.default.bold(import_picocolors40.default.cyan(result.kitCo
|
|
|
116453
116883
|
init_logger();
|
|
116454
116884
|
import { existsSync as existsSync82 } from "node:fs";
|
|
116455
116885
|
import { rm as rm19 } from "node:fs/promises";
|
|
116456
|
-
import { join as
|
|
116886
|
+
import { join as join165 } from "node:path";
|
|
116457
116887
|
var import_picocolors41 = __toESM(require_picocolors(), 1);
|
|
116458
116888
|
|
|
116459
116889
|
// src/commands/watch/phases/implementation-runner.ts
|
|
@@ -116971,8 +117401,8 @@ function spawnAndCollect3(command, args) {
|
|
|
116971
117401
|
}
|
|
116972
117402
|
|
|
116973
117403
|
// src/commands/watch/phases/issue-processor.ts
|
|
116974
|
-
import { mkdir as mkdir40, writeFile as
|
|
116975
|
-
import { join as
|
|
117404
|
+
import { mkdir as mkdir40, writeFile as writeFile42 } from "node:fs/promises";
|
|
117405
|
+
import { join as join161 } from "node:path";
|
|
116976
117406
|
|
|
116977
117407
|
// src/commands/watch/phases/approval-detector.ts
|
|
116978
117408
|
init_logger();
|
|
@@ -117350,9 +117780,9 @@ async function checkAwaitingApproval(state, setup, options2, watchLog, projectDi
|
|
|
117350
117780
|
|
|
117351
117781
|
// src/commands/watch/phases/plan-dir-finder.ts
|
|
117352
117782
|
import { readdir as readdir46, stat as stat24 } from "node:fs/promises";
|
|
117353
|
-
import { join as
|
|
117783
|
+
import { join as join160 } from "node:path";
|
|
117354
117784
|
async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
|
|
117355
|
-
const plansRoot =
|
|
117785
|
+
const plansRoot = join160(cwd2, "plans");
|
|
117356
117786
|
try {
|
|
117357
117787
|
const entries = await readdir46(plansRoot);
|
|
117358
117788
|
const tenMinAgo = Date.now() - 10 * 60 * 1000;
|
|
@@ -117361,14 +117791,14 @@ async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
|
|
|
117361
117791
|
for (const entry of entries) {
|
|
117362
117792
|
if (entry === "watch" || entry === "reports" || entry === "visuals")
|
|
117363
117793
|
continue;
|
|
117364
|
-
const dirPath =
|
|
117794
|
+
const dirPath = join160(plansRoot, entry);
|
|
117365
117795
|
const dirStat = await stat24(dirPath);
|
|
117366
117796
|
if (!dirStat.isDirectory())
|
|
117367
117797
|
continue;
|
|
117368
117798
|
if (dirStat.mtimeMs < tenMinAgo)
|
|
117369
117799
|
continue;
|
|
117370
117800
|
try {
|
|
117371
|
-
await stat24(
|
|
117801
|
+
await stat24(join160(dirPath, "plan.md"));
|
|
117372
117802
|
} catch {
|
|
117373
117803
|
continue;
|
|
117374
117804
|
}
|
|
@@ -117599,14 +118029,14 @@ async function handlePlanGeneration(issue, state, config, setup, options2, watch
|
|
|
117599
118029
|
stats.plansCreated++;
|
|
117600
118030
|
const detectedPlanDir = await findRecentPlanDir(projectDir, issue.number, watchLog);
|
|
117601
118031
|
if (detectedPlanDir) {
|
|
117602
|
-
state.activeIssues[numStr].planPath =
|
|
118032
|
+
state.activeIssues[numStr].planPath = join161(detectedPlanDir, "plan.md");
|
|
117603
118033
|
watchLog.info(`Plan directory detected: ${detectedPlanDir}`);
|
|
117604
118034
|
} else {
|
|
117605
118035
|
try {
|
|
117606
|
-
const planDir =
|
|
118036
|
+
const planDir = join161(projectDir, "plans", "watch");
|
|
117607
118037
|
await mkdir40(planDir, { recursive: true });
|
|
117608
|
-
const planFilePath =
|
|
117609
|
-
await
|
|
118038
|
+
const planFilePath = join161(planDir, `issue-${issue.number}-plan.md`);
|
|
118039
|
+
await writeFile42(planFilePath, planResult.planText, "utf-8");
|
|
117610
118040
|
state.activeIssues[numStr].planPath = planFilePath;
|
|
117611
118041
|
watchLog.info(`Plan saved (fallback) to ${planFilePath}`);
|
|
117612
118042
|
} catch (err) {
|
|
@@ -117751,7 +118181,7 @@ init_ck_config_manager();
|
|
|
117751
118181
|
init_file_io();
|
|
117752
118182
|
init_logger();
|
|
117753
118183
|
import { existsSync as existsSync78 } from "node:fs";
|
|
117754
|
-
import { mkdir as mkdir41, readFile as
|
|
118184
|
+
import { mkdir as mkdir41, readFile as readFile71 } from "node:fs/promises";
|
|
117755
118185
|
import { dirname as dirname54 } from "node:path";
|
|
117756
118186
|
var PROCESSED_ISSUES_CAP = 500;
|
|
117757
118187
|
async function readCkJson(projectDir) {
|
|
@@ -117759,7 +118189,7 @@ async function readCkJson(projectDir) {
|
|
|
117759
118189
|
try {
|
|
117760
118190
|
if (!existsSync78(configPath))
|
|
117761
118191
|
return {};
|
|
117762
|
-
const content = await
|
|
118192
|
+
const content = await readFile71(configPath, "utf-8");
|
|
117763
118193
|
return JSON.parse(content);
|
|
117764
118194
|
} catch (error) {
|
|
117765
118195
|
logger.warning(`Failed to parse .ck.json: ${error instanceof Error ? error.message : "Unknown"}`);
|
|
@@ -117912,18 +118342,18 @@ init_logger();
|
|
|
117912
118342
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
117913
118343
|
import { existsSync as existsSync79 } from "node:fs";
|
|
117914
118344
|
import { readdir as readdir47, stat as stat25 } from "node:fs/promises";
|
|
117915
|
-
import { join as
|
|
118345
|
+
import { join as join162 } from "node:path";
|
|
117916
118346
|
async function scanForRepos(parentDir) {
|
|
117917
118347
|
const repos = [];
|
|
117918
118348
|
const entries = await readdir47(parentDir);
|
|
117919
118349
|
for (const entry of entries) {
|
|
117920
118350
|
if (entry.startsWith("."))
|
|
117921
118351
|
continue;
|
|
117922
|
-
const fullPath =
|
|
118352
|
+
const fullPath = join162(parentDir, entry);
|
|
117923
118353
|
const entryStat = await stat25(fullPath);
|
|
117924
118354
|
if (!entryStat.isDirectory())
|
|
117925
118355
|
continue;
|
|
117926
|
-
const gitDir =
|
|
118356
|
+
const gitDir = join162(fullPath, ".git");
|
|
117927
118357
|
if (!existsSync79(gitDir))
|
|
117928
118358
|
continue;
|
|
117929
118359
|
const result = spawnSync7("gh", ["repo", "view", "--json", "owner,name"], {
|
|
@@ -117950,7 +118380,7 @@ init_logger();
|
|
|
117950
118380
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
117951
118381
|
import { existsSync as existsSync80 } from "node:fs";
|
|
117952
118382
|
import { homedir as homedir53 } from "node:os";
|
|
117953
|
-
import { join as
|
|
118383
|
+
import { join as join163 } from "node:path";
|
|
117954
118384
|
async function validateSetup(cwd2) {
|
|
117955
118385
|
const workDir = cwd2 ?? process.cwd();
|
|
117956
118386
|
const ghVersion = spawnSync8("gh", ["--version"], { encoding: "utf-8", timeout: 1e4 });
|
|
@@ -117981,7 +118411,7 @@ Run this command from a directory with a GitHub remote.`);
|
|
|
117981
118411
|
} catch {
|
|
117982
118412
|
throw new Error(`Failed to parse repository info: ${ghRepo.stdout}`);
|
|
117983
118413
|
}
|
|
117984
|
-
const skillsPath =
|
|
118414
|
+
const skillsPath = join163(homedir53(), ".claude", "skills");
|
|
117985
118415
|
const skillsAvailable = existsSync80(skillsPath);
|
|
117986
118416
|
if (!skillsAvailable) {
|
|
117987
118417
|
logger.warning(`ClaudeKit Engineer skills not found at ${skillsPath}`);
|
|
@@ -118000,7 +118430,7 @@ init_path_resolver();
|
|
|
118000
118430
|
import { createWriteStream as createWriteStream3, statSync as statSync14 } from "node:fs";
|
|
118001
118431
|
import { existsSync as existsSync81 } from "node:fs";
|
|
118002
118432
|
import { mkdir as mkdir42, rename as rename15 } from "node:fs/promises";
|
|
118003
|
-
import { join as
|
|
118433
|
+
import { join as join164 } from "node:path";
|
|
118004
118434
|
|
|
118005
118435
|
class WatchLogger {
|
|
118006
118436
|
logStream = null;
|
|
@@ -118008,7 +118438,7 @@ class WatchLogger {
|
|
|
118008
118438
|
logPath = null;
|
|
118009
118439
|
maxBytes;
|
|
118010
118440
|
constructor(logDir, maxBytes = 0) {
|
|
118011
|
-
this.logDir = logDir ??
|
|
118441
|
+
this.logDir = logDir ?? join164(PathResolver.getClaudeKitDir(), "logs");
|
|
118012
118442
|
this.maxBytes = maxBytes;
|
|
118013
118443
|
}
|
|
118014
118444
|
async init() {
|
|
@@ -118017,7 +118447,7 @@ class WatchLogger {
|
|
|
118017
118447
|
await mkdir42(this.logDir, { recursive: true });
|
|
118018
118448
|
}
|
|
118019
118449
|
const dateStr = formatDate(new Date);
|
|
118020
|
-
this.logPath =
|
|
118450
|
+
this.logPath = join164(this.logDir, `watch-${dateStr}.log`);
|
|
118021
118451
|
this.logStream = createWriteStream3(this.logPath, { flags: "a", mode: 384 });
|
|
118022
118452
|
} catch (error) {
|
|
118023
118453
|
logger.warning(`Cannot create watch log file: ${error instanceof Error ? error.message : "Unknown"}`);
|
|
@@ -118199,7 +118629,7 @@ async function watchCommand(options2) {
|
|
|
118199
118629
|
}
|
|
118200
118630
|
async function discoverRepos(options2, watchLog) {
|
|
118201
118631
|
const cwd2 = process.cwd();
|
|
118202
|
-
const isGitRepo = existsSync82(
|
|
118632
|
+
const isGitRepo = existsSync82(join165(cwd2, ".git"));
|
|
118203
118633
|
if (options2.force) {
|
|
118204
118634
|
await forceRemoveLock(watchLog);
|
|
118205
118635
|
}
|
|
@@ -118456,8 +118886,8 @@ function registerCommands(cli) {
|
|
|
118456
118886
|
// src/cli/version-display.ts
|
|
118457
118887
|
init_package();
|
|
118458
118888
|
init_config_version_checker();
|
|
118459
|
-
import { existsSync as existsSync94, readFileSync as
|
|
118460
|
-
import { join as
|
|
118889
|
+
import { existsSync as existsSync94, readFileSync as readFileSync26 } from "node:fs";
|
|
118890
|
+
import { join as join177 } from "node:path";
|
|
118461
118891
|
|
|
118462
118892
|
// src/domains/versioning/version-checker.ts
|
|
118463
118893
|
init_version_utils();
|
|
@@ -118471,15 +118901,15 @@ init_types3();
|
|
|
118471
118901
|
init_logger();
|
|
118472
118902
|
init_path_resolver();
|
|
118473
118903
|
import { existsSync as existsSync93 } from "node:fs";
|
|
118474
|
-
import { mkdir as mkdir43, readFile as
|
|
118475
|
-
import { join as
|
|
118904
|
+
import { mkdir as mkdir43, readFile as readFile73, writeFile as writeFile45 } from "node:fs/promises";
|
|
118905
|
+
import { join as join176 } from "node:path";
|
|
118476
118906
|
|
|
118477
118907
|
class VersionCacheManager {
|
|
118478
118908
|
static CACHE_FILENAME = "version-check.json";
|
|
118479
118909
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
118480
118910
|
static getCacheFile() {
|
|
118481
118911
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
118482
|
-
return
|
|
118912
|
+
return join176(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
118483
118913
|
}
|
|
118484
118914
|
static async load() {
|
|
118485
118915
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -118488,7 +118918,7 @@ class VersionCacheManager {
|
|
|
118488
118918
|
logger.debug("Version check cache not found");
|
|
118489
118919
|
return null;
|
|
118490
118920
|
}
|
|
118491
|
-
const content = await
|
|
118921
|
+
const content = await readFile73(cacheFile, "utf-8");
|
|
118492
118922
|
const cache5 = JSON.parse(content);
|
|
118493
118923
|
if (!cache5.lastCheck || !cache5.currentVersion || !cache5.latestVersion) {
|
|
118494
118924
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -118508,7 +118938,7 @@ class VersionCacheManager {
|
|
|
118508
118938
|
if (!existsSync93(cacheDir)) {
|
|
118509
118939
|
await mkdir43(cacheDir, { recursive: true, mode: 448 });
|
|
118510
118940
|
}
|
|
118511
|
-
await
|
|
118941
|
+
await writeFile45(cacheFile, JSON.stringify(cache5, null, 2), "utf-8");
|
|
118512
118942
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
118513
118943
|
} catch (error) {
|
|
118514
118944
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -118790,13 +119220,13 @@ async function displayVersion() {
|
|
|
118790
119220
|
let localInstalledKits = [];
|
|
118791
119221
|
let globalInstalledKits = [];
|
|
118792
119222
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
118793
|
-
const globalMetadataPath =
|
|
119223
|
+
const globalMetadataPath = join177(globalKitDir, "metadata.json");
|
|
118794
119224
|
const prefix = PathResolver.getPathPrefix(false);
|
|
118795
|
-
const localMetadataPath = prefix ?
|
|
119225
|
+
const localMetadataPath = prefix ? join177(process.cwd(), prefix, "metadata.json") : join177(process.cwd(), "metadata.json");
|
|
118796
119226
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
118797
119227
|
if (!isLocalSameAsGlobal && existsSync94(localMetadataPath)) {
|
|
118798
119228
|
try {
|
|
118799
|
-
const rawMetadata = JSON.parse(
|
|
119229
|
+
const rawMetadata = JSON.parse(readFileSync26(localMetadataPath, "utf-8"));
|
|
118800
119230
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
118801
119231
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
118802
119232
|
if (kitsDisplay) {
|
|
@@ -118810,7 +119240,7 @@ async function displayVersion() {
|
|
|
118810
119240
|
}
|
|
118811
119241
|
if (existsSync94(globalMetadataPath)) {
|
|
118812
119242
|
try {
|
|
118813
|
-
const rawMetadata = JSON.parse(
|
|
119243
|
+
const rawMetadata = JSON.parse(readFileSync26(globalMetadataPath, "utf-8"));
|
|
118814
119244
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
118815
119245
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
118816
119246
|
if (kitsDisplay) {
|
|
@@ -119180,7 +119610,7 @@ var output2 = new OutputManager2;
|
|
|
119180
119610
|
|
|
119181
119611
|
// src/shared/temp-cleanup.ts
|
|
119182
119612
|
init_logger();
|
|
119183
|
-
var
|
|
119613
|
+
var import_fs_extra45 = __toESM(require_lib(), 1);
|
|
119184
119614
|
import { rmSync as rmSync9 } from "node:fs";
|
|
119185
119615
|
var tempDirs2 = new Set;
|
|
119186
119616
|
async function cleanup() {
|
|
@@ -119189,7 +119619,7 @@ async function cleanup() {
|
|
|
119189
119619
|
logger.debug(`Cleaning up ${tempDirs2.size} temporary director(ies)...`);
|
|
119190
119620
|
for (const dir of tempDirs2) {
|
|
119191
119621
|
try {
|
|
119192
|
-
await
|
|
119622
|
+
await import_fs_extra45.remove(dir);
|
|
119193
119623
|
logger.debug(`Cleaned up temp directory: ${dir}`);
|
|
119194
119624
|
} catch (error) {
|
|
119195
119625
|
logger.debug(`Failed to clean temp directory ${dir}: ${error}`);
|