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
|
-
|
|
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
|
-
|
|
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 = "
|
|
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(
|
|
34017
|
-
|
|
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
|
-
|
|
34021
|
-
|
|
34022
|
-
|
|
34023
|
-
|
|
34024
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
36315
|
-
options:
|
|
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
|
|
36328
|
-
f2.warn("No
|
|
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
|
|
36333
|
-
const toUpdate = selectedItems.filter((i) => i.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
|
-
|
|
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 (
|
|
36372
|
-
results.push(source_default.green(`${
|
|
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 (
|
|
36376
|
-
results.push(source_default.yellow(`${
|
|
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...");
|