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.
- package/dist/cli.js +550 -167
- 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
|
|
33220
|
-
}
|
|
33221
|
-
|
|
33222
|
-
|
|
33223
|
-
return `
|
|
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
|
-
|
|
33277
|
-
|
|
33278
|
-
|
|
33279
|
-
|
|
33280
|
-
|
|
33281
|
-
|
|
33282
|
-
|
|
33283
|
-
|
|
33284
|
-
|
|
33285
|
-
|
|
33286
|
-
|
|
33287
|
-
|
|
33288
|
-
|
|
33289
|
-
|
|
33290
|
-
|
|
33291
|
-
settings.hooks.Stop.
|
|
33292
|
-
|
|
33293
|
-
|
|
33294
|
-
|
|
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
|
|
33298
|
-
|
|
33299
|
-
hooks
|
|
33300
|
-
|
|
33301
|
-
|
|
33302
|
-
|
|
33303
|
-
|
|
33304
|
-
|
|
33305
|
-
|
|
33306
|
-
|
|
33307
|
-
|
|
33308
|
-
|
|
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
|
|
33738
|
-
import
|
|
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
|
|
33744
|
-
import
|
|
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
|
-
|
|
33776
|
-
|
|
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
|
|
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 =
|
|
33794
|
-
const isGitRepo = await
|
|
33795
|
-
const hasClaudeConfig = await
|
|
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
|
|
34174
|
+
return path10.join(process.env.HOME || process.env.USERPROFILE || "~", ".claude");
|
|
33800
34175
|
}
|
|
33801
34176
|
|
|
33802
34177
|
// src/utils/file-installer.ts
|
|
33803
|
-
var
|
|
33804
|
-
import
|
|
34178
|
+
var import_fs_extra10 = __toESM(require_lib4(), 1);
|
|
34179
|
+
import path12 from "path";
|
|
33805
34180
|
|
|
33806
34181
|
// src/utils/github.ts
|
|
33807
|
-
var
|
|
33808
|
-
import
|
|
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
|
|
33857
|
-
await
|
|
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
|
|
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 =
|
|
33881
|
-
if (!await
|
|
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
|
|
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 =
|
|
33900
|
-
if (!await
|
|
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
|
|
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 =
|
|
33946
|
-
const hookFilePath =
|
|
33947
|
-
const settingsPath =
|
|
33948
|
-
if (await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
34029
|
-
import
|
|
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
|
|
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(
|
|
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 =
|
|
34127
|
-
const commandFilePath =
|
|
34128
|
-
if (await
|
|
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
|
|
34336
|
-
import
|
|
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 ?
|
|
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
|
|
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 =
|
|
34349
|
-
await
|
|
34350
|
-
const success = await downloadDirectoryFromGitHub("scripts/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 =
|
|
34735
|
+
const settingsPath = path15.join(claudeDir, "settings.json");
|
|
34361
34736
|
let settings = {};
|
|
34362
34737
|
try {
|
|
34363
|
-
const existingSettings = await
|
|
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 ${
|
|
34744
|
+
command: `bun ${path15.join(claudeDir, "scripts/statusline/src/index.ts")}`,
|
|
34370
34745
|
padding: 0
|
|
34371
34746
|
};
|
|
34372
|
-
await
|
|
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
|
|
35037
|
-
import
|
|
35411
|
+
import os12 from "os";
|
|
35412
|
+
import path18 from "path";
|
|
35038
35413
|
|
|
35039
35414
|
// src/lib/pro-installer.ts
|
|
35040
|
-
var
|
|
35041
|
-
import
|
|
35042
|
-
import
|
|
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
|
|
35060
|
-
await
|
|
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
|
|
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 =
|
|
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 ||
|
|
35106
|
-
const tempDir =
|
|
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
|
|
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
|
|
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
|
|
35128
|
-
import
|
|
35129
|
-
import
|
|
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 =
|
|
35506
|
+
const platform = os11.platform();
|
|
35132
35507
|
if (platform === "win32") {
|
|
35133
|
-
const appData = process.env.APPDATA ||
|
|
35134
|
-
return
|
|
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 ||
|
|
35137
|
-
return
|
|
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
|
|
35516
|
+
return path17.join(getConfigDir(), "token.txt");
|
|
35142
35517
|
}
|
|
35143
35518
|
async function saveToken(githubToken) {
|
|
35144
35519
|
const tokenFile = getTokenFilePath();
|
|
35145
|
-
await
|
|
35146
|
-
await
|
|
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
|
|
35525
|
+
if (!await import_fs_extra15.default.pathExists(tokenFile)) {
|
|
35151
35526
|
return null;
|
|
35152
35527
|
}
|
|
35153
35528
|
try {
|
|
35154
|
-
const token = await
|
|
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:
|
|
35538
|
+
platform: os11.platform()
|
|
35164
35539
|
};
|
|
35165
35540
|
}
|
|
35166
35541
|
|
|
35167
35542
|
// src/commands/pro.ts
|
|
35168
|
-
var
|
|
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 =
|
|
35179
|
-
if (await
|
|
35180
|
-
const files = await
|
|
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 =
|
|
35187
|
-
if (await
|
|
35188
|
-
const files = await
|
|
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 =
|
|
35195
|
-
if (await
|
|
35196
|
-
const items = await
|
|
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
|
|
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 ?
|
|
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
|
|
35383
|
-
import
|
|
35757
|
+
import os13 from "os";
|
|
35758
|
+
import path20 from "path";
|
|
35384
35759
|
|
|
35385
35760
|
// src/lib/sync-utils.ts
|
|
35386
|
-
var
|
|
35387
|
-
import
|
|
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
|
|
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
|
|
35819
|
+
if (!await import_fs_extra17.default.pathExists(dir)) {
|
|
35445
35820
|
return files;
|
|
35446
35821
|
}
|
|
35447
|
-
const items = await
|
|
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 =
|
|
35452
|
-
const stat = await
|
|
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
|
|
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 =
|
|
35844
|
+
const fullPath = path19.join(dir, item);
|
|
35470
35845
|
const relativePath = `${basePath}/${item}`;
|
|
35471
|
-
const stat = await
|
|
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 =
|
|
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 =
|
|
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 =
|
|
35526
|
-
const stat = await
|
|
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 =
|
|
35932
|
+
const settingsPath = path19.join(claudeDir, "settings.json");
|
|
35558
35933
|
try {
|
|
35559
|
-
const content = await
|
|
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
|
|
35641
|
-
await
|
|
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 =
|
|
36026
|
+
const settingsPath = path19.join(claudeDir, "settings.json");
|
|
35652
36027
|
let settings = {};
|
|
35653
36028
|
try {
|
|
35654
|
-
const content = await
|
|
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] =
|
|
36048
|
+
settings.hooks[hook.hookType][existingIndex] = transformedHook;
|
|
35673
36049
|
} else {
|
|
35674
|
-
settings.hooks[hook.hookType].push(
|
|
36050
|
+
settings.hooks[hook.hookType].push(transformedHook);
|
|
35675
36051
|
}
|
|
35676
36052
|
success++;
|
|
35677
36053
|
} catch {
|
|
35678
36054
|
failed++;
|
|
35679
36055
|
}
|
|
35680
36056
|
}
|
|
35681
|
-
await
|
|
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 =
|
|
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
|
|
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 ?
|
|
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;
|