claudekit-cli 3.19.0 → 3.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +204 -158
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -22342,6 +22342,153 @@ function getInstalledKits(metadata) {
22342
22342
  return [];
22343
22343
  }
22344
22344
 
22345
+ // node_modules/yocto-queue/index.js
22346
+ class Node {
22347
+ value;
22348
+ next;
22349
+ constructor(value) {
22350
+ this.value = value;
22351
+ }
22352
+ }
22353
+
22354
+ class Queue {
22355
+ #head;
22356
+ #tail;
22357
+ #size;
22358
+ constructor() {
22359
+ this.clear();
22360
+ }
22361
+ enqueue(value) {
22362
+ const node = new Node(value);
22363
+ if (this.#head) {
22364
+ this.#tail.next = node;
22365
+ this.#tail = node;
22366
+ } else {
22367
+ this.#head = node;
22368
+ this.#tail = node;
22369
+ }
22370
+ this.#size++;
22371
+ }
22372
+ dequeue() {
22373
+ const current = this.#head;
22374
+ if (!current) {
22375
+ return;
22376
+ }
22377
+ this.#head = this.#head.next;
22378
+ this.#size--;
22379
+ if (!this.#head) {
22380
+ this.#tail = undefined;
22381
+ }
22382
+ return current.value;
22383
+ }
22384
+ peek() {
22385
+ if (!this.#head) {
22386
+ return;
22387
+ }
22388
+ return this.#head.value;
22389
+ }
22390
+ clear() {
22391
+ this.#head = undefined;
22392
+ this.#tail = undefined;
22393
+ this.#size = 0;
22394
+ }
22395
+ get size() {
22396
+ return this.#size;
22397
+ }
22398
+ *[Symbol.iterator]() {
22399
+ let current = this.#head;
22400
+ while (current) {
22401
+ yield current.value;
22402
+ current = current.next;
22403
+ }
22404
+ }
22405
+ *drain() {
22406
+ while (this.#head) {
22407
+ yield this.dequeue();
22408
+ }
22409
+ }
22410
+ }
22411
+
22412
+ // node_modules/p-limit/index.js
22413
+ function pLimit(concurrency) {
22414
+ validateConcurrency(concurrency);
22415
+ const queue = new Queue;
22416
+ let activeCount = 0;
22417
+ const resumeNext = () => {
22418
+ if (activeCount < concurrency && queue.size > 0) {
22419
+ activeCount++;
22420
+ queue.dequeue()();
22421
+ }
22422
+ };
22423
+ const next = () => {
22424
+ activeCount--;
22425
+ resumeNext();
22426
+ };
22427
+ const run = async (function_, resolve2, arguments_) => {
22428
+ const result = (async () => function_(...arguments_))();
22429
+ resolve2(result);
22430
+ try {
22431
+ await result;
22432
+ } catch {}
22433
+ next();
22434
+ };
22435
+ const enqueue = (function_, resolve2, arguments_) => {
22436
+ new Promise((internalResolve) => {
22437
+ queue.enqueue(internalResolve);
22438
+ }).then(run.bind(undefined, function_, resolve2, arguments_));
22439
+ if (activeCount < concurrency) {
22440
+ resumeNext();
22441
+ }
22442
+ };
22443
+ const generator = (function_, ...arguments_) => new Promise((resolve2) => {
22444
+ enqueue(function_, resolve2, arguments_);
22445
+ });
22446
+ Object.defineProperties(generator, {
22447
+ activeCount: {
22448
+ get: () => activeCount
22449
+ },
22450
+ pendingCount: {
22451
+ get: () => queue.size
22452
+ },
22453
+ clearQueue: {
22454
+ value() {
22455
+ queue.clear();
22456
+ }
22457
+ },
22458
+ concurrency: {
22459
+ get: () => concurrency,
22460
+ set(newConcurrency) {
22461
+ validateConcurrency(newConcurrency);
22462
+ concurrency = newConcurrency;
22463
+ queueMicrotask(() => {
22464
+ while (activeCount < concurrency && queue.size > 0) {
22465
+ resumeNext();
22466
+ }
22467
+ });
22468
+ }
22469
+ },
22470
+ map: {
22471
+ async value(iterable, function_) {
22472
+ const promises2 = Array.from(iterable, (value, index) => this(function_, value, index));
22473
+ return Promise.all(promises2);
22474
+ }
22475
+ }
22476
+ });
22477
+ return generator;
22478
+ }
22479
+ function validateConcurrency(concurrency) {
22480
+ if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
22481
+ throw new TypeError("Expected `concurrency` to be a number from 1 and up");
22482
+ }
22483
+ }
22484
+
22485
+ // src/shared/concurrent-file-ops.ts
22486
+ var DEFAULT_CONCURRENCY = 50;
22487
+ async function mapWithLimit(items, fn, concurrency = DEFAULT_CONCURRENCY) {
22488
+ const limit = pLimit(concurrency);
22489
+ return Promise.all(items.map((item) => limit(() => fn(item))));
22490
+ }
22491
+
22345
22492
  // src/services/file-operations/ownership-checker.ts
22346
22493
  class OwnershipChecker {
22347
22494
  static async calculateChecksum(filePath) {
@@ -22392,7 +22539,7 @@ class OwnershipChecker {
22392
22539
  };
22393
22540
  }
22394
22541
  static async checkBatch(filePaths, metadata, claudeDir) {
22395
- const results = await Promise.all(filePaths.map((path2) => OwnershipChecker.checkOwnership(path2, metadata, claudeDir)));
22542
+ const results = await mapWithLimit(filePaths, (path2) => OwnershipChecker.checkOwnership(path2, metadata, claudeDir));
22396
22543
  return new Map(results.map((r2) => [r2.path, r2]));
22397
22544
  }
22398
22545
  }
@@ -31361,7 +31508,7 @@ class Yallist {
31361
31508
  function insertAfter(self2, node, value) {
31362
31509
  const prev = node;
31363
31510
  const next = node ? node.next : self2.head;
31364
- const inserted = new Node(value, prev, next, self2);
31511
+ const inserted = new Node2(value, prev, next, self2);
31365
31512
  if (inserted.next === undefined) {
31366
31513
  self2.tail = inserted;
31367
31514
  }
@@ -31372,21 +31519,21 @@ function insertAfter(self2, node, value) {
31372
31519
  return inserted;
31373
31520
  }
31374
31521
  function push(self2, item) {
31375
- self2.tail = new Node(item, self2.tail, undefined, self2);
31522
+ self2.tail = new Node2(item, self2.tail, undefined, self2);
31376
31523
  if (!self2.head) {
31377
31524
  self2.head = self2.tail;
31378
31525
  }
31379
31526
  self2.length++;
31380
31527
  }
31381
31528
  function unshift(self2, item) {
31382
- self2.head = new Node(item, undefined, self2.head, self2);
31529
+ self2.head = new Node2(item, undefined, self2.head, self2);
31383
31530
  if (!self2.tail) {
31384
31531
  self2.tail = self2.head;
31385
31532
  }
31386
31533
  self2.length++;
31387
31534
  }
31388
31535
 
31389
- class Node {
31536
+ class Node2 {
31390
31537
  list;
31391
31538
  next;
31392
31539
  prev;
@@ -36570,146 +36717,6 @@ class ReleaseManifestLoader {
36570
36717
  init_environment();
36571
36718
  init_logger();
36572
36719
 
36573
- // node_modules/yocto-queue/index.js
36574
- class Node2 {
36575
- value;
36576
- next;
36577
- constructor(value) {
36578
- this.value = value;
36579
- }
36580
- }
36581
-
36582
- class Queue {
36583
- #head;
36584
- #tail;
36585
- #size;
36586
- constructor() {
36587
- this.clear();
36588
- }
36589
- enqueue(value) {
36590
- const node = new Node2(value);
36591
- if (this.#head) {
36592
- this.#tail.next = node;
36593
- this.#tail = node;
36594
- } else {
36595
- this.#head = node;
36596
- this.#tail = node;
36597
- }
36598
- this.#size++;
36599
- }
36600
- dequeue() {
36601
- const current = this.#head;
36602
- if (!current) {
36603
- return;
36604
- }
36605
- this.#head = this.#head.next;
36606
- this.#size--;
36607
- if (!this.#head) {
36608
- this.#tail = undefined;
36609
- }
36610
- return current.value;
36611
- }
36612
- peek() {
36613
- if (!this.#head) {
36614
- return;
36615
- }
36616
- return this.#head.value;
36617
- }
36618
- clear() {
36619
- this.#head = undefined;
36620
- this.#tail = undefined;
36621
- this.#size = 0;
36622
- }
36623
- get size() {
36624
- return this.#size;
36625
- }
36626
- *[Symbol.iterator]() {
36627
- let current = this.#head;
36628
- while (current) {
36629
- yield current.value;
36630
- current = current.next;
36631
- }
36632
- }
36633
- *drain() {
36634
- while (this.#head) {
36635
- yield this.dequeue();
36636
- }
36637
- }
36638
- }
36639
-
36640
- // node_modules/p-limit/index.js
36641
- function pLimit(concurrency) {
36642
- validateConcurrency(concurrency);
36643
- const queue = new Queue;
36644
- let activeCount = 0;
36645
- const resumeNext = () => {
36646
- if (activeCount < concurrency && queue.size > 0) {
36647
- activeCount++;
36648
- queue.dequeue()();
36649
- }
36650
- };
36651
- const next = () => {
36652
- activeCount--;
36653
- resumeNext();
36654
- };
36655
- const run = async (function_, resolve6, arguments_) => {
36656
- const result = (async () => function_(...arguments_))();
36657
- resolve6(result);
36658
- try {
36659
- await result;
36660
- } catch {}
36661
- next();
36662
- };
36663
- const enqueue = (function_, resolve6, arguments_) => {
36664
- new Promise((internalResolve) => {
36665
- queue.enqueue(internalResolve);
36666
- }).then(run.bind(undefined, function_, resolve6, arguments_));
36667
- if (activeCount < concurrency) {
36668
- resumeNext();
36669
- }
36670
- };
36671
- const generator = (function_, ...arguments_) => new Promise((resolve6) => {
36672
- enqueue(function_, resolve6, arguments_);
36673
- });
36674
- Object.defineProperties(generator, {
36675
- activeCount: {
36676
- get: () => activeCount
36677
- },
36678
- pendingCount: {
36679
- get: () => queue.size
36680
- },
36681
- clearQueue: {
36682
- value() {
36683
- queue.clear();
36684
- }
36685
- },
36686
- concurrency: {
36687
- get: () => concurrency,
36688
- set(newConcurrency) {
36689
- validateConcurrency(newConcurrency);
36690
- concurrency = newConcurrency;
36691
- queueMicrotask(() => {
36692
- while (activeCount < concurrency && queue.size > 0) {
36693
- resumeNext();
36694
- }
36695
- });
36696
- }
36697
- },
36698
- map: {
36699
- async value(iterable, function_) {
36700
- const promises3 = Array.from(iterable, (value, index) => this(function_, value, index));
36701
- return Promise.all(promises3);
36702
- }
36703
- }
36704
- });
36705
- return generator;
36706
- }
36707
- function validateConcurrency(concurrency) {
36708
- if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
36709
- throw new TypeError("Expected `concurrency` to be a number from 1 and up");
36710
- }
36711
- }
36712
-
36713
36720
  // src/services/file-operations/manifest/manifest-updater.ts
36714
36721
  import { join as join41 } from "node:path";
36715
36722
  init_logger();
@@ -37053,10 +37060,10 @@ class LegacyMigration {
37053
37060
  }
37054
37061
  }
37055
37062
  if (filesInManifest.length > 0) {
37056
- const checksumResults = await Promise.all(filesInManifest.map(async ({ file, relativePath, manifestChecksum }) => {
37063
+ const checksumResults = await mapWithLimit(filesInManifest, async ({ file, relativePath, manifestChecksum }) => {
37057
37064
  const actualChecksum = await OwnershipChecker.calculateChecksum(file);
37058
37065
  return { relativePath, actualChecksum, manifestChecksum };
37059
- }));
37066
+ });
37060
37067
  for (const { relativePath, actualChecksum, manifestChecksum } of checksumResults) {
37061
37068
  if (actualChecksum === manifestChecksum) {
37062
37069
  preview.ckPristine.push(relativePath);
@@ -37108,11 +37115,11 @@ User-created files (sample):`);
37108
37115
  ...preview.userCreated.map((p) => ({ relativePath: p, ownership: "user" }))
37109
37116
  ];
37110
37117
  if (filesToChecksum.length > 0) {
37111
- const checksumResults = await Promise.all(filesToChecksum.map(async ({ relativePath, ownership }) => {
37118
+ const checksumResults = await mapWithLimit(filesToChecksum, async ({ relativePath, ownership }) => {
37112
37119
  const fullPath = join43(claudeDir, relativePath);
37113
37120
  const checksum = await OwnershipChecker.calculateChecksum(fullPath);
37114
37121
  return { relativePath, checksum, ownership };
37115
- }));
37122
+ });
37116
37123
  for (const { relativePath, checksum, ownership } of checksumResults) {
37117
37124
  trackedFiles.push({
37118
37125
  path: relativePath,
@@ -39639,13 +39646,52 @@ async function handleSelection(ctx) {
39639
39646
  return { ...ctx, cancelled: true };
39640
39647
  }
39641
39648
  }
39642
- let kitType = ctx.options.kit || config.defaults?.kit;
39643
- if (kitType && accessibleKits && !accessibleKits.includes(kitType)) {
39644
- logger.error(`No access to ${AVAILABLE_KITS[kitType].name}`);
39645
- logger.info("Purchase at https://claudekit.cc");
39646
- return { ...ctx, cancelled: true };
39647
- }
39649
+ let kitType;
39648
39650
  let pendingKits;
39651
+ const kitOption = ctx.options.kit || config.defaults?.kit;
39652
+ if (kitOption) {
39653
+ const allKitTypes = Object.keys(AVAILABLE_KITS);
39654
+ if (kitOption === "all") {
39655
+ const kitsToInstall = accessibleKits ?? allKitTypes;
39656
+ if (kitsToInstall.length === 0) {
39657
+ logger.error("No kits accessible for installation");
39658
+ return { ...ctx, cancelled: true };
39659
+ }
39660
+ kitType = kitsToInstall[0];
39661
+ if (kitsToInstall.length > 1) {
39662
+ pendingKits = kitsToInstall.slice(1);
39663
+ }
39664
+ logger.info(`Installing all accessible kits: ${kitsToInstall.map((k2) => AVAILABLE_KITS[k2].name).join(", ")}`);
39665
+ } else if (kitOption.includes(",")) {
39666
+ const requestedKits = kitOption.split(",").map((k2) => k2.trim());
39667
+ const invalidKits = requestedKits.filter((k2) => !allKitTypes.includes(k2));
39668
+ if (invalidKits.length > 0) {
39669
+ logger.error(`Invalid kit(s): ${invalidKits.join(", ")}`);
39670
+ logger.info(`Valid kits: ${allKitTypes.join(", ")}`);
39671
+ return { ...ctx, cancelled: true };
39672
+ }
39673
+ if (accessibleKits) {
39674
+ const noAccessKits = requestedKits.filter((k2) => !accessibleKits.includes(k2));
39675
+ if (noAccessKits.length > 0) {
39676
+ logger.error(`No access to: ${noAccessKits.map((k2) => AVAILABLE_KITS[k2].name).join(", ")}`);
39677
+ logger.info("Purchase at https://claudekit.cc");
39678
+ return { ...ctx, cancelled: true };
39679
+ }
39680
+ }
39681
+ kitType = requestedKits[0];
39682
+ if (requestedKits.length > 1) {
39683
+ pendingKits = requestedKits.slice(1);
39684
+ }
39685
+ logger.info(`Installing kits: ${requestedKits.map((k2) => AVAILABLE_KITS[k2].name).join(", ")}`);
39686
+ } else {
39687
+ kitType = kitOption;
39688
+ if (accessibleKits && !accessibleKits.includes(kitType)) {
39689
+ logger.error(`No access to ${AVAILABLE_KITS[kitType].name}`);
39690
+ logger.info("Purchase at https://claudekit.cc");
39691
+ return { ...ctx, cancelled: true };
39692
+ }
39693
+ }
39694
+ }
39649
39695
  if (!kitType) {
39650
39696
  if (ctx.isNonInteractive) {
39651
39697
  if (!accessibleKits || accessibleKits.length === 0) {
@@ -41868,7 +41914,7 @@ var import_picocolors24 = __toESM(require_picocolors(), 1);
41868
41914
  // package.json
41869
41915
  var package_default = {
41870
41916
  name: "claudekit-cli",
41871
- version: "3.19.0",
41917
+ version: "3.20.0",
41872
41918
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
41873
41919
  type: "module",
41874
41920
  repository: {
@@ -42238,13 +42284,13 @@ ${import_picocolors25.default.bold(import_picocolors25.default.cyan(result.kitCo
42238
42284
  // src/cli/command-registry.ts
42239
42285
  init_logger();
42240
42286
  function registerCommands(cli) {
42241
- cli.command("new", "Bootstrap a new ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--force", "Overwrite existing files without confirmation").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--opencode", "Install OpenCode CLI package (non-interactive mode)").option("--gemini", "Install Google Gemini CLI package (non-interactive mode)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").action(async (options) => {
42287
+ cli.command("new", "Bootstrap a new ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use: engineer, marketing, all, or comma-separated").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--force", "Overwrite existing files without confirmation").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--opencode", "Install OpenCode CLI package (non-interactive mode)").option("--gemini", "Install Google Gemini CLI package (non-interactive mode)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").action(async (options) => {
42242
42288
  if (options.exclude && !Array.isArray(options.exclude)) {
42243
42289
  options.exclude = [options.exclude];
42244
42290
  }
42245
42291
  await newCommand(options);
42246
42292
  });
42247
- cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Completely remove .claude directory before downloading (requires confirmation)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").action(async (options) => {
42293
+ cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use: engineer, marketing, all, or comma-separated").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Completely remove .claude directory before downloading (requires confirmation)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").action(async (options) => {
42248
42294
  if (options.exclude && !Array.isArray(options.exclude)) {
42249
42295
  options.exclude = [options.exclude];
42250
42296
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.19.0",
3
+ "version": "3.20.0",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {