aiblueprint-cli 1.1.4 → 1.1.8
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/README.md +496 -41
- package/claude-code-config/agents/action.md +36 -0
- package/claude-code-config/agents/explore-codebase.md +6 -0
- package/claude-code-config/agents/explore-docs.md +88 -0
- package/claude-code-config/agents/fix-grammar.md +49 -0
- package/claude-code-config/agents/snipper.md +2 -0
- package/claude-code-config/agents/websearch.md +1 -0
- package/claude-code-config/commands/commit.md +1 -1
- package/claude-code-config/commands/debug.md +91 -0
- package/claude-code-config/commands/epct/code.md +171 -0
- package/claude-code-config/commands/epct/deploy.md +116 -0
- package/claude-code-config/commands/epct/explore.md +97 -0
- package/claude-code-config/commands/epct/plan.md +132 -0
- package/claude-code-config/commands/epct/tasks.md +206 -0
- package/claude-code-config/commands/explore.md +45 -0
- package/claude-code-config/commands/melvynx-plugin.md +1 -0
- package/claude-code-config/commands/oneshot.md +57 -0
- package/claude-code-config/hooks/hooks.json +15 -0
- package/claude-code-config/scripts/statusline/CLAUDE.md +178 -0
- package/claude-code-config/scripts/statusline/README.md +105 -0
- package/claude-code-config/scripts/statusline/biome.json +34 -0
- package/claude-code-config/scripts/statusline/bun.lockb +0 -0
- package/claude-code-config/scripts/statusline/data/.gitignore +5 -0
- package/claude-code-config/scripts/statusline/fixtures/test-input.json +25 -0
- package/claude-code-config/scripts/statusline/package.json +21 -0
- package/claude-code-config/scripts/statusline/src/commands/CLAUDE.md +3 -0
- package/claude-code-config/scripts/statusline/src/commands/spend-month.ts +60 -0
- package/claude-code-config/scripts/statusline/src/commands/spend-today.ts +42 -0
- package/claude-code-config/scripts/statusline/src/index.ts +141 -0
- package/claude-code-config/scripts/statusline/src/lib/context.ts +103 -0
- package/claude-code-config/scripts/statusline/src/lib/formatters.ts +218 -0
- package/claude-code-config/scripts/statusline/src/lib/git.ts +100 -0
- package/claude-code-config/scripts/statusline/src/lib/spend.ts +119 -0
- package/claude-code-config/scripts/statusline/src/lib/types.ts +25 -0
- package/claude-code-config/scripts/statusline/src/lib/usage-limits.ts +147 -0
- package/claude-code-config/scripts/statusline/statusline.config.ts +122 -0
- package/claude-code-config/scripts/statusline/test.ts +20 -0
- package/claude-code-config/scripts/statusline/tsconfig.json +27 -0
- package/dist/cli.js +722 -256
- package/package.json +1 -2
- package/claude-code-config/output-styles/assistant.md +0 -15
- package/claude-code-config/output-styles/honnest.md +0 -9
- package/claude-code-config/output-styles/senior-dev.md +0 -14
- package/claude-code-config/scripts/statusline-ccusage.sh +0 -188
- package/claude-code-config/scripts/statusline.readme.md +0 -194
- /package/claude-code-config/{hooks → scripts}/hook-post-file.ts +0 -0
package/dist/cli.js
CHANGED
|
@@ -32360,10 +32360,9 @@ var inquirer = {
|
|
|
32360
32360
|
var lib_default = inquirer;
|
|
32361
32361
|
|
|
32362
32362
|
// src/commands/setup.ts
|
|
32363
|
-
var
|
|
32364
|
-
import
|
|
32365
|
-
import
|
|
32366
|
-
import { execSync } from "child_process";
|
|
32363
|
+
var import_fs_extra5 = __toESM(require_lib4(), 1);
|
|
32364
|
+
import path7 from "path";
|
|
32365
|
+
import os5 from "os";
|
|
32367
32366
|
|
|
32368
32367
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
32369
32368
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -32858,8 +32857,311 @@ var source_default = chalk;
|
|
|
32858
32857
|
// src/commands/setup.ts
|
|
32859
32858
|
import { fileURLToPath } from "url";
|
|
32860
32859
|
import { dirname } from "path";
|
|
32861
|
-
|
|
32862
|
-
|
|
32860
|
+
|
|
32861
|
+
// src/commands/setup/shell-shortcuts.ts
|
|
32862
|
+
var import_fs_extra = __toESM(require_lib4(), 1);
|
|
32863
|
+
import path2 from "path";
|
|
32864
|
+
import os3 from "os";
|
|
32865
|
+
async function setupShellShortcuts() {
|
|
32866
|
+
try {
|
|
32867
|
+
const platform = os3.platform();
|
|
32868
|
+
let shellConfigFile;
|
|
32869
|
+
if (platform === "darwin") {
|
|
32870
|
+
shellConfigFile = path2.join(os3.homedir(), ".zshenv");
|
|
32871
|
+
} else if (platform === "linux") {
|
|
32872
|
+
const shell = process.env.SHELL || "";
|
|
32873
|
+
if (shell.includes("zsh")) {
|
|
32874
|
+
shellConfigFile = path2.join(os3.homedir(), ".zshrc");
|
|
32875
|
+
} else {
|
|
32876
|
+
shellConfigFile = path2.join(os3.homedir(), ".bashrc");
|
|
32877
|
+
}
|
|
32878
|
+
} else {
|
|
32879
|
+
console.log(source_default.yellow("Shell shortcuts are only supported on macOS and Linux"));
|
|
32880
|
+
return;
|
|
32881
|
+
}
|
|
32882
|
+
const aliases = `
|
|
32883
|
+
# AIBlueprint Claude Code aliases
|
|
32884
|
+
alias cc="claude --dangerously-skip-permissions"
|
|
32885
|
+
alias ccc="claude --dangerously-skip-permissions -c"
|
|
32886
|
+
`;
|
|
32887
|
+
const existingContent = await import_fs_extra.default.readFile(shellConfigFile, "utf-8").catch(() => "");
|
|
32888
|
+
if (!existingContent.includes("AIBlueprint Claude Code aliases")) {
|
|
32889
|
+
await import_fs_extra.default.appendFile(shellConfigFile, aliases);
|
|
32890
|
+
}
|
|
32891
|
+
} catch (error) {
|
|
32892
|
+
console.error(source_default.red("Error setting up shell shortcuts:"), error);
|
|
32893
|
+
throw error;
|
|
32894
|
+
}
|
|
32895
|
+
}
|
|
32896
|
+
|
|
32897
|
+
// src/commands/setup/symlinks.ts
|
|
32898
|
+
var import_fs_extra2 = __toESM(require_lib4(), 1);
|
|
32899
|
+
import path3 from "path";
|
|
32900
|
+
import os4 from "os";
|
|
32901
|
+
async function getToolPaths(tool, customFolder) {
|
|
32902
|
+
let baseDir;
|
|
32903
|
+
switch (tool) {
|
|
32904
|
+
case "claude-code":
|
|
32905
|
+
baseDir = customFolder ? path3.resolve(customFolder) : path3.join(os4.homedir(), ".claude");
|
|
32906
|
+
return {
|
|
32907
|
+
baseDir,
|
|
32908
|
+
commandsPath: path3.join(baseDir, "commands"),
|
|
32909
|
+
agentsPath: path3.join(baseDir, "agents")
|
|
32910
|
+
};
|
|
32911
|
+
case "codex":
|
|
32912
|
+
baseDir = customFolder ? path3.resolve(customFolder) : path3.join(os4.homedir(), ".codex");
|
|
32913
|
+
return {
|
|
32914
|
+
baseDir,
|
|
32915
|
+
commandsPath: path3.join(baseDir, "prompts")
|
|
32916
|
+
};
|
|
32917
|
+
case "opencode":
|
|
32918
|
+
baseDir = customFolder ? path3.resolve(customFolder) : path3.join(os4.homedir(), ".config", "opencode");
|
|
32919
|
+
return {
|
|
32920
|
+
baseDir,
|
|
32921
|
+
commandsPath: path3.join(baseDir, "command")
|
|
32922
|
+
};
|
|
32923
|
+
case "factoryai":
|
|
32924
|
+
baseDir = customFolder ? path3.resolve(customFolder) : path3.join(os4.homedir(), ".factory");
|
|
32925
|
+
return {
|
|
32926
|
+
baseDir,
|
|
32927
|
+
commandsPath: path3.join(baseDir, "commands"),
|
|
32928
|
+
agentsPath: path3.join(baseDir, "droids")
|
|
32929
|
+
};
|
|
32930
|
+
default:
|
|
32931
|
+
throw new Error(`Unknown tool type: ${tool}`);
|
|
32932
|
+
}
|
|
32933
|
+
}
|
|
32934
|
+
async function createSymlink(sourcePath, targetPath, options = {}) {
|
|
32935
|
+
try {
|
|
32936
|
+
const sourceExists = await import_fs_extra2.default.pathExists(sourcePath);
|
|
32937
|
+
if (!sourceExists) {
|
|
32938
|
+
console.log(source_default.yellow(` Source path ${sourcePath} does not exist. Skipping symlink creation...`));
|
|
32939
|
+
return false;
|
|
32940
|
+
}
|
|
32941
|
+
const targetDir = path3.dirname(targetPath);
|
|
32942
|
+
await import_fs_extra2.default.ensureDir(targetDir);
|
|
32943
|
+
const targetExists = await import_fs_extra2.default.pathExists(targetPath);
|
|
32944
|
+
if (targetExists) {
|
|
32945
|
+
const stat = await import_fs_extra2.default.lstat(targetPath);
|
|
32946
|
+
if (stat.isSymbolicLink()) {
|
|
32947
|
+
await import_fs_extra2.default.remove(targetPath);
|
|
32948
|
+
} else {
|
|
32949
|
+
console.log(source_default.yellow(options.skipMessage || ` ${targetPath} already exists and is not a symlink. Skipping...`));
|
|
32950
|
+
return false;
|
|
32951
|
+
}
|
|
32952
|
+
}
|
|
32953
|
+
await import_fs_extra2.default.symlink(sourcePath, targetPath);
|
|
32954
|
+
return true;
|
|
32955
|
+
} catch (error) {
|
|
32956
|
+
console.error(source_default.red(options.errorPrefix || "Error creating symlink:"), error);
|
|
32957
|
+
throw error;
|
|
32958
|
+
}
|
|
32959
|
+
}
|
|
32960
|
+
async function setupCodexSymlink(claudeDir, customCodexFolder, customClaudeCodeFolder) {
|
|
32961
|
+
try {
|
|
32962
|
+
let codexDir;
|
|
32963
|
+
if (customCodexFolder) {
|
|
32964
|
+
codexDir = path3.resolve(customCodexFolder);
|
|
32965
|
+
} else if (customClaudeCodeFolder) {
|
|
32966
|
+
const parentDir = path3.dirname(claudeDir);
|
|
32967
|
+
codexDir = path3.join(parentDir, "codex");
|
|
32968
|
+
} else {
|
|
32969
|
+
codexDir = path3.join(os4.homedir(), ".codex");
|
|
32970
|
+
}
|
|
32971
|
+
const promptsPath = path3.join(codexDir, "prompts");
|
|
32972
|
+
const commandsPath = path3.join(claudeDir, "commands");
|
|
32973
|
+
await createSymlink(commandsPath, promptsPath, {
|
|
32974
|
+
skipMessage: " ~/.codex/prompts already exists and is not a symlink. Skipping...",
|
|
32975
|
+
errorPrefix: "Error setting up Codex symlink:"
|
|
32976
|
+
});
|
|
32977
|
+
} catch (error) {
|
|
32978
|
+
console.error(source_default.red("Error setting up Codex symlink:"), error);
|
|
32979
|
+
}
|
|
32980
|
+
}
|
|
32981
|
+
async function setupOpenCodeSymlink(claudeDir, customOpenCodeFolder, customClaudeCodeFolder) {
|
|
32982
|
+
try {
|
|
32983
|
+
let openCodeDir;
|
|
32984
|
+
if (customOpenCodeFolder) {
|
|
32985
|
+
openCodeDir = path3.resolve(customOpenCodeFolder);
|
|
32986
|
+
} else if (customClaudeCodeFolder) {
|
|
32987
|
+
const parentDir = path3.dirname(claudeDir);
|
|
32988
|
+
openCodeDir = path3.join(parentDir, ".opencode");
|
|
32989
|
+
} else {
|
|
32990
|
+
openCodeDir = path3.join(os4.homedir(), ".config", "opencode");
|
|
32991
|
+
}
|
|
32992
|
+
const commandPath = path3.join(openCodeDir, "command");
|
|
32993
|
+
const commandsPath = path3.join(claudeDir, "commands");
|
|
32994
|
+
await createSymlink(commandsPath, commandPath, {
|
|
32995
|
+
skipMessage: " ~/.config/opencode/command already exists and is not a symlink. Skipping...",
|
|
32996
|
+
errorPrefix: "Error setting up OpenCode symlink:"
|
|
32997
|
+
});
|
|
32998
|
+
} catch (error) {
|
|
32999
|
+
console.error(source_default.red("Error setting up OpenCode symlink:"), error);
|
|
33000
|
+
}
|
|
33001
|
+
}
|
|
33002
|
+
|
|
33003
|
+
// src/commands/setup/dependencies.ts
|
|
33004
|
+
import { execSync } from "child_process";
|
|
33005
|
+
import path4 from "path";
|
|
33006
|
+
async function checkAndInstallDependencies() {
|
|
33007
|
+
const checkCommand = (cmd) => {
|
|
33008
|
+
try {
|
|
33009
|
+
execSync(`which ${cmd}`, { stdio: "ignore" });
|
|
33010
|
+
return true;
|
|
33011
|
+
} catch {
|
|
33012
|
+
return false;
|
|
33013
|
+
}
|
|
33014
|
+
};
|
|
33015
|
+
if (!checkCommand("bun")) {
|
|
33016
|
+
console.log(source_default.yellow(`
|
|
33017
|
+
Installing bun...`));
|
|
33018
|
+
try {
|
|
33019
|
+
execSync("npm install -g bun", { stdio: "inherit" });
|
|
33020
|
+
} catch (error) {
|
|
33021
|
+
console.log(source_default.red(" Failed to install bun. Please install it manually: npm install -g bun"));
|
|
33022
|
+
}
|
|
33023
|
+
}
|
|
33024
|
+
if (!checkCommand("ccusage")) {
|
|
33025
|
+
console.log(source_default.yellow(`
|
|
33026
|
+
Installing ccusage...`));
|
|
33027
|
+
try {
|
|
33028
|
+
execSync("npm install -g ccusage", { stdio: "inherit" });
|
|
33029
|
+
} catch (error) {
|
|
33030
|
+
console.log(source_default.red(" Failed to install ccusage. Please install it manually: npm install -g ccusage"));
|
|
33031
|
+
}
|
|
33032
|
+
}
|
|
33033
|
+
}
|
|
33034
|
+
async function installStatuslineDependencies(claudeDir) {
|
|
33035
|
+
const statuslineDir = path4.join(claudeDir, "scripts/statusline");
|
|
33036
|
+
console.log(source_default.yellow(`
|
|
33037
|
+
Installing statusline dependencies...`));
|
|
33038
|
+
try {
|
|
33039
|
+
execSync("bun install", {
|
|
33040
|
+
cwd: statuslineDir,
|
|
33041
|
+
stdio: "inherit"
|
|
33042
|
+
});
|
|
33043
|
+
console.log(source_default.green(" ✓ Statusline dependencies installed"));
|
|
33044
|
+
} catch (error) {
|
|
33045
|
+
console.log(source_default.red(" Failed to install statusline dependencies. Please run 'bun install' manually in ~/.claude/scripts/statusline"));
|
|
33046
|
+
}
|
|
33047
|
+
}
|
|
33048
|
+
|
|
33049
|
+
// src/commands/setup/settings.ts
|
|
33050
|
+
var import_fs_extra3 = __toESM(require_lib4(), 1);
|
|
33051
|
+
import path5 from "path";
|
|
33052
|
+
async function updateSettings(options, claudeDir) {
|
|
33053
|
+
const settingsPath = path5.join(claudeDir, "settings.json");
|
|
33054
|
+
let settings = {};
|
|
33055
|
+
try {
|
|
33056
|
+
const existingSettings = await import_fs_extra3.default.readFile(settingsPath, "utf-8");
|
|
33057
|
+
settings = JSON.parse(existingSettings);
|
|
33058
|
+
} catch {
|
|
33059
|
+
}
|
|
33060
|
+
if (options.customStatusline) {
|
|
33061
|
+
if (settings.statusLine) {
|
|
33062
|
+
const confirmAnswer = await lib_default.prompt([
|
|
33063
|
+
{
|
|
33064
|
+
type: "confirm",
|
|
33065
|
+
name: "replace",
|
|
33066
|
+
message: "You already have a statusLine configuration. Replace it?"
|
|
33067
|
+
}
|
|
33068
|
+
]);
|
|
33069
|
+
if (!confirmAnswer.replace) {
|
|
33070
|
+
console.log(source_default.yellow(" Keeping existing statusLine configuration"));
|
|
33071
|
+
} else {
|
|
33072
|
+
settings.statusLine = {
|
|
33073
|
+
type: "command",
|
|
33074
|
+
command: `bun ${path5.join(claudeDir, "scripts/statusline/src/index.ts")}`,
|
|
33075
|
+
padding: 0
|
|
33076
|
+
};
|
|
33077
|
+
}
|
|
33078
|
+
} else {
|
|
33079
|
+
settings.statusLine = {
|
|
33080
|
+
type: "command",
|
|
33081
|
+
command: `bun ${path5.join(claudeDir, "scripts/statusline/src/index.ts")}`,
|
|
33082
|
+
padding: 0
|
|
33083
|
+
};
|
|
33084
|
+
}
|
|
33085
|
+
}
|
|
33086
|
+
if (!settings.hooks) {
|
|
33087
|
+
settings.hooks = {};
|
|
33088
|
+
}
|
|
33089
|
+
if (options.commandValidation) {
|
|
33090
|
+
if (!settings.hooks.PreToolUse) {
|
|
33091
|
+
settings.hooks.PreToolUse = [];
|
|
33092
|
+
}
|
|
33093
|
+
const bashHook = {
|
|
33094
|
+
matcher: "Bash",
|
|
33095
|
+
hooks: [
|
|
33096
|
+
{
|
|
33097
|
+
type: "command",
|
|
33098
|
+
command: `bun ${path5.join(claudeDir, "scripts/validate-command.js")}`
|
|
33099
|
+
}
|
|
33100
|
+
]
|
|
33101
|
+
};
|
|
33102
|
+
const existingBashHook = settings.hooks.PreToolUse.find((h) => h.matcher === "Bash");
|
|
33103
|
+
if (!existingBashHook) {
|
|
33104
|
+
settings.hooks.PreToolUse.push(bashHook);
|
|
33105
|
+
}
|
|
33106
|
+
}
|
|
33107
|
+
if (options.notificationSounds) {
|
|
33108
|
+
if (!settings.hooks.Stop) {
|
|
33109
|
+
settings.hooks.Stop = [];
|
|
33110
|
+
}
|
|
33111
|
+
const stopHook = {
|
|
33112
|
+
matcher: "",
|
|
33113
|
+
hooks: [
|
|
33114
|
+
{
|
|
33115
|
+
type: "command",
|
|
33116
|
+
command: `afplay -v 0.1 ${path5.join(claudeDir, "song/finish.mp3")}`
|
|
33117
|
+
}
|
|
33118
|
+
]
|
|
33119
|
+
};
|
|
33120
|
+
const existingStopHook = settings.hooks.Stop.find((h) => h.hooks?.some((hook) => hook.command?.includes("finish.mp3")));
|
|
33121
|
+
if (!existingStopHook) {
|
|
33122
|
+
settings.hooks.Stop.push(stopHook);
|
|
33123
|
+
}
|
|
33124
|
+
if (!settings.hooks.Notification) {
|
|
33125
|
+
settings.hooks.Notification = [];
|
|
33126
|
+
}
|
|
33127
|
+
const notificationHook = {
|
|
33128
|
+
matcher: "",
|
|
33129
|
+
hooks: [
|
|
33130
|
+
{
|
|
33131
|
+
type: "command",
|
|
33132
|
+
command: `afplay -v 0.1 ${path5.join(claudeDir, "song/need-human.mp3")}`
|
|
33133
|
+
}
|
|
33134
|
+
]
|
|
33135
|
+
};
|
|
33136
|
+
const existingNotificationHook = settings.hooks.Notification.find((h) => h.hooks?.some((hook) => hook.command?.includes("need-human.mp3")));
|
|
33137
|
+
if (!existingNotificationHook) {
|
|
33138
|
+
settings.hooks.Notification.push(notificationHook);
|
|
33139
|
+
}
|
|
33140
|
+
}
|
|
33141
|
+
if (options.postEditTypeScript) {
|
|
33142
|
+
if (!settings.hooks.PostToolUse) {
|
|
33143
|
+
settings.hooks.PostToolUse = [];
|
|
33144
|
+
}
|
|
33145
|
+
const postEditHook = {
|
|
33146
|
+
matcher: "Edit|Write|MultiEdit",
|
|
33147
|
+
hooks: [
|
|
33148
|
+
{
|
|
33149
|
+
type: "command",
|
|
33150
|
+
command: `bun ${path5.join(claudeDir, "scripts/hook-post-file.ts")}`
|
|
33151
|
+
}
|
|
33152
|
+
]
|
|
33153
|
+
};
|
|
33154
|
+
const existingPostEditHook = settings.hooks.PostToolUse.find((h) => h.matcher === "Edit|Write|MultiEdit" && h.hooks?.some((hook) => hook.command?.includes("hook-post-file.ts")));
|
|
33155
|
+
if (!existingPostEditHook) {
|
|
33156
|
+
settings.hooks.PostToolUse.push(postEditHook);
|
|
33157
|
+
}
|
|
33158
|
+
}
|
|
33159
|
+
await import_fs_extra3.default.writeJson(settingsPath, settings, { spaces: 2 });
|
|
33160
|
+
}
|
|
33161
|
+
|
|
33162
|
+
// src/commands/setup/utils.ts
|
|
33163
|
+
var import_fs_extra4 = __toESM(require_lib4(), 1);
|
|
33164
|
+
import path6 from "path";
|
|
32863
33165
|
|
|
32864
33166
|
class SimpleSpinner {
|
|
32865
33167
|
message = "";
|
|
@@ -32880,8 +33182,8 @@ async function downloadFromGitHub(relativePath, targetPath) {
|
|
|
32880
33182
|
return false;
|
|
32881
33183
|
}
|
|
32882
33184
|
const content = await response.arrayBuffer();
|
|
32883
|
-
await
|
|
32884
|
-
await
|
|
33185
|
+
await import_fs_extra4.default.ensureDir(path6.dirname(targetPath));
|
|
33186
|
+
await import_fs_extra4.default.writeFile(targetPath, Buffer.from(content));
|
|
32885
33187
|
return true;
|
|
32886
33188
|
} catch (error) {
|
|
32887
33189
|
return false;
|
|
@@ -32898,10 +33200,10 @@ async function downloadDirectoryFromGitHub(dirPath, targetDir) {
|
|
|
32898
33200
|
if (!Array.isArray(files)) {
|
|
32899
33201
|
return false;
|
|
32900
33202
|
}
|
|
32901
|
-
await
|
|
33203
|
+
await import_fs_extra4.default.ensureDir(targetDir);
|
|
32902
33204
|
for (const file of files) {
|
|
32903
33205
|
const relativePath = `${dirPath}/${file.name}`;
|
|
32904
|
-
const targetPath =
|
|
33206
|
+
const targetPath = path6.join(targetDir, file.name);
|
|
32905
33207
|
if (file.type === "file") {
|
|
32906
33208
|
await downloadFromGitHub(relativePath, targetPath);
|
|
32907
33209
|
} else if (file.type === "dir") {
|
|
@@ -32913,7 +33215,18 @@ async function downloadDirectoryFromGitHub(dirPath, targetDir) {
|
|
|
32913
33215
|
return false;
|
|
32914
33216
|
}
|
|
32915
33217
|
}
|
|
32916
|
-
|
|
33218
|
+
|
|
33219
|
+
// src/commands/setup.ts
|
|
33220
|
+
var __filename2 = fileURLToPath(import.meta.url);
|
|
33221
|
+
var __dirname2 = dirname(__filename2);
|
|
33222
|
+
var GITHUB_RAW_BASE2 = "https://raw.githubusercontent.com/Melvynx/aiblueprint-cli/main/claude-code-config";
|
|
33223
|
+
async function setupCommand(params = {}) {
|
|
33224
|
+
const {
|
|
33225
|
+
claudeCodeFolder: customClaudeCodeFolder,
|
|
33226
|
+
codexFolder: customCodexFolder,
|
|
33227
|
+
openCodeFolder: customOpenCodeFolder,
|
|
33228
|
+
skipInteractive
|
|
33229
|
+
} = params;
|
|
32917
33230
|
try {
|
|
32918
33231
|
console.log(source_default.blue.bold(`
|
|
32919
33232
|
\uD83D\uDE80 AIBlueprint Claude Code Setup
|
|
@@ -32921,23 +33234,72 @@ async function setupCommand(customFolder, skipInteractive) {
|
|
|
32921
33234
|
console.log(source_default.bgBlue(" Setting up your Claude Code environment "));
|
|
32922
33235
|
let features;
|
|
32923
33236
|
if (skipInteractive) {
|
|
32924
|
-
features = [
|
|
33237
|
+
features = [
|
|
33238
|
+
"shellShortcuts",
|
|
33239
|
+
"commandValidation",
|
|
33240
|
+
"customStatusline",
|
|
33241
|
+
"aiblueprintCommands",
|
|
33242
|
+
"aiblueprintAgents",
|
|
33243
|
+
"notificationSounds",
|
|
33244
|
+
"codexSymlink",
|
|
33245
|
+
"openCodeSymlink"
|
|
33246
|
+
];
|
|
32925
33247
|
console.log(source_default.green("✓ Installing all features (--skip mode)"));
|
|
32926
33248
|
} else {
|
|
32927
|
-
const answers = await lib_default.prompt([
|
|
32928
|
-
|
|
32929
|
-
|
|
32930
|
-
|
|
32931
|
-
|
|
32932
|
-
|
|
32933
|
-
|
|
32934
|
-
|
|
32935
|
-
|
|
32936
|
-
|
|
32937
|
-
|
|
32938
|
-
|
|
32939
|
-
|
|
32940
|
-
|
|
33249
|
+
const answers = await lib_default.prompt([
|
|
33250
|
+
{
|
|
33251
|
+
type: "checkbox",
|
|
33252
|
+
name: "features",
|
|
33253
|
+
message: "Which features would you like to install?",
|
|
33254
|
+
choices: [
|
|
33255
|
+
{
|
|
33256
|
+
value: "shellShortcuts",
|
|
33257
|
+
name: "Shell shortcuts (cc, ccc aliases) - Quick access to Claude Code",
|
|
33258
|
+
checked: true
|
|
33259
|
+
},
|
|
33260
|
+
{
|
|
33261
|
+
value: "commandValidation",
|
|
33262
|
+
name: "Command validation - Security hook for bash commands",
|
|
33263
|
+
checked: true
|
|
33264
|
+
},
|
|
33265
|
+
{
|
|
33266
|
+
value: "customStatusline",
|
|
33267
|
+
name: "Custom statusline - Shows git, costs, tokens info",
|
|
33268
|
+
checked: true
|
|
33269
|
+
},
|
|
33270
|
+
{
|
|
33271
|
+
value: "aiblueprintCommands",
|
|
33272
|
+
name: "AIBlueprint commands - Pre-configured command templates",
|
|
33273
|
+
checked: true
|
|
33274
|
+
},
|
|
33275
|
+
{
|
|
33276
|
+
value: "aiblueprintAgents",
|
|
33277
|
+
name: "AIBlueprint agents - Specialized AI agents",
|
|
33278
|
+
checked: true
|
|
33279
|
+
},
|
|
33280
|
+
{
|
|
33281
|
+
value: "notificationSounds",
|
|
33282
|
+
name: "Notification sounds - Audio alerts for events",
|
|
33283
|
+
checked: true
|
|
33284
|
+
},
|
|
33285
|
+
{
|
|
33286
|
+
value: "postEditTypeScript",
|
|
33287
|
+
name: "Post-edit TypeScript hook - Auto-format and lint TypeScript files",
|
|
33288
|
+
checked: false
|
|
33289
|
+
},
|
|
33290
|
+
{
|
|
33291
|
+
value: "codexSymlink",
|
|
33292
|
+
name: "Codex symlink - Link commands to ~/.codex/prompts",
|
|
33293
|
+
checked: false
|
|
33294
|
+
},
|
|
33295
|
+
{
|
|
33296
|
+
value: "openCodeSymlink",
|
|
33297
|
+
name: "OpenCode symlink - Link commands to ~/.config/opencode/command",
|
|
33298
|
+
checked: false
|
|
33299
|
+
}
|
|
33300
|
+
]
|
|
33301
|
+
}
|
|
33302
|
+
]);
|
|
32941
33303
|
features = answers.features;
|
|
32942
33304
|
if (!features || features.length === 0) {
|
|
32943
33305
|
console.log(source_default.yellow("Setup cancelled - no features selected"));
|
|
@@ -32950,16 +33312,18 @@ async function setupCommand(customFolder, skipInteractive) {
|
|
|
32950
33312
|
customStatusline: features.includes("customStatusline"),
|
|
32951
33313
|
aiblueprintCommands: features.includes("aiblueprintCommands"),
|
|
32952
33314
|
aiblueprintAgents: features.includes("aiblueprintAgents"),
|
|
32953
|
-
|
|
32954
|
-
|
|
33315
|
+
notificationSounds: features.includes("notificationSounds"),
|
|
33316
|
+
postEditTypeScript: features.includes("postEditTypeScript"),
|
|
33317
|
+
codexSymlink: features.includes("codexSymlink"),
|
|
33318
|
+
openCodeSymlink: features.includes("openCodeSymlink")
|
|
32955
33319
|
};
|
|
32956
33320
|
const s = new SimpleSpinner;
|
|
32957
|
-
const claudeDir =
|
|
33321
|
+
const claudeDir = customClaudeCodeFolder ? path7.resolve(customClaudeCodeFolder) : path7.join(os5.homedir(), ".claude");
|
|
32958
33322
|
console.log(source_default.gray(`Installing to: ${claudeDir}`));
|
|
32959
|
-
await
|
|
33323
|
+
await import_fs_extra5.default.ensureDir(claudeDir);
|
|
32960
33324
|
let useGitHub = true;
|
|
32961
33325
|
let sourceDir;
|
|
32962
|
-
const testUrl = `${
|
|
33326
|
+
const testUrl = `${GITHUB_RAW_BASE2}/scripts/validate-command.js`;
|
|
32963
33327
|
try {
|
|
32964
33328
|
const testResponse = await fetch(testUrl);
|
|
32965
33329
|
useGitHub = testResponse.ok;
|
|
@@ -32969,14 +33333,14 @@ async function setupCommand(customFolder, skipInteractive) {
|
|
|
32969
33333
|
if (!useGitHub) {
|
|
32970
33334
|
const currentDir = process.cwd();
|
|
32971
33335
|
const possiblePaths = [
|
|
32972
|
-
|
|
32973
|
-
|
|
32974
|
-
|
|
32975
|
-
|
|
33336
|
+
path7.join(currentDir, "claude-code-config"),
|
|
33337
|
+
path7.join(__dirname2, "../../claude-code-config"),
|
|
33338
|
+
path7.join(__dirname2, "../claude-code-config"),
|
|
33339
|
+
path7.join(path7.dirname(process.argv[1]), "../claude-code-config")
|
|
32976
33340
|
];
|
|
32977
33341
|
sourceDir = possiblePaths.find((p) => {
|
|
32978
33342
|
try {
|
|
32979
|
-
return
|
|
33343
|
+
return import_fs_extra5.default.existsSync(p);
|
|
32980
33344
|
} catch {
|
|
32981
33345
|
return false;
|
|
32982
33346
|
}
|
|
@@ -32993,56 +33357,66 @@ async function setupCommand(customFolder, skipInteractive) {
|
|
|
32993
33357
|
await setupShellShortcuts();
|
|
32994
33358
|
s.stop("Shell shortcuts configured");
|
|
32995
33359
|
}
|
|
32996
|
-
if (options.commandValidation || options.customStatusline || options.notificationSounds) {
|
|
33360
|
+
if (options.commandValidation || options.customStatusline || options.notificationSounds || options.postEditTypeScript) {
|
|
32997
33361
|
s.start("Setting up scripts");
|
|
32998
33362
|
if (useGitHub) {
|
|
32999
|
-
const scriptsDir =
|
|
33000
|
-
await
|
|
33001
|
-
const scriptFiles = [
|
|
33363
|
+
const scriptsDir = path7.join(claudeDir, "scripts");
|
|
33364
|
+
await import_fs_extra5.default.ensureDir(scriptsDir);
|
|
33365
|
+
const scriptFiles = [
|
|
33366
|
+
"validate-command.js",
|
|
33367
|
+
"validate-command.readme.md"
|
|
33368
|
+
];
|
|
33369
|
+
if (options.postEditTypeScript) {
|
|
33370
|
+
scriptFiles.push("hook-post-file.ts");
|
|
33371
|
+
}
|
|
33002
33372
|
for (const file of scriptFiles) {
|
|
33003
|
-
await downloadFromGitHub(`scripts/${file}`,
|
|
33373
|
+
await downloadFromGitHub(`scripts/${file}`, path7.join(scriptsDir, file));
|
|
33374
|
+
}
|
|
33375
|
+
if (options.customStatusline) {
|
|
33376
|
+
await downloadDirectoryFromGitHub("scripts/statusline", path7.join(scriptsDir, "statusline"));
|
|
33004
33377
|
}
|
|
33005
33378
|
} else {
|
|
33006
|
-
await
|
|
33379
|
+
await import_fs_extra5.default.copy(path7.join(sourceDir, "scripts"), path7.join(claudeDir, "scripts"), { overwrite: true });
|
|
33007
33380
|
}
|
|
33008
33381
|
s.stop("Scripts installed");
|
|
33009
33382
|
}
|
|
33010
33383
|
if (options.aiblueprintCommands) {
|
|
33011
33384
|
s.start("Setting up AIBlueprint commands");
|
|
33012
33385
|
if (useGitHub) {
|
|
33013
|
-
await downloadDirectoryFromGitHub("commands",
|
|
33386
|
+
await downloadDirectoryFromGitHub("commands", path7.join(claudeDir, "commands"));
|
|
33014
33387
|
} else {
|
|
33015
|
-
await
|
|
33388
|
+
await import_fs_extra5.default.copy(path7.join(sourceDir, "commands"), path7.join(claudeDir, "commands"), { overwrite: true });
|
|
33016
33389
|
}
|
|
33017
33390
|
s.stop("Commands installed");
|
|
33018
33391
|
}
|
|
33392
|
+
if (options.codexSymlink && options.aiblueprintCommands) {
|
|
33393
|
+
s.start("Setting up Codex symlink");
|
|
33394
|
+
await setupCodexSymlink(claudeDir, customCodexFolder, customClaudeCodeFolder);
|
|
33395
|
+
s.stop("Codex symlink configured");
|
|
33396
|
+
}
|
|
33397
|
+
if (options.openCodeSymlink && options.aiblueprintCommands) {
|
|
33398
|
+
s.start("Setting up OpenCode symlink");
|
|
33399
|
+
await setupOpenCodeSymlink(claudeDir, customOpenCodeFolder, customClaudeCodeFolder);
|
|
33400
|
+
s.stop("OpenCode symlink configured");
|
|
33401
|
+
}
|
|
33019
33402
|
if (options.aiblueprintAgents) {
|
|
33020
33403
|
s.start("Setting up AIBlueprint agents");
|
|
33021
33404
|
if (useGitHub) {
|
|
33022
|
-
await downloadDirectoryFromGitHub("agents",
|
|
33405
|
+
await downloadDirectoryFromGitHub("agents", path7.join(claudeDir, "agents"));
|
|
33023
33406
|
} else {
|
|
33024
|
-
await
|
|
33407
|
+
await import_fs_extra5.default.copy(path7.join(sourceDir, "agents"), path7.join(claudeDir, "agents"), { overwrite: true });
|
|
33025
33408
|
}
|
|
33026
33409
|
s.stop("Agents installed");
|
|
33027
33410
|
}
|
|
33028
|
-
if (options.outputStyles) {
|
|
33029
|
-
s.start("Setting up output styles");
|
|
33030
|
-
if (useGitHub) {
|
|
33031
|
-
await downloadDirectoryFromGitHub("output-styles", path2.join(claudeDir, "output-styles"));
|
|
33032
|
-
} else {
|
|
33033
|
-
await import_fs_extra.default.copy(path2.join(sourceDir, "output-styles"), path2.join(claudeDir, "output-styles"), { overwrite: true });
|
|
33034
|
-
}
|
|
33035
|
-
s.stop("Output styles installed");
|
|
33036
|
-
}
|
|
33037
33411
|
if (options.notificationSounds) {
|
|
33038
33412
|
s.start("Setting up notification sounds");
|
|
33039
33413
|
if (useGitHub) {
|
|
33040
|
-
const songDir =
|
|
33041
|
-
await
|
|
33042
|
-
await downloadFromGitHub("song/finish.mp3",
|
|
33043
|
-
await downloadFromGitHub("song/need-human.mp3",
|
|
33414
|
+
const songDir = path7.join(claudeDir, "song");
|
|
33415
|
+
await import_fs_extra5.default.ensureDir(songDir);
|
|
33416
|
+
await downloadFromGitHub("song/finish.mp3", path7.join(songDir, "finish.mp3"));
|
|
33417
|
+
await downloadFromGitHub("song/need-human.mp3", path7.join(songDir, "need-human.mp3"));
|
|
33044
33418
|
} else {
|
|
33045
|
-
await
|
|
33419
|
+
await import_fs_extra5.default.copy(path7.join(sourceDir, "song"), path7.join(claudeDir, "song"), { overwrite: true });
|
|
33046
33420
|
}
|
|
33047
33421
|
s.stop("Notification sounds installed");
|
|
33048
33422
|
}
|
|
@@ -33050,6 +33424,9 @@ async function setupCommand(customFolder, skipInteractive) {
|
|
|
33050
33424
|
s.start("Checking dependencies");
|
|
33051
33425
|
await checkAndInstallDependencies();
|
|
33052
33426
|
s.stop("Dependencies checked");
|
|
33427
|
+
s.start("Installing statusline dependencies");
|
|
33428
|
+
await installStatuslineDependencies(claudeDir);
|
|
33429
|
+
s.stop("Statusline dependencies installed");
|
|
33053
33430
|
}
|
|
33054
33431
|
s.start("Updating settings.json");
|
|
33055
33432
|
await updateSettings(options, claudeDir);
|
|
@@ -33070,164 +33447,16 @@ Next steps:`));
|
|
|
33070
33447
|
process.exit(1);
|
|
33071
33448
|
}
|
|
33072
33449
|
}
|
|
33073
|
-
async function setupShellShortcuts() {
|
|
33074
|
-
try {
|
|
33075
|
-
const platform = os3.platform();
|
|
33076
|
-
let shellConfigFile;
|
|
33077
|
-
if (platform === "darwin") {
|
|
33078
|
-
shellConfigFile = path2.join(os3.homedir(), ".zshenv");
|
|
33079
|
-
} else if (platform === "linux") {
|
|
33080
|
-
const shell = process.env.SHELL || "";
|
|
33081
|
-
if (shell.includes("zsh")) {
|
|
33082
|
-
shellConfigFile = path2.join(os3.homedir(), ".zshrc");
|
|
33083
|
-
} else {
|
|
33084
|
-
shellConfigFile = path2.join(os3.homedir(), ".bashrc");
|
|
33085
|
-
}
|
|
33086
|
-
} else {
|
|
33087
|
-
console.log(source_default.yellow("Shell shortcuts are only supported on macOS and Linux"));
|
|
33088
|
-
return;
|
|
33089
|
-
}
|
|
33090
|
-
const aliases = `
|
|
33091
|
-
# AIBlueprint Claude Code aliases
|
|
33092
|
-
alias cc="claude --dangerously-skip-permissions"
|
|
33093
|
-
alias ccc="claude --dangerously-skip-permissions -c"
|
|
33094
|
-
`;
|
|
33095
|
-
const existingContent = await import_fs_extra.default.readFile(shellConfigFile, "utf-8").catch(() => "");
|
|
33096
|
-
if (!existingContent.includes("AIBlueprint Claude Code aliases")) {
|
|
33097
|
-
await import_fs_extra.default.appendFile(shellConfigFile, aliases);
|
|
33098
|
-
}
|
|
33099
|
-
} catch (error) {
|
|
33100
|
-
console.error(source_default.red("Error setting up shell shortcuts:"), error);
|
|
33101
|
-
throw error;
|
|
33102
|
-
}
|
|
33103
|
-
}
|
|
33104
|
-
async function checkAndInstallDependencies() {
|
|
33105
|
-
const checkCommand = (cmd) => {
|
|
33106
|
-
try {
|
|
33107
|
-
execSync(`which ${cmd}`, { stdio: "ignore" });
|
|
33108
|
-
return true;
|
|
33109
|
-
} catch {
|
|
33110
|
-
return false;
|
|
33111
|
-
}
|
|
33112
|
-
};
|
|
33113
|
-
if (!checkCommand("bun")) {
|
|
33114
|
-
console.log(source_default.yellow(`
|
|
33115
|
-
Installing bun...`));
|
|
33116
|
-
try {
|
|
33117
|
-
execSync("npm install -g bun", { stdio: "inherit" });
|
|
33118
|
-
} catch (error) {
|
|
33119
|
-
console.log(source_default.red(" Failed to install bun. Please install it manually: npm install -g bun"));
|
|
33120
|
-
}
|
|
33121
|
-
}
|
|
33122
|
-
if (!checkCommand("ccusage")) {
|
|
33123
|
-
console.log(source_default.yellow(`
|
|
33124
|
-
Installing ccusage...`));
|
|
33125
|
-
try {
|
|
33126
|
-
execSync("npm install -g ccusage", { stdio: "inherit" });
|
|
33127
|
-
} catch (error) {
|
|
33128
|
-
console.log(source_default.red(" Failed to install ccusage. Please install it manually: npm install -g ccusage"));
|
|
33129
|
-
}
|
|
33130
|
-
}
|
|
33131
|
-
}
|
|
33132
|
-
async function updateSettings(options, claudeDir) {
|
|
33133
|
-
const settingsPath = path2.join(claudeDir, "settings.json");
|
|
33134
|
-
let settings = {};
|
|
33135
|
-
try {
|
|
33136
|
-
const existingSettings = await import_fs_extra.default.readFile(settingsPath, "utf-8");
|
|
33137
|
-
settings = JSON.parse(existingSettings);
|
|
33138
|
-
} catch {
|
|
33139
|
-
}
|
|
33140
|
-
if (options.customStatusline) {
|
|
33141
|
-
if (settings.statusLine) {
|
|
33142
|
-
const confirmAnswer = await lib_default.prompt([{
|
|
33143
|
-
type: "confirm",
|
|
33144
|
-
name: "replace",
|
|
33145
|
-
message: "You already have a statusLine configuration. Replace it?"
|
|
33146
|
-
}]);
|
|
33147
|
-
if (!confirmAnswer.replace) {
|
|
33148
|
-
console.log(source_default.yellow(" Keeping existing statusLine configuration"));
|
|
33149
|
-
} else {
|
|
33150
|
-
settings.statusLine = {
|
|
33151
|
-
type: "command",
|
|
33152
|
-
command: `bash ${path2.join(claudeDir, "scripts/statusline-ccusage.sh")}`,
|
|
33153
|
-
padding: 0
|
|
33154
|
-
};
|
|
33155
|
-
}
|
|
33156
|
-
} else {
|
|
33157
|
-
settings.statusLine = {
|
|
33158
|
-
type: "command",
|
|
33159
|
-
command: `bash ${path2.join(claudeDir, "scripts/statusline-ccusage.sh")}`,
|
|
33160
|
-
padding: 0
|
|
33161
|
-
};
|
|
33162
|
-
}
|
|
33163
|
-
}
|
|
33164
|
-
if (!settings.hooks) {
|
|
33165
|
-
settings.hooks = {};
|
|
33166
|
-
}
|
|
33167
|
-
if (options.commandValidation) {
|
|
33168
|
-
if (!settings.hooks.PreToolUse) {
|
|
33169
|
-
settings.hooks.PreToolUse = [];
|
|
33170
|
-
}
|
|
33171
|
-
const bashHook = {
|
|
33172
|
-
matcher: "Bash",
|
|
33173
|
-
hooks: [
|
|
33174
|
-
{
|
|
33175
|
-
type: "command",
|
|
33176
|
-
command: `bun ${path2.join(claudeDir, "scripts/validate-command.js")}`
|
|
33177
|
-
}
|
|
33178
|
-
]
|
|
33179
|
-
};
|
|
33180
|
-
const existingBashHook = settings.hooks.PreToolUse.find((h) => h.matcher === "Bash");
|
|
33181
|
-
if (!existingBashHook) {
|
|
33182
|
-
settings.hooks.PreToolUse.push(bashHook);
|
|
33183
|
-
}
|
|
33184
|
-
}
|
|
33185
|
-
if (options.notificationSounds) {
|
|
33186
|
-
if (!settings.hooks.Stop) {
|
|
33187
|
-
settings.hooks.Stop = [];
|
|
33188
|
-
}
|
|
33189
|
-
const stopHook = {
|
|
33190
|
-
matcher: "",
|
|
33191
|
-
hooks: [
|
|
33192
|
-
{
|
|
33193
|
-
type: "command",
|
|
33194
|
-
command: `afplay -v 0.1 ${path2.join(claudeDir, "song/finish.mp3")}`
|
|
33195
|
-
}
|
|
33196
|
-
]
|
|
33197
|
-
};
|
|
33198
|
-
const existingStopHook = settings.hooks.Stop.find((h) => h.hooks?.some((hook) => hook.command?.includes("finish.mp3")));
|
|
33199
|
-
if (!existingStopHook) {
|
|
33200
|
-
settings.hooks.Stop.push(stopHook);
|
|
33201
|
-
}
|
|
33202
|
-
if (!settings.hooks.Notification) {
|
|
33203
|
-
settings.hooks.Notification = [];
|
|
33204
|
-
}
|
|
33205
|
-
const notificationHook = {
|
|
33206
|
-
matcher: "",
|
|
33207
|
-
hooks: [
|
|
33208
|
-
{
|
|
33209
|
-
type: "command",
|
|
33210
|
-
command: `afplay -v 0.1 ${path2.join(claudeDir, "song/need-human.mp3")}`
|
|
33211
|
-
}
|
|
33212
|
-
]
|
|
33213
|
-
};
|
|
33214
|
-
const existingNotificationHook = settings.hooks.Notification.find((h) => h.hooks?.some((hook) => hook.command?.includes("need-human.mp3")));
|
|
33215
|
-
if (!existingNotificationHook) {
|
|
33216
|
-
settings.hooks.Notification.push(notificationHook);
|
|
33217
|
-
}
|
|
33218
|
-
}
|
|
33219
|
-
await import_fs_extra.default.writeJson(settingsPath, settings, { spaces: 2 });
|
|
33220
|
-
}
|
|
33221
33450
|
|
|
33222
33451
|
// src/commands/addHook.ts
|
|
33223
|
-
var
|
|
33224
|
-
import
|
|
33452
|
+
var import_fs_extra9 = __toESM(require_lib4(), 1);
|
|
33453
|
+
import path11 from "path";
|
|
33225
33454
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
33226
33455
|
import { dirname as dirname3 } from "path";
|
|
33227
33456
|
|
|
33228
33457
|
// src/utils/claude-config.ts
|
|
33229
|
-
var
|
|
33230
|
-
import
|
|
33458
|
+
var import_fs_extra6 = __toESM(require_lib4(), 1);
|
|
33459
|
+
import path8 from "path";
|
|
33231
33460
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
33232
33461
|
import { dirname as dirname2 } from "path";
|
|
33233
33462
|
var __filename3 = fileURLToPath2(import.meta.url);
|
|
@@ -33258,14 +33487,14 @@ function parseYamlFrontmatter(content) {
|
|
|
33258
33487
|
}
|
|
33259
33488
|
function getLocalConfigPaths(subDir) {
|
|
33260
33489
|
return [
|
|
33261
|
-
|
|
33262
|
-
|
|
33490
|
+
path8.join(__dirname3, `../claude-code-config/${subDir}`),
|
|
33491
|
+
path8.join(__dirname3, `../../claude-code-config/${subDir}`)
|
|
33263
33492
|
];
|
|
33264
33493
|
}
|
|
33265
33494
|
async function findLocalConfigDir(subDir) {
|
|
33266
33495
|
const possiblePaths = getLocalConfigPaths(subDir);
|
|
33267
33496
|
for (const testPath of possiblePaths) {
|
|
33268
|
-
if (await
|
|
33497
|
+
if (await import_fs_extra6.default.pathExists(testPath)) {
|
|
33269
33498
|
return testPath;
|
|
33270
33499
|
}
|
|
33271
33500
|
}
|
|
@@ -33276,26 +33505,26 @@ async function getTargetDirectory(options) {
|
|
|
33276
33505
|
return options.folder;
|
|
33277
33506
|
}
|
|
33278
33507
|
const cwd = process.cwd();
|
|
33279
|
-
const localClaudeDir =
|
|
33280
|
-
const isGitRepo = await
|
|
33281
|
-
const hasClaudeConfig = await
|
|
33508
|
+
const localClaudeDir = path8.join(cwd, ".claude");
|
|
33509
|
+
const isGitRepo = await import_fs_extra6.default.pathExists(path8.join(cwd, ".git"));
|
|
33510
|
+
const hasClaudeConfig = await import_fs_extra6.default.pathExists(localClaudeDir);
|
|
33282
33511
|
if (isGitRepo || hasClaudeConfig) {
|
|
33283
33512
|
return localClaudeDir;
|
|
33284
33513
|
}
|
|
33285
|
-
return
|
|
33514
|
+
return path8.join(process.env.HOME || process.env.USERPROFILE || "~", ".claude");
|
|
33286
33515
|
}
|
|
33287
33516
|
|
|
33288
33517
|
// src/utils/file-installer.ts
|
|
33289
|
-
var
|
|
33290
|
-
import
|
|
33518
|
+
var import_fs_extra8 = __toESM(require_lib4(), 1);
|
|
33519
|
+
import path10 from "path";
|
|
33291
33520
|
|
|
33292
33521
|
// src/utils/github.ts
|
|
33293
|
-
var
|
|
33294
|
-
import
|
|
33295
|
-
var
|
|
33522
|
+
var import_fs_extra7 = __toESM(require_lib4(), 1);
|
|
33523
|
+
import path9 from "path";
|
|
33524
|
+
var GITHUB_RAW_BASE3 = "https://raw.githubusercontent.com/Melvynx/aiblueprint-cli/main/claude-code-config";
|
|
33296
33525
|
async function downloadFromGitHub2(relativePath) {
|
|
33297
33526
|
try {
|
|
33298
|
-
const url = `${
|
|
33527
|
+
const url = `${GITHUB_RAW_BASE3}/${relativePath}`;
|
|
33299
33528
|
const response = await fetch(url);
|
|
33300
33529
|
if (!response.ok) {
|
|
33301
33530
|
return null;
|
|
@@ -33320,7 +33549,7 @@ async function listFilesFromGitHub(dirPath) {
|
|
|
33320
33549
|
}
|
|
33321
33550
|
async function isGitHubAvailable() {
|
|
33322
33551
|
try {
|
|
33323
|
-
const testUrl = `${
|
|
33552
|
+
const testUrl = `${GITHUB_RAW_BASE3}/commands/commit.md`;
|
|
33324
33553
|
const testResponse = await fetch(testUrl);
|
|
33325
33554
|
return testResponse.ok;
|
|
33326
33555
|
} catch {
|
|
@@ -33330,8 +33559,8 @@ async function isGitHubAvailable() {
|
|
|
33330
33559
|
async function downloadAndWriteFile(relativePath, targetPath) {
|
|
33331
33560
|
const content = await downloadFromGitHub2(relativePath);
|
|
33332
33561
|
if (content) {
|
|
33333
|
-
await
|
|
33334
|
-
await
|
|
33562
|
+
await import_fs_extra7.default.ensureDir(path9.dirname(targetPath));
|
|
33563
|
+
await import_fs_extra7.default.writeFile(targetPath, content);
|
|
33335
33564
|
return true;
|
|
33336
33565
|
}
|
|
33337
33566
|
return false;
|
|
@@ -33340,7 +33569,7 @@ async function downloadAndWriteFile(relativePath, targetPath) {
|
|
|
33340
33569
|
// src/utils/file-installer.ts
|
|
33341
33570
|
async function installFileWithGitHubFallback(options) {
|
|
33342
33571
|
const { sourceDir, targetPath, fileName } = options;
|
|
33343
|
-
await
|
|
33572
|
+
await import_fs_extra8.default.ensureDir(path10.dirname(targetPath));
|
|
33344
33573
|
const useGitHub = options.useGitHub ?? await isGitHubAvailable();
|
|
33345
33574
|
if (useGitHub) {
|
|
33346
33575
|
const relativePath = `${sourceDir}/${fileName}`;
|
|
@@ -33354,11 +33583,11 @@ async function installFileWithGitHubFallback(options) {
|
|
|
33354
33583
|
if (!localConfigDir) {
|
|
33355
33584
|
throw new Error(`Neither GitHub nor local ${sourceDir} directory found`);
|
|
33356
33585
|
}
|
|
33357
|
-
const localFilePath =
|
|
33358
|
-
if (!await
|
|
33586
|
+
const localFilePath = path10.join(localConfigDir, fileName);
|
|
33587
|
+
if (!await import_fs_extra8.default.pathExists(localFilePath)) {
|
|
33359
33588
|
throw new Error(`File not found: ${fileName}`);
|
|
33360
33589
|
}
|
|
33361
|
-
await
|
|
33590
|
+
await import_fs_extra8.default.copy(localFilePath, targetPath);
|
|
33362
33591
|
}
|
|
33363
33592
|
async function getFileContentWithGitHubFallback(sourceDir, fileName) {
|
|
33364
33593
|
const useGitHub = await isGitHubAvailable();
|
|
@@ -33373,11 +33602,11 @@ async function getFileContentWithGitHubFallback(sourceDir, fileName) {
|
|
|
33373
33602
|
if (!localConfigDir) {
|
|
33374
33603
|
throw new Error(`Neither GitHub nor local ${sourceDir} directory found`);
|
|
33375
33604
|
}
|
|
33376
|
-
const localFilePath =
|
|
33377
|
-
if (!await
|
|
33605
|
+
const localFilePath = path10.join(localConfigDir, fileName);
|
|
33606
|
+
if (!await import_fs_extra8.default.pathExists(localFilePath)) {
|
|
33378
33607
|
throw new Error(`File not found: ${fileName}`);
|
|
33379
33608
|
}
|
|
33380
|
-
return await
|
|
33609
|
+
return await import_fs_extra8.default.readFile(localFilePath, "utf-8");
|
|
33381
33610
|
}
|
|
33382
33611
|
|
|
33383
33612
|
// src/commands/addHook.ts
|
|
@@ -33399,6 +33628,8 @@ var supportedHooks = {
|
|
|
33399
33628
|
name: "Post Edit TypeScript Hook",
|
|
33400
33629
|
description: "Runs Prettier, ESLint, and TypeScript checks after editing TypeScript files",
|
|
33401
33630
|
hookFile: "hook-post-file.ts",
|
|
33631
|
+
sourceDir: "scripts",
|
|
33632
|
+
targetDir: "scripts",
|
|
33402
33633
|
event: "PostToolUse",
|
|
33403
33634
|
matcher: "Edit|Write|MultiEdit"
|
|
33404
33635
|
}
|
|
@@ -33417,10 +33648,10 @@ async function addHookCommand(hookType, options) {
|
|
|
33417
33648
|
const s = new SimpleSpinner2;
|
|
33418
33649
|
const targetDir = await getTargetDirectory(options);
|
|
33419
33650
|
const claudeDir = targetDir;
|
|
33420
|
-
const
|
|
33421
|
-
const hookFilePath =
|
|
33422
|
-
const settingsPath =
|
|
33423
|
-
if (await
|
|
33651
|
+
const targetHookDir = path11.join(claudeDir, hook.targetDir || "hooks");
|
|
33652
|
+
const hookFilePath = path11.join(targetHookDir, hook.hookFile);
|
|
33653
|
+
const settingsPath = path11.join(claudeDir, "settings.json");
|
|
33654
|
+
if (await import_fs_extra9.default.pathExists(hookFilePath)) {
|
|
33424
33655
|
const overwriteAnswer = await lib_default.prompt([{
|
|
33425
33656
|
type: "confirm",
|
|
33426
33657
|
name: "overwrite",
|
|
@@ -33433,18 +33664,18 @@ async function addHookCommand(hookType, options) {
|
|
|
33433
33664
|
}
|
|
33434
33665
|
try {
|
|
33435
33666
|
s.start("Installing hook...");
|
|
33436
|
-
await
|
|
33667
|
+
await import_fs_extra9.default.ensureDir(targetHookDir);
|
|
33437
33668
|
await installFileWithGitHubFallback({
|
|
33438
|
-
sourceDir: "hooks",
|
|
33669
|
+
sourceDir: hook.sourceDir || "hooks",
|
|
33439
33670
|
targetPath: hookFilePath,
|
|
33440
33671
|
fileName: hook.hookFile
|
|
33441
33672
|
});
|
|
33442
|
-
await
|
|
33673
|
+
await import_fs_extra9.default.chmod(hookFilePath, 493);
|
|
33443
33674
|
s.stop("Hook file installed");
|
|
33444
33675
|
s.start("Updating settings.json...");
|
|
33445
33676
|
let settings = {};
|
|
33446
33677
|
try {
|
|
33447
|
-
const existingSettings = await
|
|
33678
|
+
const existingSettings = await import_fs_extra9.default.readFile(settingsPath, "utf-8");
|
|
33448
33679
|
settings = JSON.parse(existingSettings);
|
|
33449
33680
|
} catch {
|
|
33450
33681
|
settings = {};
|
|
@@ -33460,7 +33691,7 @@ async function addHookCommand(hookType, options) {
|
|
|
33460
33691
|
hooks: [
|
|
33461
33692
|
{
|
|
33462
33693
|
type: "command",
|
|
33463
|
-
command: `bun $CLAUDE_PROJECT_DIR/.claude
|
|
33694
|
+
command: `bun $CLAUDE_PROJECT_DIR/.claude/${hook.targetDir || "hooks"}/${hook.hookFile}`
|
|
33464
33695
|
}
|
|
33465
33696
|
]
|
|
33466
33697
|
};
|
|
@@ -33481,7 +33712,7 @@ async function addHookCommand(hookType, options) {
|
|
|
33481
33712
|
} else {
|
|
33482
33713
|
settings.hooks[hook.event].push(newHook);
|
|
33483
33714
|
}
|
|
33484
|
-
await
|
|
33715
|
+
await import_fs_extra9.default.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
33485
33716
|
s.stop("Settings updated");
|
|
33486
33717
|
console.log(source_default.green("✨ Hook installed successfully!"));
|
|
33487
33718
|
console.log(source_default.gray(`
|
|
@@ -33500,8 +33731,8 @@ The hook will run automatically when you edit TypeScript files with Claude Code.
|
|
|
33500
33731
|
}
|
|
33501
33732
|
|
|
33502
33733
|
// src/commands/addCommand.ts
|
|
33503
|
-
var
|
|
33504
|
-
import
|
|
33734
|
+
var import_fs_extra10 = __toESM(require_lib4(), 1);
|
|
33735
|
+
import path12 from "path";
|
|
33505
33736
|
class SimpleSpinner3 {
|
|
33506
33737
|
message = "";
|
|
33507
33738
|
start(message) {
|
|
@@ -33518,12 +33749,13 @@ async function discoverAvailableCommands() {
|
|
|
33518
33749
|
let mdFiles = [];
|
|
33519
33750
|
if (useGitHub) {
|
|
33520
33751
|
mdFiles = (await listFilesFromGitHub("commands")).filter((file) => file.endsWith(".md"));
|
|
33521
|
-
}
|
|
33752
|
+
}
|
|
33753
|
+
if (mdFiles.length === 0) {
|
|
33522
33754
|
const commandsDir = await findLocalConfigDir("commands");
|
|
33523
33755
|
if (!commandsDir) {
|
|
33524
33756
|
throw new Error("Commands directory not found");
|
|
33525
33757
|
}
|
|
33526
|
-
const files = await
|
|
33758
|
+
const files = await import_fs_extra10.default.readdir(commandsDir);
|
|
33527
33759
|
mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
33528
33760
|
}
|
|
33529
33761
|
for (const file of mdFiles) {
|
|
@@ -33584,9 +33816,9 @@ async function addCommandCommand(commandName, options = {}) {
|
|
|
33584
33816
|
if (options.folder) {
|
|
33585
33817
|
console.log(source_default.gray(`Using custom folder: ${targetDir}`));
|
|
33586
33818
|
}
|
|
33587
|
-
const commandsDir =
|
|
33588
|
-
const commandFilePath =
|
|
33589
|
-
if (await
|
|
33819
|
+
const commandsDir = path12.join(targetDir, "commands");
|
|
33820
|
+
const commandFilePath = path12.join(commandsDir, command.commandFile);
|
|
33821
|
+
if (await import_fs_extra10.default.pathExists(commandFilePath)) {
|
|
33590
33822
|
const overwriteAnswer = await lib_default.prompt([{
|
|
33591
33823
|
type: "confirm",
|
|
33592
33824
|
name: "overwrite",
|
|
@@ -33626,6 +33858,219 @@ The command will be available immediately in Claude Code.`));
|
|
|
33626
33858
|
}
|
|
33627
33859
|
}
|
|
33628
33860
|
|
|
33861
|
+
// src/commands/symlink.ts
|
|
33862
|
+
var TOOLS = [
|
|
33863
|
+
{
|
|
33864
|
+
name: "Claude Code",
|
|
33865
|
+
value: "claude-code",
|
|
33866
|
+
supportsCommands: true,
|
|
33867
|
+
supportsAgents: true
|
|
33868
|
+
},
|
|
33869
|
+
{
|
|
33870
|
+
name: "Codex",
|
|
33871
|
+
value: "codex",
|
|
33872
|
+
supportsCommands: true,
|
|
33873
|
+
supportsAgents: false
|
|
33874
|
+
},
|
|
33875
|
+
{
|
|
33876
|
+
name: "OpenCode",
|
|
33877
|
+
value: "opencode",
|
|
33878
|
+
supportsCommands: true,
|
|
33879
|
+
supportsAgents: false
|
|
33880
|
+
},
|
|
33881
|
+
{
|
|
33882
|
+
name: "FactoryAI",
|
|
33883
|
+
value: "factoryai",
|
|
33884
|
+
supportsCommands: true,
|
|
33885
|
+
supportsAgents: true
|
|
33886
|
+
}
|
|
33887
|
+
];
|
|
33888
|
+
async function symlinkCommand(params = {}) {
|
|
33889
|
+
try {
|
|
33890
|
+
console.log(source_default.blue.bold(`
|
|
33891
|
+
\uD83D\uDD17 Symlink Manager
|
|
33892
|
+
`));
|
|
33893
|
+
console.log(source_default.gray("Create symlinks between different CLI tool configurations"));
|
|
33894
|
+
const sourceAnswer = await lib_default.prompt([
|
|
33895
|
+
{
|
|
33896
|
+
type: "list",
|
|
33897
|
+
name: "source",
|
|
33898
|
+
message: "Select source tool:",
|
|
33899
|
+
choices: TOOLS.map((tool) => ({
|
|
33900
|
+
name: tool.name,
|
|
33901
|
+
value: tool.value
|
|
33902
|
+
}))
|
|
33903
|
+
}
|
|
33904
|
+
]);
|
|
33905
|
+
const sourceTool = sourceAnswer.source;
|
|
33906
|
+
const sourceConfig = TOOLS.find((t) => t.value === sourceTool);
|
|
33907
|
+
const contentTypeChoices = [];
|
|
33908
|
+
if (sourceConfig.supportsCommands) {
|
|
33909
|
+
contentTypeChoices.push({ name: "Commands only", value: "commands" });
|
|
33910
|
+
}
|
|
33911
|
+
if (sourceConfig.supportsAgents) {
|
|
33912
|
+
contentTypeChoices.push({ name: "Agents only", value: "agents" });
|
|
33913
|
+
}
|
|
33914
|
+
if (sourceConfig.supportsCommands && sourceConfig.supportsAgents) {
|
|
33915
|
+
contentTypeChoices.push({ name: "Both", value: "both" });
|
|
33916
|
+
}
|
|
33917
|
+
if (contentTypeChoices.length === 0) {
|
|
33918
|
+
console.log(source_default.red(`
|
|
33919
|
+
❌ Error: ${sourceConfig.name} doesn't support any syncable content`));
|
|
33920
|
+
process.exit(1);
|
|
33921
|
+
}
|
|
33922
|
+
const contentAnswer = await lib_default.prompt([
|
|
33923
|
+
{
|
|
33924
|
+
type: "list",
|
|
33925
|
+
name: "contentType",
|
|
33926
|
+
message: "What would you like to sync?",
|
|
33927
|
+
choices: contentTypeChoices
|
|
33928
|
+
}
|
|
33929
|
+
]);
|
|
33930
|
+
const syncType = contentAnswer.contentType;
|
|
33931
|
+
const syncCommands = syncType === "commands" || syncType === "both";
|
|
33932
|
+
const syncAgents = syncType === "agents" || syncType === "both";
|
|
33933
|
+
const destinationChoices = [];
|
|
33934
|
+
for (const tool of TOOLS) {
|
|
33935
|
+
if (tool.value === sourceTool)
|
|
33936
|
+
continue;
|
|
33937
|
+
if (syncCommands && tool.supportsCommands) {
|
|
33938
|
+
destinationChoices.push({
|
|
33939
|
+
name: syncAgents ? `${tool.name} (commands)` : tool.name,
|
|
33940
|
+
value: `${tool.value}-commands`,
|
|
33941
|
+
tool: tool.value,
|
|
33942
|
+
contentType: "commands"
|
|
33943
|
+
});
|
|
33944
|
+
}
|
|
33945
|
+
if (syncAgents && tool.supportsAgents) {
|
|
33946
|
+
destinationChoices.push({
|
|
33947
|
+
name: syncCommands ? `${tool.name} (agents)` : tool.name,
|
|
33948
|
+
value: `${tool.value}-agents`,
|
|
33949
|
+
tool: tool.value,
|
|
33950
|
+
contentType: "agents"
|
|
33951
|
+
});
|
|
33952
|
+
}
|
|
33953
|
+
}
|
|
33954
|
+
if (destinationChoices.length === 0) {
|
|
33955
|
+
console.log(source_default.yellow(`
|
|
33956
|
+
⚠️ No compatible destination tools found for the selected sync type`));
|
|
33957
|
+
process.exit(0);
|
|
33958
|
+
}
|
|
33959
|
+
const destinationAnswer = await lib_default.prompt([
|
|
33960
|
+
{
|
|
33961
|
+
type: "checkbox",
|
|
33962
|
+
name: "destinations",
|
|
33963
|
+
message: "Select destination tools (multi-select):",
|
|
33964
|
+
choices: destinationChoices.map((choice) => ({
|
|
33965
|
+
name: choice.name,
|
|
33966
|
+
value: choice.value,
|
|
33967
|
+
checked: false
|
|
33968
|
+
})),
|
|
33969
|
+
validate: (answer) => {
|
|
33970
|
+
if (answer.length === 0) {
|
|
33971
|
+
return "Please select at least one destination";
|
|
33972
|
+
}
|
|
33973
|
+
return true;
|
|
33974
|
+
}
|
|
33975
|
+
}
|
|
33976
|
+
]);
|
|
33977
|
+
const selectedDestinations = destinationAnswer.destinations;
|
|
33978
|
+
const customFolders = {
|
|
33979
|
+
"claude-code": params.claudeCodeFolder,
|
|
33980
|
+
codex: params.codexFolder,
|
|
33981
|
+
opencode: params.openCodeFolder,
|
|
33982
|
+
factoryai: params.factoryAiFolder
|
|
33983
|
+
};
|
|
33984
|
+
const sourcePaths = await getToolPaths(sourceTool, customFolders[sourceTool]);
|
|
33985
|
+
console.log(source_default.blue(`
|
|
33986
|
+
\uD83D\uDCE6 Creating symlinks...
|
|
33987
|
+
`));
|
|
33988
|
+
let successCount = 0;
|
|
33989
|
+
let skipCount = 0;
|
|
33990
|
+
for (const destValue of selectedDestinations) {
|
|
33991
|
+
const destChoice = destinationChoices.find((c) => c.value === destValue);
|
|
33992
|
+
const destPaths = await getToolPaths(destChoice.tool, customFolders[destChoice.tool]);
|
|
33993
|
+
let sourcePath;
|
|
33994
|
+
let targetPath;
|
|
33995
|
+
if (destChoice.contentType === "commands") {
|
|
33996
|
+
sourcePath = sourcePaths.commandsPath;
|
|
33997
|
+
targetPath = destPaths.commandsPath;
|
|
33998
|
+
} else {
|
|
33999
|
+
sourcePath = sourcePaths.agentsPath;
|
|
34000
|
+
targetPath = destPaths.agentsPath;
|
|
34001
|
+
}
|
|
34002
|
+
const toolName = TOOLS.find((t) => t.value === destChoice.tool)?.name || destChoice.tool;
|
|
34003
|
+
const contentLabel = destChoice.contentType === "commands" ? "commands" : "agents";
|
|
34004
|
+
try {
|
|
34005
|
+
const success = await createSymlink(sourcePath, targetPath, {
|
|
34006
|
+
skipMessage: source_default.yellow(` ⚠️ ${toolName} ${contentLabel} path already exists and is not a symlink. Skipping...`)
|
|
34007
|
+
});
|
|
34008
|
+
if (success) {
|
|
34009
|
+
console.log(source_default.green(` ✓ ${toolName} (${contentLabel}) symlink created`));
|
|
34010
|
+
successCount++;
|
|
34011
|
+
} else {
|
|
34012
|
+
skipCount++;
|
|
34013
|
+
}
|
|
34014
|
+
} catch (error) {
|
|
34015
|
+
console.error(source_default.red(` ✗ Failed to create ${toolName} (${contentLabel}) symlink:`), error);
|
|
34016
|
+
}
|
|
34017
|
+
}
|
|
34018
|
+
console.log(source_default.green(`
|
|
34019
|
+
✨ Symlink setup complete! ${successCount} created, ${skipCount} skipped`));
|
|
34020
|
+
} catch (error) {
|
|
34021
|
+
console.error(source_default.red(`
|
|
34022
|
+
❌ Symlink setup failed:`), error);
|
|
34023
|
+
process.exit(1);
|
|
34024
|
+
}
|
|
34025
|
+
}
|
|
34026
|
+
|
|
34027
|
+
// src/commands/statusline.ts
|
|
34028
|
+
var import_fs_extra11 = __toESM(require_lib4(), 1);
|
|
34029
|
+
import path13 from "path";
|
|
34030
|
+
import { homedir } from "os";
|
|
34031
|
+
async function statuslineCommand(options) {
|
|
34032
|
+
const claudeDir = options.folder ? path13.resolve(options.folder) : path13.join(homedir(), ".claude");
|
|
34033
|
+
console.log(source_default.blue("\uD83D\uDE80 Setting up AIBlueprint Statusline..."));
|
|
34034
|
+
console.log(source_default.gray(` Target: ${claudeDir}
|
|
34035
|
+
`));
|
|
34036
|
+
await import_fs_extra11.default.ensureDir(claudeDir);
|
|
34037
|
+
console.log(source_default.cyan("\uD83D\uDCE6 Checking dependencies..."));
|
|
34038
|
+
await checkAndInstallDependencies();
|
|
34039
|
+
console.log(source_default.cyan(`
|
|
34040
|
+
\uD83D\uDCE5 Downloading statusline files...`));
|
|
34041
|
+
const scriptsDir = path13.join(claudeDir, "scripts");
|
|
34042
|
+
await import_fs_extra11.default.ensureDir(scriptsDir);
|
|
34043
|
+
const success = await downloadDirectoryFromGitHub("scripts/statusline", path13.join(scriptsDir, "statusline"));
|
|
34044
|
+
if (!success) {
|
|
34045
|
+
console.log(source_default.red(" Failed to download statusline files from GitHub"));
|
|
34046
|
+
return;
|
|
34047
|
+
}
|
|
34048
|
+
console.log(source_default.cyan(`
|
|
34049
|
+
\uD83D\uDCE6 Installing statusline dependencies...`));
|
|
34050
|
+
await installStatuslineDependencies(claudeDir);
|
|
34051
|
+
console.log(source_default.cyan(`
|
|
34052
|
+
⚙️ Configuring settings.json...`));
|
|
34053
|
+
const settingsPath = path13.join(claudeDir, "settings.json");
|
|
34054
|
+
let settings = {};
|
|
34055
|
+
try {
|
|
34056
|
+
const existingSettings = await import_fs_extra11.default.readFile(settingsPath, "utf-8");
|
|
34057
|
+
settings = JSON.parse(existingSettings);
|
|
34058
|
+
} catch {
|
|
34059
|
+
}
|
|
34060
|
+
settings.statusLine = {
|
|
34061
|
+
type: "command",
|
|
34062
|
+
command: `bun ${path13.join(claudeDir, "scripts/statusline/src/index.ts")}`,
|
|
34063
|
+
padding: 0
|
|
34064
|
+
};
|
|
34065
|
+
await import_fs_extra11.default.writeJson(settingsPath, settings, { spaces: 2 });
|
|
34066
|
+
console.log(source_default.green(`
|
|
34067
|
+
✅ Statusline setup complete!`));
|
|
34068
|
+
console.log(source_default.gray(`
|
|
34069
|
+
Your Claude Code statusline is now configured.`));
|
|
34070
|
+
console.log(source_default.gray(`Restart Claude Code to see the changes.
|
|
34071
|
+
`));
|
|
34072
|
+
}
|
|
34073
|
+
|
|
33629
34074
|
// src/cli.ts
|
|
33630
34075
|
import { readFileSync as readFileSync2 } from "fs";
|
|
33631
34076
|
import { dirname as dirname4, join } from "path";
|
|
@@ -33634,10 +34079,15 @@ var __dirname5 = dirname4(fileURLToPath4(import.meta.url));
|
|
|
33634
34079
|
var packageJson = JSON.parse(readFileSync2(join(__dirname5, "../package.json"), "utf8"));
|
|
33635
34080
|
var program2 = new Command;
|
|
33636
34081
|
program2.name("aiblueprint").description("AIBlueprint CLI for setting up Claude Code configurations").version(packageJson.version);
|
|
33637
|
-
var claudeCodeCmd = program2.command("claude-code").description("Claude Code configuration commands").option("-f, --folder <path>", "Specify custom folder path (default: ~/.claude)").option("-s, --skip", "Skip interactive prompts and install all features");
|
|
34082
|
+
var claudeCodeCmd = program2.command("claude-code").description("Claude Code configuration commands").option("-f, --folder <path>", "Specify custom Claude Code folder path (default: ~/.claude) - alias for --claudeCodeFolder").option("--claudeCodeFolder <path>", "Specify custom Claude Code folder path (default: ~/.claude)").option("--codexFolder <path>", "Specify custom Codex folder path (default: ~/.codex)").option("--openCodeFolder <path>", "Specify custom OpenCode folder path (default: ~/.config/opencode)").option("--factoryAiFolder <path>", "Specify custom FactoryAI folder path (default: ~/.factory)").option("-s, --skip", "Skip interactive prompts and install all features");
|
|
33638
34083
|
claudeCodeCmd.command("setup").description("Setup Claude Code configuration with AIBlueprint defaults").action((options, command) => {
|
|
33639
34084
|
const parentOptions = command.parent.opts();
|
|
33640
|
-
setupCommand(
|
|
34085
|
+
setupCommand({
|
|
34086
|
+
claudeCodeFolder: parentOptions.claudeCodeFolder || parentOptions.folder,
|
|
34087
|
+
codexFolder: parentOptions.codexFolder,
|
|
34088
|
+
openCodeFolder: parentOptions.openCodeFolder,
|
|
34089
|
+
skipInteractive: parentOptions.skip
|
|
34090
|
+
});
|
|
33641
34091
|
});
|
|
33642
34092
|
var addCmd = claudeCodeCmd.command("add").description(`Add components to your Claude Code configuration
|
|
33643
34093
|
` + `Examples:
|
|
@@ -33646,11 +34096,27 @@ var addCmd = claudeCodeCmd.command("add").description(`Add components to your Cl
|
|
|
33646
34096
|
` + " aiblueprint claude-code add commands commit");
|
|
33647
34097
|
addCmd.command("hook <type>").description("Add a hook to your Claude Code configuration. Available types: post-edit-typescript").action((type, options, command) => {
|
|
33648
34098
|
const parentOptions = command.parent.parent.opts();
|
|
33649
|
-
|
|
34099
|
+
const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
|
|
34100
|
+
addHookCommand(type, { folder: claudeCodeFolder });
|
|
33650
34101
|
});
|
|
33651
34102
|
addCmd.command("commands [command-name]").description("Install a Claude Code command or list all available commands (use without argument to list)").action((commandName, options, command) => {
|
|
33652
34103
|
const parentOptions = command.parent.parent.opts();
|
|
33653
|
-
|
|
34104
|
+
const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
|
|
34105
|
+
addCommandCommand(commandName, { folder: claudeCodeFolder });
|
|
34106
|
+
});
|
|
34107
|
+
claudeCodeCmd.command("symlink").description("Create symlinks between different CLI tools (Claude Code, Codex, OpenCode, FactoryAI)").action((options, command) => {
|
|
34108
|
+
const parentOptions = command.parent.opts();
|
|
34109
|
+
symlinkCommand({
|
|
34110
|
+
claudeCodeFolder: parentOptions.claudeCodeFolder || parentOptions.folder,
|
|
34111
|
+
codexFolder: parentOptions.codexFolder,
|
|
34112
|
+
openCodeFolder: parentOptions.openCodeFolder,
|
|
34113
|
+
factoryAiFolder: parentOptions.factoryAiFolder
|
|
34114
|
+
});
|
|
34115
|
+
});
|
|
34116
|
+
claudeCodeCmd.command("statusline").description("Setup custom statusline with git status, costs, and token usage").action((options, command) => {
|
|
34117
|
+
const parentOptions = command.parent.opts();
|
|
34118
|
+
const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
|
|
34119
|
+
statuslineCommand({ folder: claudeCodeFolder });
|
|
33654
34120
|
});
|
|
33655
34121
|
program2.parse(process.argv);
|
|
33656
34122
|
if (!process.argv.slice(2).length) {
|