aiblueprint-cli 1.4.0 → 1.4.1

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 (2) hide show
  1. package/dist/cli.js +131 -42
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -33212,17 +33212,95 @@ async function installStatuslineDependencies(claudeDir) {
33212
33212
  // src/commands/setup/settings.ts
33213
33213
  var import_fs_extra3 = __toESM(require_lib4(), 1);
33214
33214
  import path5 from "path";
33215
+
33216
+ // src/lib/platform.ts
33215
33217
  import os6 from "os";
33218
+ import { execSync as execSync2 } from "child_process";
33219
+ function escapeShellArg(arg) {
33220
+ return "'" + arg.replace(/'/g, "'\\''") + "'";
33221
+ }
33222
+ var cachedAudioPlayer = undefined;
33223
+ function detectAudioPlayer() {
33224
+ if (cachedAudioPlayer !== undefined)
33225
+ return cachedAudioPlayer;
33226
+ const platform = os6.platform();
33227
+ if (platform === "darwin") {
33228
+ cachedAudioPlayer = "afplay";
33229
+ return cachedAudioPlayer;
33230
+ }
33231
+ if (platform === "win32") {
33232
+ cachedAudioPlayer = "powershell";
33233
+ return cachedAudioPlayer;
33234
+ }
33235
+ const linuxPlayers = ["paplay", "aplay", "mpv", "ffplay"];
33236
+ for (const player of linuxPlayers) {
33237
+ try {
33238
+ execSync2(`which ${player}`, { stdio: "ignore" });
33239
+ cachedAudioPlayer = player;
33240
+ return cachedAudioPlayer;
33241
+ } catch {
33242
+ continue;
33243
+ }
33244
+ }
33245
+ cachedAudioPlayer = null;
33246
+ return cachedAudioPlayer;
33247
+ }
33216
33248
  function getPlaySoundCommand(soundPath) {
33249
+ const player = detectAudioPlayer();
33250
+ if (!player)
33251
+ return null;
33217
33252
  const platform = os6.platform();
33253
+ const safePath = escapeShellArg(soundPath);
33218
33254
  if (platform === "darwin") {
33219
- return `afplay -v 0.1 "${soundPath}"`;
33220
- } else if (platform === "win32") {
33221
- return `powershell -c "(New-Object Media.SoundPlayer '${soundPath}').PlaySync()"`;
33222
- } else {
33223
- return `paplay "${soundPath}" 2>/dev/null || aplay "${soundPath}" 2>/dev/null || true`;
33255
+ return `afplay -v 0.1 ${safePath}`;
33256
+ }
33257
+ if (platform === "win32") {
33258
+ const escapedPath = soundPath.replace(/'/g, "''");
33259
+ return `powershell -c "(New-Object Media.SoundPlayer '${escapedPath}').PlaySync()"`;
33260
+ }
33261
+ switch (player) {
33262
+ case "paplay":
33263
+ return `paplay ${safePath} 2>/dev/null || true`;
33264
+ case "aplay":
33265
+ return `aplay ${safePath} 2>/dev/null || true`;
33266
+ case "mpv":
33267
+ return `mpv --no-video --volume=10 ${safePath} 2>/dev/null || true`;
33268
+ case "ffplay":
33269
+ return `ffplay -nodisp -autoexit -volume 10 ${safePath} 2>/dev/null || true`;
33270
+ default:
33271
+ return null;
33224
33272
  }
33225
33273
  }
33274
+ var KNOWN_CLAUDE_PATHS = [
33275
+ /\/Users\/[^/]+\/\.claude\//,
33276
+ /\/home\/[^/]+\/\.claude\//,
33277
+ /C:\\Users\\[^\\]+\\\.claude\\/i
33278
+ ];
33279
+ function transformHookCommand(command, claudeDir) {
33280
+ let transformed = command;
33281
+ for (const pattern of KNOWN_CLAUDE_PATHS) {
33282
+ transformed = transformed.replace(pattern, `${claudeDir}/`);
33283
+ }
33284
+ transformed = transformed.replace(/\\/g, "/");
33285
+ return transformed;
33286
+ }
33287
+ function transformHook(hook, claudeDir) {
33288
+ if (!hook)
33289
+ return hook;
33290
+ const transformed = { ...hook };
33291
+ if (transformed.command && typeof transformed.command === "string") {
33292
+ transformed.command = transformHookCommand(transformed.command, claudeDir);
33293
+ }
33294
+ if (Array.isArray(transformed.hooks)) {
33295
+ transformed.hooks = transformed.hooks.map((h) => transformHook(h, claudeDir));
33296
+ }
33297
+ return transformed;
33298
+ }
33299
+
33300
+ // src/commands/setup/settings.ts
33301
+ function toPosixPath(p) {
33302
+ return p.replace(/\\/g, "/");
33303
+ }
33226
33304
  async function hasExistingStatusLine(claudeDir) {
33227
33305
  const settingsPath = path5.join(claudeDir, "settings.json");
33228
33306
  try {
@@ -33246,7 +33324,7 @@ async function updateSettings(options, claudeDir) {
33246
33324
  if (shouldReplace) {
33247
33325
  settings.statusLine = {
33248
33326
  type: "command",
33249
- command: `bun ${path5.join(claudeDir, "scripts/statusline/src/index.ts")}`,
33327
+ command: `bun ${toPosixPath(path5.join(claudeDir, "scripts/statusline/src/index.ts"))}`,
33250
33328
  padding: 0
33251
33329
  };
33252
33330
  }
@@ -33263,7 +33341,7 @@ async function updateSettings(options, claudeDir) {
33263
33341
  hooks: [
33264
33342
  {
33265
33343
  type: "command",
33266
- command: `bun ${path5.join(claudeDir, "scripts/command-validator/src/cli.ts")}`
33344
+ command: `bun ${toPosixPath(path5.join(claudeDir, "scripts/command-validator/src/cli.ts"))}`
33267
33345
  }
33268
33346
  ]
33269
33347
  };
@@ -33273,39 +33351,45 @@ async function updateSettings(options, claudeDir) {
33273
33351
  }
33274
33352
  }
33275
33353
  if (options.notificationSounds) {
33276
- if (!settings.hooks.Stop) {
33277
- settings.hooks.Stop = [];
33278
- }
33279
- const finishSoundPath = path5.join(claudeDir, "song/finish.mp3");
33280
- const stopHook = {
33281
- matcher: "",
33282
- hooks: [
33283
- {
33284
- type: "command",
33285
- command: getPlaySoundCommand(finishSoundPath)
33286
- }
33287
- ]
33288
- };
33289
- const existingStopHook = settings.hooks.Stop.find((h) => h.hooks?.some((hook) => hook.command?.includes("finish.mp3")));
33290
- if (!existingStopHook) {
33291
- settings.hooks.Stop.push(stopHook);
33292
- }
33293
- if (!settings.hooks.Notification) {
33294
- settings.hooks.Notification = [];
33354
+ const finishSoundPath = toPosixPath(path5.join(claudeDir, "song/finish.mp3"));
33355
+ const finishSoundCommand = getPlaySoundCommand(finishSoundPath);
33356
+ if (finishSoundCommand) {
33357
+ if (!settings.hooks.Stop) {
33358
+ settings.hooks.Stop = [];
33359
+ }
33360
+ const stopHook = {
33361
+ matcher: "",
33362
+ hooks: [
33363
+ {
33364
+ type: "command",
33365
+ command: finishSoundCommand
33366
+ }
33367
+ ]
33368
+ };
33369
+ const existingStopHook = settings.hooks.Stop.find((h) => h.hooks?.some((hook) => hook.command?.includes("finish.mp3")));
33370
+ if (!existingStopHook) {
33371
+ settings.hooks.Stop.push(stopHook);
33372
+ }
33295
33373
  }
33296
- const needHumanSoundPath = path5.join(claudeDir, "song/need-human.mp3");
33297
- const notificationHook = {
33298
- matcher: "",
33299
- hooks: [
33300
- {
33301
- type: "command",
33302
- command: getPlaySoundCommand(needHumanSoundPath)
33303
- }
33304
- ]
33305
- };
33306
- const existingNotificationHook = settings.hooks.Notification.find((h) => h.hooks?.some((hook) => hook.command?.includes("need-human.mp3")));
33307
- if (!existingNotificationHook) {
33308
- settings.hooks.Notification.push(notificationHook);
33374
+ const needHumanSoundPath = toPosixPath(path5.join(claudeDir, "song/need-human.mp3"));
33375
+ const needHumanSoundCommand = getPlaySoundCommand(needHumanSoundPath);
33376
+ if (needHumanSoundCommand) {
33377
+ if (!settings.hooks.Notification) {
33378
+ settings.hooks.Notification = [];
33379
+ }
33380
+ const notificationHook = {
33381
+ matcher: "",
33382
+ hooks: [
33383
+ {
33384
+ type: "command",
33385
+ command: needHumanSoundCommand
33386
+ }
33387
+ ]
33388
+ };
33389
+ const existingNotificationHook = settings.hooks.Notification.find((h) => h.hooks?.some((hook) => hook.command?.includes("need-human.mp3")));
33390
+ if (!existingNotificationHook) {
33391
+ settings.hooks.Notification.push(notificationHook);
33392
+ }
33309
33393
  }
33310
33394
  }
33311
33395
  if (options.postEditTypeScript) {
@@ -33317,7 +33401,7 @@ async function updateSettings(options, claudeDir) {
33317
33401
  hooks: [
33318
33402
  {
33319
33403
  type: "command",
33320
- command: `bun ${path5.join(claudeDir, "scripts/hook-post-file.ts")}`
33404
+ command: `bun ${toPosixPath(path5.join(claudeDir, "scripts/hook-post-file.ts"))}`
33321
33405
  }
33322
33406
  ]
33323
33407
  };
@@ -33610,9 +33694,13 @@ async function setupCommand(params = {}) {
33610
33694
  }
33611
33695
  if (options.customStatusline) {
33612
33696
  await downloadDirectoryFromGitHub("scripts/statusline", path8.join(scriptsDir, "statusline"));
33697
+ await import_fs_extra6.default.ensureDir(path8.join(scriptsDir, "statusline/data"));
33613
33698
  }
33614
33699
  } else {
33615
33700
  await import_fs_extra6.default.copy(path8.join(sourceDir, "scripts"), path8.join(claudeDir, "scripts"), { overwrite: true });
33701
+ if (options.customStatusline) {
33702
+ await import_fs_extra6.default.ensureDir(path8.join(claudeDir, "scripts/statusline/data"));
33703
+ }
33616
33704
  }
33617
33705
  s.stop("Scripts installed");
33618
33706
  }
@@ -35668,10 +35756,11 @@ async function syncSelectedHooks(claudeDir, hooks, onProgress) {
35668
35756
  settings.hooks[hook.hookType] = [];
35669
35757
  }
35670
35758
  const existingIndex = settings.hooks[hook.hookType].findIndex((h2) => h2.matcher === hook.matcher);
35759
+ const transformedHook = transformHook(hook.remoteHook, claudeDir);
35671
35760
  if (existingIndex >= 0) {
35672
- settings.hooks[hook.hookType][existingIndex] = hook.remoteHook;
35761
+ settings.hooks[hook.hookType][existingIndex] = transformedHook;
35673
35762
  } else {
35674
- settings.hooks[hook.hookType].push(hook.remoteHook);
35763
+ settings.hooks[hook.hookType].push(transformedHook);
35675
35764
  }
35676
35765
  success++;
35677
35766
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiblueprint-cli",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "AIBlueprint CLI for setting up Claude Code configurations",
5
5
  "author": "AIBlueprint",
6
6
  "license": "MIT",