aiblueprint-cli 1.4.0 → 1.4.2

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 +550 -167
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -33212,16 +33212,116 @@ 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 cachedPlatformInfo = null;
33223
+ var cachedAudioPlayer = undefined;
33224
+ function isWSL() {
33225
+ if (os6.platform() !== "linux")
33226
+ return false;
33227
+ const release = os6.release().toLowerCase();
33228
+ return release.includes("microsoft") || release.includes("wsl");
33229
+ }
33230
+ function getPlatformInfo() {
33231
+ if (cachedPlatformInfo)
33232
+ return cachedPlatformInfo;
33233
+ const platform = os6.platform();
33234
+ const wsl = isWSL();
33235
+ cachedPlatformInfo = {
33236
+ platform,
33237
+ isWindows: platform === "win32",
33238
+ isMacOS: platform === "darwin",
33239
+ isLinux: platform === "linux" && !wsl,
33240
+ isWSL: wsl,
33241
+ homeDir: os6.homedir()
33242
+ };
33243
+ return cachedPlatformInfo;
33244
+ }
33245
+ function detectAudioPlayer() {
33246
+ if (cachedAudioPlayer !== undefined)
33247
+ return cachedAudioPlayer;
33248
+ const platform = os6.platform();
33249
+ if (platform === "darwin") {
33250
+ cachedAudioPlayer = "afplay";
33251
+ return cachedAudioPlayer;
33252
+ }
33253
+ if (platform === "win32") {
33254
+ cachedAudioPlayer = "powershell";
33255
+ return cachedAudioPlayer;
33256
+ }
33257
+ const linuxPlayers = ["paplay", "aplay", "mpv", "ffplay"];
33258
+ for (const player of linuxPlayers) {
33259
+ try {
33260
+ execSync2(`which ${player}`, { stdio: "ignore" });
33261
+ cachedAudioPlayer = player;
33262
+ return cachedAudioPlayer;
33263
+ } catch {
33264
+ continue;
33265
+ }
33266
+ }
33267
+ cachedAudioPlayer = null;
33268
+ return cachedAudioPlayer;
33269
+ }
33216
33270
  function getPlaySoundCommand(soundPath) {
33271
+ const player = detectAudioPlayer();
33272
+ if (!player)
33273
+ return null;
33217
33274
  const platform = os6.platform();
33275
+ const safePath = escapeShellArg(soundPath);
33218
33276
  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`;
33277
+ return `afplay -v 0.1 ${safePath}`;
33278
+ }
33279
+ if (platform === "win32") {
33280
+ const escapedPath = soundPath.replace(/'/g, "''");
33281
+ return `powershell -c "(New-Object Media.SoundPlayer '${escapedPath}').PlaySync()"`;
33282
+ }
33283
+ switch (player) {
33284
+ case "paplay":
33285
+ return `paplay ${safePath} 2>/dev/null || true`;
33286
+ case "aplay":
33287
+ return `aplay ${safePath} 2>/dev/null || true`;
33288
+ case "mpv":
33289
+ return `mpv --no-video --volume=10 ${safePath} 2>/dev/null || true`;
33290
+ case "ffplay":
33291
+ return `ffplay -nodisp -autoexit -volume 10 ${safePath} 2>/dev/null || true`;
33292
+ default:
33293
+ return null;
33294
+ }
33295
+ }
33296
+ var KNOWN_CLAUDE_PATHS = [
33297
+ /\/Users\/[^/]+\/\.claude\//,
33298
+ /\/home\/[^/]+\/\.claude\//,
33299
+ /C:\\Users\\[^\\]+\\\.claude\\/i
33300
+ ];
33301
+ function transformHookCommand(command, claudeDir) {
33302
+ let transformed = command;
33303
+ for (const pattern of KNOWN_CLAUDE_PATHS) {
33304
+ transformed = transformed.replace(pattern, `${claudeDir}/`);
33224
33305
  }
33306
+ transformed = transformed.replace(/\\/g, "/");
33307
+ return transformed;
33308
+ }
33309
+ function transformHook(hook, claudeDir) {
33310
+ if (!hook)
33311
+ return hook;
33312
+ const transformed = { ...hook };
33313
+ if (transformed.command && typeof transformed.command === "string") {
33314
+ transformed.command = transformHookCommand(transformed.command, claudeDir);
33315
+ }
33316
+ if (Array.isArray(transformed.hooks)) {
33317
+ transformed.hooks = transformed.hooks.map((h) => transformHook(h, claudeDir));
33318
+ }
33319
+ return transformed;
33320
+ }
33321
+
33322
+ // src/commands/setup/settings.ts
33323
+ function toPosixPath(p) {
33324
+ return p.replace(/\\/g, "/");
33225
33325
  }
33226
33326
  async function hasExistingStatusLine(claudeDir) {
33227
33327
  const settingsPath = path5.join(claudeDir, "settings.json");
@@ -33246,7 +33346,7 @@ async function updateSettings(options, claudeDir) {
33246
33346
  if (shouldReplace) {
33247
33347
  settings.statusLine = {
33248
33348
  type: "command",
33249
- command: `bun ${path5.join(claudeDir, "scripts/statusline/src/index.ts")}`,
33349
+ command: `bun ${toPosixPath(path5.join(claudeDir, "scripts/statusline/src/index.ts"))}`,
33250
33350
  padding: 0
33251
33351
  };
33252
33352
  }
@@ -33263,7 +33363,7 @@ async function updateSettings(options, claudeDir) {
33263
33363
  hooks: [
33264
33364
  {
33265
33365
  type: "command",
33266
- command: `bun ${path5.join(claudeDir, "scripts/command-validator/src/cli.ts")}`
33366
+ command: `bun ${toPosixPath(path5.join(claudeDir, "scripts/command-validator/src/cli.ts"))}`
33267
33367
  }
33268
33368
  ]
33269
33369
  };
@@ -33273,39 +33373,45 @@ async function updateSettings(options, claudeDir) {
33273
33373
  }
33274
33374
  }
33275
33375
  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 = [];
33376
+ const finishSoundPath = toPosixPath(path5.join(claudeDir, "song/finish.mp3"));
33377
+ const finishSoundCommand = getPlaySoundCommand(finishSoundPath);
33378
+ if (finishSoundCommand) {
33379
+ if (!settings.hooks.Stop) {
33380
+ settings.hooks.Stop = [];
33381
+ }
33382
+ const stopHook = {
33383
+ matcher: "",
33384
+ hooks: [
33385
+ {
33386
+ type: "command",
33387
+ command: finishSoundCommand
33388
+ }
33389
+ ]
33390
+ };
33391
+ const existingStopHook = settings.hooks.Stop.find((h) => h.hooks?.some((hook) => hook.command?.includes("finish.mp3")));
33392
+ if (!existingStopHook) {
33393
+ settings.hooks.Stop.push(stopHook);
33394
+ }
33295
33395
  }
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);
33396
+ const needHumanSoundPath = toPosixPath(path5.join(claudeDir, "song/need-human.mp3"));
33397
+ const needHumanSoundCommand = getPlaySoundCommand(needHumanSoundPath);
33398
+ if (needHumanSoundCommand) {
33399
+ if (!settings.hooks.Notification) {
33400
+ settings.hooks.Notification = [];
33401
+ }
33402
+ const notificationHook = {
33403
+ matcher: "",
33404
+ hooks: [
33405
+ {
33406
+ type: "command",
33407
+ command: needHumanSoundCommand
33408
+ }
33409
+ ]
33410
+ };
33411
+ const existingNotificationHook = settings.hooks.Notification.find((h) => h.hooks?.some((hook) => hook.command?.includes("need-human.mp3")));
33412
+ if (!existingNotificationHook) {
33413
+ settings.hooks.Notification.push(notificationHook);
33414
+ }
33309
33415
  }
33310
33416
  }
33311
33417
  if (options.postEditTypeScript) {
@@ -33317,7 +33423,7 @@ async function updateSettings(options, claudeDir) {
33317
33423
  hooks: [
33318
33424
  {
33319
33425
  type: "command",
33320
- command: `bun ${path5.join(claudeDir, "scripts/hook-post-file.ts")}`
33426
+ command: `bun ${toPosixPath(path5.join(claudeDir, "scripts/hook-post-file.ts"))}`
33321
33427
  }
33322
33428
  ]
33323
33429
  };
@@ -33610,9 +33716,13 @@ async function setupCommand(params = {}) {
33610
33716
  }
33611
33717
  if (options.customStatusline) {
33612
33718
  await downloadDirectoryFromGitHub("scripts/statusline", path8.join(scriptsDir, "statusline"));
33719
+ await import_fs_extra6.default.ensureDir(path8.join(scriptsDir, "statusline/data"));
33613
33720
  }
33614
33721
  } else {
33615
33722
  await import_fs_extra6.default.copy(path8.join(sourceDir, "scripts"), path8.join(claudeDir, "scripts"), { overwrite: true });
33723
+ if (options.customStatusline) {
33724
+ await import_fs_extra6.default.ensureDir(path8.join(claudeDir, "scripts/statusline/data"));
33725
+ }
33616
33726
  }
33617
33727
  s.stop("Scripts installed");
33618
33728
  }
@@ -33733,15 +33843,280 @@ Next steps:`));
33733
33843
  }
33734
33844
  }
33735
33845
 
33846
+ // src/commands/setup-terminal.ts
33847
+ var import_fs_extra7 = __toESM(require_lib4(), 1);
33848
+ import path9 from "path";
33849
+ import os9 from "os";
33850
+ import { execSync as execSync3, exec } from "child_process";
33851
+ var OHMYZSH_INSTALL_URL = "https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh";
33852
+ var INSTALL_TIMEOUT = 120000;
33853
+ var PLUGIN_TIMEOUT = 60000;
33854
+ var THEMES = [
33855
+ { value: "robbyrussell", name: "robbyrussell (default) - Clean and minimal" },
33856
+ { value: "agnoster", name: "agnoster - Powerline style (requires patched font)" },
33857
+ { value: "af-magic", name: "af-magic - Colorful with git info" },
33858
+ { value: "dst", name: "dst - Clean with directory path" },
33859
+ { value: "simple", name: "simple - Minimalist" },
33860
+ { value: "bira", name: "bira - Two-line prompt with user info" },
33861
+ { value: "custom", name: "Custom theme (enter name manually)" }
33862
+ ];
33863
+ var PLUGINS = ["git", "zsh-autosuggestions", "zsh-syntax-highlighting"];
33864
+ function sanitizeThemeName(theme) {
33865
+ const sanitized = theme.replace(/[^a-zA-Z0-9_-]/g, "");
33866
+ if (sanitized.length === 0) {
33867
+ return "robbyrussell";
33868
+ }
33869
+ return sanitized;
33870
+ }
33871
+ function commandExists(cmd) {
33872
+ if (!/^[a-zA-Z0-9_-]+$/.test(cmd)) {
33873
+ return false;
33874
+ }
33875
+ try {
33876
+ execSync3(`which ${cmd}`, { stdio: "ignore" });
33877
+ return true;
33878
+ } catch {
33879
+ return false;
33880
+ }
33881
+ }
33882
+ function isOhMyZshInstalled(homeDir) {
33883
+ const ohMyZshDir = path9.join(homeDir, ".oh-my-zsh");
33884
+ return import_fs_extra7.default.existsSync(ohMyZshDir);
33885
+ }
33886
+ function backupFile(filePath) {
33887
+ if (!import_fs_extra7.default.existsSync(filePath))
33888
+ return null;
33889
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
33890
+ const backupPath = `${filePath}.backup-${timestamp}`;
33891
+ try {
33892
+ import_fs_extra7.default.copyFileSync(filePath, backupPath);
33893
+ return backupPath;
33894
+ } catch (error) {
33895
+ throw new Error(`Failed to create backup: ${error.message}`);
33896
+ }
33897
+ }
33898
+ async function installOhMyZsh(homeDir) {
33899
+ return new Promise((resolve, reject) => {
33900
+ const installCmd = `sh -c "$(curl -fsSL ${OHMYZSH_INSTALL_URL})" "" --unattended`;
33901
+ const env2 = { ...process.env, HOME: homeDir, ZSH: path9.join(homeDir, ".oh-my-zsh") };
33902
+ exec(installCmd, { timeout: INSTALL_TIMEOUT, env: env2 }, (error, stdout, stderr) => {
33903
+ if (error) {
33904
+ if (error.killed) {
33905
+ reject(new Error("Oh My ZSH installation timed out. Please check your network connection."));
33906
+ } else {
33907
+ reject(new Error(`Failed to install Oh My ZSH: ${stderr || error.message}`));
33908
+ }
33909
+ } else {
33910
+ resolve();
33911
+ }
33912
+ });
33913
+ });
33914
+ }
33915
+ async function installPlugin(pluginName, repoUrl, homeDir) {
33916
+ if (!/^[a-zA-Z0-9_-]+$/.test(pluginName)) {
33917
+ throw new Error(`Invalid plugin name: ${pluginName}`);
33918
+ }
33919
+ if (!/^https:\/\/github\.com\/[\w-]+\/[\w-]+$/.test(repoUrl)) {
33920
+ throw new Error(`Invalid repository URL: ${repoUrl}`);
33921
+ }
33922
+ const customPluginsDir = path9.join(homeDir, ".oh-my-zsh/custom/plugins", pluginName);
33923
+ if (import_fs_extra7.default.existsSync(customPluginsDir)) {
33924
+ return;
33925
+ }
33926
+ return new Promise((resolve, reject) => {
33927
+ exec(`git clone ${repoUrl} "${customPluginsDir}"`, { timeout: PLUGIN_TIMEOUT }, (error, stdout, stderr) => {
33928
+ if (error) {
33929
+ if (error.killed) {
33930
+ reject(new Error(`Plugin ${pluginName} installation timed out. Please check your network connection.`));
33931
+ } else {
33932
+ reject(new Error(`Failed to install ${pluginName}: ${stderr || error.message}`));
33933
+ }
33934
+ } else {
33935
+ resolve();
33936
+ }
33937
+ });
33938
+ });
33939
+ }
33940
+ function updateZshrcTheme(theme, homeDir) {
33941
+ const zshrcPath = path9.join(homeDir, ".zshrc");
33942
+ const sanitizedTheme = sanitizeThemeName(theme);
33943
+ if (!import_fs_extra7.default.existsSync(zshrcPath)) {
33944
+ throw new Error(".zshrc file not found. Please ensure Oh My ZSH is installed correctly.");
33945
+ }
33946
+ try {
33947
+ let content = import_fs_extra7.default.readFileSync(zshrcPath, "utf-8");
33948
+ if (content.match(/^ZSH_THEME=/m)) {
33949
+ content = content.replace(/^ZSH_THEME=.*/m, `ZSH_THEME="${sanitizedTheme}"`);
33950
+ } else {
33951
+ content = `ZSH_THEME="${sanitizedTheme}"
33952
+ ${content}`;
33953
+ }
33954
+ import_fs_extra7.default.writeFileSync(zshrcPath, content);
33955
+ } catch (error) {
33956
+ if (error.message.includes(".zshrc file not found")) {
33957
+ throw error;
33958
+ }
33959
+ throw new Error(`Failed to update theme in .zshrc: ${error.message}`);
33960
+ }
33961
+ }
33962
+ function updateZshrcPlugins(plugins, homeDir) {
33963
+ const zshrcPath = path9.join(homeDir, ".zshrc");
33964
+ if (!import_fs_extra7.default.existsSync(zshrcPath)) {
33965
+ throw new Error(".zshrc file not found. Please ensure Oh My ZSH is installed correctly.");
33966
+ }
33967
+ try {
33968
+ let content = import_fs_extra7.default.readFileSync(zshrcPath, "utf-8");
33969
+ const pluginsString = plugins.join(" ");
33970
+ if (content.match(/^plugins=\(/m)) {
33971
+ content = content.replace(/^plugins=\([^)]*\)/m, `plugins=(${pluginsString})`);
33972
+ } else {
33973
+ content = `${content}
33974
+ plugins=(${pluginsString})`;
33975
+ }
33976
+ import_fs_extra7.default.writeFileSync(zshrcPath, content);
33977
+ } catch (error) {
33978
+ if (error.message.includes(".zshrc file not found")) {
33979
+ throw error;
33980
+ }
33981
+ throw new Error(`Failed to update plugins in .zshrc: ${error.message}`);
33982
+ }
33983
+ }
33984
+ async function setupTerminalCommand(options = {}) {
33985
+ const { skipInteractive, homeDir: customHomeDir } = options;
33986
+ const homeDir = customHomeDir || os9.homedir();
33987
+ try {
33988
+ console.log(source_default.blue.bold(`
33989
+ \uD83D\uDDA5️ AIBlueprint Terminal Setup ${source_default.gray(`v${getVersion()}`)}
33990
+ `));
33991
+ console.log(source_default.bgBlue(" Setting up your terminal with Oh My ZSH "));
33992
+ const platformInfo = getPlatformInfo();
33993
+ if (platformInfo.isWindows) {
33994
+ console.log(source_default.red(`
33995
+ ❌ This command is not supported on Windows.`));
33996
+ console.log(source_default.yellow("Please use WSL (Windows Subsystem for Linux) instead:"));
33997
+ console.log(source_default.gray(" 1. Open PowerShell as Administrator"));
33998
+ console.log(source_default.gray(" 2. Run: wsl --install"));
33999
+ console.log(source_default.gray(" 3. Restart your computer"));
34000
+ console.log(source_default.gray(" 4. Open WSL and run this command again"));
34001
+ process.exit(1);
34002
+ }
34003
+ const s = new SimpleSpinner;
34004
+ s.start("Checking prerequisites");
34005
+ const missingPrereqs = [];
34006
+ if (!commandExists("curl")) {
34007
+ missingPrereqs.push("curl");
34008
+ }
34009
+ if (!commandExists("git")) {
34010
+ missingPrereqs.push("git");
34011
+ }
34012
+ if (!commandExists("zsh")) {
34013
+ missingPrereqs.push("zsh");
34014
+ }
34015
+ if (missingPrereqs.length > 0) {
34016
+ s.stop(source_default.red("Missing prerequisites"));
34017
+ console.log(source_default.red(`
34018
+ ❌ Missing required tools: ${missingPrereqs.join(", ")}`));
34019
+ 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(" ")));
34025
+ }
34026
+ process.exit(1);
34027
+ }
34028
+ s.stop("Prerequisites OK");
34029
+ let selectedTheme = "robbyrussell";
34030
+ if (!skipInteractive) {
34031
+ const themeAnswer = await lib_default.prompt([
34032
+ {
34033
+ type: "list",
34034
+ name: "theme",
34035
+ message: "Which theme would you like to use?",
34036
+ choices: THEMES,
34037
+ default: "robbyrussell"
34038
+ }
34039
+ ]);
34040
+ if (themeAnswer.theme === "custom") {
34041
+ const customThemeAnswer = await lib_default.prompt([
34042
+ {
34043
+ type: "input",
34044
+ name: "customTheme",
34045
+ message: "Enter the theme name (see: https://github.com/ohmyzsh/ohmyzsh/wiki/Themes):",
34046
+ default: "robbyrussell",
34047
+ validate: (value) => {
34048
+ const sanitized = sanitizeThemeName(value);
34049
+ if (sanitized !== value) {
34050
+ return `Theme name can only contain letters, numbers, hyphens, and underscores. Will use: "${sanitized}"`;
34051
+ }
34052
+ return true;
34053
+ }
34054
+ }
34055
+ ]);
34056
+ selectedTheme = sanitizeThemeName(customThemeAnswer.customTheme);
34057
+ } else {
34058
+ selectedTheme = themeAnswer.theme;
34059
+ }
34060
+ }
34061
+ const zshrcPath = path9.join(homeDir, ".zshrc");
34062
+ if (import_fs_extra7.default.existsSync(zshrcPath)) {
34063
+ s.start("Backing up .zshrc");
34064
+ const backupPath = backupFile(zshrcPath);
34065
+ if (backupPath) {
34066
+ s.stop(`Backup created: ${source_default.gray(backupPath)}`);
34067
+ } else {
34068
+ s.stop("No backup needed");
34069
+ }
34070
+ }
34071
+ if (isOhMyZshInstalled(homeDir)) {
34072
+ console.log(source_default.green("✓ Oh My ZSH already installed"));
34073
+ } else {
34074
+ s.start("Installing Oh My ZSH (this may take a minute)");
34075
+ await installOhMyZsh(homeDir);
34076
+ s.stop("Oh My ZSH installed");
34077
+ }
34078
+ s.start("Installing zsh-autosuggestions plugin");
34079
+ await installPlugin("zsh-autosuggestions", "https://github.com/zsh-users/zsh-autosuggestions", homeDir);
34080
+ s.stop("zsh-autosuggestions installed");
34081
+ s.start("Installing zsh-syntax-highlighting plugin");
34082
+ await installPlugin("zsh-syntax-highlighting", "https://github.com/zsh-users/zsh-syntax-highlighting", homeDir);
34083
+ s.stop("zsh-syntax-highlighting installed");
34084
+ s.start(`Configuring theme: ${selectedTheme}`);
34085
+ updateZshrcTheme(selectedTheme, homeDir);
34086
+ s.stop(`Theme set to: ${selectedTheme}`);
34087
+ s.start("Configuring plugins");
34088
+ updateZshrcPlugins(PLUGINS, homeDir);
34089
+ s.stop("Plugins configured");
34090
+ console.log(source_default.green(`
34091
+ ✨ Terminal setup complete!`));
34092
+ console.log(source_default.gray(`
34093
+ Next steps:`));
34094
+ console.log(source_default.gray(" • Restart your terminal or run: source ~/.zshrc"));
34095
+ console.log(source_default.gray(` • Theme: ${selectedTheme}`));
34096
+ console.log(source_default.gray(` • Plugins: ${PLUGINS.join(", ")}`));
34097
+ if (selectedTheme === "agnoster") {
34098
+ console.log(source_default.yellow(`
34099
+ ⚠️ Note: agnoster theme requires a Powerline-patched font.`));
34100
+ console.log(source_default.gray(" Install from: https://github.com/powerline/fonts"));
34101
+ }
34102
+ console.log(source_default.blue(`
34103
+ \uD83D\uDCDA Explore more themes: https://github.com/ohmyzsh/ohmyzsh/wiki/Themes`));
34104
+ } catch (error) {
34105
+ console.error(source_default.red(`
34106
+ ❌ Setup failed:`), error);
34107
+ process.exit(1);
34108
+ }
34109
+ }
34110
+
33736
34111
  // src/commands/addHook.ts
33737
- var import_fs_extra10 = __toESM(require_lib4(), 1);
33738
- import path12 from "path";
34112
+ var import_fs_extra11 = __toESM(require_lib4(), 1);
34113
+ import path13 from "path";
33739
34114
  import { fileURLToPath as fileURLToPath4 } from "url";
33740
34115
  import { dirname as dirname4 } from "path";
33741
34116
 
33742
34117
  // src/utils/claude-config.ts
33743
- var import_fs_extra7 = __toESM(require_lib4(), 1);
33744
- import path9 from "path";
34118
+ var import_fs_extra8 = __toESM(require_lib4(), 1);
34119
+ import path10 from "path";
33745
34120
  import { fileURLToPath as fileURLToPath3 } from "url";
33746
34121
  import { dirname as dirname3 } from "path";
33747
34122
  var __filename3 = fileURLToPath3(import.meta.url);
@@ -33772,14 +34147,14 @@ function parseYamlFrontmatter(content) {
33772
34147
  }
33773
34148
  function getLocalConfigPaths(subDir) {
33774
34149
  return [
33775
- path9.join(__dirname3, `../claude-code-config/${subDir}`),
33776
- path9.join(__dirname3, `../../claude-code-config/${subDir}`)
34150
+ path10.join(__dirname3, `../claude-code-config/${subDir}`),
34151
+ path10.join(__dirname3, `../../claude-code-config/${subDir}`)
33777
34152
  ];
33778
34153
  }
33779
34154
  async function findLocalConfigDir(subDir) {
33780
34155
  const possiblePaths = getLocalConfigPaths(subDir);
33781
34156
  for (const testPath of possiblePaths) {
33782
- if (await import_fs_extra7.default.pathExists(testPath)) {
34157
+ if (await import_fs_extra8.default.pathExists(testPath)) {
33783
34158
  return testPath;
33784
34159
  }
33785
34160
  }
@@ -33790,22 +34165,22 @@ async function getTargetDirectory(options) {
33790
34165
  return options.folder;
33791
34166
  }
33792
34167
  const cwd = process.cwd();
33793
- const localClaudeDir = path9.join(cwd, ".claude");
33794
- const isGitRepo = await import_fs_extra7.default.pathExists(path9.join(cwd, ".git"));
33795
- const hasClaudeConfig = await import_fs_extra7.default.pathExists(localClaudeDir);
34168
+ const localClaudeDir = path10.join(cwd, ".claude");
34169
+ const isGitRepo = await import_fs_extra8.default.pathExists(path10.join(cwd, ".git"));
34170
+ const hasClaudeConfig = await import_fs_extra8.default.pathExists(localClaudeDir);
33796
34171
  if (isGitRepo || hasClaudeConfig) {
33797
34172
  return localClaudeDir;
33798
34173
  }
33799
- return path9.join(process.env.HOME || process.env.USERPROFILE || "~", ".claude");
34174
+ return path10.join(process.env.HOME || process.env.USERPROFILE || "~", ".claude");
33800
34175
  }
33801
34176
 
33802
34177
  // src/utils/file-installer.ts
33803
- var import_fs_extra9 = __toESM(require_lib4(), 1);
33804
- import path11 from "path";
34178
+ var import_fs_extra10 = __toESM(require_lib4(), 1);
34179
+ import path12 from "path";
33805
34180
 
33806
34181
  // src/utils/github.ts
33807
- var import_fs_extra8 = __toESM(require_lib4(), 1);
33808
- import path10 from "path";
34182
+ var import_fs_extra9 = __toESM(require_lib4(), 1);
34183
+ import path11 from "path";
33809
34184
  var GITHUB_RAW_BASE3 = "https://raw.githubusercontent.com/Melvynx/aiblueprint-cli/main/claude-code-config";
33810
34185
  async function downloadFromGitHub2(relativePath) {
33811
34186
  try {
@@ -33853,8 +34228,8 @@ async function isGitHubAvailable() {
33853
34228
  async function downloadAndWriteFile(relativePath, targetPath) {
33854
34229
  const content = await downloadFromGitHub2(relativePath);
33855
34230
  if (content) {
33856
- await import_fs_extra8.default.ensureDir(path10.dirname(targetPath));
33857
- await import_fs_extra8.default.writeFile(targetPath, content);
34231
+ await import_fs_extra9.default.ensureDir(path11.dirname(targetPath));
34232
+ await import_fs_extra9.default.writeFile(targetPath, content);
33858
34233
  return true;
33859
34234
  }
33860
34235
  return false;
@@ -33863,7 +34238,7 @@ async function downloadAndWriteFile(relativePath, targetPath) {
33863
34238
  // src/utils/file-installer.ts
33864
34239
  async function installFileWithGitHubFallback(options) {
33865
34240
  const { sourceDir, targetPath, fileName } = options;
33866
- await import_fs_extra9.default.ensureDir(path11.dirname(targetPath));
34241
+ await import_fs_extra10.default.ensureDir(path12.dirname(targetPath));
33867
34242
  const useGitHub = options.useGitHub ?? await isGitHubAvailable();
33868
34243
  if (useGitHub) {
33869
34244
  const relativePath = `${sourceDir}/${fileName}`;
@@ -33877,11 +34252,11 @@ async function installFileWithGitHubFallback(options) {
33877
34252
  if (!localConfigDir) {
33878
34253
  throw new Error(`Neither GitHub nor local ${sourceDir} directory found`);
33879
34254
  }
33880
- const localFilePath = path11.join(localConfigDir, fileName);
33881
- if (!await import_fs_extra9.default.pathExists(localFilePath)) {
34255
+ const localFilePath = path12.join(localConfigDir, fileName);
34256
+ if (!await import_fs_extra10.default.pathExists(localFilePath)) {
33882
34257
  throw new Error(`File not found: ${fileName}`);
33883
34258
  }
33884
- await import_fs_extra9.default.copy(localFilePath, targetPath);
34259
+ await import_fs_extra10.default.copy(localFilePath, targetPath);
33885
34260
  }
33886
34261
  async function getFileContentWithGitHubFallback(sourceDir, fileName) {
33887
34262
  const useGitHub = await isGitHubAvailable();
@@ -33896,11 +34271,11 @@ async function getFileContentWithGitHubFallback(sourceDir, fileName) {
33896
34271
  if (!localConfigDir) {
33897
34272
  throw new Error(`Neither GitHub nor local ${sourceDir} directory found`);
33898
34273
  }
33899
- const localFilePath = path11.join(localConfigDir, fileName);
33900
- if (!await import_fs_extra9.default.pathExists(localFilePath)) {
34274
+ const localFilePath = path12.join(localConfigDir, fileName);
34275
+ if (!await import_fs_extra10.default.pathExists(localFilePath)) {
33901
34276
  throw new Error(`File not found: ${fileName}`);
33902
34277
  }
33903
- return await import_fs_extra9.default.readFile(localFilePath, "utf-8");
34278
+ return await import_fs_extra10.default.readFile(localFilePath, "utf-8");
33904
34279
  }
33905
34280
 
33906
34281
  // src/commands/addHook.ts
@@ -33942,10 +34317,10 @@ async function addHookCommand(hookType, options) {
33942
34317
  const s = new SimpleSpinner2;
33943
34318
  const targetDir = await getTargetDirectory(options);
33944
34319
  const claudeDir = targetDir;
33945
- const targetHookDir = path12.join(claudeDir, hook.targetDir || "hooks");
33946
- const hookFilePath = path12.join(targetHookDir, hook.hookFile);
33947
- const settingsPath = path12.join(claudeDir, "settings.json");
33948
- if (await import_fs_extra10.default.pathExists(hookFilePath)) {
34320
+ const targetHookDir = path13.join(claudeDir, hook.targetDir || "hooks");
34321
+ const hookFilePath = path13.join(targetHookDir, hook.hookFile);
34322
+ const settingsPath = path13.join(claudeDir, "settings.json");
34323
+ if (await import_fs_extra11.default.pathExists(hookFilePath)) {
33949
34324
  const overwriteAnswer = await lib_default.prompt([{
33950
34325
  type: "confirm",
33951
34326
  name: "overwrite",
@@ -33958,18 +34333,18 @@ async function addHookCommand(hookType, options) {
33958
34333
  }
33959
34334
  try {
33960
34335
  s.start("Installing hook...");
33961
- await import_fs_extra10.default.ensureDir(targetHookDir);
34336
+ await import_fs_extra11.default.ensureDir(targetHookDir);
33962
34337
  await installFileWithGitHubFallback({
33963
34338
  sourceDir: hook.sourceDir || "hooks",
33964
34339
  targetPath: hookFilePath,
33965
34340
  fileName: hook.hookFile
33966
34341
  });
33967
- await import_fs_extra10.default.chmod(hookFilePath, 493);
34342
+ await import_fs_extra11.default.chmod(hookFilePath, 493);
33968
34343
  s.stop("Hook file installed");
33969
34344
  s.start("Updating settings.json...");
33970
34345
  let settings = {};
33971
34346
  try {
33972
- const existingSettings = await import_fs_extra10.default.readFile(settingsPath, "utf-8");
34347
+ const existingSettings = await import_fs_extra11.default.readFile(settingsPath, "utf-8");
33973
34348
  settings = JSON.parse(existingSettings);
33974
34349
  } catch {
33975
34350
  settings = {};
@@ -34006,7 +34381,7 @@ async function addHookCommand(hookType, options) {
34006
34381
  } else {
34007
34382
  settings.hooks[hook.event].push(newHook);
34008
34383
  }
34009
- await import_fs_extra10.default.writeFile(settingsPath, JSON.stringify(settings, null, 2));
34384
+ await import_fs_extra11.default.writeFile(settingsPath, JSON.stringify(settings, null, 2));
34010
34385
  s.stop("Settings updated");
34011
34386
  console.log(source_default.green("✨ Hook installed successfully!"));
34012
34387
  console.log(source_default.gray(`
@@ -34025,8 +34400,8 @@ The hook will run automatically when you edit TypeScript files with Claude Code.
34025
34400
  }
34026
34401
 
34027
34402
  // src/commands/addCommand.ts
34028
- var import_fs_extra11 = __toESM(require_lib4(), 1);
34029
- import path13 from "path";
34403
+ var import_fs_extra12 = __toESM(require_lib4(), 1);
34404
+ import path14 from "path";
34030
34405
  class SimpleSpinner3 {
34031
34406
  message = "";
34032
34407
  start(message) {
@@ -34039,11 +34414,11 @@ class SimpleSpinner3 {
34039
34414
  }
34040
34415
  async function getLocalMdFilesRecursively(dir, basePath = "") {
34041
34416
  const files = [];
34042
- const entries = await import_fs_extra11.default.readdir(dir, { withFileTypes: true });
34417
+ const entries = await import_fs_extra12.default.readdir(dir, { withFileTypes: true });
34043
34418
  for (const entry of entries) {
34044
34419
  const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;
34045
34420
  if (entry.isDirectory()) {
34046
- const subFiles = await getLocalMdFilesRecursively(path13.join(dir, entry.name), relativePath);
34421
+ const subFiles = await getLocalMdFilesRecursively(path14.join(dir, entry.name), relativePath);
34047
34422
  files.push(...subFiles);
34048
34423
  } else if (entry.name.endsWith(".md")) {
34049
34424
  files.push(relativePath);
@@ -34099,8 +34474,8 @@ function displayAvailableCommands(commands) {
34099
34474
  console.log();
34100
34475
  });
34101
34476
  console.log(source_default.gray("Usage:"));
34102
- console.log(source_default.gray(" aiblueprint claude-code add commands <command-name> # Install specific command"));
34103
- console.log(source_default.gray(" aiblueprint claude-code add commands # Show this list"));
34477
+ console.log(source_default.gray(" npx aiblueprint-cli@latest claude-code add commands <command-name> # Install specific command"));
34478
+ console.log(source_default.gray(" npx aiblueprint-cli@latest claude-code add commands # Show this list"));
34104
34479
  }
34105
34480
  async function addCommandCommand(commandName, options = {}) {
34106
34481
  console.log(source_default.bgBlue(` aiblueprint-cli v${getVersion()} `));
@@ -34123,9 +34498,9 @@ async function addCommandCommand(commandName, options = {}) {
34123
34498
  if (options.folder) {
34124
34499
  console.log(source_default.gray(`Using custom folder: ${targetDir}`));
34125
34500
  }
34126
- const commandsDir = path13.join(targetDir, "commands");
34127
- const commandFilePath = path13.join(commandsDir, command.commandFile);
34128
- if (await import_fs_extra11.default.pathExists(commandFilePath)) {
34501
+ const commandsDir = path14.join(targetDir, "commands");
34502
+ const commandFilePath = path14.join(commandsDir, command.commandFile);
34503
+ if (await import_fs_extra12.default.pathExists(commandFilePath)) {
34129
34504
  const overwriteAnswer = await lib_default.prompt([{
34130
34505
  type: "confirm",
34131
34506
  name: "overwrite",
@@ -34332,22 +34707,22 @@ async function symlinkCommand(params = {}) {
34332
34707
  }
34333
34708
 
34334
34709
  // src/commands/statusline.ts
34335
- var import_fs_extra12 = __toESM(require_lib4(), 1);
34336
- import path14 from "path";
34710
+ var import_fs_extra13 = __toESM(require_lib4(), 1);
34711
+ import path15 from "path";
34337
34712
  import { homedir } from "os";
34338
34713
  async function statuslineCommand(options) {
34339
- const claudeDir = options.folder ? path14.resolve(options.folder) : path14.join(homedir(), ".claude");
34714
+ const claudeDir = options.folder ? path15.resolve(options.folder) : path15.join(homedir(), ".claude");
34340
34715
  console.log(source_default.blue(`\uD83D\uDE80 Setting up AIBlueprint Statusline ${source_default.gray(`v${getVersion()}`)}...`));
34341
34716
  console.log(source_default.gray(` Target: ${claudeDir}
34342
34717
  `));
34343
- await import_fs_extra12.default.ensureDir(claudeDir);
34718
+ await import_fs_extra13.default.ensureDir(claudeDir);
34344
34719
  console.log(source_default.cyan("\uD83D\uDCE6 Checking dependencies..."));
34345
34720
  await checkAndInstallDependencies();
34346
34721
  console.log(source_default.cyan(`
34347
34722
  \uD83D\uDCE5 Downloading statusline files...`));
34348
- const scriptsDir = path14.join(claudeDir, "scripts");
34349
- await import_fs_extra12.default.ensureDir(scriptsDir);
34350
- const success = await downloadDirectoryFromGitHub("scripts/statusline", path14.join(scriptsDir, "statusline"));
34723
+ const scriptsDir = path15.join(claudeDir, "scripts");
34724
+ await import_fs_extra13.default.ensureDir(scriptsDir);
34725
+ const success = await downloadDirectoryFromGitHub("scripts/statusline", path15.join(scriptsDir, "statusline"));
34351
34726
  if (!success) {
34352
34727
  console.log(source_default.red(" Failed to download statusline files from GitHub"));
34353
34728
  return;
@@ -34357,19 +34732,19 @@ async function statuslineCommand(options) {
34357
34732
  await installStatuslineDependencies(claudeDir);
34358
34733
  console.log(source_default.cyan(`
34359
34734
  ⚙️ Configuring settings.json...`));
34360
- const settingsPath = path14.join(claudeDir, "settings.json");
34735
+ const settingsPath = path15.join(claudeDir, "settings.json");
34361
34736
  let settings = {};
34362
34737
  try {
34363
- const existingSettings = await import_fs_extra12.default.readFile(settingsPath, "utf-8");
34738
+ const existingSettings = await import_fs_extra13.default.readFile(settingsPath, "utf-8");
34364
34739
  settings = JSON.parse(existingSettings);
34365
34740
  } catch {
34366
34741
  }
34367
34742
  settings.statusLine = {
34368
34743
  type: "command",
34369
- command: `bun ${path14.join(claudeDir, "scripts/statusline/src/index.ts")}`,
34744
+ command: `bun ${path15.join(claudeDir, "scripts/statusline/src/index.ts")}`,
34370
34745
  padding: 0
34371
34746
  };
34372
- await import_fs_extra12.default.writeJson(settingsPath, settings, { spaces: 2 });
34747
+ await import_fs_extra13.default.writeJson(settingsPath, settings, { spaces: 2 });
34373
34748
  console.log(source_default.green(`
34374
34749
  ✅ Statusline setup complete!`));
34375
34750
  console.log(source_default.gray(`
@@ -35033,13 +35408,13 @@ var de = () => {
35033
35408
  };
35034
35409
 
35035
35410
  // src/commands/pro.ts
35036
- import os11 from "os";
35037
- import path17 from "path";
35411
+ import os12 from "os";
35412
+ import path18 from "path";
35038
35413
 
35039
35414
  // src/lib/pro-installer.ts
35040
- var import_fs_extra13 = __toESM(require_lib4(), 1);
35041
- import os9 from "os";
35042
- import path15 from "path";
35415
+ var import_fs_extra14 = __toESM(require_lib4(), 1);
35416
+ import os10 from "os";
35417
+ import path16 from "path";
35043
35418
  var PREMIUM_REPO = "Melvynx/aiblueprint-cli-premium";
35044
35419
  var PREMIUM_BRANCH = "main";
35045
35420
  async function downloadFromPrivateGitHub(repo, branch, relativePath, targetPath, githubToken) {
@@ -35056,8 +35431,8 @@ async function downloadFromPrivateGitHub(repo, branch, relativePath, targetPath,
35056
35431
  return false;
35057
35432
  }
35058
35433
  const content = await response.arrayBuffer();
35059
- await import_fs_extra13.default.ensureDir(path15.dirname(targetPath));
35060
- await import_fs_extra13.default.writeFile(targetPath, Buffer.from(content));
35434
+ await import_fs_extra14.default.ensureDir(path16.dirname(targetPath));
35435
+ await import_fs_extra14.default.writeFile(targetPath, Buffer.from(content));
35061
35436
  return true;
35062
35437
  } catch (error) {
35063
35438
  console.error(`Error downloading ${relativePath}:`, error);
@@ -35082,10 +35457,10 @@ async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetD
35082
35457
  console.error(`Unexpected response for directory ${dirPath}`);
35083
35458
  return false;
35084
35459
  }
35085
- await import_fs_extra13.default.ensureDir(targetDir);
35460
+ await import_fs_extra14.default.ensureDir(targetDir);
35086
35461
  for (const file of files) {
35087
35462
  const relativePath = dirPath ? `${dirPath}/${file.name}` : file.name;
35088
- const targetPath = path15.join(targetDir, file.name);
35463
+ const targetPath = path16.join(targetDir, file.name);
35089
35464
  const displayPath = relativePath.replace("claude-code-config/", "");
35090
35465
  if (file.type === "file") {
35091
35466
  onProgress?.(displayPath, "file");
@@ -35102,14 +35477,14 @@ async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetD
35102
35477
  }
35103
35478
  async function installProConfigs(options) {
35104
35479
  const { githubToken, claudeCodeFolder, onProgress } = options;
35105
- const claudeFolder = claudeCodeFolder || path15.join(os9.homedir(), ".claude");
35106
- const tempDir = path15.join(os9.tmpdir(), `aiblueprint-premium-${Date.now()}`);
35480
+ const claudeFolder = claudeCodeFolder || path16.join(os10.homedir(), ".claude");
35481
+ const tempDir = path16.join(os10.tmpdir(), `aiblueprint-premium-${Date.now()}`);
35107
35482
  try {
35108
35483
  const success = await downloadDirectoryFromPrivateGitHub(PREMIUM_REPO, PREMIUM_BRANCH, "claude-code-config", tempDir, githubToken, onProgress);
35109
35484
  if (!success) {
35110
35485
  throw new Error("Failed to download premium configurations");
35111
35486
  }
35112
- await import_fs_extra13.default.copy(tempDir, claudeFolder, {
35487
+ await import_fs_extra14.default.copy(tempDir, claudeFolder, {
35113
35488
  overwrite: true,
35114
35489
  recursive: true
35115
35490
  });
@@ -35117,41 +35492,41 @@ async function installProConfigs(options) {
35117
35492
  throw new Error(`Failed to install premium configs: ${error instanceof Error ? error.message : "Unknown error"}`);
35118
35493
  } finally {
35119
35494
  try {
35120
- await import_fs_extra13.default.remove(tempDir);
35495
+ await import_fs_extra14.default.remove(tempDir);
35121
35496
  } catch {
35122
35497
  }
35123
35498
  }
35124
35499
  }
35125
35500
 
35126
35501
  // src/lib/token-storage.ts
35127
- var import_fs_extra14 = __toESM(require_lib4(), 1);
35128
- import os10 from "os";
35129
- import path16 from "path";
35502
+ var import_fs_extra15 = __toESM(require_lib4(), 1);
35503
+ import os11 from "os";
35504
+ import path17 from "path";
35130
35505
  function getConfigDir() {
35131
- const platform = os10.platform();
35506
+ const platform = os11.platform();
35132
35507
  if (platform === "win32") {
35133
- const appData = process.env.APPDATA || path16.join(os10.homedir(), "AppData", "Roaming");
35134
- return path16.join(appData, "aiblueprint");
35508
+ const appData = process.env.APPDATA || path17.join(os11.homedir(), "AppData", "Roaming");
35509
+ return path17.join(appData, "aiblueprint");
35135
35510
  } else {
35136
- const configHome = process.env.XDG_CONFIG_HOME || path16.join(os10.homedir(), ".config");
35137
- return path16.join(configHome, "aiblueprint");
35511
+ const configHome = process.env.XDG_CONFIG_HOME || path17.join(os11.homedir(), ".config");
35512
+ return path17.join(configHome, "aiblueprint");
35138
35513
  }
35139
35514
  }
35140
35515
  function getTokenFilePath() {
35141
- return path16.join(getConfigDir(), "token.txt");
35516
+ return path17.join(getConfigDir(), "token.txt");
35142
35517
  }
35143
35518
  async function saveToken(githubToken) {
35144
35519
  const tokenFile = getTokenFilePath();
35145
- await import_fs_extra14.default.ensureDir(path16.dirname(tokenFile));
35146
- await import_fs_extra14.default.writeFile(tokenFile, githubToken, { mode: 384 });
35520
+ await import_fs_extra15.default.ensureDir(path17.dirname(tokenFile));
35521
+ await import_fs_extra15.default.writeFile(tokenFile, githubToken, { mode: 384 });
35147
35522
  }
35148
35523
  async function getToken() {
35149
35524
  const tokenFile = getTokenFilePath();
35150
- if (!await import_fs_extra14.default.pathExists(tokenFile)) {
35525
+ if (!await import_fs_extra15.default.pathExists(tokenFile)) {
35151
35526
  return null;
35152
35527
  }
35153
35528
  try {
35154
- const token = await import_fs_extra14.default.readFile(tokenFile, "utf-8");
35529
+ const token = await import_fs_extra15.default.readFile(tokenFile, "utf-8");
35155
35530
  return token.trim();
35156
35531
  } catch (error) {
35157
35532
  return null;
@@ -35160,12 +35535,12 @@ async function getToken() {
35160
35535
  function getTokenInfo() {
35161
35536
  return {
35162
35537
  path: getTokenFilePath(),
35163
- platform: os10.platform()
35538
+ platform: os11.platform()
35164
35539
  };
35165
35540
  }
35166
35541
 
35167
35542
  // src/commands/pro.ts
35168
- var import_fs_extra15 = __toESM(require_lib4(), 1);
35543
+ var import_fs_extra16 = __toESM(require_lib4(), 1);
35169
35544
  var API_URL = "https://codeline.app/api/products";
35170
35545
  var PRODUCT_ID = "prd_XJVgxVPbGG";
35171
35546
  async function countInstalledItems(claudeDir) {
@@ -35175,27 +35550,27 @@ async function countInstalledItems(claudeDir) {
35175
35550
  skills: 0
35176
35551
  };
35177
35552
  try {
35178
- const commandsDir = path17.join(claudeDir, "commands");
35179
- if (await import_fs_extra15.default.pathExists(commandsDir)) {
35180
- const files = await import_fs_extra15.default.readdir(commandsDir);
35553
+ const commandsDir = path18.join(claudeDir, "commands");
35554
+ if (await import_fs_extra16.default.pathExists(commandsDir)) {
35555
+ const files = await import_fs_extra16.default.readdir(commandsDir);
35181
35556
  counts.commands = files.filter((f3) => f3.endsWith(".md")).length;
35182
35557
  }
35183
35558
  } catch {
35184
35559
  }
35185
35560
  try {
35186
- const agentsDir = path17.join(claudeDir, "agents");
35187
- if (await import_fs_extra15.default.pathExists(agentsDir)) {
35188
- const files = await import_fs_extra15.default.readdir(agentsDir);
35561
+ const agentsDir = path18.join(claudeDir, "agents");
35562
+ if (await import_fs_extra16.default.pathExists(agentsDir)) {
35563
+ const files = await import_fs_extra16.default.readdir(agentsDir);
35189
35564
  counts.agents = files.filter((f3) => f3.endsWith(".md")).length;
35190
35565
  }
35191
35566
  } catch {
35192
35567
  }
35193
35568
  try {
35194
- const skillsDir = path17.join(claudeDir, "skills");
35195
- if (await import_fs_extra15.default.pathExists(skillsDir)) {
35196
- const items = await import_fs_extra15.default.readdir(skillsDir);
35569
+ const skillsDir = path18.join(claudeDir, "skills");
35570
+ if (await import_fs_extra16.default.pathExists(skillsDir)) {
35571
+ const items = await import_fs_extra16.default.readdir(skillsDir);
35197
35572
  const dirs = await Promise.all(items.map(async (item) => {
35198
- const stat = await import_fs_extra15.default.stat(path17.join(skillsDir, item));
35573
+ const stat = await import_fs_extra16.default.stat(path18.join(skillsDir, item));
35199
35574
  return stat.isDirectory();
35200
35575
  }));
35201
35576
  counts.skills = dirs.filter(Boolean).length;
@@ -35258,7 +35633,7 @@ async function proActivateCommand(userToken) {
35258
35633
  f2.info(`Product: ${data.product.title}`);
35259
35634
  f2.info(`Token saved to: ${tokenInfo.path}`);
35260
35635
  f2.info(source_default.cyan(`
35261
- \uD83D\uDCA1 Next step: Run 'aiblueprint claude-code pro setup' to install premium configs`));
35636
+ \uD83D\uDCA1 Next step: Run 'npx aiblueprint-cli@latest claude-code pro setup' to install premium configs`));
35262
35637
  $e(source_default.green("✅ Activation complete!"));
35263
35638
  } catch (error) {
35264
35639
  if (error instanceof Error) {
@@ -35274,7 +35649,7 @@ async function proStatusCommand() {
35274
35649
  const token = await getToken();
35275
35650
  if (!token) {
35276
35651
  f2.warn("No token found");
35277
- f2.info("Run: aiblueprint claude-code pro activate <token>");
35652
+ f2.info("Run: npx aiblueprint-cli@latest claude-code pro activate <token>");
35278
35653
  f2.info("Get your token at: https://mlv.sh/claude-cli");
35279
35654
  $e(source_default.yellow("⚠️ Not activated"));
35280
35655
  process.exit(0);
@@ -35298,11 +35673,11 @@ async function proSetupCommand(options = {}) {
35298
35673
  const githubToken = await getToken();
35299
35674
  if (!githubToken) {
35300
35675
  f2.error("No token found");
35301
- f2.info("Run: aiblueprint claude-code pro activate <token>");
35676
+ f2.info("Run: npx aiblueprint-cli@latest claude-code pro activate <token>");
35302
35677
  $e(source_default.red("❌ Not activated"));
35303
35678
  process.exit(1);
35304
35679
  }
35305
- const claudeDir = options.folder ? path17.resolve(options.folder) : path17.join(os11.homedir(), ".claude");
35680
+ const claudeDir = options.folder ? path18.resolve(options.folder) : path18.join(os12.homedir(), ".claude");
35306
35681
  const spinner = de();
35307
35682
  const onProgress = (file, type) => {
35308
35683
  spinner.message(`Installing: ${source_default.cyan(file)} ${source_default.gray(`(${type})`)}`);
@@ -35357,7 +35732,7 @@ async function proUpdateCommand(options = {}) {
35357
35732
  const githubToken = await getToken();
35358
35733
  if (!githubToken) {
35359
35734
  f2.error("No token found");
35360
- f2.info("Run: aiblueprint claude-code pro activate <token>");
35735
+ f2.info("Run: npx aiblueprint-cli@latest claude-code pro activate <token>");
35361
35736
  $e(source_default.red("❌ Not activated"));
35362
35737
  process.exit(1);
35363
35738
  }
@@ -35379,12 +35754,12 @@ async function proUpdateCommand(options = {}) {
35379
35754
  }
35380
35755
 
35381
35756
  // src/commands/sync.ts
35382
- import os12 from "os";
35383
- import path19 from "path";
35757
+ import os13 from "os";
35758
+ import path20 from "path";
35384
35759
 
35385
35760
  // src/lib/sync-utils.ts
35386
- var import_fs_extra16 = __toESM(require_lib4(), 1);
35387
- import path18 from "path";
35761
+ var import_fs_extra17 = __toESM(require_lib4(), 1);
35762
+ import path19 from "path";
35388
35763
  import crypto from "crypto";
35389
35764
  var PREMIUM_REPO2 = "Melvynx/aiblueprint-cli-premium";
35390
35765
  var PREMIUM_BRANCH2 = "main";
@@ -35433,7 +35808,7 @@ async function listRemoteFilesRecursive(dirPath, githubToken, basePath = "") {
35433
35808
  }
35434
35809
  async function computeLocalFileSha(filePath) {
35435
35810
  try {
35436
- const content = await import_fs_extra16.default.readFile(filePath);
35811
+ const content = await import_fs_extra17.default.readFile(filePath);
35437
35812
  return computeFileSha(content);
35438
35813
  } catch {
35439
35814
  return null;
@@ -35441,15 +35816,15 @@ async function computeLocalFileSha(filePath) {
35441
35816
  }
35442
35817
  async function listLocalFiles(dir) {
35443
35818
  const files = [];
35444
- if (!await import_fs_extra16.default.pathExists(dir)) {
35819
+ if (!await import_fs_extra17.default.pathExists(dir)) {
35445
35820
  return files;
35446
35821
  }
35447
- const items = await import_fs_extra16.default.readdir(dir);
35822
+ const items = await import_fs_extra17.default.readdir(dir);
35448
35823
  for (const item of items) {
35449
35824
  if (item === "node_modules" || item === ".DS_Store")
35450
35825
  continue;
35451
- const fullPath = path18.join(dir, item);
35452
- const stat = await import_fs_extra16.default.stat(fullPath);
35826
+ const fullPath = path19.join(dir, item);
35827
+ const stat = await import_fs_extra17.default.stat(fullPath);
35453
35828
  if (stat.isDirectory()) {
35454
35829
  files.push(item);
35455
35830
  const subFiles = await listLocalFilesRecursive(fullPath, item);
@@ -35462,13 +35837,13 @@ async function listLocalFiles(dir) {
35462
35837
  }
35463
35838
  async function listLocalFilesRecursive(dir, basePath) {
35464
35839
  const files = [];
35465
- const items = await import_fs_extra16.default.readdir(dir);
35840
+ const items = await import_fs_extra17.default.readdir(dir);
35466
35841
  for (const item of items) {
35467
35842
  if (item === "node_modules" || item === ".DS_Store")
35468
35843
  continue;
35469
- const fullPath = path18.join(dir, item);
35844
+ const fullPath = path19.join(dir, item);
35470
35845
  const relativePath = `${basePath}/${item}`;
35471
- const stat = await import_fs_extra16.default.stat(fullPath);
35846
+ const stat = await import_fs_extra17.default.stat(fullPath);
35472
35847
  if (stat.isDirectory()) {
35473
35848
  files.push(relativePath);
35474
35849
  const subFiles = await listLocalFilesRecursive(fullPath, relativePath);
@@ -35481,7 +35856,7 @@ async function listLocalFilesRecursive(dir, basePath) {
35481
35856
  }
35482
35857
  async function analyzeCategory(category, claudeDir, githubToken) {
35483
35858
  const items = [];
35484
- const localDir = path18.join(claudeDir, category);
35859
+ const localDir = path19.join(claudeDir, category);
35485
35860
  const remoteFiles = await listRemoteFilesRecursive(category, githubToken);
35486
35861
  const localFiles = await listLocalFiles(localDir);
35487
35862
  const remoteSet = new Map;
@@ -35490,7 +35865,7 @@ async function analyzeCategory(category, claudeDir, githubToken) {
35490
35865
  }
35491
35866
  const localSet = new Set(localFiles);
35492
35867
  for (const [remotePath, { sha, isFolder }] of remoteSet) {
35493
- const localPath = path18.join(localDir, remotePath);
35868
+ const localPath = path19.join(localDir, remotePath);
35494
35869
  if (isFolder) {
35495
35870
  continue;
35496
35871
  }
@@ -35522,8 +35897,8 @@ async function analyzeCategory(category, claudeDir, githubToken) {
35522
35897
  }
35523
35898
  for (const localPath of localSet) {
35524
35899
  if (!remoteSet.has(localPath)) {
35525
- const fullPath = path18.join(localDir, localPath);
35526
- const stat = await import_fs_extra16.default.stat(fullPath).catch(() => null);
35900
+ const fullPath = path19.join(localDir, localPath);
35901
+ const stat = await import_fs_extra17.default.stat(fullPath).catch(() => null);
35527
35902
  if (stat && !stat.isDirectory()) {
35528
35903
  items.push({
35529
35904
  name: localPath,
@@ -35554,9 +35929,9 @@ async function fetchRemoteSettings(githubToken) {
35554
35929
  }
35555
35930
  }
35556
35931
  async function getLocalSettings(claudeDir) {
35557
- const settingsPath = path18.join(claudeDir, "settings.json");
35932
+ const settingsPath = path19.join(claudeDir, "settings.json");
35558
35933
  try {
35559
- const content = await import_fs_extra16.default.readFile(settingsPath, "utf-8");
35934
+ const content = await import_fs_extra17.default.readFile(settingsPath, "utf-8");
35560
35935
  return JSON.parse(content);
35561
35936
  } catch {
35562
35937
  return {};
@@ -35637,8 +36012,8 @@ async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken)
35637
36012
  return false;
35638
36013
  }
35639
36014
  const content = await response.arrayBuffer();
35640
- await import_fs_extra16.default.ensureDir(path18.dirname(targetPath));
35641
- await import_fs_extra16.default.writeFile(targetPath, Buffer.from(content));
36015
+ await import_fs_extra17.default.ensureDir(path19.dirname(targetPath));
36016
+ await import_fs_extra17.default.writeFile(targetPath, Buffer.from(content));
35642
36017
  return true;
35643
36018
  } catch {
35644
36019
  return false;
@@ -35648,10 +36023,10 @@ async function syncSelectedHooks(claudeDir, hooks, onProgress) {
35648
36023
  if (hooks.length === 0) {
35649
36024
  return { success: 0, failed: 0 };
35650
36025
  }
35651
- const settingsPath = path18.join(claudeDir, "settings.json");
36026
+ const settingsPath = path19.join(claudeDir, "settings.json");
35652
36027
  let settings = {};
35653
36028
  try {
35654
- const content = await import_fs_extra16.default.readFile(settingsPath, "utf-8");
36029
+ const content = await import_fs_extra17.default.readFile(settingsPath, "utf-8");
35655
36030
  settings = JSON.parse(content);
35656
36031
  } catch {
35657
36032
  settings = {};
@@ -35668,17 +36043,18 @@ async function syncSelectedHooks(claudeDir, hooks, onProgress) {
35668
36043
  settings.hooks[hook.hookType] = [];
35669
36044
  }
35670
36045
  const existingIndex = settings.hooks[hook.hookType].findIndex((h2) => h2.matcher === hook.matcher);
36046
+ const transformedHook = transformHook(hook.remoteHook, claudeDir);
35671
36047
  if (existingIndex >= 0) {
35672
- settings.hooks[hook.hookType][existingIndex] = hook.remoteHook;
36048
+ settings.hooks[hook.hookType][existingIndex] = transformedHook;
35673
36049
  } else {
35674
- settings.hooks[hook.hookType].push(hook.remoteHook);
36050
+ settings.hooks[hook.hookType].push(transformedHook);
35675
36051
  }
35676
36052
  success++;
35677
36053
  } catch {
35678
36054
  failed++;
35679
36055
  }
35680
36056
  }
35681
- await import_fs_extra16.default.writeFile(settingsPath, JSON.stringify(settings, null, 2));
36057
+ await import_fs_extra17.default.writeFile(settingsPath, JSON.stringify(settings, null, 2));
35682
36058
  return { success, failed };
35683
36059
  }
35684
36060
  async function syncSelectedItems(claudeDir, items, githubToken, onProgress) {
@@ -35686,11 +36062,11 @@ async function syncSelectedItems(claudeDir, items, githubToken, onProgress) {
35686
36062
  let failed = 0;
35687
36063
  let deleted = 0;
35688
36064
  for (const item of items) {
35689
- const targetPath = path18.join(claudeDir, item.relativePath);
36065
+ const targetPath = path19.join(claudeDir, item.relativePath);
35690
36066
  if (item.status === "deleted") {
35691
36067
  onProgress?.(item.relativePath, "deleting");
35692
36068
  try {
35693
- await import_fs_extra16.default.remove(targetPath);
36069
+ await import_fs_extra17.default.remove(targetPath);
35694
36070
  deleted++;
35695
36071
  } catch {
35696
36072
  failed++;
@@ -35837,11 +36213,11 @@ async function proSyncCommand(options = {}) {
35837
36213
  const githubToken = await getToken();
35838
36214
  if (!githubToken) {
35839
36215
  f2.error("No token found");
35840
- f2.info("Run: aiblueprint claude-code pro activate <token>");
36216
+ f2.info("Run: npx aiblueprint-cli@latest claude-code pro activate <token>");
35841
36217
  $e(source_default.red("❌ Not activated"));
35842
36218
  process.exit(1);
35843
36219
  }
35844
- const claudeDir = options.folder ? path19.resolve(options.folder) : path19.join(os12.homedir(), ".claude");
36220
+ const claudeDir = options.folder ? path20.resolve(options.folder) : path20.join(os13.homedir(), ".claude");
35845
36221
  const spinner = de();
35846
36222
  spinner.start("Analyzing changes...");
35847
36223
  const result = await analyzeSyncChanges(claudeDir, githubToken);
@@ -36033,11 +36409,18 @@ claudeCodeCmd.command("setup").description("Setup Claude Code configuration with
36033
36409
  skipInteractive: parentOptions.skip
36034
36410
  });
36035
36411
  });
36412
+ claudeCodeCmd.command("setup-terminal").description("Setup terminal with Oh My ZSH, plugins, and a beautiful theme").action((options, command) => {
36413
+ const parentOptions = command.parent.opts();
36414
+ setupTerminalCommand({
36415
+ skipInteractive: parentOptions.skip,
36416
+ homeDir: parentOptions.claudeCodeFolder || parentOptions.folder
36417
+ });
36418
+ });
36036
36419
  var addCmd = claudeCodeCmd.command("add").description(`Add components to your Claude Code configuration
36037
36420
  ` + `Examples:
36038
- ` + ` aiblueprint claude-code add hook post-edit-typescript
36039
- ` + ` aiblueprint claude-code add commands
36040
- ` + " aiblueprint claude-code add commands commit");
36421
+ ` + ` npx aiblueprint-cli@latest claude-code add hook post-edit-typescript
36422
+ ` + ` npx aiblueprint-cli@latest claude-code add commands
36423
+ ` + " npx aiblueprint-cli@latest claude-code add commands commit");
36041
36424
  addCmd.command("hook <type>").description("Add a hook to your Claude Code configuration. Available types: post-edit-typescript").action((type, options, command) => {
36042
36425
  const parentOptions = command.parent.parent.opts();
36043
36426
  const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiblueprint-cli",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "AIBlueprint CLI for setting up Claude Code configurations",
5
5
  "author": "AIBlueprint",
6
6
  "license": "MIT",