aiblueprint-cli 1.2.3 → 1.3.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.
@@ -29,11 +29,16 @@ Add to `~/.claude/settings.json`:
29
29
 
30
30
  ### Authentication
31
31
 
32
- OAuth token stored in macOS Keychain:
32
+ OAuth token storage (platform-specific):
33
+
34
+ **macOS**: Stored in Keychain
33
35
  - **Service**: `Claude Code-credentials`
36
+ - **Access**: `security find-generic-password -s "Claude Code-credentials" -w`
37
+
38
+ **Windows & Linux**: Stored in file system
39
+ - **Location**: `~/.claude/.credentials.json`
34
40
  - **Format**: JSON with `claudeAiOauth.accessToken`
35
41
  - **Token type**: `sk-ant-oat01-...` (OAuth token, not API key)
36
- - **Access**: `security find-generic-password -s "Claude Code-credentials" -w`
37
42
 
38
43
  ## Architecture
39
44
 
@@ -172,7 +177,7 @@ This ensures statusline never crashes Claude Code.
172
177
 
173
178
  ## Known Limitations
174
179
 
175
- - macOS only (uses Keychain)
176
180
  - Requires `git` CLI for git status
177
181
  - Requires Claude Code OAuth (not API key)
178
182
  - Transcript must be accessible (permissions)
183
+ - Cross-platform support: macOS (Keychain), Windows & Linux (file-based credentials)
package/dist/cli.js CHANGED
@@ -32490,7 +32490,7 @@ var lib_default = inquirer;
32490
32490
  // src/commands/setup.ts
32491
32491
  var import_fs_extra5 = __toESM(require_lib4(), 1);
32492
32492
  import path7 from "path";
32493
- import os5 from "os";
32493
+ import os7 from "os";
32494
32494
 
32495
32495
  // node_modules/chalk/source/vendor/ansi-styles/index.js
32496
32496
  var ANSI_BACKGROUND_OFFSET = 10;
@@ -32994,8 +32994,14 @@ async function setupShellShortcuts() {
32994
32994
  try {
32995
32995
  const platform = os3.platform();
32996
32996
  let shellConfigFile;
32997
+ let aliases;
32997
32998
  if (platform === "darwin") {
32998
32999
  shellConfigFile = path2.join(os3.homedir(), ".zshenv");
33000
+ aliases = `
33001
+ # AIBlueprint Claude Code aliases
33002
+ alias cc="claude --dangerously-skip-permissions"
33003
+ alias ccc="claude --dangerously-skip-permissions -c"
33004
+ `;
32999
33005
  } else if (platform === "linux") {
33000
33006
  const shell = process.env.SHELL || "";
33001
33007
  if (shell.includes("zsh")) {
@@ -33003,17 +33009,35 @@ async function setupShellShortcuts() {
33003
33009
  } else {
33004
33010
  shellConfigFile = path2.join(os3.homedir(), ".bashrc");
33005
33011
  }
33006
- } else {
33007
- console.log(source_default.yellow("Shell shortcuts are only supported on macOS and Linux"));
33008
- return;
33009
- }
33010
- const aliases = `
33012
+ aliases = `
33011
33013
  # AIBlueprint Claude Code aliases
33012
33014
  alias cc="claude --dangerously-skip-permissions"
33013
33015
  alias ccc="claude --dangerously-skip-permissions -c"
33014
33016
  `;
33017
+ } else if (platform === "win32") {
33018
+ const pwshProfileDir = path2.join(os3.homedir(), "Documents", "PowerShell");
33019
+ const windowsPwshProfileDir = path2.join(os3.homedir(), "Documents", "WindowsPowerShell");
33020
+ let profileDir;
33021
+ if (await import_fs_extra.default.pathExists(pwshProfileDir)) {
33022
+ profileDir = pwshProfileDir;
33023
+ } else if (await import_fs_extra.default.pathExists(windowsPwshProfileDir)) {
33024
+ profileDir = windowsPwshProfileDir;
33025
+ } else {
33026
+ profileDir = pwshProfileDir;
33027
+ await import_fs_extra.default.ensureDir(profileDir);
33028
+ }
33029
+ shellConfigFile = path2.join(profileDir, "Profile.ps1");
33030
+ aliases = `
33031
+ # AIBlueprint Claude Code shortcuts
33032
+ function cc { claude --dangerously-skip-permissions $args }
33033
+ function ccc { claude --dangerously-skip-permissions -c $args }
33034
+ `;
33035
+ } else {
33036
+ console.log(source_default.yellow(`Shell shortcuts are not supported on platform: ${platform}`));
33037
+ return;
33038
+ }
33015
33039
  const existingContent = await import_fs_extra.default.readFile(shellConfigFile, "utf-8").catch(() => "");
33016
- if (!existingContent.includes("AIBlueprint Claude Code aliases")) {
33040
+ if (!existingContent.includes("AIBlueprint Claude Code")) {
33017
33041
  await import_fs_extra.default.appendFile(shellConfigFile, aliases);
33018
33042
  }
33019
33043
  } catch (error) {
@@ -33078,7 +33102,12 @@ async function createSymlink(sourcePath, targetPath, options = {}) {
33078
33102
  return false;
33079
33103
  }
33080
33104
  }
33081
- await import_fs_extra2.default.symlink(sourcePath, targetPath);
33105
+ const isWindows = os4.platform() === "win32";
33106
+ if (isWindows) {
33107
+ await import_fs_extra2.default.symlink(sourcePath, targetPath, "junction");
33108
+ } else {
33109
+ await import_fs_extra2.default.symlink(sourcePath, targetPath);
33110
+ }
33082
33111
  return true;
33083
33112
  } catch (error) {
33084
33113
  console.error(source_default.red(options.errorPrefix || "Error creating symlink:"), error);
@@ -33131,10 +33160,13 @@ async function setupOpenCodeSymlink(claudeDir, customOpenCodeFolder, customClaud
33131
33160
  // src/commands/setup/dependencies.ts
33132
33161
  import { execSync } from "child_process";
33133
33162
  import path4 from "path";
33163
+ import os5 from "os";
33134
33164
  async function checkAndInstallDependencies() {
33165
+ const isWindows = os5.platform() === "win32";
33135
33166
  const checkCommand = (cmd) => {
33136
33167
  try {
33137
- execSync(`which ${cmd}`, { stdio: "ignore" });
33168
+ const whichCmd = isWindows ? `where ${cmd}` : `which ${cmd}`;
33169
+ execSync(whichCmd, { stdio: "ignore" });
33138
33170
  return true;
33139
33171
  } catch {
33140
33172
  return false;
@@ -33177,6 +33209,27 @@ async function installStatuslineDependencies(claudeDir) {
33177
33209
  // src/commands/setup/settings.ts
33178
33210
  var import_fs_extra3 = __toESM(require_lib4(), 1);
33179
33211
  import path5 from "path";
33212
+ import os6 from "os";
33213
+ function getPlaySoundCommand(soundPath) {
33214
+ const platform = os6.platform();
33215
+ if (platform === "darwin") {
33216
+ return `afplay -v 0.1 "${soundPath}"`;
33217
+ } else if (platform === "win32") {
33218
+ return `powershell -c "(New-Object Media.SoundPlayer '${soundPath}').PlaySync()"`;
33219
+ } else {
33220
+ return `paplay "${soundPath}" 2>/dev/null || aplay "${soundPath}" 2>/dev/null || true`;
33221
+ }
33222
+ }
33223
+ async function hasExistingStatusLine(claudeDir) {
33224
+ const settingsPath = path5.join(claudeDir, "settings.json");
33225
+ try {
33226
+ const existingSettings = await import_fs_extra3.default.readFile(settingsPath, "utf-8");
33227
+ const settings = JSON.parse(existingSettings);
33228
+ return !!settings.statusLine;
33229
+ } catch {
33230
+ return false;
33231
+ }
33232
+ }
33180
33233
  async function updateSettings(options, claudeDir) {
33181
33234
  const settingsPath = path5.join(claudeDir, "settings.json");
33182
33235
  let settings = {};
@@ -33186,24 +33239,8 @@ async function updateSettings(options, claudeDir) {
33186
33239
  } catch {
33187
33240
  }
33188
33241
  if (options.customStatusline) {
33189
- if (settings.statusLine) {
33190
- const confirmAnswer = await lib_default.prompt([
33191
- {
33192
- type: "confirm",
33193
- name: "replace",
33194
- message: "You already have a statusLine configuration. Replace it?"
33195
- }
33196
- ]);
33197
- if (!confirmAnswer.replace) {
33198
- console.log(source_default.yellow(" Keeping existing statusLine configuration"));
33199
- } else {
33200
- settings.statusLine = {
33201
- type: "command",
33202
- command: `bun ${path5.join(claudeDir, "scripts/statusline/src/index.ts")}`,
33203
- padding: 0
33204
- };
33205
- }
33206
- } else {
33242
+ const shouldReplace = options.replaceStatusline !== false;
33243
+ if (shouldReplace) {
33207
33244
  settings.statusLine = {
33208
33245
  type: "command",
33209
33246
  command: `bun ${path5.join(claudeDir, "scripts/statusline/src/index.ts")}`,
@@ -33236,12 +33273,13 @@ async function updateSettings(options, claudeDir) {
33236
33273
  if (!settings.hooks.Stop) {
33237
33274
  settings.hooks.Stop = [];
33238
33275
  }
33276
+ const finishSoundPath = path5.join(claudeDir, "song/finish.mp3");
33239
33277
  const stopHook = {
33240
33278
  matcher: "",
33241
33279
  hooks: [
33242
33280
  {
33243
33281
  type: "command",
33244
- command: `afplay -v 0.1 ${path5.join(claudeDir, "song/finish.mp3")}`
33282
+ command: getPlaySoundCommand(finishSoundPath)
33245
33283
  }
33246
33284
  ]
33247
33285
  };
@@ -33252,12 +33290,13 @@ async function updateSettings(options, claudeDir) {
33252
33290
  if (!settings.hooks.Notification) {
33253
33291
  settings.hooks.Notification = [];
33254
33292
  }
33293
+ const needHumanSoundPath = path5.join(claudeDir, "song/need-human.mp3");
33255
33294
  const notificationHook = {
33256
33295
  matcher: "",
33257
33296
  hooks: [
33258
33297
  {
33259
33298
  type: "command",
33260
- command: `afplay -v 0.1 ${path5.join(claudeDir, "song/need-human.mp3")}`
33299
+ command: getPlaySoundCommand(needHumanSoundPath)
33261
33300
  }
33262
33301
  ]
33263
33302
  };
@@ -33322,24 +33361,35 @@ async function downloadDirectoryFromGitHub(dirPath, targetDir) {
33322
33361
  const apiUrl = `https://api.github.com/repos/Melvynx/aiblueprint-cli/contents/claude-code-config/${dirPath}`;
33323
33362
  const response = await fetch(apiUrl);
33324
33363
  if (!response.ok) {
33364
+ console.error(source_default.yellow(` Warning: Failed to fetch directory from GitHub: ${dirPath} (HTTP ${response.status})`));
33325
33365
  return false;
33326
33366
  }
33327
33367
  const files = await response.json();
33328
33368
  if (!Array.isArray(files)) {
33369
+ console.error(source_default.yellow(` Warning: Invalid response from GitHub API for: ${dirPath}`));
33329
33370
  return false;
33330
33371
  }
33331
33372
  await import_fs_extra4.default.ensureDir(targetDir);
33373
+ let allSuccess = true;
33332
33374
  for (const file of files) {
33333
33375
  const relativePath = `${dirPath}/${file.name}`;
33334
33376
  const targetPath = path6.join(targetDir, file.name);
33335
33377
  if (file.type === "file") {
33336
- await downloadFromGitHub(relativePath, targetPath);
33378
+ const success = await downloadFromGitHub(relativePath, targetPath);
33379
+ if (!success) {
33380
+ console.error(source_default.yellow(` Warning: Failed to download file: ${relativePath}`));
33381
+ allSuccess = false;
33382
+ }
33337
33383
  } else if (file.type === "dir") {
33338
- await downloadDirectoryFromGitHub(relativePath, targetPath);
33384
+ const success = await downloadDirectoryFromGitHub(relativePath, targetPath);
33385
+ if (!success) {
33386
+ allSuccess = false;
33387
+ }
33339
33388
  }
33340
33389
  }
33341
- return true;
33390
+ return allSuccess;
33342
33391
  } catch (error) {
33392
+ console.error(source_default.yellow(` Warning: Error downloading directory ${dirPath}: ${error instanceof Error ? error.message : String(error)}`));
33343
33393
  return false;
33344
33394
  }
33345
33395
  }
@@ -33443,10 +33493,11 @@ async function setupCommand(params = {}) {
33443
33493
  notificationSounds: features.includes("notificationSounds"),
33444
33494
  postEditTypeScript: features.includes("postEditTypeScript"),
33445
33495
  codexSymlink: features.includes("codexSymlink"),
33446
- openCodeSymlink: features.includes("openCodeSymlink")
33496
+ openCodeSymlink: features.includes("openCodeSymlink"),
33497
+ skipInteractive
33447
33498
  };
33448
33499
  const s = new SimpleSpinner;
33449
- const claudeDir = customClaudeCodeFolder ? path7.resolve(customClaudeCodeFolder) : path7.join(os5.homedir(), ".claude");
33500
+ const claudeDir = customClaudeCodeFolder ? path7.resolve(customClaudeCodeFolder) : path7.join(os7.homedir(), ".claude");
33450
33501
  console.log(source_default.gray(`Installing to: ${claudeDir}`));
33451
33502
  await import_fs_extra5.default.ensureDir(claudeDir);
33452
33503
  let useGitHub = true;
@@ -33577,6 +33628,23 @@ async function setupCommand(params = {}) {
33577
33628
  await installStatuslineDependencies(claudeDir);
33578
33629
  s.stop("Statusline dependencies installed");
33579
33630
  }
33631
+ if (options.customStatusline && !skipInteractive) {
33632
+ const existingStatusLine = await hasExistingStatusLine(claudeDir);
33633
+ if (existingStatusLine) {
33634
+ const confirmAnswer = await lib_default.prompt([
33635
+ {
33636
+ type: "confirm",
33637
+ name: "replace",
33638
+ message: "You already have a statusLine configuration. Replace it?",
33639
+ default: true
33640
+ }
33641
+ ]);
33642
+ options.replaceStatusline = confirmAnswer.replace;
33643
+ if (!confirmAnswer.replace) {
33644
+ console.log(source_default.yellow(" Keeping existing statusLine configuration"));
33645
+ }
33646
+ }
33647
+ }
33580
33648
  s.start("Updating settings.json");
33581
33649
  await updateSettings(options, claudeDir);
33582
33650
  s.stop("Settings updated");
@@ -33584,7 +33652,12 @@ async function setupCommand(params = {}) {
33584
33652
  console.log(source_default.gray(`
33585
33653
  Next steps:`));
33586
33654
  if (options.shellShortcuts) {
33587
- console.log(source_default.gray(" • Restart your terminal or run: source ~/.zshenv (macOS) or source ~/.bashrc (Linux)"));
33655
+ const platform = os7.platform();
33656
+ if (platform === "win32") {
33657
+ console.log(source_default.gray(" • Restart PowerShell to load the new functions"));
33658
+ } else {
33659
+ console.log(source_default.gray(" • Restart your terminal or run: source ~/.zshenv (macOS) or source ~/.bashrc (Linux)"));
33660
+ }
33588
33661
  console.log(source_default.gray(' • Use "cc" for Claude Code with permissions skipped'));
33589
33662
  console.log(source_default.gray(' • Use "ccc" for Claude Code with permissions skipped and continue mode'));
33590
33663
  }
@@ -34708,7 +34781,7 @@ var de = () => {
34708
34781
 
34709
34782
  // src/lib/pro-installer.ts
34710
34783
  var import_fs_extra12 = __toESM(require_lib4(), 1);
34711
- import os6 from "os";
34784
+ import os8 from "os";
34712
34785
  import path14 from "path";
34713
34786
  var PREMIUM_REPO = "Melvynx/aiblueprint-cli-premium";
34714
34787
  var PREMIUM_BRANCH = "main";
@@ -34770,8 +34843,8 @@ async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetD
34770
34843
  }
34771
34844
  async function installProConfigs(options) {
34772
34845
  const { githubToken, claudeCodeFolder } = options;
34773
- const claudeFolder = claudeCodeFolder || path14.join(os6.homedir(), ".claude");
34774
- const tempDir = path14.join(os6.tmpdir(), `aiblueprint-premium-${Date.now()}`);
34846
+ const claudeFolder = claudeCodeFolder || path14.join(os8.homedir(), ".claude");
34847
+ const tempDir = path14.join(os8.tmpdir(), `aiblueprint-premium-${Date.now()}`);
34775
34848
  try {
34776
34849
  const success = await downloadDirectoryFromPrivateGitHub(PREMIUM_REPO, PREMIUM_BRANCH, "claude-code-config", tempDir, githubToken);
34777
34850
  if (!success) {
@@ -34795,9 +34868,9 @@ async function installProConfigs(options) {
34795
34868
  // src/lib/setup-helper.ts
34796
34869
  var import_fs_extra13 = __toESM(require_lib4(), 1);
34797
34870
  import path15 from "path";
34798
- import os7 from "os";
34871
+ import os9 from "os";
34799
34872
  async function installBasicConfigs(options = {}, skipStatusline = false) {
34800
- const claudeDir = options.claudeCodeFolder || path15.join(os7.homedir(), ".claude");
34873
+ const claudeDir = options.claudeCodeFolder || path15.join(os9.homedir(), ".claude");
34801
34874
  await import_fs_extra13.default.ensureDir(claudeDir);
34802
34875
  console.log(source_default.gray("\uD83D\uDCE6 Installing free configurations..."));
34803
34876
  console.log(source_default.gray(" • Commands..."));
@@ -34814,15 +34887,15 @@ async function installBasicConfigs(options = {}, skipStatusline = false) {
34814
34887
 
34815
34888
  // src/lib/token-storage.ts
34816
34889
  var import_fs_extra14 = __toESM(require_lib4(), 1);
34817
- import os8 from "os";
34890
+ import os10 from "os";
34818
34891
  import path16 from "path";
34819
34892
  function getConfigDir() {
34820
- const platform = os8.platform();
34893
+ const platform = os10.platform();
34821
34894
  if (platform === "win32") {
34822
- const appData = process.env.APPDATA || path16.join(os8.homedir(), "AppData", "Roaming");
34895
+ const appData = process.env.APPDATA || path16.join(os10.homedir(), "AppData", "Roaming");
34823
34896
  return path16.join(appData, "aiblueprint");
34824
34897
  } else {
34825
- const configHome = process.env.XDG_CONFIG_HOME || path16.join(os8.homedir(), ".config");
34898
+ const configHome = process.env.XDG_CONFIG_HOME || path16.join(os10.homedir(), ".config");
34826
34899
  return path16.join(configHome, "aiblueprint");
34827
34900
  }
34828
34901
  }
@@ -34849,7 +34922,7 @@ async function getToken() {
34849
34922
  function getTokenInfo() {
34850
34923
  return {
34851
34924
  path: getTokenFilePath(),
34852
- platform: os8.platform()
34925
+ platform: os10.platform()
34853
34926
  };
34854
34927
  }
34855
34928
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiblueprint-cli",
3
- "version": "1.2.3",
3
+ "version": "1.3.0",
4
4
  "description": "AIBlueprint CLI for setting up Claude Code configurations",
5
5
  "author": "AIBlueprint",
6
6
  "license": "MIT",