aiblueprint-cli 1.3.4 → 1.3.6
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 +249 -23
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -35324,6 +35324,8 @@ async function listRemoteFilesRecursive(dirPath, githubToken, basePath = "") {
|
|
|
35324
35324
|
const results = [];
|
|
35325
35325
|
const files = await listRemoteDirectory(dirPath, githubToken);
|
|
35326
35326
|
for (const file of files) {
|
|
35327
|
+
if (file.name === "node_modules" || file.name === ".DS_Store")
|
|
35328
|
+
continue;
|
|
35327
35329
|
const relativePath = basePath ? `${basePath}/${file.name}` : file.name;
|
|
35328
35330
|
if (file.type === "file") {
|
|
35329
35331
|
results.push({ path: relativePath, sha: file.sha, isFolder: false });
|
|
@@ -35350,6 +35352,8 @@ async function listLocalFiles(dir) {
|
|
|
35350
35352
|
}
|
|
35351
35353
|
const items = await import_fs_extra15.default.readdir(dir);
|
|
35352
35354
|
for (const item of items) {
|
|
35355
|
+
if (item === "node_modules" || item === ".DS_Store")
|
|
35356
|
+
continue;
|
|
35353
35357
|
const fullPath = path17.join(dir, item);
|
|
35354
35358
|
const stat = await import_fs_extra15.default.stat(fullPath);
|
|
35355
35359
|
if (stat.isDirectory()) {
|
|
@@ -35366,6 +35370,8 @@ async function listLocalFilesRecursive(dir, basePath) {
|
|
|
35366
35370
|
const files = [];
|
|
35367
35371
|
const items = await import_fs_extra15.default.readdir(dir);
|
|
35368
35372
|
for (const item of items) {
|
|
35373
|
+
if (item === "node_modules" || item === ".DS_Store")
|
|
35374
|
+
continue;
|
|
35369
35375
|
const fullPath = path17.join(dir, item);
|
|
35370
35376
|
const relativePath = `${basePath}/${item}`;
|
|
35371
35377
|
const stat = await import_fs_extra15.default.stat(fullPath);
|
|
@@ -35436,6 +35442,68 @@ async function analyzeCategory(category, claudeDir, githubToken) {
|
|
|
35436
35442
|
}
|
|
35437
35443
|
return items;
|
|
35438
35444
|
}
|
|
35445
|
+
async function fetchRemoteSettings(githubToken) {
|
|
35446
|
+
try {
|
|
35447
|
+
const url = `https://raw.githubusercontent.com/${PREMIUM_REPO2}/${PREMIUM_BRANCH2}/claude-code-config/settings.json`;
|
|
35448
|
+
const response = await fetch(url, {
|
|
35449
|
+
headers: {
|
|
35450
|
+
Authorization: `token ${githubToken}`,
|
|
35451
|
+
Accept: "application/vnd.github.v3.raw"
|
|
35452
|
+
}
|
|
35453
|
+
});
|
|
35454
|
+
if (!response.ok) {
|
|
35455
|
+
return null;
|
|
35456
|
+
}
|
|
35457
|
+
return await response.json();
|
|
35458
|
+
} catch {
|
|
35459
|
+
return null;
|
|
35460
|
+
}
|
|
35461
|
+
}
|
|
35462
|
+
async function getLocalSettings(claudeDir) {
|
|
35463
|
+
const settingsPath = path17.join(claudeDir, "settings.json");
|
|
35464
|
+
try {
|
|
35465
|
+
const content = await import_fs_extra15.default.readFile(settingsPath, "utf-8");
|
|
35466
|
+
return JSON.parse(content);
|
|
35467
|
+
} catch {
|
|
35468
|
+
return {};
|
|
35469
|
+
}
|
|
35470
|
+
}
|
|
35471
|
+
function analyzeHooksChanges(remoteSettings, localSettings) {
|
|
35472
|
+
const hookItems = [];
|
|
35473
|
+
if (!remoteSettings?.hooks) {
|
|
35474
|
+
return hookItems;
|
|
35475
|
+
}
|
|
35476
|
+
const localHooks = localSettings?.hooks || {};
|
|
35477
|
+
for (const [hookType, remoteHookArray] of Object.entries(remoteSettings.hooks)) {
|
|
35478
|
+
if (!Array.isArray(remoteHookArray))
|
|
35479
|
+
continue;
|
|
35480
|
+
const localHookArray = localHooks[hookType] || [];
|
|
35481
|
+
for (const remoteHook of remoteHookArray) {
|
|
35482
|
+
const matcher = remoteHook.matcher || "";
|
|
35483
|
+
const existingLocal = localHookArray.find((h2) => h2.matcher === matcher);
|
|
35484
|
+
if (!existingLocal) {
|
|
35485
|
+
hookItems.push({
|
|
35486
|
+
hookType,
|
|
35487
|
+
matcher,
|
|
35488
|
+
status: "new",
|
|
35489
|
+
remoteHook
|
|
35490
|
+
});
|
|
35491
|
+
} else {
|
|
35492
|
+
const remoteStr = JSON.stringify(remoteHook);
|
|
35493
|
+
const localStr = JSON.stringify(existingLocal);
|
|
35494
|
+
if (remoteStr !== localStr) {
|
|
35495
|
+
hookItems.push({
|
|
35496
|
+
hookType,
|
|
35497
|
+
matcher,
|
|
35498
|
+
status: "modified",
|
|
35499
|
+
remoteHook
|
|
35500
|
+
});
|
|
35501
|
+
}
|
|
35502
|
+
}
|
|
35503
|
+
}
|
|
35504
|
+
}
|
|
35505
|
+
return hookItems;
|
|
35506
|
+
}
|
|
35439
35507
|
async function analyzeSyncChanges(claudeDir, githubToken) {
|
|
35440
35508
|
const allItems = [];
|
|
35441
35509
|
const categories = [
|
|
@@ -35448,10 +35516,16 @@ async function analyzeSyncChanges(claudeDir, githubToken) {
|
|
|
35448
35516
|
const items = await analyzeCategory(category, claudeDir, githubToken);
|
|
35449
35517
|
allItems.push(...items);
|
|
35450
35518
|
}
|
|
35519
|
+
const remoteSettings = await fetchRemoteSettings(githubToken);
|
|
35520
|
+
const localSettings = await getLocalSettings(claudeDir);
|
|
35521
|
+
const hooks = remoteSettings ? analyzeHooksChanges(remoteSettings, localSettings) : [];
|
|
35522
|
+
const hooksNewCount = hooks.filter((h2) => h2.status === "new").length;
|
|
35523
|
+
const hooksModifiedCount = hooks.filter((h2) => h2.status === "modified").length;
|
|
35451
35524
|
return {
|
|
35452
35525
|
items: allItems,
|
|
35453
|
-
|
|
35454
|
-
|
|
35526
|
+
hooks,
|
|
35527
|
+
newCount: allItems.filter((i) => i.status === "new").length + hooksNewCount,
|
|
35528
|
+
modifiedCount: allItems.filter((i) => i.status === "modified").length + hooksModifiedCount,
|
|
35455
35529
|
deletedCount: allItems.filter((i) => i.status === "deleted").length,
|
|
35456
35530
|
unchangedCount: allItems.filter((i) => i.status === "unchanged").length
|
|
35457
35531
|
};
|
|
@@ -35476,6 +35550,43 @@ async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken)
|
|
|
35476
35550
|
return false;
|
|
35477
35551
|
}
|
|
35478
35552
|
}
|
|
35553
|
+
async function syncSelectedHooks(claudeDir, hooks, onProgress) {
|
|
35554
|
+
if (hooks.length === 0) {
|
|
35555
|
+
return { success: 0, failed: 0 };
|
|
35556
|
+
}
|
|
35557
|
+
const settingsPath = path17.join(claudeDir, "settings.json");
|
|
35558
|
+
let settings = {};
|
|
35559
|
+
try {
|
|
35560
|
+
const content = await import_fs_extra15.default.readFile(settingsPath, "utf-8");
|
|
35561
|
+
settings = JSON.parse(content);
|
|
35562
|
+
} catch {
|
|
35563
|
+
settings = {};
|
|
35564
|
+
}
|
|
35565
|
+
if (!settings.hooks) {
|
|
35566
|
+
settings.hooks = {};
|
|
35567
|
+
}
|
|
35568
|
+
let success = 0;
|
|
35569
|
+
let failed = 0;
|
|
35570
|
+
for (const hook of hooks) {
|
|
35571
|
+
onProgress?.(`${hook.hookType}[${hook.matcher || "*"}]`, hook.status === "new" ? "adding" : "updating");
|
|
35572
|
+
try {
|
|
35573
|
+
if (!settings.hooks[hook.hookType]) {
|
|
35574
|
+
settings.hooks[hook.hookType] = [];
|
|
35575
|
+
}
|
|
35576
|
+
const existingIndex = settings.hooks[hook.hookType].findIndex((h2) => h2.matcher === hook.matcher);
|
|
35577
|
+
if (existingIndex >= 0) {
|
|
35578
|
+
settings.hooks[hook.hookType][existingIndex] = hook.remoteHook;
|
|
35579
|
+
} else {
|
|
35580
|
+
settings.hooks[hook.hookType].push(hook.remoteHook);
|
|
35581
|
+
}
|
|
35582
|
+
success++;
|
|
35583
|
+
} catch {
|
|
35584
|
+
failed++;
|
|
35585
|
+
}
|
|
35586
|
+
}
|
|
35587
|
+
await import_fs_extra15.default.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
35588
|
+
return { success, failed };
|
|
35589
|
+
}
|
|
35479
35590
|
async function syncSelectedItems(claudeDir, items, githubToken, onProgress) {
|
|
35480
35591
|
let success = 0;
|
|
35481
35592
|
let failed = 0;
|
|
@@ -35528,6 +35639,104 @@ function groupByCategory(items) {
|
|
|
35528
35639
|
}
|
|
35529
35640
|
return grouped;
|
|
35530
35641
|
}
|
|
35642
|
+
function aggregateByTopLevelFolder(items) {
|
|
35643
|
+
const folderMap = new Map;
|
|
35644
|
+
for (const item of items) {
|
|
35645
|
+
const parts = item.name.split("/");
|
|
35646
|
+
const topLevel = parts[0];
|
|
35647
|
+
if (!folderMap.has(topLevel)) {
|
|
35648
|
+
folderMap.set(topLevel, { name: topLevel, newCount: 0, modifiedCount: 0, deletedCount: 0 });
|
|
35649
|
+
}
|
|
35650
|
+
const summary = folderMap.get(topLevel);
|
|
35651
|
+
if (item.status === "new")
|
|
35652
|
+
summary.newCount++;
|
|
35653
|
+
else if (item.status === "modified")
|
|
35654
|
+
summary.modifiedCount++;
|
|
35655
|
+
else if (item.status === "deleted")
|
|
35656
|
+
summary.deletedCount++;
|
|
35657
|
+
}
|
|
35658
|
+
return Array.from(folderMap.values());
|
|
35659
|
+
}
|
|
35660
|
+
function formatFolderSummary(summary) {
|
|
35661
|
+
const parts = [];
|
|
35662
|
+
if (summary.newCount > 0)
|
|
35663
|
+
parts.push(source_default.green(`+${summary.newCount}`));
|
|
35664
|
+
if (summary.modifiedCount > 0)
|
|
35665
|
+
parts.push(source_default.yellow(`~${summary.modifiedCount}`));
|
|
35666
|
+
if (summary.deletedCount > 0)
|
|
35667
|
+
parts.push(source_default.red(`-${summary.deletedCount}`));
|
|
35668
|
+
const countStr = parts.length > 0 ? ` (${parts.join(", ")})` : "";
|
|
35669
|
+
return `\uD83D\uDCC1 ${summary.name}${countStr}`;
|
|
35670
|
+
}
|
|
35671
|
+
function createSelectionChoices(changedItems, hooks = []) {
|
|
35672
|
+
const choices = [];
|
|
35673
|
+
const folderedCategories = ["scripts", "skills"];
|
|
35674
|
+
const grouped = groupByCategory(changedItems);
|
|
35675
|
+
for (const [category, items] of grouped) {
|
|
35676
|
+
if (folderedCategories.includes(category)) {
|
|
35677
|
+
const folderMap = new Map;
|
|
35678
|
+
for (const item of items) {
|
|
35679
|
+
const topLevel = item.name.split("/")[0];
|
|
35680
|
+
if (!folderMap.has(topLevel))
|
|
35681
|
+
folderMap.set(topLevel, []);
|
|
35682
|
+
folderMap.get(topLevel).push(item);
|
|
35683
|
+
}
|
|
35684
|
+
for (const [folder, folderItems] of folderMap) {
|
|
35685
|
+
const summary = aggregateByTopLevelFolder(folderItems)[0];
|
|
35686
|
+
choices.push({
|
|
35687
|
+
value: { type: "folder", folder, category, items: folderItems },
|
|
35688
|
+
label: `\uD83D\uDCC1 ${category}/${folder}`,
|
|
35689
|
+
hint: formatFolderHint(summary)
|
|
35690
|
+
});
|
|
35691
|
+
}
|
|
35692
|
+
} else {
|
|
35693
|
+
for (const item of items) {
|
|
35694
|
+
const icons = { new: "\uD83C\uDD95", modified: "\uD83D\uDCDD", deleted: "\uD83D\uDDD1️", unchanged: "" };
|
|
35695
|
+
const actions = { new: "add", modified: "update", deleted: "remove", unchanged: "" };
|
|
35696
|
+
choices.push({
|
|
35697
|
+
value: { type: "file", item },
|
|
35698
|
+
label: `${icons[item.status]} ${item.relativePath}`,
|
|
35699
|
+
hint: actions[item.status]
|
|
35700
|
+
});
|
|
35701
|
+
}
|
|
35702
|
+
}
|
|
35703
|
+
}
|
|
35704
|
+
for (const hook of hooks) {
|
|
35705
|
+
const icon = hook.status === "new" ? "\uD83C\uDD95" : "\uD83D\uDCDD";
|
|
35706
|
+
const action = hook.status === "new" ? "add" : "update";
|
|
35707
|
+
const matcherDisplay = hook.matcher || "*";
|
|
35708
|
+
choices.push({
|
|
35709
|
+
value: { type: "hook", hook },
|
|
35710
|
+
label: `${icon} settings.json → ${hook.hookType}[${matcherDisplay}]`,
|
|
35711
|
+
hint: action
|
|
35712
|
+
});
|
|
35713
|
+
}
|
|
35714
|
+
return choices;
|
|
35715
|
+
}
|
|
35716
|
+
function formatFolderHint(summary) {
|
|
35717
|
+
const parts = [];
|
|
35718
|
+
if (summary.newCount > 0)
|
|
35719
|
+
parts.push(`+${summary.newCount}`);
|
|
35720
|
+
if (summary.modifiedCount > 0)
|
|
35721
|
+
parts.push(`~${summary.modifiedCount}`);
|
|
35722
|
+
if (summary.deletedCount > 0)
|
|
35723
|
+
parts.push(`-${summary.deletedCount}`);
|
|
35724
|
+
return parts.join(", ");
|
|
35725
|
+
}
|
|
35726
|
+
function expandSelections(selections) {
|
|
35727
|
+
const items = [];
|
|
35728
|
+
const hooks = [];
|
|
35729
|
+
for (const sel of selections) {
|
|
35730
|
+
if (sel.type === "file") {
|
|
35731
|
+
items.push(sel.item);
|
|
35732
|
+
} else if (sel.type === "folder") {
|
|
35733
|
+
items.push(...sel.items);
|
|
35734
|
+
} else if (sel.type === "hook") {
|
|
35735
|
+
hooks.push(sel.hook);
|
|
35736
|
+
}
|
|
35737
|
+
}
|
|
35738
|
+
return { items, hooks };
|
|
35739
|
+
}
|
|
35531
35740
|
async function proSyncCommand(options = {}) {
|
|
35532
35741
|
oe(source_default.blue(`\uD83D\uDD04 Sync Premium Configurations ${source_default.gray(`v${getVersion()}`)}`));
|
|
35533
35742
|
try {
|
|
@@ -35544,7 +35753,8 @@ async function proSyncCommand(options = {}) {
|
|
|
35544
35753
|
const result = await analyzeSyncChanges(claudeDir, githubToken);
|
|
35545
35754
|
spinner.stop("Analysis complete");
|
|
35546
35755
|
const changedItems = result.items.filter((i) => i.status !== "unchanged");
|
|
35547
|
-
|
|
35756
|
+
const changedHooks = result.hooks;
|
|
35757
|
+
if (changedItems.length === 0 && changedHooks.length === 0) {
|
|
35548
35758
|
f2.success("Everything is up to date!");
|
|
35549
35759
|
$e(source_default.green("✅ No changes needed"));
|
|
35550
35760
|
return;
|
|
@@ -35553,24 +35763,33 @@ async function proSyncCommand(options = {}) {
|
|
|
35553
35763
|
f2.message("");
|
|
35554
35764
|
f2.message(source_default.bold("Changes by category:"));
|
|
35555
35765
|
const grouped = groupByCategory(changedItems);
|
|
35766
|
+
const folderedCategories = ["scripts", "skills"];
|
|
35556
35767
|
for (const [category, items] of grouped) {
|
|
35557
35768
|
f2.message("");
|
|
35558
35769
|
f2.message(source_default.cyan.bold(` ${category.toUpperCase()}`));
|
|
35559
|
-
|
|
35560
|
-
|
|
35770
|
+
if (folderedCategories.includes(category)) {
|
|
35771
|
+
const folderSummaries = aggregateByTopLevelFolder(items);
|
|
35772
|
+
for (const summary2 of folderSummaries) {
|
|
35773
|
+
f2.message(` ${formatFolderSummary(summary2)}`);
|
|
35774
|
+
}
|
|
35775
|
+
} else {
|
|
35776
|
+
for (const item of items) {
|
|
35777
|
+
f2.message(` ${formatItem(item)}`);
|
|
35778
|
+
}
|
|
35561
35779
|
}
|
|
35562
35780
|
}
|
|
35563
|
-
|
|
35564
|
-
|
|
35565
|
-
|
|
35566
|
-
const
|
|
35567
|
-
|
|
35568
|
-
|
|
35569
|
-
|
|
35570
|
-
|
|
35571
|
-
|
|
35572
|
-
});
|
|
35781
|
+
if (changedHooks.length > 0) {
|
|
35782
|
+
f2.message("");
|
|
35783
|
+
f2.message(source_default.cyan.bold(` SETTINGS (hooks)`));
|
|
35784
|
+
for (const hook of changedHooks) {
|
|
35785
|
+
const icon = hook.status === "new" ? "\uD83C\uDD95" : "\uD83D\uDCDD";
|
|
35786
|
+
const color = hook.status === "new" ? source_default.green : source_default.yellow;
|
|
35787
|
+
const matcherDisplay = hook.matcher || "*";
|
|
35788
|
+
f2.message(` ${icon} ${color(`${hook.hookType}[${matcherDisplay}]`)}`);
|
|
35789
|
+
}
|
|
35573
35790
|
}
|
|
35791
|
+
f2.message("");
|
|
35792
|
+
const choices = createSelectionChoices(changedItems, changedHooks);
|
|
35574
35793
|
const selected = await ae({
|
|
35575
35794
|
message: "Select items to sync:",
|
|
35576
35795
|
options: choices,
|
|
@@ -35581,14 +35800,16 @@ async function proSyncCommand(options = {}) {
|
|
|
35581
35800
|
ue("Sync cancelled");
|
|
35582
35801
|
process.exit(0);
|
|
35583
35802
|
}
|
|
35584
|
-
const
|
|
35585
|
-
|
|
35803
|
+
const expanded = expandSelections(selected);
|
|
35804
|
+
const selectedItems = expanded.items;
|
|
35805
|
+
const selectedHooks = expanded.hooks;
|
|
35806
|
+
if (selectedItems.length === 0 && selectedHooks.length === 0) {
|
|
35586
35807
|
f2.warn("No items selected");
|
|
35587
35808
|
$e(source_default.yellow("⚠️ Nothing to sync"));
|
|
35588
35809
|
return;
|
|
35589
35810
|
}
|
|
35590
|
-
const toAdd = selectedItems.filter((i) => i.status === "new").length;
|
|
35591
|
-
const toUpdate = selectedItems.filter((i) => i.status === "modified").length;
|
|
35811
|
+
const toAdd = selectedItems.filter((i) => i.status === "new").length + selectedHooks.filter((h2) => h2.status === "new").length;
|
|
35812
|
+
const toUpdate = selectedItems.filter((i) => i.status === "modified").length + selectedHooks.filter((h2) => h2.status === "modified").length;
|
|
35592
35813
|
const toRemove = selectedItems.filter((i) => i.status === "deleted").length;
|
|
35593
35814
|
const summary = [
|
|
35594
35815
|
toAdd > 0 ? `add ${toAdd}` : "",
|
|
@@ -35607,14 +35828,19 @@ async function proSyncCommand(options = {}) {
|
|
|
35607
35828
|
const syncResult = await syncSelectedItems(claudeDir, selectedItems, githubToken, (file, action) => {
|
|
35608
35829
|
spinner.message(`${action}: ${source_default.cyan(file)}`);
|
|
35609
35830
|
});
|
|
35831
|
+
const hooksResult = await syncSelectedHooks(claudeDir, selectedHooks, (hook, action) => {
|
|
35832
|
+
spinner.message(`${action}: ${source_default.cyan(hook)}`);
|
|
35833
|
+
});
|
|
35610
35834
|
spinner.stop("Sync complete");
|
|
35835
|
+
const totalSuccess = syncResult.success + hooksResult.success;
|
|
35836
|
+
const totalFailed = syncResult.failed + hooksResult.failed;
|
|
35611
35837
|
const results = [];
|
|
35612
|
-
if (
|
|
35613
|
-
results.push(source_default.green(`${
|
|
35838
|
+
if (totalSuccess > 0)
|
|
35839
|
+
results.push(source_default.green(`${totalSuccess} added/updated`));
|
|
35614
35840
|
if (syncResult.deleted > 0)
|
|
35615
35841
|
results.push(source_default.red(`${syncResult.deleted} removed`));
|
|
35616
|
-
if (
|
|
35617
|
-
results.push(source_default.yellow(`${
|
|
35842
|
+
if (totalFailed > 0)
|
|
35843
|
+
results.push(source_default.yellow(`${totalFailed} failed`));
|
|
35618
35844
|
f2.success(results.join(", "));
|
|
35619
35845
|
const scriptsWereSynced = selectedItems.some((i) => i.category === "scripts");
|
|
35620
35846
|
if (scriptsWereSynced) {
|