aiblueprint-cli 1.3.0 → 1.3.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/dist/cli.js CHANGED
@@ -33765,15 +33765,24 @@ async function listFilesFromGitHub(dirPath) {
33765
33765
  if (!response.ok) {
33766
33766
  return [];
33767
33767
  }
33768
- const files = await response.json();
33769
- return files.filter((file) => file.type === "file").map((file) => file.name);
33768
+ const items = await response.json();
33769
+ const files = [];
33770
+ for (const item of items) {
33771
+ if (item.type === "file") {
33772
+ files.push(item.name);
33773
+ } else if (item.type === "dir") {
33774
+ const subFiles = await listFilesFromGitHub(`${dirPath}/${item.name}`);
33775
+ files.push(...subFiles.map((f) => `${item.name}/${f}`));
33776
+ }
33777
+ }
33778
+ return files;
33770
33779
  } catch (error) {
33771
33780
  return [];
33772
33781
  }
33773
33782
  }
33774
33783
  async function isGitHubAvailable() {
33775
33784
  try {
33776
- const testUrl = `${GITHUB_RAW_BASE3}/commands/commit.md`;
33785
+ const testUrl = `${GITHUB_RAW_BASE3}/commands/apex.md`;
33777
33786
  const testResponse = await fetch(testUrl);
33778
33787
  return testResponse.ok;
33779
33788
  } catch {
@@ -33967,6 +33976,20 @@ class SimpleSpinner3 {
33967
33976
  console.log(source_default.green(`✓ ${message}`));
33968
33977
  }
33969
33978
  }
33979
+ async function getLocalMdFilesRecursively(dir, basePath = "") {
33980
+ const files = [];
33981
+ const entries = await import_fs_extra10.default.readdir(dir, { withFileTypes: true });
33982
+ for (const entry of entries) {
33983
+ const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;
33984
+ if (entry.isDirectory()) {
33985
+ const subFiles = await getLocalMdFilesRecursively(path12.join(dir, entry.name), relativePath);
33986
+ files.push(...subFiles);
33987
+ } else if (entry.name.endsWith(".md")) {
33988
+ files.push(relativePath);
33989
+ }
33990
+ }
33991
+ return files;
33992
+ }
33970
33993
  async function discoverAvailableCommands() {
33971
33994
  const commands = {};
33972
33995
  const useGitHub = await isGitHubAvailable();
@@ -33979,8 +34002,7 @@ async function discoverAvailableCommands() {
33979
34002
  if (!commandsDir) {
33980
34003
  throw new Error("Commands directory not found");
33981
34004
  }
33982
- const files = await import_fs_extra10.default.readdir(commandsDir);
33983
- mdFiles = files.filter((file) => file.endsWith(".md"));
34005
+ mdFiles = await getLocalMdFilesRecursively(commandsDir);
33984
34006
  }
33985
34007
  for (const file of mdFiles) {
33986
34008
  const commandName = file.replace(".md", "");
@@ -33988,7 +34010,7 @@ async function discoverAvailableCommands() {
33988
34010
  const content = await getFileContentWithGitHubFallback("commands", file);
33989
34011
  const { metadata } = parseYamlFrontmatter(content);
33990
34012
  commands[commandName] = {
33991
- name: commandName.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
34013
+ name: commandName.split("/").map((part) => part.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase())).join("/"),
33992
34014
  description: metadata.description || "No description available",
33993
34015
  allowedTools: metadata["allowed-tools"],
33994
34016
  argumentHint: metadata["argument-hint"],
@@ -34608,6 +34630,59 @@ class x {
34608
34630
  }
34609
34631
  }
34610
34632
  }
34633
+
34634
+ class BD extends x {
34635
+ get cursor() {
34636
+ return this.value ? 0 : 1;
34637
+ }
34638
+ get _value() {
34639
+ return this.cursor === 0;
34640
+ }
34641
+ constructor(u) {
34642
+ super(u, false), this.value = !!u.initialValue, this.on("value", () => {
34643
+ this.value = this._value;
34644
+ }), this.on("confirm", (F) => {
34645
+ this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = F, this.state = "submit", this.close();
34646
+ }), this.on("cursor", () => {
34647
+ this.value = !this.value;
34648
+ });
34649
+ }
34650
+ }
34651
+ var fD = Object.defineProperty;
34652
+ var gD = (e, u, F) => (u in e) ? fD(e, u, { enumerable: true, configurable: true, writable: true, value: F }) : e[u] = F;
34653
+ var K = (e, u, F) => (gD(e, typeof u != "symbol" ? u + "" : u, F), F);
34654
+ var vD = class extends x {
34655
+ constructor(u) {
34656
+ super(u, false), K(this, "options"), K(this, "cursor", 0), this.options = u.options, this.value = [...u.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: F }) => F === u.cursorAt), 0), this.on("key", (F) => {
34657
+ F === "a" && this.toggleAll();
34658
+ }), this.on("cursor", (F) => {
34659
+ switch (F) {
34660
+ case "left":
34661
+ case "up":
34662
+ this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
34663
+ break;
34664
+ case "down":
34665
+ case "right":
34666
+ this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
34667
+ break;
34668
+ case "space":
34669
+ this.toggleValue();
34670
+ break;
34671
+ }
34672
+ });
34673
+ }
34674
+ get _value() {
34675
+ return this.options[this.cursor].value;
34676
+ }
34677
+ toggleAll() {
34678
+ const u = this.value.length === this.options.length;
34679
+ this.value = u ? [] : this.options.map((F) => F.value);
34680
+ }
34681
+ toggleValue() {
34682
+ const u = this.value.includes(this._value);
34683
+ this.value = u ? this.value.filter((F) => F !== this._value) : [...this.value, this._value];
34684
+ }
34685
+ };
34611
34686
  var TD = Object.defineProperty;
34612
34687
  var jD = (e, u, F) => (u in e) ? TD(e, u, { enumerable: true, configurable: true, writable: true, value: F }) : e[u] = F;
34613
34688
  var MD = (e, u, F) => (jD(e, typeof u != "symbol" ? u + "" : u, F), F);
@@ -34665,7 +34740,7 @@ var H = o("◆", "*");
34665
34740
  var I2 = o("■", "x");
34666
34741
  var x2 = o("▲", "x");
34667
34742
  var S2 = o("◇", "o");
34668
- var K = o("┌", "T");
34743
+ var K2 = o("┌", "T");
34669
34744
  var a2 = o("│", "|");
34670
34745
  var d2 = o("└", "—");
34671
34746
  var b2 = o("●", ">");
@@ -34716,13 +34791,76 @@ ${import_picocolors2.default.cyan(d2)}
34716
34791
  `;
34717
34792
  }
34718
34793
  } }).prompt();
34794
+ var se = (r2) => {
34795
+ const n = r2.active ?? "Yes", i = r2.inactive ?? "No";
34796
+ return new BD({ active: n, inactive: i, initialValue: r2.initialValue ?? true, render() {
34797
+ const t = `${import_picocolors2.default.gray(a2)}
34798
+ ${y2(this.state)} ${r2.message}
34799
+ `, s = this.value ? n : i;
34800
+ switch (this.state) {
34801
+ case "submit":
34802
+ return `${t}${import_picocolors2.default.gray(a2)} ${import_picocolors2.default.dim(s)}`;
34803
+ case "cancel":
34804
+ return `${t}${import_picocolors2.default.gray(a2)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}
34805
+ ${import_picocolors2.default.gray(a2)}`;
34806
+ default:
34807
+ return `${t}${import_picocolors2.default.cyan(a2)} ${this.value ? `${import_picocolors2.default.green(b2)} ${n}` : `${import_picocolors2.default.dim(E)} ${import_picocolors2.default.dim(n)}`} ${import_picocolors2.default.dim("/")} ${this.value ? `${import_picocolors2.default.dim(E)} ${import_picocolors2.default.dim(i)}` : `${import_picocolors2.default.green(b2)} ${i}`}
34808
+ ${import_picocolors2.default.cyan(d2)}
34809
+ `;
34810
+ }
34811
+ } }).prompt();
34812
+ };
34813
+ var ae = (r2) => {
34814
+ const n = (i, t) => {
34815
+ const s = i.label ?? String(i.value);
34816
+ return t === "active" ? `${import_picocolors2.default.cyan(C)} ${s} ${i.hint ? import_picocolors2.default.dim(`(${i.hint})`) : ""}` : t === "selected" ? `${import_picocolors2.default.green(w2)} ${import_picocolors2.default.dim(s)}` : t === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}` : t === "active-selected" ? `${import_picocolors2.default.green(w2)} ${s} ${i.hint ? import_picocolors2.default.dim(`(${i.hint})`) : ""}` : t === "submitted" ? `${import_picocolors2.default.dim(s)}` : `${import_picocolors2.default.dim(M2)} ${import_picocolors2.default.dim(s)}`;
34817
+ };
34818
+ return new vD({ options: r2.options, initialValues: r2.initialValues, required: r2.required ?? true, cursorAt: r2.cursorAt, validate(i) {
34819
+ if (this.required && i.length === 0)
34820
+ return `Please select at least one option.
34821
+ ${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
34822
+ }, render() {
34823
+ let i = `${import_picocolors2.default.gray(a2)}
34824
+ ${y2(this.state)} ${r2.message}
34825
+ `;
34826
+ switch (this.state) {
34827
+ case "submit":
34828
+ return `${i}${import_picocolors2.default.gray(a2)} ${this.options.filter(({ value: t }) => this.value.includes(t)).map((t) => n(t, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
34829
+ case "cancel": {
34830
+ const t = this.options.filter(({ value: s }) => this.value.includes(s)).map((s) => n(s, "cancelled")).join(import_picocolors2.default.dim(", "));
34831
+ return `${i}${import_picocolors2.default.gray(a2)} ${t.trim() ? `${t}
34832
+ ${import_picocolors2.default.gray(a2)}` : ""}`;
34833
+ }
34834
+ case "error": {
34835
+ const t = this.error.split(`
34836
+ `).map((s, c2) => c2 === 0 ? `${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(s)}` : ` ${s}`).join(`
34837
+ `);
34838
+ return i + import_picocolors2.default.yellow(a2) + " " + this.options.map((s, c2) => {
34839
+ const l2 = this.value.includes(s.value), u = c2 === this.cursor;
34840
+ return u && l2 ? n(s, "active-selected") : l2 ? n(s, "selected") : n(s, u ? "active" : "inactive");
34841
+ }).join(`
34842
+ ${import_picocolors2.default.yellow(a2)} `) + `
34843
+ ` + t + `
34844
+ `;
34845
+ }
34846
+ default:
34847
+ return `${i}${import_picocolors2.default.cyan(a2)} ${this.options.map((t, s) => {
34848
+ const c2 = this.value.includes(t.value), l2 = s === this.cursor;
34849
+ return l2 && c2 ? n(t, "active-selected") : c2 ? n(t, "selected") : n(t, l2 ? "active" : "inactive");
34850
+ }).join(`
34851
+ ${import_picocolors2.default.cyan(a2)} `)}
34852
+ ${import_picocolors2.default.cyan(d2)}
34853
+ `;
34854
+ }
34855
+ } }).prompt();
34856
+ };
34719
34857
  var ue = (r2 = "") => {
34720
34858
  process.stdout.write(`${import_picocolors2.default.gray(d2)} ${import_picocolors2.default.red(r2)}
34721
34859
 
34722
34860
  `);
34723
34861
  };
34724
34862
  var oe = (r2 = "") => {
34725
- process.stdout.write(`${import_picocolors2.default.gray(K)} ${r2}
34863
+ process.stdout.write(`${import_picocolors2.default.gray(K2)} ${r2}
34726
34864
  `);
34727
34865
  };
34728
34866
  var $e = (r2 = "") => {
@@ -35133,6 +35271,348 @@ async function proUpdateCommand(options = {}) {
35133
35271
  }
35134
35272
  }
35135
35273
 
35274
+ // src/commands/sync.ts
35275
+ import os11 from "os";
35276
+ import path19 from "path";
35277
+
35278
+ // src/lib/sync-utils.ts
35279
+ var import_fs_extra16 = __toESM(require_lib4(), 1);
35280
+ import path18 from "path";
35281
+ import crypto from "crypto";
35282
+ var PREMIUM_REPO2 = "Melvynx/aiblueprint-cli-premium";
35283
+ var PREMIUM_BRANCH2 = "main";
35284
+ function computeFileSha(content) {
35285
+ const size = content.length;
35286
+ const header = `blob ${size}\x00`;
35287
+ const fullContent = Buffer.concat([Buffer.from(header), content]);
35288
+ return crypto.createHash("sha1").update(fullContent).digest("hex");
35289
+ }
35290
+ async function listRemoteDirectory(dirPath, githubToken) {
35291
+ const apiUrl = `https://api.github.com/repos/${PREMIUM_REPO2}/contents/claude-code-config/${dirPath}?ref=${PREMIUM_BRANCH2}`;
35292
+ const response = await fetch(apiUrl, {
35293
+ headers: {
35294
+ Authorization: `token ${githubToken}`,
35295
+ Accept: "application/vnd.github.v3+json"
35296
+ }
35297
+ });
35298
+ if (!response.ok) {
35299
+ if (response.status === 404) {
35300
+ return [];
35301
+ }
35302
+ throw new Error(`Failed to list directory ${dirPath}: ${response.status}`);
35303
+ }
35304
+ const files = await response.json();
35305
+ if (!Array.isArray(files)) {
35306
+ return [];
35307
+ }
35308
+ return files;
35309
+ }
35310
+ async function computeLocalFileSha(filePath) {
35311
+ try {
35312
+ const content = await import_fs_extra16.default.readFile(filePath);
35313
+ return computeFileSha(content);
35314
+ } catch {
35315
+ return null;
35316
+ }
35317
+ }
35318
+ async function computeFolderSha(folderPath) {
35319
+ try {
35320
+ if (!await import_fs_extra16.default.pathExists(folderPath)) {
35321
+ return null;
35322
+ }
35323
+ const files = await getAllFilesRecursive(folderPath);
35324
+ if (files.length === 0) {
35325
+ return null;
35326
+ }
35327
+ const hashes = [];
35328
+ for (const file of files.sort()) {
35329
+ const content = await import_fs_extra16.default.readFile(file);
35330
+ hashes.push(computeFileSha(content));
35331
+ }
35332
+ return crypto.createHash("sha1").update(hashes.join("")).digest("hex");
35333
+ } catch {
35334
+ return null;
35335
+ }
35336
+ }
35337
+ async function getAllFilesRecursive(dir) {
35338
+ const files = [];
35339
+ const items = await import_fs_extra16.default.readdir(dir);
35340
+ for (const item of items) {
35341
+ const fullPath = path18.join(dir, item);
35342
+ const stat = await import_fs_extra16.default.stat(fullPath);
35343
+ if (stat.isDirectory()) {
35344
+ const subFiles = await getAllFilesRecursive(fullPath);
35345
+ files.push(...subFiles);
35346
+ } else {
35347
+ files.push(fullPath);
35348
+ }
35349
+ }
35350
+ return files;
35351
+ }
35352
+ async function computeRemoteFolderSha(dirPath, githubToken) {
35353
+ const hashes = [];
35354
+ await collectRemoteFolderHashes(dirPath, githubToken, hashes);
35355
+ hashes.sort();
35356
+ return crypto.createHash("sha1").update(hashes.join("")).digest("hex");
35357
+ }
35358
+ async function collectRemoteFolderHashes(dirPath, githubToken, hashes) {
35359
+ const files = await listRemoteDirectory(dirPath, githubToken);
35360
+ for (const file of files) {
35361
+ if (file.type === "file") {
35362
+ hashes.push(file.sha);
35363
+ } else if (file.type === "dir") {
35364
+ await collectRemoteFolderHashes(`${dirPath}/${file.name}`, githubToken, hashes);
35365
+ }
35366
+ }
35367
+ }
35368
+ async function analyzeSyncChanges(claudeDir, githubToken) {
35369
+ const items = [];
35370
+ const commandsRemote = await listRemoteDirectory("commands", githubToken);
35371
+ for (const file of commandsRemote) {
35372
+ if (file.type === "file" && file.name.endsWith(".md")) {
35373
+ const localPath = path18.join(claudeDir, "commands", file.name);
35374
+ const localSha = await computeLocalFileSha(localPath);
35375
+ let status = "new";
35376
+ if (localSha) {
35377
+ status = localSha === file.sha ? "unchanged" : "modified";
35378
+ }
35379
+ items.push({
35380
+ name: file.name.replace(".md", ""),
35381
+ relativePath: `commands/${file.name}`,
35382
+ type: "file",
35383
+ status,
35384
+ remoteSha: file.sha,
35385
+ localSha: localSha || undefined,
35386
+ category: "commands"
35387
+ });
35388
+ }
35389
+ }
35390
+ const agentsRemote = await listRemoteDirectory("agents", githubToken);
35391
+ for (const file of agentsRemote) {
35392
+ if (file.type === "file" && file.name.endsWith(".md")) {
35393
+ const localPath = path18.join(claudeDir, "agents", file.name);
35394
+ const localSha = await computeLocalFileSha(localPath);
35395
+ let status = "new";
35396
+ if (localSha) {
35397
+ status = localSha === file.sha ? "unchanged" : "modified";
35398
+ }
35399
+ items.push({
35400
+ name: file.name.replace(".md", ""),
35401
+ relativePath: `agents/${file.name}`,
35402
+ type: "file",
35403
+ status,
35404
+ remoteSha: file.sha,
35405
+ localSha: localSha || undefined,
35406
+ category: "agents"
35407
+ });
35408
+ }
35409
+ }
35410
+ const skillsRemote = await listRemoteDirectory("skills", githubToken);
35411
+ if (skillsRemote.length > 0) {
35412
+ const remoteSha = await computeRemoteFolderSha("skills", githubToken);
35413
+ const localSha = await computeFolderSha(path18.join(claudeDir, "skills"));
35414
+ let status = "new";
35415
+ if (localSha) {
35416
+ status = localSha === remoteSha ? "unchanged" : "modified";
35417
+ }
35418
+ items.push({
35419
+ name: "skills",
35420
+ relativePath: "skills",
35421
+ type: "folder",
35422
+ status,
35423
+ remoteSha,
35424
+ localSha: localSha || undefined,
35425
+ category: "skills"
35426
+ });
35427
+ }
35428
+ const scriptsRemote = await listRemoteDirectory("scripts", githubToken);
35429
+ if (scriptsRemote.length > 0) {
35430
+ const remoteSha = await computeRemoteFolderSha("scripts", githubToken);
35431
+ const localSha = await computeFolderSha(path18.join(claudeDir, "scripts"));
35432
+ let status = "new";
35433
+ if (localSha) {
35434
+ status = localSha === remoteSha ? "unchanged" : "modified";
35435
+ }
35436
+ items.push({
35437
+ name: "scripts",
35438
+ relativePath: "scripts",
35439
+ type: "folder",
35440
+ status,
35441
+ remoteSha,
35442
+ localSha: localSha || undefined,
35443
+ category: "scripts"
35444
+ });
35445
+ }
35446
+ return {
35447
+ items,
35448
+ newCount: items.filter((i) => i.status === "new").length,
35449
+ modifiedCount: items.filter((i) => i.status === "modified").length,
35450
+ unchangedCount: items.filter((i) => i.status === "unchanged").length
35451
+ };
35452
+ }
35453
+ async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken) {
35454
+ try {
35455
+ const url = `https://raw.githubusercontent.com/${PREMIUM_REPO2}/${PREMIUM_BRANCH2}/claude-code-config/${relativePath}`;
35456
+ const response = await fetch(url, {
35457
+ headers: {
35458
+ Authorization: `token ${githubToken}`,
35459
+ Accept: "application/vnd.github.v3.raw"
35460
+ }
35461
+ });
35462
+ if (!response.ok) {
35463
+ return false;
35464
+ }
35465
+ const content = await response.arrayBuffer();
35466
+ await import_fs_extra16.default.ensureDir(path18.dirname(targetPath));
35467
+ await import_fs_extra16.default.writeFile(targetPath, Buffer.from(content));
35468
+ return true;
35469
+ } catch {
35470
+ return false;
35471
+ }
35472
+ }
35473
+ async function downloadDirectoryFromPrivateGitHub2(dirPath, targetDir, githubToken) {
35474
+ try {
35475
+ const files = await listRemoteDirectory(dirPath, githubToken);
35476
+ await import_fs_extra16.default.ensureDir(targetDir);
35477
+ for (const file of files) {
35478
+ const relativePath = `${dirPath}/${file.name}`;
35479
+ const targetPath = path18.join(targetDir, file.name);
35480
+ if (file.type === "file") {
35481
+ await downloadFromPrivateGitHub2(relativePath, targetPath, githubToken);
35482
+ } else if (file.type === "dir") {
35483
+ await downloadDirectoryFromPrivateGitHub2(relativePath, targetPath, githubToken);
35484
+ }
35485
+ }
35486
+ return true;
35487
+ } catch {
35488
+ return false;
35489
+ }
35490
+ }
35491
+ async function syncSelectedItems(claudeDir, items, githubToken) {
35492
+ let success = 0;
35493
+ let failed = 0;
35494
+ for (const item of items) {
35495
+ const targetPath = path18.join(claudeDir, item.relativePath);
35496
+ if (item.type === "file") {
35497
+ const ok = await downloadFromPrivateGitHub2(item.relativePath, targetPath, githubToken);
35498
+ if (ok) {
35499
+ success++;
35500
+ } else {
35501
+ failed++;
35502
+ }
35503
+ } else {
35504
+ const ok = await downloadDirectoryFromPrivateGitHub2(item.relativePath, targetPath, githubToken);
35505
+ if (ok) {
35506
+ success++;
35507
+ } else {
35508
+ failed++;
35509
+ }
35510
+ }
35511
+ }
35512
+ return { success, failed };
35513
+ }
35514
+
35515
+ // src/commands/sync.ts
35516
+ async function proSyncCommand(options = {}) {
35517
+ oe(source_default.blue("\uD83D\uDD04 Sync Premium Configurations"));
35518
+ try {
35519
+ const githubToken = await getToken();
35520
+ if (!githubToken) {
35521
+ f2.error("No token found");
35522
+ f2.info("Run: aiblueprint claude-code pro activate <token>");
35523
+ $e(source_default.red("❌ Not activated"));
35524
+ process.exit(1);
35525
+ }
35526
+ const claudeDir = options.folder ? path19.resolve(options.folder) : path19.join(os11.homedir(), ".claude");
35527
+ const spinner = de();
35528
+ spinner.start("Analyzing changes...");
35529
+ const result = await analyzeSyncChanges(claudeDir, githubToken);
35530
+ spinner.stop("Analysis complete");
35531
+ if (result.newCount === 0 && result.modifiedCount === 0) {
35532
+ f2.success("Everything is up to date!");
35533
+ $e(source_default.green("✅ No changes needed"));
35534
+ return;
35535
+ }
35536
+ f2.info(`Found ${result.newCount} new, ${result.modifiedCount} modified, ${result.unchangedCount} unchanged`);
35537
+ const newItems = result.items.filter((i) => i.status === "new");
35538
+ const modifiedItems = result.items.filter((i) => i.status === "modified");
35539
+ const choices = [];
35540
+ if (newItems.length > 0) {
35541
+ for (const item of newItems) {
35542
+ choices.push({
35543
+ value: item,
35544
+ label: `\uD83C\uDD95 ${item.name}`,
35545
+ hint: `${item.category} (new ${item.type})`
35546
+ });
35547
+ }
35548
+ }
35549
+ if (modifiedItems.length > 0) {
35550
+ for (const item of modifiedItems) {
35551
+ choices.push({
35552
+ value: item,
35553
+ label: `\uD83D\uDCDD ${item.name}`,
35554
+ hint: `${item.category} (modified ${item.type})`
35555
+ });
35556
+ }
35557
+ }
35558
+ const selected = await ae({
35559
+ message: "Select items to sync:",
35560
+ options: choices,
35561
+ initialValues: choices.map((c2) => c2.value),
35562
+ required: false
35563
+ });
35564
+ if (lD(selected)) {
35565
+ ue("Sync cancelled");
35566
+ process.exit(0);
35567
+ }
35568
+ const selectedItems = selected;
35569
+ if (selectedItems.length === 0) {
35570
+ f2.warn("No items selected");
35571
+ $e(source_default.yellow("⚠️ Nothing to sync"));
35572
+ return;
35573
+ }
35574
+ const confirmResult = await se({
35575
+ message: `Sync ${selectedItems.length} item(s)?`,
35576
+ initialValue: true
35577
+ });
35578
+ if (lD(confirmResult) || !confirmResult) {
35579
+ ue("Sync cancelled");
35580
+ process.exit(0);
35581
+ }
35582
+ spinner.start(`Syncing ${selectedItems.length} item(s)...`);
35583
+ const syncResult = await syncSelectedItems(claudeDir, selectedItems, githubToken);
35584
+ spinner.stop("Sync complete");
35585
+ if (syncResult.failed > 0) {
35586
+ f2.warn(`${syncResult.success} succeeded, ${syncResult.failed} failed`);
35587
+ } else {
35588
+ f2.success(`${syncResult.success} item(s) synced successfully`);
35589
+ }
35590
+ const syncedByCategory = {
35591
+ commands: selectedItems.filter((i) => i.category === "commands").length,
35592
+ agents: selectedItems.filter((i) => i.category === "agents").length,
35593
+ skills: selectedItems.filter((i) => i.category === "skills").length,
35594
+ scripts: selectedItems.filter((i) => i.category === "scripts").length
35595
+ };
35596
+ const summary = [];
35597
+ if (syncedByCategory.commands > 0)
35598
+ summary.push(`${syncedByCategory.commands} command(s)`);
35599
+ if (syncedByCategory.agents > 0)
35600
+ summary.push(`${syncedByCategory.agents} agent(s)`);
35601
+ if (syncedByCategory.skills > 0)
35602
+ summary.push("skills folder");
35603
+ if (syncedByCategory.scripts > 0)
35604
+ summary.push("scripts folder");
35605
+ f2.info(`Synced: ${summary.join(", ")}`);
35606
+ $e(source_default.green("✅ Sync completed"));
35607
+ } catch (error) {
35608
+ if (error instanceof Error) {
35609
+ f2.error(error.message);
35610
+ }
35611
+ $e(source_default.red("❌ Sync failed"));
35612
+ process.exit(1);
35613
+ }
35614
+ }
35615
+
35136
35616
  // src/cli.ts
35137
35617
  import { readFileSync as readFileSync2 } from "fs";
35138
35618
  import { dirname as dirname4, join } from "path";
@@ -35197,6 +35677,11 @@ proCmd.command("update").description("Update premium configurations").action((op
35197
35677
  const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
35198
35678
  proUpdateCommand({ folder: claudeCodeFolder });
35199
35679
  });
35680
+ proCmd.command("sync").description("Sync premium configurations with selective update").action((options, command) => {
35681
+ const parentOptions = command.parent.parent.opts();
35682
+ const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
35683
+ proSyncCommand({ folder: claudeCodeFolder });
35684
+ });
35200
35685
  program2.parse(process.argv);
35201
35686
  if (!process.argv.slice(2).length) {
35202
35687
  console.log(source_default.blue("\uD83D\uDE80 AIBlueprint CLI"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiblueprint-cli",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "AIBlueprint CLI for setting up Claude Code configurations",
5
5
  "author": "AIBlueprint",
6
6
  "license": "MIT",
@@ -1,47 +0,0 @@
1
- ---
2
- allowed-tools: Bash(git :*)
3
- description: Quick commit and push with minimal, clean messages
4
- ---
5
-
6
- You are a git commit automation tool. Create minimal, clean commits for a tidy git history.
7
-
8
- ## Workflow
9
-
10
- 1. **Stage**: `git add -A` to stage all changes
11
- 2. **Analyze**: `git diff --cached --stat` to see what changed
12
- 3. **Commit**: Generate ONE-LINE message (max 50 chars):
13
- - `fix: [what was fixed]`
14
- - `feat: [what was added]`
15
- - `update: [what was modified]`
16
- - `refactor: [what was reorganized]`
17
- 4. **Push**: `git push` immediatelyne
18
-
19
- ## Message Rules
20
-
21
- - **ONE LINE ONLY** - no body, no details
22
- - **Under 50 characters** - be concise
23
- - **No periods** - waste of space
24
- - **Present tense** - "add" not "added"
25
- - **Lowercase after colon** - `fix: typo` not `fix: Typo`
26
-
27
- ## Examples
28
-
29
- ```
30
- feat: add user authentication
31
- fix: resolve memory leak
32
- update: improve error handling
33
- refactor: simplify api routes
34
- docs: update readme
35
- ```
36
-
37
- ## Execution
38
-
39
- - NO interactive commands
40
- - NO verbose messages
41
- - NO "Generated with" signatures
42
- - If no changes, exit silently
43
- - If push fails, report error only
44
-
45
- ## Priority
46
-
47
- Speed > Detail. Keep commits atomic and history clean.