claudekit-cli 4.1.1 → 4.2.1-dev.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "4.1.1",
3
- "generatedAt": "2026-05-11T16:31:15.910Z",
2
+ "version": "4.2.1-dev.1",
3
+ "generatedAt": "2026-05-12T16:42:41.480Z",
4
4
  "commands": {
5
5
  "agents": {
6
6
  "name": "agents",
package/dist/index.js CHANGED
@@ -62890,7 +62890,7 @@ var package_default;
62890
62890
  var init_package = __esm(() => {
62891
62891
  package_default = {
62892
62892
  name: "claudekit-cli",
62893
- version: "4.1.1",
62893
+ version: "4.2.1-dev.1",
62894
62894
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
62895
62895
  type: "module",
62896
62896
  repository: {
@@ -62934,6 +62934,7 @@ var init_package = __esm(() => {
62934
62934
  "dev:all": "./scripts/dev-quick-start.sh all",
62935
62935
  metrics: "bun run scripts/workflow-metrics.ts",
62936
62936
  validate: "bun run typecheck && bun run lint && bun test && bun run ui:test && bun run build",
62937
+ "ci:local": "bash scripts/ci-local.sh",
62937
62938
  "install:hooks": "./.githooks/install.sh",
62938
62939
  prepare: `node -e "try{require('child_process').execSync('git rev-parse --git-dir',{stdio:'ignore'});require('child_process').execSync('bash .githooks/install.sh',{stdio:'inherit'})}catch(e){console.warn('[i] Hook install skipped:',e.message)}"`,
62939
62940
  "help:check-parity": "bun run scripts/check-help-parity.ts",
@@ -64888,8 +64889,20 @@ function buildInitCommand(isGlobal, kit, beta, yes) {
64888
64889
  function resolveCkExecutable(platformName = process.platform) {
64889
64890
  return platformName === "win32" ? "ck.cmd" : "ck";
64890
64891
  }
64891
- function shouldRunCkExecutableInShell(platformName = process.platform) {
64892
- return platformName === "win32";
64892
+ function resolveCkInitSpawnCommand(initArgs, options2 = {}) {
64893
+ const execPath = options2.execPath ?? process.execPath;
64894
+ const argv = options2.argv ?? process.argv;
64895
+ const currentEntrypoint = argv[1];
64896
+ if (currentEntrypoint) {
64897
+ return {
64898
+ command: execPath,
64899
+ args: [currentEntrypoint, ...initArgs]
64900
+ };
64901
+ }
64902
+ return {
64903
+ command: resolveCkExecutable(options2.platformName),
64904
+ args: initArgs
64905
+ };
64893
64906
  }
64894
64907
  async function fetchLatestReleaseTag(kit, beta) {
64895
64908
  try {
@@ -64999,10 +65012,8 @@ async function promptKitUpdate(beta, yes, deps) {
64999
65012
  const displayCmd = `ck ${args.join(" ")}`;
65000
65013
  logger.info(`Running: ${displayCmd}`);
65001
65014
  const spawnFn = deps?.spawnInitFn ?? ((spawnArgs) => new Promise((resolve30) => {
65002
- const child = spawn2(resolveCkExecutable(), spawnArgs, {
65003
- stdio: "inherit",
65004
- shell: shouldRunCkExecutableInShell()
65005
- });
65015
+ const initCommand = resolveCkInitSpawnCommand(spawnArgs);
65016
+ const child = spawn2(initCommand.command, initCommand.args, { stdio: "inherit" });
65006
65017
  child.on("close", (code) => resolve30(code ?? 1));
65007
65018
  child.on("error", (err) => {
65008
65019
  logger.verbose(`Failed to spawn ck init: ${err.message}`);
@@ -73995,76 +74006,6 @@ var init_ownership_display = __esm(() => {
73995
74006
  import_picocolors25 = __toESM(require_picocolors(), 1);
73996
74007
  });
73997
74008
 
73998
- // src/ui/node_modules/picocolors/picocolors.js
73999
- var require_picocolors2 = __commonJS((exports, module) => {
74000
- var p = process || {};
74001
- var argv = p.argv || [];
74002
- var env2 = p.env || {};
74003
- var isColorSupported = !(!!env2.NO_COLOR || argv.includes("--no-color")) && (!!env2.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env2.TERM !== "dumb" || !!env2.CI);
74004
- var formatter = (open6, close, replace3 = open6) => (input) => {
74005
- let string = "" + input, index = string.indexOf(close, open6.length);
74006
- return ~index ? open6 + replaceClose(string, close, replace3, index) + close : open6 + string + close;
74007
- };
74008
- var replaceClose = (string, close, replace3, index) => {
74009
- let result = "", cursor = 0;
74010
- do {
74011
- result += string.substring(cursor, index) + replace3;
74012
- cursor = index + close.length;
74013
- index = string.indexOf(close, cursor);
74014
- } while (~index);
74015
- return result + string.substring(cursor);
74016
- };
74017
- var createColors = (enabled = isColorSupported) => {
74018
- let f3 = enabled ? formatter : () => String;
74019
- return {
74020
- isColorSupported: enabled,
74021
- reset: f3("\x1B[0m", "\x1B[0m"),
74022
- bold: f3("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
74023
- dim: f3("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
74024
- italic: f3("\x1B[3m", "\x1B[23m"),
74025
- underline: f3("\x1B[4m", "\x1B[24m"),
74026
- inverse: f3("\x1B[7m", "\x1B[27m"),
74027
- hidden: f3("\x1B[8m", "\x1B[28m"),
74028
- strikethrough: f3("\x1B[9m", "\x1B[29m"),
74029
- black: f3("\x1B[30m", "\x1B[39m"),
74030
- red: f3("\x1B[31m", "\x1B[39m"),
74031
- green: f3("\x1B[32m", "\x1B[39m"),
74032
- yellow: f3("\x1B[33m", "\x1B[39m"),
74033
- blue: f3("\x1B[34m", "\x1B[39m"),
74034
- magenta: f3("\x1B[35m", "\x1B[39m"),
74035
- cyan: f3("\x1B[36m", "\x1B[39m"),
74036
- white: f3("\x1B[37m", "\x1B[39m"),
74037
- gray: f3("\x1B[90m", "\x1B[39m"),
74038
- bgBlack: f3("\x1B[40m", "\x1B[49m"),
74039
- bgRed: f3("\x1B[41m", "\x1B[49m"),
74040
- bgGreen: f3("\x1B[42m", "\x1B[49m"),
74041
- bgYellow: f3("\x1B[43m", "\x1B[49m"),
74042
- bgBlue: f3("\x1B[44m", "\x1B[49m"),
74043
- bgMagenta: f3("\x1B[45m", "\x1B[49m"),
74044
- bgCyan: f3("\x1B[46m", "\x1B[49m"),
74045
- bgWhite: f3("\x1B[47m", "\x1B[49m"),
74046
- blackBright: f3("\x1B[90m", "\x1B[39m"),
74047
- redBright: f3("\x1B[91m", "\x1B[39m"),
74048
- greenBright: f3("\x1B[92m", "\x1B[39m"),
74049
- yellowBright: f3("\x1B[93m", "\x1B[39m"),
74050
- blueBright: f3("\x1B[94m", "\x1B[39m"),
74051
- magentaBright: f3("\x1B[95m", "\x1B[39m"),
74052
- cyanBright: f3("\x1B[96m", "\x1B[39m"),
74053
- whiteBright: f3("\x1B[97m", "\x1B[39m"),
74054
- bgBlackBright: f3("\x1B[100m", "\x1B[49m"),
74055
- bgRedBright: f3("\x1B[101m", "\x1B[49m"),
74056
- bgGreenBright: f3("\x1B[102m", "\x1B[49m"),
74057
- bgYellowBright: f3("\x1B[103m", "\x1B[49m"),
74058
- bgBlueBright: f3("\x1B[104m", "\x1B[49m"),
74059
- bgMagentaBright: f3("\x1B[105m", "\x1B[49m"),
74060
- bgCyanBright: f3("\x1B[106m", "\x1B[49m"),
74061
- bgWhiteBright: f3("\x1B[107m", "\x1B[49m")
74062
- };
74063
- };
74064
- module.exports = createColors();
74065
- module.exports.createColors = createColors;
74066
- });
74067
-
74068
74009
  // src/commands/watch/phases/implementation-git-helpers.ts
74069
74010
  import { spawn as spawn5 } from "node:child_process";
74070
74011
  async function getCurrentBranch2(cwd2) {
@@ -74173,9 +74114,9 @@ __export(exports_worktree_manager, {
74173
74114
  });
74174
74115
  import { existsSync as existsSync70 } from "node:fs";
74175
74116
  import { readFile as readFile66, writeFile as writeFile37 } from "node:fs/promises";
74176
- import { join as join151 } from "node:path";
74117
+ import { join as join152 } from "node:path";
74177
74118
  async function createWorktree(projectDir, issueNumber, baseBranch) {
74178
- const worktreePath = join151(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
74119
+ const worktreePath = join152(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
74179
74120
  const branchName = `ck-watch/issue-${issueNumber}`;
74180
74121
  await spawnAndCollect("git", ["fetch", "origin", baseBranch], projectDir).catch(() => {
74181
74122
  logger.warning(`[worktree] Could not fetch origin/${baseBranch}, using local`);
@@ -74193,7 +74134,7 @@ async function createWorktree(projectDir, issueNumber, baseBranch) {
74193
74134
  return worktreePath;
74194
74135
  }
74195
74136
  async function removeWorktree(projectDir, issueNumber) {
74196
- const worktreePath = join151(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
74137
+ const worktreePath = join152(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
74197
74138
  const branchName = `ck-watch/issue-${issueNumber}`;
74198
74139
  try {
74199
74140
  await spawnAndCollect("git", ["worktree", "remove", worktreePath, "--force"], projectDir);
@@ -74207,7 +74148,7 @@ async function listActiveWorktrees(projectDir) {
74207
74148
  try {
74208
74149
  const output2 = await spawnAndCollect("git", ["worktree", "list", "--porcelain"], projectDir);
74209
74150
  const issueNumbers = [];
74210
- const worktreePrefix = join151(projectDir, WORKTREE_DIR, "issue-").replace(/\\/g, "/");
74151
+ const worktreePrefix = join152(projectDir, WORKTREE_DIR, "issue-").replace(/\\/g, "/");
74211
74152
  for (const line of output2.split(`
74212
74153
  `)) {
74213
74154
  if (line.startsWith("worktree ")) {
@@ -74235,7 +74176,7 @@ async function cleanupAllWorktrees(projectDir) {
74235
74176
  await spawnAndCollect("git", ["worktree", "prune"], projectDir).catch(() => {});
74236
74177
  }
74237
74178
  async function ensureGitignore(projectDir) {
74238
- const gitignorePath = join151(projectDir, ".gitignore");
74179
+ const gitignorePath = join152(projectDir, ".gitignore");
74239
74180
  try {
74240
74181
  const content = existsSync70(gitignorePath) ? await readFile66(gitignorePath, "utf-8") : "";
74241
74182
  if (!content.includes(".worktrees")) {
@@ -74342,7 +74283,7 @@ import { createHash as createHash9 } from "node:crypto";
74342
74283
  import { existsSync as existsSync76, mkdirSync as mkdirSync5, readFileSync as readFileSync18, readdirSync as readdirSync11, statSync as statSync14 } from "node:fs";
74343
74284
  import { rename as rename14, writeFile as writeFile39 } from "node:fs/promises";
74344
74285
  import { homedir as homedir53 } from "node:os";
74345
- import { basename as basename31, join as join158 } from "node:path";
74286
+ import { basename as basename31, join as join159 } from "node:path";
74346
74287
  function getCachedContext(repoPath) {
74347
74288
  const cachePath = getCacheFilePath(repoPath);
74348
74289
  if (!existsSync76(cachePath))
@@ -74385,25 +74326,25 @@ function computeSourceHash(repoPath) {
74385
74326
  }
74386
74327
  function getDocSourcePaths(repoPath) {
74387
74328
  const paths = [];
74388
- const docsDir = join158(repoPath, "docs");
74329
+ const docsDir = join159(repoPath, "docs");
74389
74330
  if (existsSync76(docsDir)) {
74390
74331
  try {
74391
74332
  const files = readdirSync11(docsDir);
74392
74333
  for (const f3 of files) {
74393
74334
  if (f3.endsWith(".md"))
74394
- paths.push(join158(docsDir, f3));
74335
+ paths.push(join159(docsDir, f3));
74395
74336
  }
74396
74337
  } catch {}
74397
74338
  }
74398
- const readme = join158(repoPath, "README.md");
74339
+ const readme = join159(repoPath, "README.md");
74399
74340
  if (existsSync76(readme))
74400
74341
  paths.push(readme);
74401
- const stylesDir = join158(repoPath, "assets", "writing-styles");
74342
+ const stylesDir = join159(repoPath, "assets", "writing-styles");
74402
74343
  if (existsSync76(stylesDir)) {
74403
74344
  try {
74404
74345
  const files = readdirSync11(stylesDir);
74405
74346
  for (const f3 of files) {
74406
- paths.push(join158(stylesDir, f3));
74347
+ paths.push(join159(stylesDir, f3));
74407
74348
  }
74408
74349
  } catch {}
74409
74350
  }
@@ -74412,11 +74353,11 @@ function getDocSourcePaths(repoPath) {
74412
74353
  function getCacheFilePath(repoPath) {
74413
74354
  const repoName = basename31(repoPath).replace(/[^a-zA-Z0-9_-]/g, "_");
74414
74355
  const pathHash = createHash9("sha256").update(repoPath).digest("hex").slice(0, 8);
74415
- return join158(CACHE_DIR, `${repoName}-${pathHash}-context-cache.json`);
74356
+ return join159(CACHE_DIR, `${repoName}-${pathHash}-context-cache.json`);
74416
74357
  }
74417
74358
  var CACHE_DIR, CACHE_TTL_MS5;
74418
74359
  var init_context_cache_manager = __esm(() => {
74419
- CACHE_DIR = join158(homedir53(), ".claudekit", "cache");
74360
+ CACHE_DIR = join159(homedir53(), ".claudekit", "cache");
74420
74361
  CACHE_TTL_MS5 = 24 * 60 * 60 * 1000;
74421
74362
  });
74422
74363
 
@@ -74597,7 +74538,7 @@ function extractContentFromResponse(response) {
74597
74538
  // src/commands/content/phases/docs-summarizer.ts
74598
74539
  import { execSync as execSync7 } from "node:child_process";
74599
74540
  import { existsSync as existsSync77, readFileSync as readFileSync19, readdirSync as readdirSync12 } from "node:fs";
74600
- import { join as join159 } from "node:path";
74541
+ import { join as join160 } from "node:path";
74601
74542
  async function summarizeProjectDocs(repoPath, contentLogger) {
74602
74543
  const rawContent = collectRawDocs(repoPath);
74603
74544
  if (rawContent.total.length < 200) {
@@ -74651,12 +74592,12 @@ function collectRawDocs(repoPath) {
74651
74592
  return capped;
74652
74593
  };
74653
74594
  const docsContent = [];
74654
- const docsDir = join159(repoPath, "docs");
74595
+ const docsDir = join160(repoPath, "docs");
74655
74596
  if (existsSync77(docsDir)) {
74656
74597
  try {
74657
74598
  const files = readdirSync12(docsDir).filter((f3) => f3.endsWith(".md")).sort();
74658
74599
  for (const f3 of files) {
74659
- const content = readCapped(join159(docsDir, f3), 5000);
74600
+ const content = readCapped(join160(docsDir, f3), 5000);
74660
74601
  if (content) {
74661
74602
  docsContent.push(`### ${f3}
74662
74603
  ${content}`);
@@ -74670,21 +74611,21 @@ ${content}`);
74670
74611
  let brand = "";
74671
74612
  const brandCandidates = ["docs/brand-guidelines.md", "docs/design-guidelines.md"];
74672
74613
  for (const p of brandCandidates) {
74673
- brand = readCapped(join159(repoPath, p), 3000);
74614
+ brand = readCapped(join160(repoPath, p), 3000);
74674
74615
  if (brand)
74675
74616
  break;
74676
74617
  }
74677
74618
  let styles3 = "";
74678
- const stylesDir = join159(repoPath, "assets", "writing-styles");
74619
+ const stylesDir = join160(repoPath, "assets", "writing-styles");
74679
74620
  if (existsSync77(stylesDir)) {
74680
74621
  try {
74681
74622
  const files = readdirSync12(stylesDir).slice(0, 3);
74682
- styles3 = files.map((f3) => readCapped(join159(stylesDir, f3), 1000)).filter(Boolean).join(`
74623
+ styles3 = files.map((f3) => readCapped(join160(stylesDir, f3), 1000)).filter(Boolean).join(`
74683
74624
 
74684
74625
  `);
74685
74626
  } catch {}
74686
74627
  }
74687
- const readme = readCapped(join159(repoPath, "README.md"), 3000);
74628
+ const readme = readCapped(join160(repoPath, "README.md"), 3000);
74688
74629
  const total = [docs, brand, styles3, readme].join(`
74689
74630
  `);
74690
74631
  return { docs, brand, styles: styles3, readme, total };
@@ -74871,9 +74812,9 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
74871
74812
  import { execSync as execSync8 } from "node:child_process";
74872
74813
  import { existsSync as existsSync78, mkdirSync as mkdirSync6, readdirSync as readdirSync13 } from "node:fs";
74873
74814
  import { homedir as homedir54 } from "node:os";
74874
- import { join as join160 } from "node:path";
74815
+ import { join as join161 } from "node:path";
74875
74816
  async function generatePhoto(_content, context, config, platform18, contentId, contentLogger) {
74876
- const mediaDir = join160(config.contentDir.replace(/^~/, homedir54()), "media", String(contentId));
74817
+ const mediaDir = join161(config.contentDir.replace(/^~/, homedir54()), "media", String(contentId));
74877
74818
  if (!existsSync78(mediaDir)) {
74878
74819
  mkdirSync6(mediaDir, { recursive: true });
74879
74820
  }
@@ -74898,7 +74839,7 @@ async function generatePhoto(_content, context, config, platform18, contentId, c
74898
74839
  const imageFile = files.find((f3) => /\.(png|jpg|jpeg|webp)$/i.test(f3));
74899
74840
  if (imageFile) {
74900
74841
  const ext2 = imageFile.split(".").pop() ?? "png";
74901
- return { path: join160(mediaDir, imageFile), ...dimensions, format: ext2 };
74842
+ return { path: join161(mediaDir, imageFile), ...dimensions, format: ext2 };
74902
74843
  }
74903
74844
  contentLogger.warn(`Photo generation produced no image for content ${contentId}`);
74904
74845
  return null;
@@ -74988,7 +74929,7 @@ var init_content_creator = __esm(() => {
74988
74929
  // src/commands/content/phases/content-logger.ts
74989
74930
  import { createWriteStream as createWriteStream4, existsSync as existsSync79, mkdirSync as mkdirSync7, statSync as statSync15 } from "node:fs";
74990
74931
  import { homedir as homedir55 } from "node:os";
74991
- import { join as join161 } from "node:path";
74932
+ import { join as join162 } from "node:path";
74992
74933
 
74993
74934
  class ContentLogger {
74994
74935
  stream = null;
@@ -74996,7 +74937,7 @@ class ContentLogger {
74996
74937
  logDir;
74997
74938
  maxBytes;
74998
74939
  constructor(maxBytes = 0) {
74999
- this.logDir = join161(homedir55(), ".claudekit", "logs");
74940
+ this.logDir = join162(homedir55(), ".claudekit", "logs");
75000
74941
  this.maxBytes = maxBytes;
75001
74942
  }
75002
74943
  init() {
@@ -75028,7 +74969,7 @@ class ContentLogger {
75028
74969
  }
75029
74970
  }
75030
74971
  getLogPath() {
75031
- return join161(this.logDir, `content-${this.getDateStr()}.log`);
74972
+ return join162(this.logDir, `content-${this.getDateStr()}.log`);
75032
74973
  }
75033
74974
  write(level, message) {
75034
74975
  this.rotateIfNeeded();
@@ -75045,18 +74986,18 @@ class ContentLogger {
75045
74986
  if (dateStr !== this.currentDate) {
75046
74987
  this.close();
75047
74988
  this.currentDate = dateStr;
75048
- const logPath = join161(this.logDir, `content-${dateStr}.log`);
74989
+ const logPath = join162(this.logDir, `content-${dateStr}.log`);
75049
74990
  this.stream = createWriteStream4(logPath, { flags: "a", mode: 384 });
75050
74991
  return;
75051
74992
  }
75052
74993
  if (this.maxBytes > 0 && this.stream) {
75053
- const logPath = join161(this.logDir, `content-${this.currentDate}.log`);
74994
+ const logPath = join162(this.logDir, `content-${this.currentDate}.log`);
75054
74995
  try {
75055
74996
  const stat25 = statSync15(logPath);
75056
74997
  if (stat25.size >= this.maxBytes) {
75057
74998
  this.close();
75058
74999
  const suffix = Date.now();
75059
- const rotatedPath = join161(this.logDir, `content-${this.currentDate}-${suffix}.log`);
75000
+ const rotatedPath = join162(this.logDir, `content-${this.currentDate}-${suffix}.log`);
75060
75001
  import("node:fs/promises").then(({ rename: rename15 }) => rename15(logPath, rotatedPath).catch(() => {}));
75061
75002
  this.stream = createWriteStream4(logPath, { flags: "w", mode: 384 });
75062
75003
  }
@@ -75282,7 +75223,7 @@ function isNoiseCommit(title, author) {
75282
75223
  // src/commands/content/phases/change-detector.ts
75283
75224
  import { execSync as execSync10, spawnSync as spawnSync9 } from "node:child_process";
75284
75225
  import { existsSync as existsSync81, readFileSync as readFileSync20, readdirSync as readdirSync14, statSync as statSync16 } from "node:fs";
75285
- import { join as join162 } from "node:path";
75226
+ import { join as join163 } from "node:path";
75286
75227
  function detectCommits(repo, since) {
75287
75228
  try {
75288
75229
  const fetchUrl = sshToHttps(repo.remoteUrl);
@@ -75391,7 +75332,7 @@ function detectTags(repo, since) {
75391
75332
  }
75392
75333
  }
75393
75334
  function detectCompletedPlans(repo, since) {
75394
- const plansDir = join162(repo.path, "plans");
75335
+ const plansDir = join163(repo.path, "plans");
75395
75336
  if (!existsSync81(plansDir))
75396
75337
  return [];
75397
75338
  const sinceMs = new Date(since).getTime();
@@ -75401,7 +75342,7 @@ function detectCompletedPlans(repo, since) {
75401
75342
  for (const entry of entries) {
75402
75343
  if (!entry.isDirectory())
75403
75344
  continue;
75404
- const planFile = join162(plansDir, entry.name, "plan.md");
75345
+ const planFile = join163(plansDir, entry.name, "plan.md");
75405
75346
  if (!existsSync81(planFile))
75406
75347
  continue;
75407
75348
  try {
@@ -75479,7 +75420,7 @@ function classifyCommit(event) {
75479
75420
  // src/commands/content/phases/repo-discoverer.ts
75480
75421
  import { execSync as execSync11 } from "node:child_process";
75481
75422
  import { readdirSync as readdirSync15 } from "node:fs";
75482
- import { join as join163 } from "node:path";
75423
+ import { join as join164 } from "node:path";
75483
75424
  function discoverRepos2(cwd2) {
75484
75425
  const repos = [];
75485
75426
  if (isGitRepoRoot(cwd2)) {
@@ -75492,7 +75433,7 @@ function discoverRepos2(cwd2) {
75492
75433
  for (const entry of entries) {
75493
75434
  if (!entry.isDirectory() || entry.name.startsWith("."))
75494
75435
  continue;
75495
- const dirPath = join163(cwd2, entry.name);
75436
+ const dirPath = join164(cwd2, entry.name);
75496
75437
  if (isGitRepoRoot(dirPath)) {
75497
75438
  const info = getRepoInfo(dirPath);
75498
75439
  if (info)
@@ -76160,9 +76101,9 @@ var init_types6 = __esm(() => {
76160
76101
 
76161
76102
  // src/commands/content/phases/state-manager.ts
76162
76103
  import { readFile as readFile68, rename as rename15, writeFile as writeFile40 } from "node:fs/promises";
76163
- import { join as join164 } from "node:path";
76104
+ import { join as join165 } from "node:path";
76164
76105
  async function loadContentConfig(projectDir) {
76165
- const configPath = join164(projectDir, CK_CONFIG_FILE2);
76106
+ const configPath = join165(projectDir, CK_CONFIG_FILE2);
76166
76107
  try {
76167
76108
  const raw2 = await readFile68(configPath, "utf-8");
76168
76109
  const json = JSON.parse(raw2);
@@ -76172,13 +76113,13 @@ async function loadContentConfig(projectDir) {
76172
76113
  }
76173
76114
  }
76174
76115
  async function saveContentConfig(projectDir, config) {
76175
- const configPath = join164(projectDir, CK_CONFIG_FILE2);
76116
+ const configPath = join165(projectDir, CK_CONFIG_FILE2);
76176
76117
  const json = await readJsonSafe(configPath);
76177
76118
  json.content = { ...json.content, ...config };
76178
76119
  await atomicWrite2(configPath, json);
76179
76120
  }
76180
76121
  async function loadContentState(projectDir) {
76181
- const configPath = join164(projectDir, CK_CONFIG_FILE2);
76122
+ const configPath = join165(projectDir, CK_CONFIG_FILE2);
76182
76123
  try {
76183
76124
  const raw2 = await readFile68(configPath, "utf-8");
76184
76125
  const json = JSON.parse(raw2);
@@ -76189,7 +76130,7 @@ async function loadContentState(projectDir) {
76189
76130
  }
76190
76131
  }
76191
76132
  async function saveContentState(projectDir, state) {
76192
- const configPath = join164(projectDir, CK_CONFIG_FILE2);
76133
+ const configPath = join165(projectDir, CK_CONFIG_FILE2);
76193
76134
  const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
76194
76135
  for (const key of Object.keys(state.dailyPostCounts)) {
76195
76136
  const dateStr = key.slice(-10);
@@ -76471,7 +76412,7 @@ var init_platform_setup_x = __esm(() => {
76471
76412
 
76472
76413
  // src/commands/content/phases/setup-wizard.ts
76473
76414
  import { existsSync as existsSync82 } from "node:fs";
76474
- import { join as join165 } from "node:path";
76415
+ import { join as join166 } from "node:path";
76475
76416
  async function runSetupWizard2(cwd2, contentLogger) {
76476
76417
  console.log();
76477
76418
  oe(import_picocolors43.default.bgCyan(import_picocolors43.default.white(" CK Content — Multi-Channel Content Engine ")));
@@ -76539,8 +76480,8 @@ async function showRepoSummary(cwd2) {
76539
76480
  function detectBrandAssets(cwd2, contentLogger) {
76540
76481
  const repos = discoverRepos2(cwd2);
76541
76482
  for (const repo of repos) {
76542
- const hasGuidelines = existsSync82(join165(repo.path, "docs", "brand-guidelines.md"));
76543
- const hasStyles = existsSync82(join165(repo.path, "assets", "writing-styles"));
76483
+ const hasGuidelines = existsSync82(join166(repo.path, "docs", "brand-guidelines.md"));
76484
+ const hasStyles = existsSync82(join166(repo.path, "assets", "writing-styles"));
76544
76485
  if (!hasGuidelines) {
76545
76486
  f2.warning(`${repo.name}: No docs/brand-guidelines.md — content will use generic tone.`);
76546
76487
  contentLogger.warn(`${repo.name}: missing docs/brand-guidelines.md`);
@@ -76682,9 +76623,9 @@ __export(exports_content_subcommands, {
76682
76623
  });
76683
76624
  import { existsSync as existsSync84, readFileSync as readFileSync21, unlinkSync as unlinkSync6 } from "node:fs";
76684
76625
  import { homedir as homedir57 } from "node:os";
76685
- import { join as join166 } from "node:path";
76626
+ import { join as join167 } from "node:path";
76686
76627
  function isDaemonRunning() {
76687
- const lockFile = join166(LOCK_DIR, `${LOCK_NAME2}.lock`);
76628
+ const lockFile = join167(LOCK_DIR, `${LOCK_NAME2}.lock`);
76688
76629
  if (!existsSync84(lockFile))
76689
76630
  return { running: false, pid: null };
76690
76631
  try {
@@ -76716,7 +76657,7 @@ async function startContent(options2) {
76716
76657
  await contentCommand(options2);
76717
76658
  }
76718
76659
  async function stopContent() {
76719
- const lockFile = join166(LOCK_DIR, `${LOCK_NAME2}.lock`);
76660
+ const lockFile = join167(LOCK_DIR, `${LOCK_NAME2}.lock`);
76720
76661
  if (!existsSync84(lockFile)) {
76721
76662
  logger.info("Content daemon is not running.");
76722
76663
  return;
@@ -76755,9 +76696,9 @@ async function statusContent() {
76755
76696
  } catch {}
76756
76697
  }
76757
76698
  async function logsContent(options2) {
76758
- const logDir = join166(homedir57(), ".claudekit", "logs");
76699
+ const logDir = join167(homedir57(), ".claudekit", "logs");
76759
76700
  const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
76760
- const logPath = join166(logDir, `content-${dateStr}.log`);
76701
+ const logPath = join167(logDir, `content-${dateStr}.log`);
76761
76702
  if (!existsSync84(logPath)) {
76762
76703
  logger.info("No content logs found for today.");
76763
76704
  return;
@@ -76789,13 +76730,13 @@ var init_content_subcommands = __esm(() => {
76789
76730
  init_setup_wizard();
76790
76731
  init_state_manager();
76791
76732
  init_content_review_commands();
76792
- LOCK_DIR = join166(homedir57(), ".claudekit", "locks");
76733
+ LOCK_DIR = join167(homedir57(), ".claudekit", "locks");
76793
76734
  });
76794
76735
 
76795
76736
  // src/commands/content/content-command.ts
76796
76737
  import { existsSync as existsSync85, mkdirSync as mkdirSync9, unlinkSync as unlinkSync7, writeFileSync as writeFileSync7 } from "node:fs";
76797
76738
  import { homedir as homedir58 } from "node:os";
76798
- import { join as join167 } from "node:path";
76739
+ import { join as join168 } from "node:path";
76799
76740
  async function contentCommand(options2) {
76800
76741
  const cwd2 = process.cwd();
76801
76742
  const contentLogger = new ContentLogger;
@@ -76973,8 +76914,8 @@ var init_content_command = __esm(() => {
76973
76914
  init_publisher();
76974
76915
  init_review_manager();
76975
76916
  init_state_manager();
76976
- LOCK_DIR2 = join167(homedir58(), ".claudekit", "locks");
76977
- LOCK_FILE = join167(LOCK_DIR2, "ck-content.lock");
76917
+ LOCK_DIR2 = join168(homedir58(), ".claudekit", "locks");
76918
+ LOCK_FILE = join168(LOCK_DIR2, "ck-content.lock");
76978
76919
  });
76979
76920
 
76980
76921
  // src/commands/content/index.ts
@@ -85272,7 +85213,7 @@ function buildDuplicateInventoryCheck(projectSkills, globalSkills) {
85272
85213
  if (duplicates.length === 0) {
85273
85214
  return pass("ck-skill-inventory", "Skill Inventory", "No duplicate project/global skills");
85274
85215
  }
85275
- return warn("ck-skill-inventory", "Skill Inventory", `${duplicates.length} duplicate project/global skill(s)`, duplicates, "Keep one installation scope per skill; inspect with: ck skills list --installed");
85216
+ return warn("ck-skill-inventory", "Skill Inventory", `${duplicates.length} duplicate project/global skill(s)`, duplicates, "Keep one installation scope per skill; inspect with: ck skills --list --installed");
85276
85217
  }
85277
85218
  function buildSkillOverridesCheck(settingsPath, read) {
85278
85219
  if (!read.settings || !Object.prototype.hasOwnProperty.call(read.settings, "skillOverrides")) {
@@ -107501,7 +107442,7 @@ import { basename as basename27, join as join142, resolve as resolve46 } from "n
107501
107442
  init_logger();
107502
107443
 
107503
107444
  // src/ui/ck-cli-design/tokens.ts
107504
- var import_picocolors27 = __toESM(require_picocolors2(), 1);
107445
+ var import_picocolors27 = __toESM(require_picocolors(), 1);
107505
107446
  import { homedir as homedir47, platform as platform16 } from "node:os";
107506
107447
  import { resolve as resolve45, win32 as win322 } from "node:path";
107507
107448
  var PANEL_MIN_WIDTH = 60;
@@ -111449,14 +111390,48 @@ init_skill_catalog_generator();
111449
111390
  init_skill_search_index();
111450
111391
  init_logger();
111451
111392
  init_agents();
111452
- init_skills_discovery();
111453
- init_skills_installer();
111454
- init_skills_registry();
111455
- init_skills_uninstaller();
111456
111393
  var import_gray_matter12 = __toESM(require_gray_matter(), 1);
111457
111394
  var import_picocolors37 = __toESM(require_picocolors(), 1);
111458
111395
  import { readFile as readFile65 } from "node:fs/promises";
111396
+ import { join as join149 } from "node:path";
111397
+
111398
+ // src/commands/skills/installed-skills-inventory.ts
111459
111399
  import { join as join148 } from "node:path";
111400
+ init_path_resolver();
111401
+ var SCOPE_SORT_ORDER = {
111402
+ project: 0,
111403
+ global: 1
111404
+ };
111405
+ async function getActiveClaudeSkillInstallations(options2 = {}) {
111406
+ const projectDir = options2.projectDir ?? process.cwd();
111407
+ const globalDir = options2.globalDir ?? PathResolver.getGlobalKitDir();
111408
+ const [projectSkills, globalSkills] = await Promise.all([
111409
+ scanSkills2(join148(projectDir, ".claude", "skills")),
111410
+ scanSkills2(join148(globalDir, "skills"))
111411
+ ]);
111412
+ const projectIds = new Set(projectSkills.map((skill) => skill.id));
111413
+ const globalIds = new Set(globalSkills.map((skill) => skill.id));
111414
+ return [
111415
+ ...projectSkills.map((skill) => ({
111416
+ skill: skill.id,
111417
+ scope: "project",
111418
+ path: skill.file,
111419
+ duplicateAcrossScopes: globalIds.has(skill.id)
111420
+ })),
111421
+ ...globalSkills.map((skill) => ({
111422
+ skill: skill.id,
111423
+ scope: "global",
111424
+ path: skill.file,
111425
+ duplicateAcrossScopes: projectIds.has(skill.id)
111426
+ }))
111427
+ ].sort((a3, b3) => a3.skill.localeCompare(b3.skill) || SCOPE_SORT_ORDER[a3.scope] - SCOPE_SORT_ORDER[b3.scope]);
111428
+ }
111429
+
111430
+ // src/commands/skills/skills-command.ts
111431
+ init_skills_discovery();
111432
+ init_skills_installer();
111433
+ init_skills_registry();
111434
+ init_skills_uninstaller();
111460
111435
 
111461
111436
  // src/commands/skills/types.ts
111462
111437
  init_zod();
@@ -111592,7 +111567,7 @@ async function handleValidate2(sourcePath) {
111592
111567
  spinner.stop(`Checked ${skills.length} skill(s)`);
111593
111568
  let hasIssues = false;
111594
111569
  for (const skill of skills) {
111595
- const skillMdPath = join148(skill.path, "SKILL.md");
111570
+ const skillMdPath = join149(skill.path, "SKILL.md");
111596
111571
  try {
111597
111572
  const content = await readFile65(skillMdPath, "utf-8");
111598
111573
  const { data } = import_gray_matter12.default(content, {
@@ -111628,30 +111603,55 @@ async function detectInstalledAgents2() {
111628
111603
  }
111629
111604
  async function listSkills2(showInstalled) {
111630
111605
  if (showInstalled) {
111631
- const installations = await getInstalledSkills();
111632
- if (installations.length === 0) {
111633
- f2.warn("No skills installed via ck skills.");
111606
+ const [installations, activeClaudeSkills] = await Promise.all([
111607
+ getInstalledSkills(),
111608
+ getActiveClaudeSkillInstallations()
111609
+ ]);
111610
+ if (installations.length === 0 && activeClaudeSkills.length === 0) {
111611
+ f2.warn("No installed skills found.");
111634
111612
  return;
111635
111613
  }
111636
111614
  console.log();
111637
- f2.step(import_picocolors37.default.bold("Installed Skills"));
111638
- console.log();
111639
- const bySkill = new Map;
111640
- for (const inst of installations) {
111641
- const list3 = bySkill.get(inst.skill) || [];
111642
- list3.push(inst);
111643
- bySkill.set(inst.skill, list3);
111615
+ if (activeClaudeSkills.length > 0) {
111616
+ f2.step(import_picocolors37.default.bold("Active Claude Code Skills"));
111617
+ console.log();
111618
+ const bySkill = new Map;
111619
+ for (const inst of activeClaudeSkills) {
111620
+ const list3 = bySkill.get(inst.skill) || [];
111621
+ list3.push(inst);
111622
+ bySkill.set(inst.skill, list3);
111623
+ }
111624
+ for (const [skill, installs] of bySkill) {
111625
+ const duplicate = installs.some((inst) => inst.duplicateAcrossScopes) ? ` ${import_picocolors37.default.yellow("(project/global duplicate)")}` : "";
111626
+ console.log(` ${import_picocolors37.default.cyan(skill)}${duplicate}`);
111627
+ for (const inst of installs) {
111628
+ console.log(` ${import_picocolors37.default.dim("→")} ${inst.scope}: ${import_picocolors37.default.dim(inst.path)}`);
111629
+ }
111630
+ }
111631
+ console.log();
111632
+ console.log(import_picocolors37.default.dim(` ${activeClaudeSkills.length} active Claude Code skill installation(s)`));
111633
+ console.log();
111644
111634
  }
111645
- for (const [skill, installs] of bySkill) {
111646
- console.log(` ${import_picocolors37.default.cyan(skill)}`);
111647
- for (const inst of installs) {
111648
- const scope = inst.global ? "global" : "project";
111649
- console.log(` ${import_picocolors37.default.dim("→")} ${inst.agent} (${scope}): ${import_picocolors37.default.dim(inst.path)}`);
111635
+ if (installations.length > 0) {
111636
+ f2.step(import_picocolors37.default.bold("Registry-managed Agent Skills"));
111637
+ console.log();
111638
+ const bySkill = new Map;
111639
+ for (const inst of installations) {
111640
+ const list3 = bySkill.get(inst.skill) || [];
111641
+ list3.push(inst);
111642
+ bySkill.set(inst.skill, list3);
111650
111643
  }
111644
+ for (const [skill, installs] of bySkill) {
111645
+ console.log(` ${import_picocolors37.default.cyan(skill)}`);
111646
+ for (const inst of installs) {
111647
+ const scope = inst.global ? "global" : "project";
111648
+ console.log(` ${import_picocolors37.default.dim("→")} ${inst.agent} (${scope}): ${import_picocolors37.default.dim(inst.path)}`);
111649
+ }
111650
+ }
111651
+ console.log();
111652
+ console.log(import_picocolors37.default.dim(` ${installations.length} registry-managed installation(s) across ${bySkill.size} skill(s)`));
111651
111653
  }
111652
111654
  console.log();
111653
- console.log(import_picocolors37.default.dim(` ${installations.length} installation(s) across ${bySkill.size} skill(s)`));
111654
- console.log();
111655
111655
  return;
111656
111656
  }
111657
111657
  const sourcePath = getSkillSourcePath();
@@ -112150,7 +112150,7 @@ async function detectInstallations() {
112150
112150
 
112151
112151
  // src/commands/uninstall/removal-handler.ts
112152
112152
  import { readdirSync as readdirSync10, rmSync as rmSync5 } from "node:fs";
112153
- import { basename as basename30, join as join150, resolve as resolve53, sep as sep13 } from "node:path";
112153
+ import { basename as basename30, join as join151, resolve as resolve53, sep as sep13 } from "node:path";
112154
112154
  init_logger();
112155
112155
  init_safe_prompts();
112156
112156
  init_safe_spinner();
@@ -112159,7 +112159,7 @@ var import_fs_extra41 = __toESM(require_lib(), 1);
112159
112159
  // src/commands/uninstall/analysis-handler.ts
112160
112160
  init_metadata_migration();
112161
112161
  import { readdirSync as readdirSync9, rmSync as rmSync4 } from "node:fs";
112162
- import { dirname as dirname45, join as join149 } from "node:path";
112162
+ import { dirname as dirname45, join as join150 } from "node:path";
112163
112163
  init_logger();
112164
112164
  init_safe_prompts();
112165
112165
  var import_fs_extra40 = __toESM(require_lib(), 1);
@@ -112219,7 +112219,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
112219
112219
  const remainingFiles = metadata.kits?.[remainingKit]?.files || [];
112220
112220
  for (const file of remainingFiles) {
112221
112221
  const relativePath = normalizeTrackedPath(file.path);
112222
- if (await import_fs_extra40.pathExists(join149(installation.path, relativePath))) {
112222
+ if (await import_fs_extra40.pathExists(join150(installation.path, relativePath))) {
112223
112223
  result.retainedManifestPaths.push(relativePath);
112224
112224
  }
112225
112225
  }
@@ -112227,7 +112227,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
112227
112227
  const kitFiles = metadata.kits[kit].files || [];
112228
112228
  for (const trackedFile of kitFiles) {
112229
112229
  const relativePath = normalizeTrackedPath(trackedFile.path);
112230
- const filePath = join149(installation.path, relativePath);
112230
+ const filePath = join150(installation.path, relativePath);
112231
112231
  if (preservedPaths.has(relativePath)) {
112232
112232
  result.toPreserve.push({ path: relativePath, reason: "shared with other kit" });
112233
112233
  continue;
@@ -112260,7 +112260,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
112260
112260
  }
112261
112261
  for (const trackedFile of allTrackedFiles) {
112262
112262
  const relativePath = normalizeTrackedPath(trackedFile.path);
112263
- const filePath = join149(installation.path, relativePath);
112263
+ const filePath = join150(installation.path, relativePath);
112264
112264
  const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
112265
112265
  if (!ownershipResult.exists)
112266
112266
  continue;
@@ -112403,7 +112403,7 @@ async function removeInstallations(installations, options2) {
112403
112403
  let removedCount = 0;
112404
112404
  let cleanedDirs = 0;
112405
112405
  for (const item of analysis.toDelete) {
112406
- const filePath = join150(installation.path, item.path);
112406
+ const filePath = join151(installation.path, item.path);
112407
112407
  if (!await import_fs_extra41.pathExists(filePath))
112408
112408
  continue;
112409
112409
  if (!await isPathSafeToRemove(filePath, installation.path)) {
@@ -112812,7 +112812,7 @@ ${import_picocolors40.default.bold(import_picocolors40.default.cyan(result.kitCo
112812
112812
  init_logger();
112813
112813
  import { existsSync as existsSync75 } from "node:fs";
112814
112814
  import { rm as rm17 } from "node:fs/promises";
112815
- import { join as join157 } from "node:path";
112815
+ import { join as join158 } from "node:path";
112816
112816
  var import_picocolors41 = __toESM(require_picocolors(), 1);
112817
112817
 
112818
112818
  // src/commands/watch/phases/implementation-runner.ts
@@ -113331,7 +113331,7 @@ function spawnAndCollect3(command, args) {
113331
113331
 
113332
113332
  // src/commands/watch/phases/issue-processor.ts
113333
113333
  import { mkdir as mkdir39, writeFile as writeFile38 } from "node:fs/promises";
113334
- import { join as join153 } from "node:path";
113334
+ import { join as join154 } from "node:path";
113335
113335
 
113336
113336
  // src/commands/watch/phases/approval-detector.ts
113337
113337
  init_logger();
@@ -113709,9 +113709,9 @@ async function checkAwaitingApproval(state, setup, options2, watchLog, projectDi
113709
113709
 
113710
113710
  // src/commands/watch/phases/plan-dir-finder.ts
113711
113711
  import { readdir as readdir44, stat as stat23 } from "node:fs/promises";
113712
- import { join as join152 } from "node:path";
113712
+ import { join as join153 } from "node:path";
113713
113713
  async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
113714
- const plansRoot = join152(cwd2, "plans");
113714
+ const plansRoot = join153(cwd2, "plans");
113715
113715
  try {
113716
113716
  const entries = await readdir44(plansRoot);
113717
113717
  const tenMinAgo = Date.now() - 10 * 60 * 1000;
@@ -113720,14 +113720,14 @@ async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
113720
113720
  for (const entry of entries) {
113721
113721
  if (entry === "watch" || entry === "reports" || entry === "visuals")
113722
113722
  continue;
113723
- const dirPath = join152(plansRoot, entry);
113723
+ const dirPath = join153(plansRoot, entry);
113724
113724
  const dirStat = await stat23(dirPath);
113725
113725
  if (!dirStat.isDirectory())
113726
113726
  continue;
113727
113727
  if (dirStat.mtimeMs < tenMinAgo)
113728
113728
  continue;
113729
113729
  try {
113730
- await stat23(join152(dirPath, "plan.md"));
113730
+ await stat23(join153(dirPath, "plan.md"));
113731
113731
  } catch {
113732
113732
  continue;
113733
113733
  }
@@ -113958,13 +113958,13 @@ async function handlePlanGeneration(issue, state, config, setup, options2, watch
113958
113958
  stats.plansCreated++;
113959
113959
  const detectedPlanDir = await findRecentPlanDir(projectDir, issue.number, watchLog);
113960
113960
  if (detectedPlanDir) {
113961
- state.activeIssues[numStr].planPath = join153(detectedPlanDir, "plan.md");
113961
+ state.activeIssues[numStr].planPath = join154(detectedPlanDir, "plan.md");
113962
113962
  watchLog.info(`Plan directory detected: ${detectedPlanDir}`);
113963
113963
  } else {
113964
113964
  try {
113965
- const planDir = join153(projectDir, "plans", "watch");
113965
+ const planDir = join154(projectDir, "plans", "watch");
113966
113966
  await mkdir39(planDir, { recursive: true });
113967
- const planFilePath = join153(planDir, `issue-${issue.number}-plan.md`);
113967
+ const planFilePath = join154(planDir, `issue-${issue.number}-plan.md`);
113968
113968
  await writeFile38(planFilePath, planResult.planText, "utf-8");
113969
113969
  state.activeIssues[numStr].planPath = planFilePath;
113970
113970
  watchLog.info(`Plan saved (fallback) to ${planFilePath}`);
@@ -114271,18 +114271,18 @@ init_logger();
114271
114271
  import { spawnSync as spawnSync7 } from "node:child_process";
114272
114272
  import { existsSync as existsSync72 } from "node:fs";
114273
114273
  import { readdir as readdir45, stat as stat24 } from "node:fs/promises";
114274
- import { join as join154 } from "node:path";
114274
+ import { join as join155 } from "node:path";
114275
114275
  async function scanForRepos(parentDir) {
114276
114276
  const repos = [];
114277
114277
  const entries = await readdir45(parentDir);
114278
114278
  for (const entry of entries) {
114279
114279
  if (entry.startsWith("."))
114280
114280
  continue;
114281
- const fullPath = join154(parentDir, entry);
114281
+ const fullPath = join155(parentDir, entry);
114282
114282
  const entryStat = await stat24(fullPath);
114283
114283
  if (!entryStat.isDirectory())
114284
114284
  continue;
114285
- const gitDir = join154(fullPath, ".git");
114285
+ const gitDir = join155(fullPath, ".git");
114286
114286
  if (!existsSync72(gitDir))
114287
114287
  continue;
114288
114288
  const result = spawnSync7("gh", ["repo", "view", "--json", "owner,name"], {
@@ -114309,7 +114309,7 @@ init_logger();
114309
114309
  import { spawnSync as spawnSync8 } from "node:child_process";
114310
114310
  import { existsSync as existsSync73 } from "node:fs";
114311
114311
  import { homedir as homedir52 } from "node:os";
114312
- import { join as join155 } from "node:path";
114312
+ import { join as join156 } from "node:path";
114313
114313
  async function validateSetup(cwd2) {
114314
114314
  const workDir = cwd2 ?? process.cwd();
114315
114315
  const ghVersion = spawnSync8("gh", ["--version"], { encoding: "utf-8", timeout: 1e4 });
@@ -114340,7 +114340,7 @@ Run this command from a directory with a GitHub remote.`);
114340
114340
  } catch {
114341
114341
  throw new Error(`Failed to parse repository info: ${ghRepo.stdout}`);
114342
114342
  }
114343
- const skillsPath = join155(homedir52(), ".claude", "skills");
114343
+ const skillsPath = join156(homedir52(), ".claude", "skills");
114344
114344
  const skillsAvailable = existsSync73(skillsPath);
114345
114345
  if (!skillsAvailable) {
114346
114346
  logger.warning(`ClaudeKit Engineer skills not found at ${skillsPath}`);
@@ -114359,7 +114359,7 @@ init_path_resolver();
114359
114359
  import { createWriteStream as createWriteStream3, statSync as statSync13 } from "node:fs";
114360
114360
  import { existsSync as existsSync74 } from "node:fs";
114361
114361
  import { mkdir as mkdir41, rename as rename13 } from "node:fs/promises";
114362
- import { join as join156 } from "node:path";
114362
+ import { join as join157 } from "node:path";
114363
114363
 
114364
114364
  class WatchLogger {
114365
114365
  logStream = null;
@@ -114367,7 +114367,7 @@ class WatchLogger {
114367
114367
  logPath = null;
114368
114368
  maxBytes;
114369
114369
  constructor(logDir, maxBytes = 0) {
114370
- this.logDir = logDir ?? join156(PathResolver.getClaudeKitDir(), "logs");
114370
+ this.logDir = logDir ?? join157(PathResolver.getClaudeKitDir(), "logs");
114371
114371
  this.maxBytes = maxBytes;
114372
114372
  }
114373
114373
  async init() {
@@ -114376,7 +114376,7 @@ class WatchLogger {
114376
114376
  await mkdir41(this.logDir, { recursive: true });
114377
114377
  }
114378
114378
  const dateStr = formatDate(new Date);
114379
- this.logPath = join156(this.logDir, `watch-${dateStr}.log`);
114379
+ this.logPath = join157(this.logDir, `watch-${dateStr}.log`);
114380
114380
  this.logStream = createWriteStream3(this.logPath, { flags: "a", mode: 384 });
114381
114381
  } catch (error) {
114382
114382
  logger.warning(`Cannot create watch log file: ${error instanceof Error ? error.message : "Unknown"}`);
@@ -114558,7 +114558,7 @@ async function watchCommand(options2) {
114558
114558
  }
114559
114559
  async function discoverRepos(options2, watchLog) {
114560
114560
  const cwd2 = process.cwd();
114561
- const isGitRepo = existsSync75(join157(cwd2, ".git"));
114561
+ const isGitRepo = existsSync75(join158(cwd2, ".git"));
114562
114562
  if (options2.force) {
114563
114563
  await forceRemoveLock(watchLog);
114564
114564
  }
@@ -114816,7 +114816,7 @@ function registerCommands(cli) {
114816
114816
  init_package();
114817
114817
  init_config_version_checker();
114818
114818
  import { existsSync as existsSync87, readFileSync as readFileSync22 } from "node:fs";
114819
- import { join as join169 } from "node:path";
114819
+ import { join as join170 } from "node:path";
114820
114820
 
114821
114821
  // src/domains/versioning/version-checker.ts
114822
114822
  init_version_utils();
@@ -114831,14 +114831,14 @@ init_logger();
114831
114831
  init_path_resolver();
114832
114832
  import { existsSync as existsSync86 } from "node:fs";
114833
114833
  import { mkdir as mkdir42, readFile as readFile69, writeFile as writeFile41 } from "node:fs/promises";
114834
- import { join as join168 } from "node:path";
114834
+ import { join as join169 } from "node:path";
114835
114835
 
114836
114836
  class VersionCacheManager {
114837
114837
  static CACHE_FILENAME = "version-check.json";
114838
114838
  static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
114839
114839
  static getCacheFile() {
114840
114840
  const cacheDir = PathResolver.getCacheDir(false);
114841
- return join168(cacheDir, VersionCacheManager.CACHE_FILENAME);
114841
+ return join169(cacheDir, VersionCacheManager.CACHE_FILENAME);
114842
114842
  }
114843
114843
  static async load() {
114844
114844
  const cacheFile = VersionCacheManager.getCacheFile();
@@ -115149,9 +115149,9 @@ async function displayVersion() {
115149
115149
  let localInstalledKits = [];
115150
115150
  let globalInstalledKits = [];
115151
115151
  const globalKitDir = PathResolver.getGlobalKitDir();
115152
- const globalMetadataPath = join169(globalKitDir, "metadata.json");
115152
+ const globalMetadataPath = join170(globalKitDir, "metadata.json");
115153
115153
  const prefix = PathResolver.getPathPrefix(false);
115154
- const localMetadataPath = prefix ? join169(process.cwd(), prefix, "metadata.json") : join169(process.cwd(), "metadata.json");
115154
+ const localMetadataPath = prefix ? join170(process.cwd(), prefix, "metadata.json") : join170(process.cwd(), "metadata.json");
115155
115155
  const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
115156
115156
  if (!isLocalSameAsGlobal && existsSync87(localMetadataPath)) {
115157
115157
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "4.1.1",
3
+ "version": "4.2.1-dev.1",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {
@@ -44,6 +44,7 @@
44
44
  "dev:all": "./scripts/dev-quick-start.sh all",
45
45
  "metrics": "bun run scripts/workflow-metrics.ts",
46
46
  "validate": "bun run typecheck && bun run lint && bun test && bun run ui:test && bun run build",
47
+ "ci:local": "bash scripts/ci-local.sh",
47
48
  "install:hooks": "./.githooks/install.sh",
48
49
  "prepare": "node -e \"try{require('child_process').execSync('git rev-parse --git-dir',{stdio:'ignore'});require('child_process').execSync('bash .githooks/install.sh',{stdio:'inherit'})}catch(e){console.warn('[i] Hook install skipped:',e.message)}\"",
49
50
  "help:check-parity": "bun run scripts/check-help-parity.ts",