aiblueprint-cli 1.3.5 → 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 +154 -18
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -35324,7 +35324,7 @@ 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")
|
|
35327
|
+
if (file.name === "node_modules" || file.name === ".DS_Store")
|
|
35328
35328
|
continue;
|
|
35329
35329
|
const relativePath = basePath ? `${basePath}/${file.name}` : file.name;
|
|
35330
35330
|
if (file.type === "file") {
|
|
@@ -35352,7 +35352,7 @@ async function listLocalFiles(dir) {
|
|
|
35352
35352
|
}
|
|
35353
35353
|
const items = await import_fs_extra15.default.readdir(dir);
|
|
35354
35354
|
for (const item of items) {
|
|
35355
|
-
if (item === "node_modules")
|
|
35355
|
+
if (item === "node_modules" || item === ".DS_Store")
|
|
35356
35356
|
continue;
|
|
35357
35357
|
const fullPath = path17.join(dir, item);
|
|
35358
35358
|
const stat = await import_fs_extra15.default.stat(fullPath);
|
|
@@ -35370,7 +35370,7 @@ async function listLocalFilesRecursive(dir, basePath) {
|
|
|
35370
35370
|
const files = [];
|
|
35371
35371
|
const items = await import_fs_extra15.default.readdir(dir);
|
|
35372
35372
|
for (const item of items) {
|
|
35373
|
-
if (item === "node_modules")
|
|
35373
|
+
if (item === "node_modules" || item === ".DS_Store")
|
|
35374
35374
|
continue;
|
|
35375
35375
|
const fullPath = path17.join(dir, item);
|
|
35376
35376
|
const relativePath = `${basePath}/${item}`;
|
|
@@ -35442,6 +35442,68 @@ async function analyzeCategory(category, claudeDir, githubToken) {
|
|
|
35442
35442
|
}
|
|
35443
35443
|
return items;
|
|
35444
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
|
+
}
|
|
35445
35507
|
async function analyzeSyncChanges(claudeDir, githubToken) {
|
|
35446
35508
|
const allItems = [];
|
|
35447
35509
|
const categories = [
|
|
@@ -35454,10 +35516,16 @@ async function analyzeSyncChanges(claudeDir, githubToken) {
|
|
|
35454
35516
|
const items = await analyzeCategory(category, claudeDir, githubToken);
|
|
35455
35517
|
allItems.push(...items);
|
|
35456
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;
|
|
35457
35524
|
return {
|
|
35458
35525
|
items: allItems,
|
|
35459
|
-
|
|
35460
|
-
|
|
35526
|
+
hooks,
|
|
35527
|
+
newCount: allItems.filter((i) => i.status === "new").length + hooksNewCount,
|
|
35528
|
+
modifiedCount: allItems.filter((i) => i.status === "modified").length + hooksModifiedCount,
|
|
35461
35529
|
deletedCount: allItems.filter((i) => i.status === "deleted").length,
|
|
35462
35530
|
unchangedCount: allItems.filter((i) => i.status === "unchanged").length
|
|
35463
35531
|
};
|
|
@@ -35482,6 +35550,43 @@ async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken)
|
|
|
35482
35550
|
return false;
|
|
35483
35551
|
}
|
|
35484
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
|
+
}
|
|
35485
35590
|
async function syncSelectedItems(claudeDir, items, githubToken, onProgress) {
|
|
35486
35591
|
let success = 0;
|
|
35487
35592
|
let failed = 0;
|
|
@@ -35563,7 +35668,7 @@ function formatFolderSummary(summary) {
|
|
|
35563
35668
|
const countStr = parts.length > 0 ? ` (${parts.join(", ")})` : "";
|
|
35564
35669
|
return `\uD83D\uDCC1 ${summary.name}${countStr}`;
|
|
35565
35670
|
}
|
|
35566
|
-
function createSelectionChoices(changedItems) {
|
|
35671
|
+
function createSelectionChoices(changedItems, hooks = []) {
|
|
35567
35672
|
const choices = [];
|
|
35568
35673
|
const folderedCategories = ["scripts", "skills"];
|
|
35569
35674
|
const grouped = groupByCategory(changedItems);
|
|
@@ -35596,6 +35701,16 @@ function createSelectionChoices(changedItems) {
|
|
|
35596
35701
|
}
|
|
35597
35702
|
}
|
|
35598
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
|
+
}
|
|
35599
35714
|
return choices;
|
|
35600
35715
|
}
|
|
35601
35716
|
function formatFolderHint(summary) {
|
|
@@ -35610,14 +35725,17 @@ function formatFolderHint(summary) {
|
|
|
35610
35725
|
}
|
|
35611
35726
|
function expandSelections(selections) {
|
|
35612
35727
|
const items = [];
|
|
35728
|
+
const hooks = [];
|
|
35613
35729
|
for (const sel of selections) {
|
|
35614
35730
|
if (sel.type === "file") {
|
|
35615
35731
|
items.push(sel.item);
|
|
35616
|
-
} else {
|
|
35732
|
+
} else if (sel.type === "folder") {
|
|
35617
35733
|
items.push(...sel.items);
|
|
35734
|
+
} else if (sel.type === "hook") {
|
|
35735
|
+
hooks.push(sel.hook);
|
|
35618
35736
|
}
|
|
35619
35737
|
}
|
|
35620
|
-
return items;
|
|
35738
|
+
return { items, hooks };
|
|
35621
35739
|
}
|
|
35622
35740
|
async function proSyncCommand(options = {}) {
|
|
35623
35741
|
oe(source_default.blue(`\uD83D\uDD04 Sync Premium Configurations ${source_default.gray(`v${getVersion()}`)}`));
|
|
@@ -35635,7 +35753,8 @@ async function proSyncCommand(options = {}) {
|
|
|
35635
35753
|
const result = await analyzeSyncChanges(claudeDir, githubToken);
|
|
35636
35754
|
spinner.stop("Analysis complete");
|
|
35637
35755
|
const changedItems = result.items.filter((i) => i.status !== "unchanged");
|
|
35638
|
-
|
|
35756
|
+
const changedHooks = result.hooks;
|
|
35757
|
+
if (changedItems.length === 0 && changedHooks.length === 0) {
|
|
35639
35758
|
f2.success("Everything is up to date!");
|
|
35640
35759
|
$e(source_default.green("✅ No changes needed"));
|
|
35641
35760
|
return;
|
|
@@ -35659,8 +35778,18 @@ async function proSyncCommand(options = {}) {
|
|
|
35659
35778
|
}
|
|
35660
35779
|
}
|
|
35661
35780
|
}
|
|
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
|
+
}
|
|
35790
|
+
}
|
|
35662
35791
|
f2.message("");
|
|
35663
|
-
const choices = createSelectionChoices(changedItems);
|
|
35792
|
+
const choices = createSelectionChoices(changedItems, changedHooks);
|
|
35664
35793
|
const selected = await ae({
|
|
35665
35794
|
message: "Select items to sync:",
|
|
35666
35795
|
options: choices,
|
|
@@ -35671,14 +35800,16 @@ async function proSyncCommand(options = {}) {
|
|
|
35671
35800
|
ue("Sync cancelled");
|
|
35672
35801
|
process.exit(0);
|
|
35673
35802
|
}
|
|
35674
|
-
const
|
|
35675
|
-
|
|
35803
|
+
const expanded = expandSelections(selected);
|
|
35804
|
+
const selectedItems = expanded.items;
|
|
35805
|
+
const selectedHooks = expanded.hooks;
|
|
35806
|
+
if (selectedItems.length === 0 && selectedHooks.length === 0) {
|
|
35676
35807
|
f2.warn("No items selected");
|
|
35677
35808
|
$e(source_default.yellow("⚠️ Nothing to sync"));
|
|
35678
35809
|
return;
|
|
35679
35810
|
}
|
|
35680
|
-
const toAdd = selectedItems.filter((i) => i.status === "new").length;
|
|
35681
|
-
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;
|
|
35682
35813
|
const toRemove = selectedItems.filter((i) => i.status === "deleted").length;
|
|
35683
35814
|
const summary = [
|
|
35684
35815
|
toAdd > 0 ? `add ${toAdd}` : "",
|
|
@@ -35697,14 +35828,19 @@ async function proSyncCommand(options = {}) {
|
|
|
35697
35828
|
const syncResult = await syncSelectedItems(claudeDir, selectedItems, githubToken, (file, action) => {
|
|
35698
35829
|
spinner.message(`${action}: ${source_default.cyan(file)}`);
|
|
35699
35830
|
});
|
|
35831
|
+
const hooksResult = await syncSelectedHooks(claudeDir, selectedHooks, (hook, action) => {
|
|
35832
|
+
spinner.message(`${action}: ${source_default.cyan(hook)}`);
|
|
35833
|
+
});
|
|
35700
35834
|
spinner.stop("Sync complete");
|
|
35835
|
+
const totalSuccess = syncResult.success + hooksResult.success;
|
|
35836
|
+
const totalFailed = syncResult.failed + hooksResult.failed;
|
|
35701
35837
|
const results = [];
|
|
35702
|
-
if (
|
|
35703
|
-
results.push(source_default.green(`${
|
|
35838
|
+
if (totalSuccess > 0)
|
|
35839
|
+
results.push(source_default.green(`${totalSuccess} added/updated`));
|
|
35704
35840
|
if (syncResult.deleted > 0)
|
|
35705
35841
|
results.push(source_default.red(`${syncResult.deleted} removed`));
|
|
35706
|
-
if (
|
|
35707
|
-
results.push(source_default.yellow(`${
|
|
35842
|
+
if (totalFailed > 0)
|
|
35843
|
+
results.push(source_default.yellow(`${totalFailed} failed`));
|
|
35708
35844
|
f2.success(results.join(", "));
|
|
35709
35845
|
const scriptsWereSynced = selectedItems.some((i) => i.category === "scripts");
|
|
35710
35846
|
if (scriptsWereSynced) {
|