aiblueprint-cli 1.4.2 → 1.4.4

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.
@@ -1,5 +1,8 @@
1
+ import { homedir } from "os";
1
2
  import type { SecurityRules } from "./types";
2
3
 
4
+ const HOME = homedir();
5
+
3
6
  export const SECURITY_RULES: SecurityRules = {
4
7
  CRITICAL_COMMANDS: [
5
8
  "del",
@@ -126,7 +129,7 @@ export const SECURITY_RULES: SecurityRules = {
126
129
  ],
127
130
 
128
131
  SAFE_RM_PATHS: [
129
- "/Users/melvynx/Developer/",
132
+ `${HOME}/Developer/`,
130
133
  "/tmp/",
131
134
  "/var/tmp/",
132
135
  `${process.cwd()}/`,
@@ -10,6 +10,11 @@
10
10
  * Manual test: echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' | bun validate-command.js
11
11
  */
12
12
 
13
+ import { homedir } from "os";
14
+ import { join } from "path";
15
+
16
+ const HOME = homedir();
17
+
13
18
  // Comprehensive dangerous command patterns database
14
19
  const SECURITY_RULES = {
15
20
  // Critical system destruction commands
@@ -161,7 +166,7 @@ const SECURITY_RULES = {
161
166
 
162
167
  // Safe paths where rm -rf is allowed
163
168
  SAFE_RM_PATHS: [
164
- "/Users/melvynx/Developer/",
169
+ `${HOME}/Developer/`,
165
170
  "/tmp/",
166
171
  "/var/tmp/",
167
172
  process.cwd() + "/", // Current working directory
@@ -205,7 +210,7 @@ const SAFE_COMMANDS = [
205
210
 
206
211
  class CommandValidator {
207
212
  constructor() {
208
- this.logFile = "/Users/melvynx/.claude/security.log";
213
+ this.logFile = join(HOME, ".claude", "security.log");
209
214
  }
210
215
 
211
216
  /**
package/dist/cli.js CHANGED
@@ -33895,6 +33895,36 @@ function backupFile(filePath) {
33895
33895
  throw new Error(`Failed to create backup: ${error.message}`);
33896
33896
  }
33897
33897
  }
33898
+ function getPackageManager() {
33899
+ if (commandExists("apt")) {
33900
+ return { cmd: "apt", installCmd: "sudo apt install -y" };
33901
+ }
33902
+ if (commandExists("apt-get")) {
33903
+ return { cmd: "apt-get", installCmd: "sudo apt-get install -y" };
33904
+ }
33905
+ if (commandExists("brew")) {
33906
+ return { cmd: "brew", installCmd: "brew install" };
33907
+ }
33908
+ if (commandExists("dnf")) {
33909
+ return { cmd: "dnf", installCmd: "sudo dnf install -y" };
33910
+ }
33911
+ if (commandExists("yum")) {
33912
+ return { cmd: "yum", installCmd: "sudo yum install -y" };
33913
+ }
33914
+ if (commandExists("pacman")) {
33915
+ return { cmd: "pacman", installCmd: "sudo pacman -S --noconfirm" };
33916
+ }
33917
+ return null;
33918
+ }
33919
+ function installPrerequisiteSync(packageName, installCmd) {
33920
+ try {
33921
+ const fullCmd = `${installCmd} ${packageName}`;
33922
+ execSync3(fullCmd, { stdio: "inherit", timeout: INSTALL_TIMEOUT });
33923
+ return true;
33924
+ } catch {
33925
+ return false;
33926
+ }
33927
+ }
33898
33928
  async function installOhMyZsh(homeDir) {
33899
33929
  return new Promise((resolve, reject) => {
33900
33930
  const installCmd = `sh -c "$(curl -fsSL ${OHMYZSH_INSTALL_URL})" "" --unattended`;
@@ -34013,19 +34043,41 @@ async function setupTerminalCommand(options = {}) {
34013
34043
  missingPrereqs.push("zsh");
34014
34044
  }
34015
34045
  if (missingPrereqs.length > 0) {
34016
- s.stop(source_default.red("Missing prerequisites"));
34017
- console.log(source_default.red(`
34046
+ s.stop(`Missing: ${missingPrereqs.join(", ")}`);
34047
+ const packageManager = getPackageManager();
34048
+ if (!packageManager) {
34049
+ console.log(source_default.red(`
34018
34050
  ❌ Missing required tools: ${missingPrereqs.join(", ")}`));
34051
+ console.log(source_default.yellow(`
34052
+ Could not detect package manager. Please install manually:`));
34053
+ if (platformInfo.isMacOS) {
34054
+ console.log(source_default.gray(" brew install " + missingPrereqs.join(" ")));
34055
+ } else {
34056
+ console.log(source_default.gray(" sudo apt install " + missingPrereqs.join(" ")));
34057
+ }
34058
+ process.exit(1);
34059
+ }
34019
34060
  console.log(source_default.yellow(`
34020
- Please install them first:`));
34021
- if (platformInfo.isMacOS) {
34022
- console.log(source_default.gray(" brew install " + missingPrereqs.join(" ")));
34023
- } else {
34024
- console.log(source_default.gray(" sudo apt install " + missingPrereqs.join(" ")));
34061
+ Installing missing prerequisites: ${missingPrereqs.join(", ")}`));
34062
+ console.log(source_default.gray(`Using package manager: ${packageManager.cmd}`));
34063
+ for (const pkg of missingPrereqs) {
34064
+ console.log(source_default.yellow(`
34065
+ \uD83D\uDCE6 Installing ${pkg}...`));
34066
+ const success = installPrerequisiteSync(pkg, packageManager.installCmd);
34067
+ if (success) {
34068
+ console.log(source_default.green(`✓ ${pkg} installed`));
34069
+ } else {
34070
+ console.log(source_default.red(`
34071
+ ❌ Failed to install ${pkg}`));
34072
+ console.log(source_default.yellow("Please install it manually:"));
34073
+ console.log(source_default.gray(` ${packageManager.installCmd} ${pkg}`));
34074
+ process.exit(1);
34075
+ }
34025
34076
  }
34026
- process.exit(1);
34077
+ console.log(source_default.green("✓ All prerequisites installed"));
34078
+ } else {
34079
+ s.stop("Prerequisites OK");
34027
34080
  }
34028
- s.stop("Prerequisites OK");
34029
34081
  let selectedTheme = "robbyrussell";
34030
34082
  if (!skipInteractive) {
34031
34083
  const themeAnswer = await lib_default.prompt([
@@ -36270,14 +36322,14 @@ async function proSyncCommand(options = {}) {
36270
36322
  {
36271
36323
  value: "updates",
36272
36324
  label: "Import all updates",
36273
- hint: `add ${newItems.length + newHooks.length} + update ${modifiedItems.length + modifiedHooks.length} files`
36325
+ hint: `add ${newItems.length} + update ${modifiedItems.length} files`
36274
36326
  }
36275
36327
  ];
36276
36328
  if (hasDeletions) {
36277
36329
  syncModeOptions.push({
36278
36330
  value: "updates_and_delete",
36279
36331
  label: "Import all updates and delete files",
36280
- hint: `add ${newItems.length + newHooks.length} + update ${modifiedItems.length + modifiedHooks.length} + delete ${deletedItems.length} files`
36332
+ hint: `add ${newItems.length} + update ${modifiedItems.length} + delete ${deletedItems.length} files`
36281
36333
  });
36282
36334
  }
36283
36335
  syncModeOptions.push({
@@ -36297,12 +36349,11 @@ async function proSyncCommand(options = {}) {
36297
36349
  let selectedHooks = [];
36298
36350
  if (syncMode === "updates") {
36299
36351
  selectedItems = [...newItems, ...modifiedItems];
36300
- selectedHooks = [...newHooks, ...modifiedHooks];
36301
36352
  } else if (syncMode === "updates_and_delete") {
36302
36353
  selectedItems = [...newItems, ...modifiedItems, ...deletedItems];
36303
- selectedHooks = [...newHooks, ...modifiedHooks];
36304
36354
  } else {
36305
- const nonDeleteChoices = choices.filter((c2) => {
36355
+ const fileChoices = choices.filter((c2) => c2.value.type !== "hook");
36356
+ const nonDeleteChoices = fileChoices.filter((c2) => {
36306
36357
  if (c2.value.type === "file")
36307
36358
  return c2.value.item.status !== "deleted";
36308
36359
  if (c2.value.type === "folder")
@@ -36311,8 +36362,8 @@ async function proSyncCommand(options = {}) {
36311
36362
  });
36312
36363
  const nonDeleteInitialValues = nonDeleteChoices.map((c2) => c2.value);
36313
36364
  const customSelected = await ae({
36314
- message: "Select items to sync (deletions excluded by default):",
36315
- options: choices,
36365
+ message: "Select files to sync (deletions excluded by default):",
36366
+ options: fileChoices,
36316
36367
  initialValues: nonDeleteInitialValues,
36317
36368
  required: false
36318
36369
  });
@@ -36322,15 +36373,14 @@ async function proSyncCommand(options = {}) {
36322
36373
  }
36323
36374
  const expanded = expandSelections(customSelected);
36324
36375
  selectedItems = expanded.items;
36325
- selectedHooks = expanded.hooks;
36326
36376
  }
36327
- if (selectedItems.length === 0 && selectedHooks.length === 0) {
36328
- f2.warn("No items selected");
36377
+ if (selectedItems.length === 0) {
36378
+ f2.warn("No files selected");
36329
36379
  $e(source_default.yellow("⚠️ Nothing to sync"));
36330
36380
  return;
36331
36381
  }
36332
- const toAdd = selectedItems.filter((i) => i.status === "new").length + selectedHooks.filter((h2) => h2.status === "new").length;
36333
- const toUpdate = selectedItems.filter((i) => i.status === "modified").length + selectedHooks.filter((h2) => h2.status === "modified").length;
36382
+ const toAdd = selectedItems.filter((i) => i.status === "new").length;
36383
+ const toUpdate = selectedItems.filter((i) => i.status === "modified").length;
36334
36384
  const toRemove = selectedItems.filter((i) => i.status === "deleted").length;
36335
36385
  f2.message("");
36336
36386
  f2.message(source_default.bold("What will happen:"));
@@ -36361,20 +36411,50 @@ async function proSyncCommand(options = {}) {
36361
36411
  const syncResult = await syncSelectedItems(claudeDir, selectedItems, githubToken, (file, action) => {
36362
36412
  spinner.message(`${action}: ${source_default.cyan(file)}`);
36363
36413
  });
36364
- const hooksResult = await syncSelectedHooks(claudeDir, selectedHooks, (hook, action) => {
36365
- spinner.message(`${action}: ${source_default.cyan(hook)}`);
36366
- });
36367
- spinner.stop("Sync complete");
36368
- const totalSuccess = syncResult.success + hooksResult.success;
36369
- const totalFailed = syncResult.failed + hooksResult.failed;
36414
+ spinner.stop("Files synced");
36370
36415
  const results = [];
36371
- if (totalSuccess > 0)
36372
- results.push(source_default.green(`${totalSuccess} added/updated`));
36416
+ if (syncResult.success > 0)
36417
+ results.push(source_default.green(`${syncResult.success} added/updated`));
36373
36418
  if (syncResult.deleted > 0)
36374
36419
  results.push(source_default.red(`${syncResult.deleted} removed`));
36375
- if (totalFailed > 0)
36376
- results.push(source_default.yellow(`${totalFailed} failed`));
36420
+ if (syncResult.failed > 0)
36421
+ results.push(source_default.yellow(`${syncResult.failed} failed`));
36377
36422
  f2.success(results.join(", "));
36423
+ if (changedHooks.length > 0) {
36424
+ f2.message("");
36425
+ f2.message(source_default.bold.yellow("⚠️ Settings.json Sync (Optional)"));
36426
+ f2.message(source_default.gray("The following hooks can be synced to your settings.json:"));
36427
+ for (const hook of changedHooks) {
36428
+ const icon = hook.status === "new" ? "\uD83C\uDD95" : "\uD83D\uDCDD";
36429
+ const color = hook.status === "new" ? source_default.green : source_default.yellow;
36430
+ const matcherDisplay = hook.matcher || "*";
36431
+ f2.message(` ${icon} ${color(`${hook.hookType}[${matcherDisplay}]`)}`);
36432
+ }
36433
+ f2.message("");
36434
+ f2.message(source_default.gray("This will modify your ~/.claude/settings.json file."));
36435
+ f2.message("");
36436
+ const syncSettingsResult = await se({
36437
+ message: "Do you want to sync these hooks to settings.json?",
36438
+ initialValue: false
36439
+ });
36440
+ if (!lD(syncSettingsResult) && syncSettingsResult) {
36441
+ const spinner2 = de();
36442
+ spinner2.start("Syncing hooks to settings.json...");
36443
+ selectedHooks = [...changedHooks];
36444
+ const hooksResult = await syncSelectedHooks(claudeDir, selectedHooks, (hook, action) => {
36445
+ spinner2.message(`${action}: ${source_default.cyan(hook)}`);
36446
+ });
36447
+ spinner2.stop("Hooks synced to settings.json");
36448
+ if (hooksResult.success > 0) {
36449
+ f2.success(source_default.green(`${hooksResult.success} hook${hooksResult.success > 1 ? "s" : ""} synced`));
36450
+ }
36451
+ if (hooksResult.failed > 0) {
36452
+ f2.warn(source_default.yellow(`${hooksResult.failed} hook${hooksResult.failed > 1 ? "s" : ""} failed`));
36453
+ }
36454
+ } else {
36455
+ f2.info(source_default.gray("Skipped settings.json sync"));
36456
+ }
36457
+ }
36378
36458
  const scriptsWereSynced = selectedItems.some((i) => i.category === "scripts");
36379
36459
  if (scriptsWereSynced) {
36380
36460
  spinner.start("Installing scripts dependencies...");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiblueprint-cli",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "description": "AIBlueprint CLI for setting up Claude Code configurations",
5
5
  "author": "AIBlueprint",
6
6
  "license": "MIT",