aiblueprint-cli 1.1.8 → 1.2.0

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.
Files changed (40) hide show
  1. package/claude-code-config/scripts/command-validator/README.md +147 -0
  2. package/claude-code-config/scripts/command-validator/biome.json +29 -0
  3. package/claude-code-config/scripts/command-validator/bun.lockb +0 -0
  4. package/claude-code-config/scripts/command-validator/dist/cli.js +544 -0
  5. package/claude-code-config/scripts/command-validator/package.json +27 -0
  6. package/claude-code-config/scripts/command-validator/src/__tests__/validator.test.ts +148 -0
  7. package/claude-code-config/scripts/command-validator/src/cli.ts +118 -0
  8. package/claude-code-config/scripts/command-validator/src/lib/security-rules.ts +172 -0
  9. package/claude-code-config/scripts/command-validator/src/lib/types.ts +33 -0
  10. package/claude-code-config/scripts/command-validator/src/lib/validator.ts +360 -0
  11. package/claude-code-config/scripts/command-validator/vitest.config.ts +7 -0
  12. package/claude-code-config/scripts/statusline/package.json +1 -3
  13. package/claude-code-config/scripts/statusline/src/index.ts +5 -107
  14. package/claude-code-config/scripts/statusline/src/lib/context.ts +66 -87
  15. package/claude-code-config/scripts/statusline/src/lib/formatters.ts +16 -186
  16. package/claude-code-config/scripts/statusline/statusline.config.ts +4 -101
  17. package/dist/cli.js +938 -12
  18. package/package.json +1 -1
  19. package/claude-code-config/agents/fix-grammar.md +0 -49
  20. package/claude-code-config/agents/snipper.md +0 -36
  21. package/claude-code-config/commands/claude-memory.md +0 -190
  22. package/claude-code-config/commands/cleanup-context.md +0 -82
  23. package/claude-code-config/commands/debug.md +0 -91
  24. package/claude-code-config/commands/deep-code-analysis.md +0 -87
  25. package/claude-code-config/commands/epct/code.md +0 -171
  26. package/claude-code-config/commands/epct/deploy.md +0 -116
  27. package/claude-code-config/commands/epct/explore.md +0 -97
  28. package/claude-code-config/commands/epct/plan.md +0 -132
  29. package/claude-code-config/commands/epct/tasks.md +0 -206
  30. package/claude-code-config/commands/explain-architecture.md +0 -113
  31. package/claude-code-config/commands/melvynx-plugin.md +0 -1
  32. package/claude-code-config/commands/prompt-agent.md +0 -126
  33. package/claude-code-config/commands/prompt-command.md +0 -225
  34. package/claude-code-config/scripts/statusline/data/.gitignore +0 -5
  35. package/claude-code-config/scripts/statusline/src/commands/CLAUDE.md +0 -3
  36. package/claude-code-config/scripts/statusline/src/commands/spend-month.ts +0 -60
  37. package/claude-code-config/scripts/statusline/src/commands/spend-today.ts +0 -42
  38. package/claude-code-config/scripts/statusline/src/lib/git.ts +0 -100
  39. package/claude-code-config/scripts/statusline/src/lib/spend.ts +0 -119
  40. package/claude-code-config/scripts/statusline/src/lib/usage-limits.ts +0 -147
@@ -0,0 +1,544 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // src/cli.ts
5
+ import { join } from "path";
6
+
7
+ // src/lib/security-rules.ts
8
+ var SECURITY_RULES = {
9
+ CRITICAL_COMMANDS: [
10
+ "del",
11
+ "format",
12
+ "mkfs",
13
+ "shred",
14
+ "dd",
15
+ "fdisk",
16
+ "parted",
17
+ "gparted",
18
+ "cfdisk"
19
+ ],
20
+ PRIVILEGE_COMMANDS: [
21
+ "sudo",
22
+ "su",
23
+ "passwd",
24
+ "chpasswd",
25
+ "usermod",
26
+ "chmod",
27
+ "chown",
28
+ "chgrp",
29
+ "setuid",
30
+ "setgid"
31
+ ],
32
+ NETWORK_COMMANDS: [
33
+ "nc",
34
+ "netcat",
35
+ "nmap",
36
+ "telnet",
37
+ "ssh-keygen",
38
+ "iptables",
39
+ "ufw",
40
+ "firewall-cmd",
41
+ "ipfw"
42
+ ],
43
+ SYSTEM_COMMANDS: [
44
+ "systemctl",
45
+ "service",
46
+ "kill",
47
+ "killall",
48
+ "pkill",
49
+ "mount",
50
+ "umount",
51
+ "swapon",
52
+ "swapoff"
53
+ ],
54
+ DANGEROUS_PATTERNS: [
55
+ /rm\s+.*-rf\s*\/\s*$/i,
56
+ /rm\s+.*-rf\s*\/etc/i,
57
+ /rm\s+.*-rf\s*\/usr/i,
58
+ /rm\s+.*-rf\s*\/bin/i,
59
+ /rm\s+.*-rf\s*\/sys/i,
60
+ /rm\s+.*-rf\s*\/proc/i,
61
+ /rm\s+.*-rf\s*\/boot/i,
62
+ /rm\s+.*-rf\s*\/home\/[^/]*\s*$/i,
63
+ /rm\s+.*-rf\s*\.\.+\//i,
64
+ /rm\s+.*-rf\s*\*.*\*/i,
65
+ /rm\s+.*-rf\s*\$\w+/i,
66
+ />\s*\/dev\/(sda|hda|nvme)/i,
67
+ /dd\s+.*of=\/dev\//i,
68
+ /shred\s+.*\/dev\//i,
69
+ /mkfs\.\w+\s+\/dev\//i,
70
+ /:\(\)\{\s*:\|:&\s*\};:/,
71
+ /while\s+true\s*;\s*do.*done/i,
72
+ /for\s*\(\(\s*;\s*;\s*\)\)/i,
73
+ /\|\s*(sh|bash|zsh|fish)$/i,
74
+ /(wget|curl)\s+.*\|\s*(sh|bash)/i,
75
+ /(wget|curl)\s+.*-O-.*\|\s*(sh|bash)/i,
76
+ /`.*rm.*`/i,
77
+ /\$\(.*rm.*\)/i,
78
+ /`.*dd.*`/i,
79
+ /\$\(.*dd.*\)/i,
80
+ /cat\s+\/etc\/(passwd|shadow|sudoers)/i,
81
+ />\s*\/etc\/(passwd|shadow|sudoers)/i,
82
+ /echo\s+.*>>\s*\/etc\/(passwd|shadow|sudoers)/i,
83
+ /\|\s*nc\s+\S+\s+\d+/i,
84
+ /curl\s+.*-d.*\$\(/i,
85
+ /wget\s+.*--post-data.*\$\(/i,
86
+ />\s*\/var\/log\//i,
87
+ /rm\s+\/var\/log\//i,
88
+ /echo\s+.*>\s*~?\/?\.bash_history/i,
89
+ /nc\s+.*-l.*-e/i,
90
+ /nc\s+.*-e.*-l/i,
91
+ /ncat\s+.*--exec/i,
92
+ /ssh-keygen.*authorized_keys/i,
93
+ /(wget|curl).*\.(sh|py|pl|exe|bin).*\|\s*(sh|bash|python)/i,
94
+ /(xmrig|ccminer|cgminer|bfgminer)/i,
95
+ /cat\s+\/dev\/(mem|kmem)/i,
96
+ /echo\s+.*>\s*\/dev\/(mem|kmem)/i,
97
+ /(insmod|rmmod|modprobe)\s+/i,
98
+ /crontab\s+-e/i,
99
+ /echo\s+.*>>\s*\/var\/spool\/cron/i,
100
+ /env\s*\|\s*grep.*PASSWORD/i,
101
+ /printenv.*PASSWORD/i,
102
+ /docker\s+(rm|rmi|kill|stop)\s+.*\$\(/i,
103
+ /docker\s+system\s+prune.*-a/i,
104
+ /docker\s+container\s+prune.*-f/i,
105
+ /docker\s+volume\s+rm.*\$\(/i,
106
+ /docker\s+network\s+rm.*\$\(/i,
107
+ /prisma\s+(migrate\s+reset|db\s+push\s+--force-reset)/i
108
+ ],
109
+ PROTECTED_PATHS: [
110
+ "/etc/",
111
+ "/usr/",
112
+ "/sbin/",
113
+ "/boot/",
114
+ "/sys/",
115
+ "/proc/",
116
+ "/dev/",
117
+ "/root/"
118
+ ],
119
+ SAFE_EXECUTABLE_PATHS: [
120
+ "/Applications/",
121
+ "/usr/local/bin/",
122
+ "/usr/bin/",
123
+ "/bin/",
124
+ "/opt/"
125
+ ],
126
+ SAFE_RM_PATHS: [
127
+ "/Users/melvynx/Developer/",
128
+ "/tmp/",
129
+ "/var/tmp/",
130
+ `${process.cwd()}/`
131
+ ]
132
+ };
133
+ var SAFE_COMMANDS = [
134
+ "ls",
135
+ "dir",
136
+ "pwd",
137
+ "whoami",
138
+ "date",
139
+ "echo",
140
+ "cat",
141
+ "head",
142
+ "tail",
143
+ "grep",
144
+ "find",
145
+ "wc",
146
+ "sort",
147
+ "uniq",
148
+ "cut",
149
+ "awk",
150
+ "sed",
151
+ "git",
152
+ "npm",
153
+ "pnpm",
154
+ "node",
155
+ "bun",
156
+ "python",
157
+ "pip",
158
+ "source",
159
+ "cd",
160
+ "cp",
161
+ "mv",
162
+ "mkdir",
163
+ "touch",
164
+ "ln",
165
+ "psql",
166
+ "mysql",
167
+ "sqlite3",
168
+ "mongo"
169
+ ];
170
+
171
+ // src/lib/validator.ts
172
+ class CommandValidator {
173
+ validate(command, toolName = "Unknown") {
174
+ const result = {
175
+ isValid: true,
176
+ severity: "LOW",
177
+ violations: [],
178
+ sanitizedCommand: command
179
+ };
180
+ if (!command || typeof command !== "string") {
181
+ result.isValid = false;
182
+ result.violations.push("Invalid command format");
183
+ return result;
184
+ }
185
+ if (command.length > 2000) {
186
+ result.isValid = false;
187
+ result.severity = "MEDIUM";
188
+ result.violations.push("Command too long (potential buffer overflow)");
189
+ return result;
190
+ }
191
+ if (/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\xFF]/.test(command)) {
192
+ result.isValid = false;
193
+ result.severity = "HIGH";
194
+ result.violations.push("Binary or encoded content detected");
195
+ return result;
196
+ }
197
+ const normalizedCmd = command.trim().toLowerCase();
198
+ const cmdParts = normalizedCmd.split(/\s+/);
199
+ const mainCommand = cmdParts[0].split("/").pop() || "";
200
+ if (mainCommand === "source" || mainCommand === "python") {
201
+ return result;
202
+ }
203
+ for (const pattern of SECURITY_RULES.DANGEROUS_PATTERNS) {
204
+ if (pattern.test(command)) {
205
+ result.isValid = false;
206
+ result.severity = "CRITICAL";
207
+ result.violations.push(`Dangerous pattern detected: ${pattern.source}`);
208
+ }
209
+ }
210
+ if (SECURITY_RULES.CRITICAL_COMMANDS.includes(mainCommand)) {
211
+ result.isValid = false;
212
+ result.severity = "CRITICAL";
213
+ result.violations.push(`Critical dangerous command: ${mainCommand}`);
214
+ }
215
+ if (SECURITY_RULES.PRIVILEGE_COMMANDS.includes(mainCommand)) {
216
+ result.isValid = false;
217
+ result.severity = "HIGH";
218
+ result.violations.push(`Privilege escalation command: ${mainCommand}`);
219
+ }
220
+ if (SECURITY_RULES.NETWORK_COMMANDS.includes(mainCommand)) {
221
+ result.isValid = false;
222
+ result.severity = "HIGH";
223
+ result.violations.push(`Network/remote access command: ${mainCommand}`);
224
+ }
225
+ if (SECURITY_RULES.SYSTEM_COMMANDS.includes(mainCommand)) {
226
+ result.isValid = false;
227
+ result.severity = "HIGH";
228
+ result.violations.push(`System manipulation command: ${mainCommand}`);
229
+ }
230
+ if (/rm\s+.*-rf\s/.test(command)) {
231
+ const isRmRfSafe = this.isRmRfCommandSafe(command);
232
+ if (!isRmRfSafe) {
233
+ result.isValid = false;
234
+ result.severity = "CRITICAL";
235
+ result.violations.push("rm -rf command targeting unsafe path");
236
+ }
237
+ }
238
+ if (SAFE_COMMANDS.includes(mainCommand) && result.violations.length === 0) {
239
+ return result;
240
+ }
241
+ if (command.includes("&&")) {
242
+ const chainedCommands = this.splitCommandChain(command);
243
+ let allSafe = true;
244
+ for (const chainedCmd of chainedCommands) {
245
+ const trimmedCmd = chainedCmd.trim();
246
+ const cmdParts2 = trimmedCmd.split(/\s+/);
247
+ const mainCommand2 = cmdParts2[0];
248
+ if (mainCommand2 === "source" || mainCommand2 === "python" || SAFE_COMMANDS.includes(mainCommand2)) {
249
+ continue;
250
+ }
251
+ const chainResult = this.validateSingleCommand(trimmedCmd, toolName);
252
+ if (!chainResult.isValid) {
253
+ result.isValid = false;
254
+ result.severity = chainResult.severity;
255
+ result.violations.push(`Chained command violation: ${trimmedCmd} - ${chainResult.violations.join(", ")}`);
256
+ allSafe = false;
257
+ }
258
+ }
259
+ if (allSafe) {
260
+ return result;
261
+ }
262
+ }
263
+ if (command.includes(";") || command.includes("||")) {
264
+ const chainedCommands = this.splitCommandChain(command);
265
+ for (const chainedCmd of chainedCommands) {
266
+ const chainResult = this.validateSingleCommand(chainedCmd.trim(), toolName);
267
+ if (!chainResult.isValid) {
268
+ result.isValid = false;
269
+ result.severity = chainResult.severity;
270
+ result.violations.push(`Chained command violation: ${chainedCmd.trim()} - ${chainResult.violations.join(", ")}`);
271
+ }
272
+ }
273
+ return result;
274
+ }
275
+ for (const path of SECURITY_RULES.PROTECTED_PATHS) {
276
+ if (command.includes(path)) {
277
+ if (path === "/dev/" && (command.includes("/dev/null") || command.includes("/dev/stderr") || command.includes("/dev/stdout"))) {
278
+ continue;
279
+ }
280
+ const cmdStart = command.trim();
281
+ let isSafeExecutable = false;
282
+ for (const safePath of SECURITY_RULES.SAFE_EXECUTABLE_PATHS) {
283
+ if (cmdStart.startsWith(safePath)) {
284
+ isSafeExecutable = true;
285
+ break;
286
+ }
287
+ }
288
+ const pathIndex = command.indexOf(path);
289
+ const beforePath = command.substring(0, pathIndex);
290
+ const redirectBeforePath = />\s*$/.test(beforePath.trim());
291
+ if (!isSafeExecutable && redirectBeforePath) {
292
+ result.isValid = false;
293
+ result.severity = "HIGH";
294
+ result.violations.push(`Dangerous operation on protected path: ${path}`);
295
+ }
296
+ }
297
+ }
298
+ return result;
299
+ }
300
+ validateSingleCommand(command, _toolName = "Unknown") {
301
+ const result = {
302
+ isValid: true,
303
+ severity: "LOW",
304
+ violations: [],
305
+ sanitizedCommand: command
306
+ };
307
+ if (!command || typeof command !== "string") {
308
+ result.isValid = false;
309
+ result.violations.push("Invalid command format");
310
+ return result;
311
+ }
312
+ if (command.length > 2000) {
313
+ result.isValid = false;
314
+ result.severity = "MEDIUM";
315
+ result.violations.push("Command too long (potential buffer overflow)");
316
+ return result;
317
+ }
318
+ if (/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\xFF]/.test(command)) {
319
+ result.isValid = false;
320
+ result.severity = "HIGH";
321
+ result.violations.push("Binary or encoded content detected");
322
+ return result;
323
+ }
324
+ const normalizedCmd = command.trim().toLowerCase();
325
+ const cmdParts = normalizedCmd.split(/\s+/);
326
+ const mainCommand = cmdParts[0].split("/").pop() || "";
327
+ if (mainCommand === "source" || mainCommand === "python") {
328
+ return result;
329
+ }
330
+ for (const pattern of SECURITY_RULES.DANGEROUS_PATTERNS) {
331
+ if (pattern.test(command)) {
332
+ result.isValid = false;
333
+ result.severity = "CRITICAL";
334
+ result.violations.push(`Dangerous pattern detected: ${pattern.source}`);
335
+ }
336
+ }
337
+ if (SECURITY_RULES.CRITICAL_COMMANDS.includes(mainCommand)) {
338
+ result.isValid = false;
339
+ result.severity = "CRITICAL";
340
+ result.violations.push(`Critical dangerous command: ${mainCommand}`);
341
+ }
342
+ if (SECURITY_RULES.PRIVILEGE_COMMANDS.includes(mainCommand)) {
343
+ result.isValid = false;
344
+ result.severity = "HIGH";
345
+ result.violations.push(`Privilege escalation command: ${mainCommand}`);
346
+ }
347
+ if (SECURITY_RULES.NETWORK_COMMANDS.includes(mainCommand)) {
348
+ result.isValid = false;
349
+ result.severity = "HIGH";
350
+ result.violations.push(`Network/remote access command: ${mainCommand}`);
351
+ }
352
+ if (SECURITY_RULES.SYSTEM_COMMANDS.includes(mainCommand)) {
353
+ result.isValid = false;
354
+ result.severity = "HIGH";
355
+ result.violations.push(`System manipulation command: ${mainCommand}`);
356
+ }
357
+ if (/rm\s+.*-rf\s/.test(command)) {
358
+ const isRmRfSafe = this.isRmRfCommandSafe(command);
359
+ if (!isRmRfSafe) {
360
+ result.isValid = false;
361
+ result.severity = "CRITICAL";
362
+ result.violations.push("rm -rf command targeting unsafe path");
363
+ }
364
+ }
365
+ if (SAFE_COMMANDS.includes(mainCommand) && result.violations.length === 0) {
366
+ return result;
367
+ }
368
+ for (const path of SECURITY_RULES.PROTECTED_PATHS) {
369
+ if (command.includes(path)) {
370
+ if (path === "/dev/" && (command.includes("/dev/null") || command.includes("/dev/stderr") || command.includes("/dev/stdout"))) {
371
+ continue;
372
+ }
373
+ const cmdStart = command.trim();
374
+ let isSafeExecutable = false;
375
+ for (const safePath of SECURITY_RULES.SAFE_EXECUTABLE_PATHS) {
376
+ if (cmdStart.startsWith(safePath)) {
377
+ isSafeExecutable = true;
378
+ break;
379
+ }
380
+ }
381
+ const pathIndex = command.indexOf(path);
382
+ const beforePath = command.substring(0, pathIndex);
383
+ const redirectBeforePath = />\s*$/.test(beforePath.trim());
384
+ if (!isSafeExecutable && redirectBeforePath) {
385
+ result.isValid = false;
386
+ result.severity = "HIGH";
387
+ result.violations.push(`Dangerous operation on protected path: ${path}`);
388
+ }
389
+ }
390
+ }
391
+ return result;
392
+ }
393
+ splitCommandChain(command) {
394
+ const commands = [];
395
+ let current = "";
396
+ let inQuotes = false;
397
+ let quoteChar = "";
398
+ for (let i = 0;i < command.length; i++) {
399
+ const char = command[i];
400
+ const nextChar = command[i + 1];
401
+ if ((char === '"' || char === "'") && !inQuotes) {
402
+ inQuotes = true;
403
+ quoteChar = char;
404
+ current += char;
405
+ } else if (char === quoteChar && inQuotes) {
406
+ inQuotes = false;
407
+ quoteChar = "";
408
+ current += char;
409
+ } else if (inQuotes) {
410
+ current += char;
411
+ } else if (char === "&" && nextChar === "&") {
412
+ commands.push(current.trim());
413
+ current = "";
414
+ i++;
415
+ } else if (char === "|" && nextChar === "|") {
416
+ commands.push(current.trim());
417
+ current = "";
418
+ i++;
419
+ } else if (char === ";") {
420
+ commands.push(current.trim());
421
+ current = "";
422
+ } else {
423
+ current += char;
424
+ }
425
+ }
426
+ if (current.trim()) {
427
+ commands.push(current.trim());
428
+ }
429
+ return commands.filter((cmd) => cmd.length > 0);
430
+ }
431
+ isRmRfCommandSafe(command) {
432
+ const rmRfMatch = command.match(/rm\s+.*-rf\s+([^\s;&|]+)/);
433
+ if (!rmRfMatch) {
434
+ return false;
435
+ }
436
+ const targetPath = rmRfMatch[1];
437
+ if (targetPath === "/" || targetPath.endsWith("/")) {
438
+ return false;
439
+ }
440
+ for (const safePath of SECURITY_RULES.SAFE_RM_PATHS) {
441
+ if (targetPath.startsWith(safePath)) {
442
+ return true;
443
+ }
444
+ }
445
+ if (!targetPath.startsWith("/")) {
446
+ return true;
447
+ }
448
+ return false;
449
+ }
450
+ }
451
+
452
+ // src/cli.ts
453
+ var LOG_FILE = join(import.meta.dir, "../data/security.log");
454
+ async function logSecurityEvent(command, toolName, result, sessionId) {
455
+ const timestamp = new Date().toISOString();
456
+ const logEntry = {
457
+ timestamp,
458
+ sessionId,
459
+ toolName,
460
+ command: command.substring(0, 500),
461
+ blocked: !result.isValid,
462
+ severity: result.severity,
463
+ violations: result.violations,
464
+ source: "claude-code-hook"
465
+ };
466
+ try {
467
+ const logLine = `${JSON.stringify(logEntry)}
468
+ `;
469
+ const file = Bun.file(LOG_FILE);
470
+ const exists = await file.exists();
471
+ if (exists) {
472
+ const existingContent = await file.text();
473
+ await Bun.write(LOG_FILE, existingContent + logLine);
474
+ } else {
475
+ await Bun.write(LOG_FILE, logLine);
476
+ }
477
+ console.error(`[SECURITY] ${result.isValid ? "ALLOWED" : "BLOCKED"}: ${command.substring(0, 100)}`);
478
+ } catch (error) {
479
+ console.error("Failed to write security log:", error);
480
+ }
481
+ }
482
+ async function main() {
483
+ const validator = new CommandValidator;
484
+ try {
485
+ const stdin = process.stdin;
486
+ const chunks = [];
487
+ for await (const chunk of stdin) {
488
+ chunks.push(chunk);
489
+ }
490
+ const input = Buffer.concat(chunks).toString();
491
+ if (!input.trim()) {
492
+ console.error("No input received from stdin");
493
+ process.exit(1);
494
+ }
495
+ let hookData;
496
+ try {
497
+ hookData = JSON.parse(input);
498
+ } catch (error) {
499
+ console.error("Invalid JSON input:", error.message);
500
+ process.exit(1);
501
+ }
502
+ const toolName = hookData.tool_name || "Unknown";
503
+ const toolInput = hookData.tool_input || {};
504
+ const sessionId = hookData.session_id || null;
505
+ if (toolName !== "Bash") {
506
+ console.log(`Skipping validation for tool: ${toolName}`);
507
+ process.exit(0);
508
+ }
509
+ const command = toolInput.command;
510
+ if (!command) {
511
+ console.error("No command found in tool input");
512
+ process.exit(1);
513
+ }
514
+ const result = validator.validate(command, toolName);
515
+ await logSecurityEvent(command, toolName, result, sessionId);
516
+ if (result.isValid) {
517
+ console.log("Command validation passed");
518
+ process.exit(0);
519
+ }
520
+ const confirmationMessage = `\u26A0\uFE0F Potentially dangerous command detected!
521
+
522
+ Command: ${command}
523
+ Violations: ${result.violations.join(", ")}
524
+ Severity: ${result.severity}
525
+
526
+ Do you want to proceed with this command?`;
527
+ const hookOutput = {
528
+ hookSpecificOutput: {
529
+ hookEventName: "PreToolUse",
530
+ permissionDecision: "ask",
531
+ permissionDecisionReason: confirmationMessage
532
+ }
533
+ };
534
+ console.log(JSON.stringify(hookOutput));
535
+ process.exit(0);
536
+ } catch (error) {
537
+ console.error("Validation script error:", error);
538
+ process.exit(2);
539
+ }
540
+ }
541
+ main().catch((error) => {
542
+ console.error("Fatal error:", error);
543
+ process.exit(2);
544
+ });
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "command-validator",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./src/lib/validator.ts",
7
+ "./types": "./src/lib/types.ts",
8
+ "./security-rules": "./src/lib/security-rules.ts"
9
+ },
10
+ "bin": {
11
+ "validate-command": "./src/cli.ts"
12
+ },
13
+ "scripts": {
14
+ "test": "vitest",
15
+ "test:ui": "vitest --ui",
16
+ "lint": "biome check --write .",
17
+ "format": "biome format --write ."
18
+ },
19
+ "devDependencies": {
20
+ "@biomejs/biome": "^2.3.2",
21
+ "@types/bun": "latest",
22
+ "vitest": "^2.1.8"
23
+ },
24
+ "peerDependencies": {
25
+ "typescript": "^5.0.0"
26
+ }
27
+ }