claudekit-cli 3.17.0 → 3.19.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 +184 -42
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6589,7 +6589,7 @@ var init_kit = __esm(() => {
6589
6589
  name: "ClaudeKit Marketing",
6590
6590
  repo: "claudekit-marketing",
6591
6591
  owner: "claudekit",
6592
- description: "[Coming Soon] Marketing toolkit"
6592
+ description: "Marketing automation toolkit for Claude"
6593
6593
  }
6594
6594
  };
6595
6595
  NEVER_COPY_PATTERNS = [
@@ -23905,13 +23905,15 @@ init_logger();
23905
23905
 
23906
23906
  // src/domains/ui/prompts/kit-prompts.ts
23907
23907
  init_types2();
23908
- async function selectKit(defaultKit) {
23908
+ var MIN_KITS_FOR_MULTISELECT = 2;
23909
+ async function selectKit(defaultKit, accessibleKits) {
23910
+ const kits = accessibleKits ?? Object.keys(AVAILABLE_KITS);
23909
23911
  const kit = await ie({
23910
23912
  message: "Select a ClaudeKit:",
23911
- options: Object.entries(AVAILABLE_KITS).map(([key, config]) => ({
23913
+ options: kits.map((key) => ({
23912
23914
  value: key,
23913
- label: config.name,
23914
- hint: config.description
23915
+ label: AVAILABLE_KITS[key].name,
23916
+ hint: AVAILABLE_KITS[key].description
23915
23917
  })),
23916
23918
  initialValue: defaultKit
23917
23919
  });
@@ -23920,6 +23922,24 @@ async function selectKit(defaultKit) {
23920
23922
  }
23921
23923
  return kit;
23922
23924
  }
23925
+ async function selectKits(accessibleKits) {
23926
+ if (accessibleKits.length < MIN_KITS_FOR_MULTISELECT) {
23927
+ throw new Error(`selectKits requires at least ${MIN_KITS_FOR_MULTISELECT} accessible kits`);
23928
+ }
23929
+ const selected = await ae({
23930
+ message: "Select ClaudeKit(s) to install:",
23931
+ options: accessibleKits.map((key) => ({
23932
+ value: key,
23933
+ label: AVAILABLE_KITS[key].name,
23934
+ hint: AVAILABLE_KITS[key].description
23935
+ })),
23936
+ required: true
23937
+ });
23938
+ if (lD(selected)) {
23939
+ throw new Error("Kit selection cancelled");
23940
+ }
23941
+ return selected;
23942
+ }
23923
23943
  async function getDirectory(defaultDir = ".") {
23924
23944
  const dir = await te({
23925
23945
  message: "Enter target directory:",
@@ -24443,8 +24463,11 @@ async function promptSkillsInstallation() {
24443
24463
  }
24444
24464
  // src/domains/ui/prompts.ts
24445
24465
  class PromptsManager {
24446
- async selectKit(defaultKit) {
24447
- return selectKit(defaultKit);
24466
+ async selectKit(defaultKit, accessibleKits) {
24467
+ return selectKit(defaultKit, accessibleKits);
24468
+ }
24469
+ async selectKits(accessibleKits) {
24470
+ return selectKits(accessibleKits);
24448
24471
  }
24449
24472
  async selectVersion(versions, defaultVersion) {
24450
24473
  return selectVersion(versions, defaultVersion);
@@ -24549,6 +24572,7 @@ class PromptsManager {
24549
24572
 
24550
24573
  // src/commands/init/init-command.ts
24551
24574
  init_logger();
24575
+ init_types2();
24552
24576
 
24553
24577
  // src/commands/init/phases/conflict-handler.ts
24554
24578
  init_logger();
@@ -39519,6 +39543,31 @@ Optional: DISCORD_WEBHOOK_URL, TELEGRAM_BOT_TOKEN`, "Configuration skipped");
39519
39543
  import { mkdir as mkdir19 } from "node:fs/promises";
39520
39544
  import { join as join62, resolve as resolve7 } from "node:path";
39521
39545
 
39546
+ // src/domains/github/kit-access-checker.ts
39547
+ init_logger();
39548
+ init_types2();
39549
+ async function detectAccessibleKits() {
39550
+ const spinner = createSpinner("Checking kit access...").start();
39551
+ const github = new GitHubClient;
39552
+ const results = await Promise.all(Object.entries(AVAILABLE_KITS).map(async ([type, config]) => {
39553
+ try {
39554
+ await github.checkAccess(config);
39555
+ logger.debug(`Access confirmed: ${type}`);
39556
+ return type;
39557
+ } catch {
39558
+ logger.debug(`No access to ${type}`);
39559
+ return null;
39560
+ }
39561
+ }));
39562
+ const accessible = results.filter((kit) => kit !== null);
39563
+ if (accessible.length === 0) {
39564
+ spinner.fail("No kit access found");
39565
+ } else {
39566
+ spinner.succeed(`Access verified: ${accessible.join(", ")}`);
39567
+ }
39568
+ return accessible;
39569
+ }
39570
+
39522
39571
  // src/domains/installation/fresh-installer.ts
39523
39572
  init_logger();
39524
39573
  import { join as join61 } from "node:path";
@@ -39581,13 +39630,44 @@ async function handleSelection(ctx) {
39581
39630
  };
39582
39631
  }
39583
39632
  const config = await ConfigManager.get();
39633
+ let accessibleKits;
39634
+ if (!ctx.options.useGit) {
39635
+ accessibleKits = await detectAccessibleKits();
39636
+ if (accessibleKits.length === 0) {
39637
+ logger.error("No ClaudeKit access found.");
39638
+ logger.info("Purchase at https://claudekit.cc");
39639
+ return { ...ctx, cancelled: true };
39640
+ }
39641
+ }
39584
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
+ }
39648
+ let pendingKits;
39585
39649
  if (!kitType) {
39586
39650
  if (ctx.isNonInteractive) {
39587
- kitType = "engineer";
39588
- logger.info("Using default kit: engineer");
39651
+ if (!accessibleKits || accessibleKits.length === 0) {
39652
+ throw new Error("Kit must be specified via --kit flag in non-interactive mode (no accessible kits detected)");
39653
+ }
39654
+ kitType = accessibleKits[0];
39655
+ logger.info(`Auto-selected: ${AVAILABLE_KITS[kitType].name}`);
39656
+ } else if (accessibleKits?.length === 1) {
39657
+ kitType = accessibleKits[0];
39658
+ logger.info(`Using ${AVAILABLE_KITS[kitType].name} (only accessible kit)`);
39659
+ } else if (accessibleKits && accessibleKits.length > 1) {
39660
+ const selectedKits = await ctx.prompts.selectKits(accessibleKits);
39661
+ if (selectedKits.length === 0) {
39662
+ throw new Error("At least one kit must be selected");
39663
+ }
39664
+ kitType = selectedKits[0];
39665
+ if (selectedKits.length > 1) {
39666
+ pendingKits = selectedKits.slice(1);
39667
+ logger.success(`Selected ${selectedKits.length} kits: ${selectedKits.map((k2) => AVAILABLE_KITS[k2].name).join(", ")}`);
39668
+ }
39589
39669
  } else {
39590
- kitType = await ctx.prompts.selectKit();
39670
+ kitType = await ctx.prompts.selectKit(undefined, accessibleKits);
39591
39671
  }
39592
39672
  }
39593
39673
  const kit = AVAILABLE_KITS[kitType];
@@ -39662,20 +39742,6 @@ async function handleSelection(ctx) {
39662
39742
  }
39663
39743
  }
39664
39744
  const github = new GitHubClient;
39665
- if (!ctx.options.useGit) {
39666
- const spinner = createSpinner("Checking repository access...").start();
39667
- logger.verbose("GitHub API check", { repo: kit.repo, owner: kit.owner });
39668
- try {
39669
- await github.checkAccess(kit);
39670
- spinner.succeed("Repository access verified");
39671
- } catch (error) {
39672
- spinner.fail("Access denied to repository");
39673
- logger.error(error.message || `Cannot access ${kit.name}`);
39674
- return { ...ctx, cancelled: true };
39675
- }
39676
- } else {
39677
- logger.verbose("Skipping API access check (--use-git mode)");
39678
- }
39679
39745
  let selectedVersion = ctx.options.release;
39680
39746
  if (!selectedVersion && ctx.isNonInteractive && !ctx.options.yes) {
39681
39747
  throw new Error("Non-interactive mode requires either: --release <tag> OR --yes (uses latest)");
@@ -39749,7 +39815,9 @@ async function handleSelection(ctx) {
39749
39815
  kitType,
39750
39816
  resolvedDir,
39751
39817
  release,
39752
- selectedVersion
39818
+ selectedVersion,
39819
+ pendingKits,
39820
+ accessibleKits
39753
39821
  };
39754
39822
  }
39755
39823
  // src/commands/init/phases/sync-handler.ts
@@ -40573,6 +40641,50 @@ async function handleTransforms(ctx) {
40573
40641
  };
40574
40642
  }
40575
40643
  // src/commands/init/init-command.ts
40644
+ async function installAdditionalKit(baseCtx, kitType) {
40645
+ const kit = AVAILABLE_KITS[kitType];
40646
+ const github = new GitHubClient;
40647
+ logger.info(`
40648
+ Installing additional kit: ${kit.name}`);
40649
+ let release;
40650
+ if (baseCtx.selectedVersion && !baseCtx.selectedVersion.includes("latest")) {
40651
+ try {
40652
+ release = await github.getReleaseByTag(kit, baseCtx.selectedVersion);
40653
+ logger.success(`Found matching version: ${release.tag_name}`);
40654
+ } catch {
40655
+ logger.warning(`Version ${baseCtx.selectedVersion} not available for ${kit.name}, using latest`);
40656
+ release = await github.getLatestRelease(kit, baseCtx.options.beta);
40657
+ logger.success(`Found: ${release.tag_name}`);
40658
+ }
40659
+ } else {
40660
+ release = await github.getLatestRelease(kit, baseCtx.options.beta);
40661
+ logger.success(`Found: ${release.tag_name}`);
40662
+ }
40663
+ let ctx = {
40664
+ ...baseCtx,
40665
+ kit,
40666
+ kitType,
40667
+ release,
40668
+ selectedVersion: release.tag_name,
40669
+ tempDir: undefined,
40670
+ archivePath: undefined,
40671
+ extractDir: undefined
40672
+ };
40673
+ ctx = await handleDownload(ctx);
40674
+ if (ctx.cancelled)
40675
+ return ctx;
40676
+ ctx = await handleTransforms(ctx);
40677
+ if (ctx.cancelled)
40678
+ return ctx;
40679
+ ctx = await handleMigration(ctx);
40680
+ if (ctx.cancelled)
40681
+ return ctx;
40682
+ ctx = await handleMerge(ctx);
40683
+ if (ctx.cancelled)
40684
+ return ctx;
40685
+ ctx = await handlePostInstall(ctx);
40686
+ return ctx;
40687
+ }
40576
40688
  function createInitContext(rawOptions, prompts) {
40577
40689
  const placeholderOptions = {
40578
40690
  dir: ".",
@@ -40653,6 +40765,28 @@ async function initCommand(options) {
40653
40765
  if (ctx.cancelled)
40654
40766
  return;
40655
40767
  }
40768
+ if (!isSyncMode && ctx.pendingKits && ctx.pendingKits.length > 0 && ctx.kitType) {
40769
+ const installedKits = [ctx.kitType];
40770
+ const kitsToInstall = [...ctx.pendingKits];
40771
+ for (const pendingKit of kitsToInstall) {
40772
+ try {
40773
+ ctx = await installAdditionalKit(ctx, pendingKit);
40774
+ if (ctx.cancelled) {
40775
+ logger.warning(`Installation of ${AVAILABLE_KITS[pendingKit].name} was cancelled`);
40776
+ break;
40777
+ }
40778
+ installedKits.push(pendingKit);
40779
+ } catch (error) {
40780
+ logger.error(`Failed to install ${AVAILABLE_KITS[pendingKit].name}: ${error instanceof Error ? error.message : "Unknown error"}`);
40781
+ if (installedKits.length > 1) {
40782
+ logger.info(`Successfully installed: ${installedKits.map((k2) => AVAILABLE_KITS[k2].name).join(", ")}`);
40783
+ }
40784
+ throw error;
40785
+ }
40786
+ }
40787
+ logger.success(`
40788
+ Installed ${installedKits.length} kits: ${installedKits.map((k2) => AVAILABLE_KITS[k2].name).join(", ")}`);
40789
+ }
40656
40790
  prompts.outro(`Project initialized successfully at ${ctx.resolvedDir}`);
40657
40791
  const protectedNote = ctx.customClaudeFiles.length > 0 ? `Your project has been initialized with the latest version.
40658
40792
  Protected files (.env, .claude custom files, etc.) were not modified.` : `Your project has been initialized with the latest version.
@@ -40683,12 +40817,34 @@ var import_fs_extra32 = __toESM(require_lib(), 1);
40683
40817
  async function directorySetup(validOptions, prompts) {
40684
40818
  const isNonInteractive2 = !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
40685
40819
  const config = await ConfigManager.get();
40820
+ let accessibleKits;
40821
+ if (!validOptions.useGit) {
40822
+ accessibleKits = await detectAccessibleKits();
40823
+ if (accessibleKits.length === 0) {
40824
+ logger.error("No ClaudeKit access found.");
40825
+ logger.info("Purchase at https://claudekit.cc");
40826
+ return null;
40827
+ }
40828
+ }
40686
40829
  let kit = validOptions.kit || config.defaults?.kit;
40830
+ if (kit && accessibleKits && !accessibleKits.includes(kit)) {
40831
+ logger.error(`No access to ${AVAILABLE_KITS[kit].name}`);
40832
+ logger.info("Purchase at https://claudekit.cc");
40833
+ return null;
40834
+ }
40687
40835
  if (!kit) {
40688
40836
  if (isNonInteractive2) {
40689
- throw new Error("Kit must be specified via --kit flag in non-interactive mode");
40837
+ kit = accessibleKits?.[0];
40838
+ if (!kit) {
40839
+ throw new Error("Kit must be specified via --kit flag in non-interactive mode");
40840
+ }
40841
+ logger.info(`Auto-selected: ${AVAILABLE_KITS[kit].name}`);
40842
+ } else if (accessibleKits?.length === 1) {
40843
+ kit = accessibleKits[0];
40844
+ logger.info(`Using ${AVAILABLE_KITS[kit].name} (only accessible kit)`);
40845
+ } else {
40846
+ kit = await prompts.selectKit(undefined, accessibleKits);
40690
40847
  }
40691
- kit = await prompts.selectKit();
40692
40848
  }
40693
40849
  const kitConfig = AVAILABLE_KITS[kit];
40694
40850
  logger.info(`Selected kit: ${kitConfig.name}`);
@@ -40812,20 +40968,6 @@ async function selectVersion2(kit, options, isNonInteractive2, prompts, github)
40812
40968
  async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2, prompts) {
40813
40969
  const kitConfig = AVAILABLE_KITS[kit];
40814
40970
  const github = new GitHubClient;
40815
- if (!validOptions.useGit) {
40816
- const spinner = createSpinner("Checking repository access...").start();
40817
- logger.verbose("GitHub API check", { repo: kitConfig.repo, owner: kitConfig.owner });
40818
- try {
40819
- await github.checkAccess(kitConfig);
40820
- spinner.succeed("Repository access verified");
40821
- } catch (error) {
40822
- spinner.fail("Access denied to repository");
40823
- logger.error(error.message || `Cannot access ${kitConfig.name}`);
40824
- return null;
40825
- }
40826
- } else {
40827
- logger.verbose("Skipping API access check (--use-git mode)");
40828
- }
40829
40971
  const versionResult = await selectVersion2(kitConfig, validOptions, isNonInteractive2, prompts, github);
40830
40972
  if (!versionResult) {
40831
40973
  return null;
@@ -41726,7 +41868,7 @@ var import_picocolors24 = __toESM(require_picocolors(), 1);
41726
41868
  // package.json
41727
41869
  var package_default = {
41728
41870
  name: "claudekit-cli",
41729
- version: "3.17.0",
41871
+ version: "3.19.0",
41730
41872
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
41731
41873
  type: "module",
41732
41874
  repository: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.17.0",
3
+ "version": "3.19.0",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {