aiblueprint-cli 1.4.45 → 1.4.48
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/{claude-code-config → ai-config}/.claude-plugin/plugin.json +2 -2
- package/ai-config/scripts/CLAUDE.md +31 -0
- package/{claude-code-config → ai-config}/scripts/package.json +1 -8
- package/ai-config/skills/codex-environment/SKILL.md +182 -0
- package/dist/cli.js +933 -767
- package/package.json +2 -2
- package/claude-code-config/hooks/hooks.json +0 -15
- package/claude-code-config/scripts/CLAUDE.md +0 -50
- package/claude-code-config/scripts/command-validator/CLAUDE.md +0 -112
- package/claude-code-config/scripts/command-validator/README.md +0 -147
- package/claude-code-config/scripts/command-validator/src/__tests__/validator.test.ts +0 -99
- package/claude-code-config/scripts/command-validator/src/cli.ts +0 -120
- package/claude-code-config/scripts/command-validator/src/lib/security-rules.ts +0 -174
- package/claude-code-config/scripts/command-validator/src/lib/types.ts +0 -34
- package/claude-code-config/scripts/command-validator/src/lib/validator.ts +0 -90
- package/claude-code-config/song/finish.mp3 +0 -0
- package/claude-code-config/song/need-human.mp3 +0 -0
- /package/{claude-code-config → ai-config}/agents/action.md +0 -0
- /package/{claude-code-config → ai-config}/agents/explore-codebase.md +0 -0
- /package/{claude-code-config → ai-config}/agents/explore-docs.md +0 -0
- /package/{claude-code-config → ai-config}/agents/websearch.md +0 -0
- /package/{claude-code-config → ai-config}/scripts/.claude/commands/fix-on-my-computer.md +0 -0
- /package/{claude-code-config → ai-config}/scripts/biome.json +0 -0
- /package/{claude-code-config → ai-config}/scripts/bun.lockb +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/CLAUDE.md +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/README.md +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/__tests__/context.test.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/__tests__/formatters.test.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/__tests__/statusline.test.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/data/.gitignore +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/data/.gitkeep +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/defaults.json +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/docs/ARCHITECTURE.md +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/fixtures/mock-transcript.jsonl +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/fixtures/test-input.json +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/index.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/lib/config-types.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/lib/config.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/lib/context.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/lib/formatters.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/lib/git.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/lib/menu-factories.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/lib/presets.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/lib/render-pure.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/lib/types.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/lib/utils.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/src/tests/spend-v2.test.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/statusline.config.json +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/test-with-fixtures.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/test.ts +0 -0
- /package/{claude-code-config → ai-config}/scripts/statusline/tsconfig.json +0 -0
- /package/{claude-code-config → ai-config}/scripts/tsconfig.json +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/scripts/setup-templates.sh +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/scripts/update-progress.sh +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/steps/step-00-init.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/steps/step-00b-branch.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/steps/step-00b-economy.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/steps/step-00b-interactive.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/steps/step-01-analyze.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/steps/step-02-plan.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/steps/step-03-execute.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/steps/step-04-validate.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/templates/00-context.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/templates/01-analyze.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/templates/02-plan.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/templates/03-execute.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/templates/04-validate.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/templates/README.md +0 -0
- /package/{claude-code-config → ai-config}/skills/apex/templates/step-complete.md +0 -0
- /package/{claude-code-config → ai-config}/skills/claude-memory/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/claude-memory/references/comprehensive-example.md +0 -0
- /package/{claude-code-config → ai-config}/skills/claude-memory/references/optimize-guide.md +0 -0
- /package/{claude-code-config → ai-config}/skills/claude-memory/references/project-patterns.md +0 -0
- /package/{claude-code-config → ai-config}/skills/claude-memory/references/prompting-techniques.md +0 -0
- /package/{claude-code-config → ai-config}/skills/claude-memory/references/rules-directory-guide.md +0 -0
- /package/{claude-code-config → ai-config}/skills/claude-memory/references/section-templates.md +0 -0
- /package/{claude-code-config → ai-config}/skills/commit/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/create-pr/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/fix-errors/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/fix-grammar/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/fix-pr-comments/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/merge/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/oneshot/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/references/anthropic-best-practices.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/references/anti-patterns.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/references/clarity-principles.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/references/context-management.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/references/few-shot-patterns.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/references/openai-best-practices.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/references/prompt-templates.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/references/reasoning-techniques.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/references/system-prompt-patterns.md +0 -0
- /package/{claude-code-config → ai-config}/skills/prompt-creator/references/xml-structure.md +0 -0
- /package/{claude-code-config → ai-config}/skills/ralph-loop/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/ralph-loop/scripts/setup.sh +0 -0
- /package/{claude-code-config → ai-config}/skills/ralph-loop/steps/step-00-init.md +0 -0
- /package/{claude-code-config → ai-config}/skills/ralph-loop/steps/step-01-interactive-prd.md +0 -0
- /package/{claude-code-config → ai-config}/skills/ralph-loop/steps/step-02-create-stories.md +0 -0
- /package/{claude-code-config → ai-config}/skills/ralph-loop/steps/step-03-finish.md +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/LICENSE.txt +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/package.json +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/references/output-patterns.md +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/references/progressive-disclosure-patterns.md +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/references/prompting-integration.md +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/references/real-world-examples.md +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/references/script-patterns.md +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/references/workflows.md +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/references/xml-tag-guide.md +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/scripts/init-skill.ts +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/scripts/package-skill.ts +0 -0
- /package/{claude-code-config → ai-config}/skills/skill-creator/scripts/validate.ts +0 -0
- /package/{claude-code-config → ai-config}/skills/subagent-creator/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/subagent-creator/references/context-management.md +0 -0
- /package/{claude-code-config → ai-config}/skills/subagent-creator/references/debugging-agents.md +0 -0
- /package/{claude-code-config → ai-config}/skills/subagent-creator/references/error-handling-and-recovery.md +0 -0
- /package/{claude-code-config → ai-config}/skills/subagent-creator/references/evaluation-and-testing.md +0 -0
- /package/{claude-code-config → ai-config}/skills/subagent-creator/references/orchestration-patterns.md +0 -0
- /package/{claude-code-config → ai-config}/skills/subagent-creator/references/subagents.md +0 -0
- /package/{claude-code-config → ai-config}/skills/subagent-creator/references/writing-subagent-prompts.md +0 -0
- /package/{claude-code-config → ai-config}/skills/ultrathink/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/SKILL.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/scripts/setup-templates.sh +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/scripts/update-progress.sh +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/steps/step-00-init.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/steps/step-00b-branch.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/steps/step-00b-economy.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/steps/step-00b-interactive.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/steps/step-01-analyze.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/steps/step-02-plan.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/steps/step-03-execute.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/steps/step-04-validate.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/templates/00-context.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/templates/01-analyze.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/templates/02-plan.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/templates/03-execute.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/templates/04-validate.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/templates/README.md +0 -0
- /package/{claude-code-config → ai-config}/skills/workflow-apex-free/templates/step-complete.md +0 -0
package/dist/cli.js
CHANGED
|
@@ -32263,9 +32263,9 @@ var inquirer = {
|
|
|
32263
32263
|
var lib_default = inquirer;
|
|
32264
32264
|
|
|
32265
32265
|
// src/commands/setup.ts
|
|
32266
|
-
var
|
|
32267
|
-
import
|
|
32268
|
-
import
|
|
32266
|
+
var import_fs_extra8 = __toESM(require_lib4(), 1);
|
|
32267
|
+
import path11 from "path";
|
|
32268
|
+
import os11 from "os";
|
|
32269
32269
|
|
|
32270
32270
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
32271
32271
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -33039,13 +33039,232 @@ async function installStatuslineDependencies(claudeDir) {
|
|
|
33039
33039
|
}
|
|
33040
33040
|
|
|
33041
33041
|
// src/commands/setup/settings.ts
|
|
33042
|
+
var import_fs_extra3 = __toESM(require_lib4(), 1);
|
|
33043
|
+
import path5 from "path";
|
|
33044
|
+
function toPosixPath(p) {
|
|
33045
|
+
return p.replace(/\\/g, "/");
|
|
33046
|
+
}
|
|
33047
|
+
async function hasExistingStatusLine(claudeDir) {
|
|
33048
|
+
const settingsPath = path5.join(claudeDir, "settings.json");
|
|
33049
|
+
try {
|
|
33050
|
+
const existingSettings = await import_fs_extra3.default.readFile(settingsPath, "utf-8");
|
|
33051
|
+
const settings = JSON.parse(existingSettings);
|
|
33052
|
+
return !!settings.statusLine;
|
|
33053
|
+
} catch {
|
|
33054
|
+
return false;
|
|
33055
|
+
}
|
|
33056
|
+
}
|
|
33057
|
+
async function updateSettings(options, claudeDir) {
|
|
33058
|
+
const settingsPath = path5.join(claudeDir, "settings.json");
|
|
33059
|
+
let settings = {};
|
|
33060
|
+
try {
|
|
33061
|
+
const existingSettings = await import_fs_extra3.default.readFile(settingsPath, "utf-8");
|
|
33062
|
+
settings = JSON.parse(existingSettings);
|
|
33063
|
+
} catch {}
|
|
33064
|
+
if (options.customStatusline) {
|
|
33065
|
+
const shouldReplace = options.replaceStatusline !== false;
|
|
33066
|
+
if (shouldReplace) {
|
|
33067
|
+
settings.statusLine = {
|
|
33068
|
+
type: "command",
|
|
33069
|
+
command: `bun ${toPosixPath(path5.join(claudeDir, "scripts/statusline/src/index.ts"))}`,
|
|
33070
|
+
padding: 0
|
|
33071
|
+
};
|
|
33072
|
+
}
|
|
33073
|
+
}
|
|
33074
|
+
if (!settings.permissions) {
|
|
33075
|
+
settings.permissions = {};
|
|
33076
|
+
}
|
|
33077
|
+
settings.permissions.defaultMode = "bypassPermissions";
|
|
33078
|
+
if (!settings.permissions.deny) {
|
|
33079
|
+
settings.permissions.deny = [];
|
|
33080
|
+
}
|
|
33081
|
+
const denyRules = [
|
|
33082
|
+
"Bash(rm -rf *)",
|
|
33083
|
+
"Bash(sudo *)",
|
|
33084
|
+
"Bash(curl * | bash)",
|
|
33085
|
+
"Bash(wget * | bash)",
|
|
33086
|
+
"Read(./.env)",
|
|
33087
|
+
"Read(./.env.*)"
|
|
33088
|
+
];
|
|
33089
|
+
for (const rule of denyRules) {
|
|
33090
|
+
if (!settings.permissions.deny.includes(rule)) {
|
|
33091
|
+
settings.permissions.deny.push(rule);
|
|
33092
|
+
}
|
|
33093
|
+
}
|
|
33094
|
+
await import_fs_extra3.default.writeJson(settingsPath, settings, { spaces: 2 });
|
|
33095
|
+
}
|
|
33096
|
+
|
|
33097
|
+
// src/commands/setup/utils.ts
|
|
33042
33098
|
var import_fs_extra4 = __toESM(require_lib4(), 1);
|
|
33043
33099
|
import path6 from "path";
|
|
33100
|
+
import os6 from "os";
|
|
33101
|
+
import { exec } from "child_process";
|
|
33102
|
+
import { promisify } from "util";
|
|
33103
|
+
var execAsync = promisify(exec);
|
|
33104
|
+
|
|
33105
|
+
class SimpleSpinner {
|
|
33106
|
+
message = "";
|
|
33107
|
+
start(message) {
|
|
33108
|
+
this.message = message;
|
|
33109
|
+
console.log(source_default.gray(`⏳ ${message}...`));
|
|
33110
|
+
}
|
|
33111
|
+
stop(message) {
|
|
33112
|
+
console.log(source_default.green(`✓ ${message}`));
|
|
33113
|
+
}
|
|
33114
|
+
}
|
|
33115
|
+
var GITHUB_REPO = "https://github.com/Melvynx/aiblueprint.git";
|
|
33116
|
+
async function cloneRepository() {
|
|
33117
|
+
const tmpDir = path6.join(os6.tmpdir(), `aiblueprint-${Date.now()}`);
|
|
33118
|
+
try {
|
|
33119
|
+
await import_fs_extra4.default.ensureDir(tmpDir);
|
|
33120
|
+
await execAsync(`git clone --depth 1 --quiet ${GITHUB_REPO} "${tmpDir}"`);
|
|
33121
|
+
return tmpDir;
|
|
33122
|
+
} catch (error) {
|
|
33123
|
+
console.error(source_default.yellow(` Warning: Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`));
|
|
33124
|
+
await import_fs_extra4.default.remove(tmpDir).catch(() => {});
|
|
33125
|
+
return null;
|
|
33126
|
+
}
|
|
33127
|
+
}
|
|
33128
|
+
async function cleanupRepository(repoPath) {
|
|
33129
|
+
try {
|
|
33130
|
+
await import_fs_extra4.default.remove(repoPath);
|
|
33131
|
+
} catch (error) {
|
|
33132
|
+
console.error(source_default.yellow(` Warning: Failed to cleanup temporary directory: ${error instanceof Error ? error.message : String(error)}`));
|
|
33133
|
+
}
|
|
33134
|
+
}
|
|
33135
|
+
async function resolveConfigDir(repoPath) {
|
|
33136
|
+
const candidates = ["ai-config", "claude-code-config"];
|
|
33137
|
+
for (const name of candidates) {
|
|
33138
|
+
const candidate = path6.join(repoPath, name);
|
|
33139
|
+
if (await import_fs_extra4.default.pathExists(candidate)) {
|
|
33140
|
+
return candidate;
|
|
33141
|
+
}
|
|
33142
|
+
}
|
|
33143
|
+
return null;
|
|
33144
|
+
}
|
|
33145
|
+
|
|
33146
|
+
// src/lib/version.ts
|
|
33147
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
33148
|
+
import { dirname, join } from "path";
|
|
33149
|
+
import { fileURLToPath } from "url";
|
|
33150
|
+
var cachedVersion = null;
|
|
33151
|
+
function getVersion() {
|
|
33152
|
+
if (cachedVersion)
|
|
33153
|
+
return cachedVersion;
|
|
33154
|
+
try {
|
|
33155
|
+
const __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
33156
|
+
const packageJson = JSON.parse(readFileSync2(join(__dirname2, "../package.json"), "utf8"));
|
|
33157
|
+
cachedVersion = packageJson.version;
|
|
33158
|
+
return cachedVersion ?? "unknown";
|
|
33159
|
+
} catch {
|
|
33160
|
+
return "unknown";
|
|
33161
|
+
}
|
|
33162
|
+
}
|
|
33163
|
+
|
|
33164
|
+
// src/lib/backup-utils.ts
|
|
33165
|
+
var import_fs_extra5 = __toESM(require_lib4(), 1);
|
|
33166
|
+
import path7 from "path";
|
|
33167
|
+
import os7 from "os";
|
|
33168
|
+
var BACKUP_BASE_DIR = path7.join(os7.homedir(), ".config", "aiblueprint", "backup");
|
|
33169
|
+
function formatDate(date) {
|
|
33170
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
33171
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${pad(date.getHours())}-${pad(date.getMinutes())}-${pad(date.getSeconds())}`;
|
|
33172
|
+
}
|
|
33173
|
+
async function listBackups() {
|
|
33174
|
+
const exists = await import_fs_extra5.default.pathExists(BACKUP_BASE_DIR);
|
|
33175
|
+
if (!exists) {
|
|
33176
|
+
return [];
|
|
33177
|
+
}
|
|
33178
|
+
const entries = await import_fs_extra5.default.readdir(BACKUP_BASE_DIR, { withFileTypes: true });
|
|
33179
|
+
const backups = [];
|
|
33180
|
+
for (const entry of entries) {
|
|
33181
|
+
if (!entry.isDirectory())
|
|
33182
|
+
continue;
|
|
33183
|
+
const match = entry.name.match(/^(\d{4})-(\d{2})-(\d{2})-(\d{2})-(\d{2})-(\d{2})$/);
|
|
33184
|
+
if (!match)
|
|
33185
|
+
continue;
|
|
33186
|
+
const [, year, month, day, hour, minute, second] = match;
|
|
33187
|
+
const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute), parseInt(second));
|
|
33188
|
+
backups.push({
|
|
33189
|
+
name: entry.name,
|
|
33190
|
+
path: path7.join(BACKUP_BASE_DIR, entry.name),
|
|
33191
|
+
date
|
|
33192
|
+
});
|
|
33193
|
+
}
|
|
33194
|
+
return backups.sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
33195
|
+
}
|
|
33196
|
+
var AGENTS_BACKUP_SUBDIR = ".agents";
|
|
33197
|
+
var CLAUDE_ITEMS = ["commands", "agents", "skills", "scripts", "settings.json"];
|
|
33198
|
+
async function copyForBackup(sourcePath, destPath) {
|
|
33199
|
+
await import_fs_extra5.default.copy(sourcePath, destPath, {
|
|
33200
|
+
overwrite: true,
|
|
33201
|
+
dereference: false,
|
|
33202
|
+
filter: async (src) => {
|
|
33203
|
+
try {
|
|
33204
|
+
const stat = await import_fs_extra5.default.lstat(src);
|
|
33205
|
+
return !stat.isSymbolicLink();
|
|
33206
|
+
} catch {
|
|
33207
|
+
return true;
|
|
33208
|
+
}
|
|
33209
|
+
}
|
|
33210
|
+
});
|
|
33211
|
+
}
|
|
33212
|
+
async function hasMeaningfulContent(dir) {
|
|
33213
|
+
if (!await import_fs_extra5.default.pathExists(dir))
|
|
33214
|
+
return false;
|
|
33215
|
+
const files = await import_fs_extra5.default.readdir(dir);
|
|
33216
|
+
return files.some((f) => f !== ".DS_Store");
|
|
33217
|
+
}
|
|
33218
|
+
async function loadBackup(backupPath, claudeDir, agentsDir) {
|
|
33219
|
+
const exists = await import_fs_extra5.default.pathExists(backupPath);
|
|
33220
|
+
if (!exists) {
|
|
33221
|
+
throw new Error(`Backup not found: ${backupPath}`);
|
|
33222
|
+
}
|
|
33223
|
+
await import_fs_extra5.default.ensureDir(claudeDir);
|
|
33224
|
+
for (const item of CLAUDE_ITEMS) {
|
|
33225
|
+
const sourcePath = path7.join(backupPath, item);
|
|
33226
|
+
const destPath = path7.join(claudeDir, item);
|
|
33227
|
+
if (await import_fs_extra5.default.pathExists(sourcePath)) {
|
|
33228
|
+
await copyForBackup(sourcePath, destPath);
|
|
33229
|
+
}
|
|
33230
|
+
}
|
|
33231
|
+
if (agentsDir) {
|
|
33232
|
+
const agentsBackupPath = path7.join(backupPath, AGENTS_BACKUP_SUBDIR);
|
|
33233
|
+
if (await import_fs_extra5.default.pathExists(agentsBackupPath)) {
|
|
33234
|
+
await import_fs_extra5.default.ensureDir(agentsDir);
|
|
33235
|
+
await copyForBackup(agentsBackupPath, agentsDir);
|
|
33236
|
+
}
|
|
33237
|
+
}
|
|
33238
|
+
}
|
|
33239
|
+
async function createBackup(claudeDir, agentsDir) {
|
|
33240
|
+
const claudeHasContent = await hasMeaningfulContent(claudeDir);
|
|
33241
|
+
const agentsHasContent = agentsDir ? await hasMeaningfulContent(agentsDir) : false;
|
|
33242
|
+
if (!claudeHasContent && !agentsHasContent) {
|
|
33243
|
+
return null;
|
|
33244
|
+
}
|
|
33245
|
+
const timestamp = formatDate(new Date);
|
|
33246
|
+
const backupPath = path7.join(BACKUP_BASE_DIR, timestamp);
|
|
33247
|
+
await import_fs_extra5.default.ensureDir(backupPath);
|
|
33248
|
+
if (claudeHasContent) {
|
|
33249
|
+
for (const item of CLAUDE_ITEMS) {
|
|
33250
|
+
const sourcePath = path7.join(claudeDir, item);
|
|
33251
|
+
const destPath = path7.join(backupPath, item);
|
|
33252
|
+
if (await import_fs_extra5.default.pathExists(sourcePath)) {
|
|
33253
|
+
await copyForBackup(sourcePath, destPath);
|
|
33254
|
+
}
|
|
33255
|
+
}
|
|
33256
|
+
}
|
|
33257
|
+
if (agentsHasContent && agentsDir) {
|
|
33258
|
+
const destPath = path7.join(backupPath, AGENTS_BACKUP_SUBDIR);
|
|
33259
|
+
await copyForBackup(agentsDir, destPath);
|
|
33260
|
+
}
|
|
33261
|
+
return backupPath;
|
|
33262
|
+
}
|
|
33044
33263
|
|
|
33045
33264
|
// src/lib/platform.ts
|
|
33046
|
-
var
|
|
33047
|
-
import
|
|
33048
|
-
import
|
|
33265
|
+
var import_fs_extra6 = __toESM(require_lib4(), 1);
|
|
33266
|
+
import os8 from "os";
|
|
33267
|
+
import path8 from "path";
|
|
33049
33268
|
import { execSync as execSync2 } from "child_process";
|
|
33050
33269
|
function escapeShellArg(arg) {
|
|
33051
33270
|
return "'" + arg.replace(/'/g, "'\\''") + "'";
|
|
@@ -33053,15 +33272,15 @@ function escapeShellArg(arg) {
|
|
|
33053
33272
|
var cachedPlatformInfo = null;
|
|
33054
33273
|
var cachedAudioPlayer = undefined;
|
|
33055
33274
|
function isWSL() {
|
|
33056
|
-
if (
|
|
33275
|
+
if (os8.platform() !== "linux")
|
|
33057
33276
|
return false;
|
|
33058
|
-
const release =
|
|
33277
|
+
const release = os8.release().toLowerCase();
|
|
33059
33278
|
return release.includes("microsoft") || release.includes("wsl");
|
|
33060
33279
|
}
|
|
33061
33280
|
function getPlatformInfo() {
|
|
33062
33281
|
if (cachedPlatformInfo)
|
|
33063
33282
|
return cachedPlatformInfo;
|
|
33064
|
-
const platform =
|
|
33283
|
+
const platform = os8.platform();
|
|
33065
33284
|
const wsl = isWSL();
|
|
33066
33285
|
cachedPlatformInfo = {
|
|
33067
33286
|
platform,
|
|
@@ -33069,14 +33288,14 @@ function getPlatformInfo() {
|
|
|
33069
33288
|
isMacOS: platform === "darwin",
|
|
33070
33289
|
isLinux: platform === "linux" && !wsl,
|
|
33071
33290
|
isWSL: wsl,
|
|
33072
|
-
homeDir:
|
|
33291
|
+
homeDir: os8.homedir()
|
|
33073
33292
|
};
|
|
33074
33293
|
return cachedPlatformInfo;
|
|
33075
33294
|
}
|
|
33076
33295
|
function detectAudioPlayer() {
|
|
33077
33296
|
if (cachedAudioPlayer !== undefined)
|
|
33078
33297
|
return cachedAudioPlayer;
|
|
33079
|
-
const platform =
|
|
33298
|
+
const platform = os8.platform();
|
|
33080
33299
|
if (platform === "darwin") {
|
|
33081
33300
|
cachedAudioPlayer = "afplay";
|
|
33082
33301
|
return cachedAudioPlayer;
|
|
@@ -33115,7 +33334,7 @@ function getPlaySoundCommand(soundPath) {
|
|
|
33115
33334
|
const player = detectAudioPlayer();
|
|
33116
33335
|
if (!player)
|
|
33117
33336
|
return null;
|
|
33118
|
-
const platform =
|
|
33337
|
+
const platform = os8.platform();
|
|
33119
33338
|
const safePath = escapeShellArg(soundPath);
|
|
33120
33339
|
if (platform === "darwin") {
|
|
33121
33340
|
return `afplay -v 0.1 ${safePath}`;
|
|
@@ -33152,33 +33371,6 @@ var KNOWN_CLAUDE_PATHS = [
|
|
|
33152
33371
|
/\/root\/\.claude\//,
|
|
33153
33372
|
/C:\\Users\\[^\\]+\\\.claude\\/i
|
|
33154
33373
|
];
|
|
33155
|
-
function transformHookCommand(command, claudeDir) {
|
|
33156
|
-
let transformed = command;
|
|
33157
|
-
for (const pattern of KNOWN_CLAUDE_PATHS) {
|
|
33158
|
-
transformed = transformed.replace(pattern, `${claudeDir}/`);
|
|
33159
|
-
}
|
|
33160
|
-
transformed = transformed.replace(/\\/g, "/");
|
|
33161
|
-
const isAudioCommand = /^(afplay|paplay|aplay|mpv|ffplay|powershell)\s/.test(transformed);
|
|
33162
|
-
if (isAudioCommand) {
|
|
33163
|
-
const newCommand = transformAudioCommand(transformed, claudeDir);
|
|
33164
|
-
if (newCommand) {
|
|
33165
|
-
return newCommand;
|
|
33166
|
-
}
|
|
33167
|
-
}
|
|
33168
|
-
return transformed;
|
|
33169
|
-
}
|
|
33170
|
-
function transformHook(hook, claudeDir) {
|
|
33171
|
-
if (!hook)
|
|
33172
|
-
return hook;
|
|
33173
|
-
const transformed = { ...hook };
|
|
33174
|
-
if (transformed.command && typeof transformed.command === "string") {
|
|
33175
|
-
transformed.command = transformHookCommand(transformed.command, claudeDir);
|
|
33176
|
-
}
|
|
33177
|
-
if (Array.isArray(transformed.hooks)) {
|
|
33178
|
-
transformed.hooks = transformed.hooks.map((h) => transformHook(h, claudeDir));
|
|
33179
|
-
}
|
|
33180
|
-
return transformed;
|
|
33181
|
-
}
|
|
33182
33374
|
var TEXT_FILE_EXTENSIONS = new Set([
|
|
33183
33375
|
".ts",
|
|
33184
33376
|
".tsx",
|
|
@@ -33225,16 +33417,16 @@ function replaceClaudePathPlaceholder(content, claudeDir) {
|
|
|
33225
33417
|
return content.replaceAll("{CLAUDE_PATH}", claudeDir);
|
|
33226
33418
|
}
|
|
33227
33419
|
async function replacePathPlaceholdersInDir(dir, claudeDir) {
|
|
33228
|
-
const entries = await
|
|
33420
|
+
const entries = await import_fs_extra6.default.readdir(dir, { withFileTypes: true });
|
|
33229
33421
|
for (const entry of entries) {
|
|
33230
|
-
const fullPath =
|
|
33422
|
+
const fullPath = path8.join(dir, entry.name);
|
|
33231
33423
|
if (entry.isDirectory()) {
|
|
33232
33424
|
await replacePathPlaceholdersInDir(fullPath, claudeDir);
|
|
33233
33425
|
} else if (isTextFile(entry.name)) {
|
|
33234
|
-
const content = await
|
|
33426
|
+
const content = await import_fs_extra6.default.readFile(fullPath, "utf-8");
|
|
33235
33427
|
const replaced = replaceClaudePathPlaceholder(content, claudeDir);
|
|
33236
33428
|
if (replaced !== content) {
|
|
33237
|
-
await
|
|
33429
|
+
await import_fs_extra6.default.writeFile(fullPath, replaced, "utf-8");
|
|
33238
33430
|
}
|
|
33239
33431
|
}
|
|
33240
33432
|
}
|
|
@@ -33263,253 +33455,10 @@ function transformFileContent(content, claudeDir) {
|
|
|
33263
33455
|
return transformed;
|
|
33264
33456
|
}
|
|
33265
33457
|
|
|
33266
|
-
// src/commands/setup/settings.ts
|
|
33267
|
-
function toPosixPath(p) {
|
|
33268
|
-
return p.replace(/\\/g, "/");
|
|
33269
|
-
}
|
|
33270
|
-
async function hasExistingStatusLine(claudeDir) {
|
|
33271
|
-
const settingsPath = path6.join(claudeDir, "settings.json");
|
|
33272
|
-
try {
|
|
33273
|
-
const existingSettings = await import_fs_extra4.default.readFile(settingsPath, "utf-8");
|
|
33274
|
-
const settings = JSON.parse(existingSettings);
|
|
33275
|
-
return !!settings.statusLine;
|
|
33276
|
-
} catch {
|
|
33277
|
-
return false;
|
|
33278
|
-
}
|
|
33279
|
-
}
|
|
33280
|
-
async function updateSettings(options, claudeDir) {
|
|
33281
|
-
const settingsPath = path6.join(claudeDir, "settings.json");
|
|
33282
|
-
let settings = {};
|
|
33283
|
-
try {
|
|
33284
|
-
const existingSettings = await import_fs_extra4.default.readFile(settingsPath, "utf-8");
|
|
33285
|
-
settings = JSON.parse(existingSettings);
|
|
33286
|
-
} catch {}
|
|
33287
|
-
if (options.customStatusline) {
|
|
33288
|
-
const shouldReplace = options.replaceStatusline !== false;
|
|
33289
|
-
if (shouldReplace) {
|
|
33290
|
-
settings.statusLine = {
|
|
33291
|
-
type: "command",
|
|
33292
|
-
command: `bun ${toPosixPath(path6.join(claudeDir, "scripts/statusline/src/index.ts"))}`,
|
|
33293
|
-
padding: 0
|
|
33294
|
-
};
|
|
33295
|
-
}
|
|
33296
|
-
}
|
|
33297
|
-
if (!settings.permissions) {
|
|
33298
|
-
settings.permissions = {};
|
|
33299
|
-
}
|
|
33300
|
-
settings.permissions.defaultMode = "bypassPermissions";
|
|
33301
|
-
if (!settings.permissions.deny) {
|
|
33302
|
-
settings.permissions.deny = [];
|
|
33303
|
-
}
|
|
33304
|
-
const denyRules = [
|
|
33305
|
-
"Bash(rm -rf *)",
|
|
33306
|
-
"Bash(sudo *)",
|
|
33307
|
-
"Bash(curl * | bash)",
|
|
33308
|
-
"Bash(wget * | bash)",
|
|
33309
|
-
"Read(./.env)",
|
|
33310
|
-
"Read(./.env.*)"
|
|
33311
|
-
];
|
|
33312
|
-
for (const rule of denyRules) {
|
|
33313
|
-
if (!settings.permissions.deny.includes(rule)) {
|
|
33314
|
-
settings.permissions.deny.push(rule);
|
|
33315
|
-
}
|
|
33316
|
-
}
|
|
33317
|
-
if (!settings.hooks) {
|
|
33318
|
-
settings.hooks = {};
|
|
33319
|
-
}
|
|
33320
|
-
if (options.commandValidation) {
|
|
33321
|
-
if (!settings.hooks.PreToolUse) {
|
|
33322
|
-
settings.hooks.PreToolUse = [];
|
|
33323
|
-
}
|
|
33324
|
-
const bashHook = {
|
|
33325
|
-
matcher: "Bash",
|
|
33326
|
-
hooks: [
|
|
33327
|
-
{
|
|
33328
|
-
type: "command",
|
|
33329
|
-
command: `bun ${toPosixPath(path6.join(claudeDir, "scripts/command-validator/src/cli.ts"))}`
|
|
33330
|
-
}
|
|
33331
|
-
]
|
|
33332
|
-
};
|
|
33333
|
-
const existingBashHook = settings.hooks.PreToolUse.find((h) => h.matcher === "Bash");
|
|
33334
|
-
if (!existingBashHook) {
|
|
33335
|
-
settings.hooks.PreToolUse.push(bashHook);
|
|
33336
|
-
}
|
|
33337
|
-
}
|
|
33338
|
-
if (options.notificationSounds) {
|
|
33339
|
-
const finishSoundPath = toPosixPath(path6.join(claudeDir, "song/finish.mp3"));
|
|
33340
|
-
const finishSoundCommand = getPlaySoundCommand(finishSoundPath);
|
|
33341
|
-
if (finishSoundCommand) {
|
|
33342
|
-
if (!settings.hooks.Stop) {
|
|
33343
|
-
settings.hooks.Stop = [];
|
|
33344
|
-
}
|
|
33345
|
-
const stopHook = {
|
|
33346
|
-
matcher: "",
|
|
33347
|
-
hooks: [
|
|
33348
|
-
{
|
|
33349
|
-
type: "command",
|
|
33350
|
-
command: finishSoundCommand
|
|
33351
|
-
}
|
|
33352
|
-
]
|
|
33353
|
-
};
|
|
33354
|
-
const existingStopHook = settings.hooks.Stop.find((h) => h.hooks?.some((hook) => hook.command?.includes("finish.mp3")));
|
|
33355
|
-
if (!existingStopHook) {
|
|
33356
|
-
settings.hooks.Stop.push(stopHook);
|
|
33357
|
-
}
|
|
33358
|
-
}
|
|
33359
|
-
const needHumanSoundPath = toPosixPath(path6.join(claudeDir, "song/need-human.mp3"));
|
|
33360
|
-
const needHumanSoundCommand = getPlaySoundCommand(needHumanSoundPath);
|
|
33361
|
-
if (needHumanSoundCommand) {
|
|
33362
|
-
if (!settings.hooks.Notification) {
|
|
33363
|
-
settings.hooks.Notification = [];
|
|
33364
|
-
}
|
|
33365
|
-
const notificationHook = {
|
|
33366
|
-
matcher: "",
|
|
33367
|
-
hooks: [
|
|
33368
|
-
{
|
|
33369
|
-
type: "command",
|
|
33370
|
-
command: needHumanSoundCommand
|
|
33371
|
-
}
|
|
33372
|
-
]
|
|
33373
|
-
};
|
|
33374
|
-
const existingNotificationHook = settings.hooks.Notification.find((h) => h.hooks?.some((hook) => hook.command?.includes("need-human.mp3")));
|
|
33375
|
-
if (!existingNotificationHook) {
|
|
33376
|
-
settings.hooks.Notification.push(notificationHook);
|
|
33377
|
-
}
|
|
33378
|
-
}
|
|
33379
|
-
}
|
|
33380
|
-
await import_fs_extra4.default.writeJson(settingsPath, settings, { spaces: 2 });
|
|
33381
|
-
}
|
|
33382
|
-
|
|
33383
|
-
// src/commands/setup/utils.ts
|
|
33384
|
-
var import_fs_extra5 = __toESM(require_lib4(), 1);
|
|
33385
|
-
import path7 from "path";
|
|
33386
|
-
import os7 from "os";
|
|
33387
|
-
import { exec } from "child_process";
|
|
33388
|
-
import { promisify } from "util";
|
|
33389
|
-
var execAsync = promisify(exec);
|
|
33390
|
-
|
|
33391
|
-
class SimpleSpinner {
|
|
33392
|
-
message = "";
|
|
33393
|
-
start(message) {
|
|
33394
|
-
this.message = message;
|
|
33395
|
-
console.log(source_default.gray(`⏳ ${message}...`));
|
|
33396
|
-
}
|
|
33397
|
-
stop(message) {
|
|
33398
|
-
console.log(source_default.green(`✓ ${message}`));
|
|
33399
|
-
}
|
|
33400
|
-
}
|
|
33401
|
-
var GITHUB_REPO = "https://github.com/Melvynx/aiblueprint.git";
|
|
33402
|
-
async function cloneRepository() {
|
|
33403
|
-
const tmpDir = path7.join(os7.tmpdir(), `aiblueprint-${Date.now()}`);
|
|
33404
|
-
try {
|
|
33405
|
-
await import_fs_extra5.default.ensureDir(tmpDir);
|
|
33406
|
-
await execAsync(`git clone --depth 1 --quiet ${GITHUB_REPO} "${tmpDir}"`);
|
|
33407
|
-
return tmpDir;
|
|
33408
|
-
} catch (error) {
|
|
33409
|
-
console.error(source_default.yellow(` Warning: Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`));
|
|
33410
|
-
await import_fs_extra5.default.remove(tmpDir).catch(() => {});
|
|
33411
|
-
return null;
|
|
33412
|
-
}
|
|
33413
|
-
}
|
|
33414
|
-
async function cleanupRepository(repoPath) {
|
|
33415
|
-
try {
|
|
33416
|
-
await import_fs_extra5.default.remove(repoPath);
|
|
33417
|
-
} catch (error) {
|
|
33418
|
-
console.error(source_default.yellow(` Warning: Failed to cleanup temporary directory: ${error instanceof Error ? error.message : String(error)}`));
|
|
33419
|
-
}
|
|
33420
|
-
}
|
|
33421
|
-
|
|
33422
|
-
// src/lib/version.ts
|
|
33423
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
33424
|
-
import { dirname, join } from "path";
|
|
33425
|
-
import { fileURLToPath } from "url";
|
|
33426
|
-
var cachedVersion = null;
|
|
33427
|
-
function getVersion() {
|
|
33428
|
-
if (cachedVersion)
|
|
33429
|
-
return cachedVersion;
|
|
33430
|
-
try {
|
|
33431
|
-
const __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
33432
|
-
const packageJson = JSON.parse(readFileSync2(join(__dirname2, "../package.json"), "utf8"));
|
|
33433
|
-
cachedVersion = packageJson.version;
|
|
33434
|
-
return cachedVersion ?? "unknown";
|
|
33435
|
-
} catch {
|
|
33436
|
-
return "unknown";
|
|
33437
|
-
}
|
|
33438
|
-
}
|
|
33439
|
-
|
|
33440
|
-
// src/lib/backup-utils.ts
|
|
33441
|
-
var import_fs_extra6 = __toESM(require_lib4(), 1);
|
|
33442
|
-
import path8 from "path";
|
|
33443
|
-
import os8 from "os";
|
|
33444
|
-
var BACKUP_BASE_DIR = path8.join(os8.homedir(), ".config", "aiblueprint", "backup");
|
|
33445
|
-
function formatDate(date) {
|
|
33446
|
-
const pad = (n) => n.toString().padStart(2, "0");
|
|
33447
|
-
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${pad(date.getHours())}-${pad(date.getMinutes())}-${pad(date.getSeconds())}`;
|
|
33448
|
-
}
|
|
33449
|
-
async function listBackups() {
|
|
33450
|
-
const exists = await import_fs_extra6.default.pathExists(BACKUP_BASE_DIR);
|
|
33451
|
-
if (!exists) {
|
|
33452
|
-
return [];
|
|
33453
|
-
}
|
|
33454
|
-
const entries = await import_fs_extra6.default.readdir(BACKUP_BASE_DIR, { withFileTypes: true });
|
|
33455
|
-
const backups = [];
|
|
33456
|
-
for (const entry of entries) {
|
|
33457
|
-
if (!entry.isDirectory())
|
|
33458
|
-
continue;
|
|
33459
|
-
const match = entry.name.match(/^(\d{4})-(\d{2})-(\d{2})-(\d{2})-(\d{2})-(\d{2})$/);
|
|
33460
|
-
if (!match)
|
|
33461
|
-
continue;
|
|
33462
|
-
const [, year, month, day, hour, minute, second] = match;
|
|
33463
|
-
const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute), parseInt(second));
|
|
33464
|
-
backups.push({
|
|
33465
|
-
name: entry.name,
|
|
33466
|
-
path: path8.join(BACKUP_BASE_DIR, entry.name),
|
|
33467
|
-
date
|
|
33468
|
-
});
|
|
33469
|
-
}
|
|
33470
|
-
return backups.sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
33471
|
-
}
|
|
33472
|
-
async function loadBackup(backupPath, claudeDir) {
|
|
33473
|
-
const exists = await import_fs_extra6.default.pathExists(backupPath);
|
|
33474
|
-
if (!exists) {
|
|
33475
|
-
throw new Error(`Backup not found: ${backupPath}`);
|
|
33476
|
-
}
|
|
33477
|
-
await import_fs_extra6.default.ensureDir(claudeDir);
|
|
33478
|
-
const itemsToCopy = ["commands", "agents", "skills", "scripts", "song", "settings.json"];
|
|
33479
|
-
for (const item of itemsToCopy) {
|
|
33480
|
-
const sourcePath = path8.join(backupPath, item);
|
|
33481
|
-
const destPath = path8.join(claudeDir, item);
|
|
33482
|
-
if (await import_fs_extra6.default.pathExists(sourcePath)) {
|
|
33483
|
-
await import_fs_extra6.default.copy(sourcePath, destPath, { overwrite: true });
|
|
33484
|
-
}
|
|
33485
|
-
}
|
|
33486
|
-
}
|
|
33487
|
-
async function createBackup(claudeDir) {
|
|
33488
|
-
const exists = await import_fs_extra6.default.pathExists(claudeDir);
|
|
33489
|
-
if (!exists) {
|
|
33490
|
-
return null;
|
|
33491
|
-
}
|
|
33492
|
-
const files = await import_fs_extra6.default.readdir(claudeDir);
|
|
33493
|
-
const hasContent = files.some((f) => f !== ".DS_Store");
|
|
33494
|
-
if (!hasContent) {
|
|
33495
|
-
return null;
|
|
33496
|
-
}
|
|
33497
|
-
const timestamp = formatDate(new Date);
|
|
33498
|
-
const backupPath = path8.join(BACKUP_BASE_DIR, timestamp);
|
|
33499
|
-
await import_fs_extra6.default.ensureDir(backupPath);
|
|
33500
|
-
const itemsToCopy = ["commands", "agents", "skills", "scripts", "song", "settings.json"];
|
|
33501
|
-
for (const item of itemsToCopy) {
|
|
33502
|
-
const sourcePath = path8.join(claudeDir, item);
|
|
33503
|
-
const destPath = path8.join(backupPath, item);
|
|
33504
|
-
if (await import_fs_extra6.default.pathExists(sourcePath)) {
|
|
33505
|
-
await import_fs_extra6.default.copy(sourcePath, destPath, { overwrite: true });
|
|
33506
|
-
}
|
|
33507
|
-
}
|
|
33508
|
-
return backupPath;
|
|
33509
|
-
}
|
|
33510
|
-
|
|
33511
33458
|
// src/lib/telemetry.ts
|
|
33512
33459
|
import os9 from "os";
|
|
33460
|
+
import fs7 from "fs";
|
|
33461
|
+
import path9 from "path";
|
|
33513
33462
|
var TELEMETRY_URL = "https://codelynx.dev/api/cli/events";
|
|
33514
33463
|
var isDisabled = () => {
|
|
33515
33464
|
return process.env.AIBLUEPRINT_TELEMETRY_DISABLED === "1";
|
|
@@ -33520,6 +33469,31 @@ var getBasePayload = () => ({
|
|
|
33520
33469
|
arch: os9.arch(),
|
|
33521
33470
|
nodeVersion: process.version
|
|
33522
33471
|
});
|
|
33472
|
+
function getTokenFilePath() {
|
|
33473
|
+
const homeDir = os9.homedir();
|
|
33474
|
+
if (os9.platform() === "win32") {
|
|
33475
|
+
const appData = process.env.APPDATA || path9.join(homeDir, "AppData", "Roaming");
|
|
33476
|
+
return path9.join(appData, "aiblueprint", "token.txt");
|
|
33477
|
+
}
|
|
33478
|
+
const configHome = process.env.XDG_CONFIG_HOME || path9.join(homeDir, ".config");
|
|
33479
|
+
return path9.join(configHome, "aiblueprint", "token.txt");
|
|
33480
|
+
}
|
|
33481
|
+
function getSystemInfo() {
|
|
33482
|
+
let hasProToken = false;
|
|
33483
|
+
try {
|
|
33484
|
+
hasProToken = fs7.existsSync(getTokenFilePath());
|
|
33485
|
+
} catch {}
|
|
33486
|
+
return {
|
|
33487
|
+
osVersion: os9.release(),
|
|
33488
|
+
osType: os9.type(),
|
|
33489
|
+
totalMemory: `${Math.round(os9.totalmem() / (1024 * 1024 * 1024))}GB`,
|
|
33490
|
+
cpus: os9.cpus().length,
|
|
33491
|
+
shell: process.env.SHELL || process.env.COMSPEC || "unknown",
|
|
33492
|
+
homeDir: os9.homedir(),
|
|
33493
|
+
locale: process.env.LANG || process.env.LC_ALL || "unknown",
|
|
33494
|
+
hasProToken
|
|
33495
|
+
};
|
|
33496
|
+
}
|
|
33523
33497
|
var pendingRequest = null;
|
|
33524
33498
|
function trackEvent(event, data) {
|
|
33525
33499
|
if (isDisabled())
|
|
@@ -33542,10 +33516,11 @@ function trackError(error, context) {
|
|
|
33542
33516
|
if (isDisabled())
|
|
33543
33517
|
return;
|
|
33544
33518
|
const message = error instanceof Error ? error.message : String(error);
|
|
33545
|
-
const stack = error instanceof Error ? error.stack?.slice(0,
|
|
33519
|
+
const stack = error instanceof Error ? error.stack?.slice(0, 1500) : undefined;
|
|
33546
33520
|
trackEvent("error", {
|
|
33547
33521
|
message,
|
|
33548
33522
|
stack,
|
|
33523
|
+
...getSystemInfo(),
|
|
33549
33524
|
...context
|
|
33550
33525
|
});
|
|
33551
33526
|
}
|
|
@@ -33555,6 +33530,116 @@ async function flushTelemetry() {
|
|
|
33555
33530
|
}
|
|
33556
33531
|
}
|
|
33557
33532
|
|
|
33533
|
+
// src/lib/agents-installer.ts
|
|
33534
|
+
var import_fs_extra7 = __toESM(require_lib4(), 1);
|
|
33535
|
+
import os10 from "os";
|
|
33536
|
+
import path10 from "path";
|
|
33537
|
+
var AGENT_CATEGORIES = ["skills"];
|
|
33538
|
+
function getAgentsDir(custom) {
|
|
33539
|
+
return custom ? path10.resolve(custom) : path10.join(os10.homedir(), ".agents");
|
|
33540
|
+
}
|
|
33541
|
+
async function platformSymlink(source, target) {
|
|
33542
|
+
await import_fs_extra7.default.ensureDir(path10.dirname(target));
|
|
33543
|
+
const isWindows2 = os10.platform() === "win32";
|
|
33544
|
+
const sourceStat = await import_fs_extra7.default.stat(source).catch(() => null);
|
|
33545
|
+
if (isWindows2 && sourceStat?.isDirectory()) {
|
|
33546
|
+
await import_fs_extra7.default.symlink(source, target, "junction");
|
|
33547
|
+
} else {
|
|
33548
|
+
await import_fs_extra7.default.symlink(source, target);
|
|
33549
|
+
}
|
|
33550
|
+
}
|
|
33551
|
+
async function installCategoryToAgents(sourceCategoryDir, category, agentsDir, claudeDir, options = {}) {
|
|
33552
|
+
const result = {
|
|
33553
|
+
copied: [],
|
|
33554
|
+
migrated: [],
|
|
33555
|
+
symlinked: [],
|
|
33556
|
+
skipped: []
|
|
33557
|
+
};
|
|
33558
|
+
if (!await import_fs_extra7.default.pathExists(sourceCategoryDir)) {
|
|
33559
|
+
return result;
|
|
33560
|
+
}
|
|
33561
|
+
const agentsCategoryDir = path10.join(agentsDir, category);
|
|
33562
|
+
await import_fs_extra7.default.ensureDir(agentsCategoryDir);
|
|
33563
|
+
const entries = await import_fs_extra7.default.readdir(sourceCategoryDir, { withFileTypes: true });
|
|
33564
|
+
for (const entry of entries) {
|
|
33565
|
+
if (entry.name === ".DS_Store" || entry.name === "node_modules")
|
|
33566
|
+
continue;
|
|
33567
|
+
const sourcePath = path10.join(sourceCategoryDir, entry.name);
|
|
33568
|
+
const agentsTarget = path10.join(agentsCategoryDir, entry.name);
|
|
33569
|
+
const claudeTarget = path10.join(claudeDir, category, entry.name);
|
|
33570
|
+
const agentsExists = await import_fs_extra7.default.pathExists(agentsTarget);
|
|
33571
|
+
if (!agentsExists) {
|
|
33572
|
+
let migrated = false;
|
|
33573
|
+
if (options.migrateClaudeDirs) {
|
|
33574
|
+
const claudeStat = await import_fs_extra7.default.lstat(claudeTarget).catch(() => null);
|
|
33575
|
+
if (claudeStat && !claudeStat.isSymbolicLink()) {
|
|
33576
|
+
await import_fs_extra7.default.move(claudeTarget, agentsTarget);
|
|
33577
|
+
result.migrated.push(entry.name);
|
|
33578
|
+
migrated = true;
|
|
33579
|
+
}
|
|
33580
|
+
}
|
|
33581
|
+
if (!migrated) {
|
|
33582
|
+
await import_fs_extra7.default.copy(sourcePath, agentsTarget, { overwrite: false });
|
|
33583
|
+
await replacePathPlaceholdersInDir(agentsTarget, claudeDir);
|
|
33584
|
+
result.copied.push(entry.name);
|
|
33585
|
+
}
|
|
33586
|
+
} else if (options.overwrite) {
|
|
33587
|
+
await import_fs_extra7.default.remove(agentsTarget);
|
|
33588
|
+
await import_fs_extra7.default.copy(sourcePath, agentsTarget, { overwrite: false });
|
|
33589
|
+
await replacePathPlaceholdersInDir(agentsTarget, claudeDir);
|
|
33590
|
+
result.copied.push(entry.name);
|
|
33591
|
+
}
|
|
33592
|
+
}
|
|
33593
|
+
await syncCategorySymlinks(category, agentsDir, claudeDir, result, options.silent);
|
|
33594
|
+
return result;
|
|
33595
|
+
}
|
|
33596
|
+
async function syncCategorySymlinks(category, agentsDir, claudeDir, result, silent = false) {
|
|
33597
|
+
const agentsCategoryDir = path10.join(agentsDir, category);
|
|
33598
|
+
const claudeCategoryDir = path10.join(claudeDir, category);
|
|
33599
|
+
if (!await import_fs_extra7.default.pathExists(agentsCategoryDir)) {
|
|
33600
|
+
return;
|
|
33601
|
+
}
|
|
33602
|
+
await import_fs_extra7.default.ensureDir(claudeCategoryDir);
|
|
33603
|
+
const entries = await import_fs_extra7.default.readdir(agentsCategoryDir, { withFileTypes: true });
|
|
33604
|
+
for (const entry of entries) {
|
|
33605
|
+
if (entry.name === ".DS_Store")
|
|
33606
|
+
continue;
|
|
33607
|
+
const agentsTarget = path10.join(agentsCategoryDir, entry.name);
|
|
33608
|
+
const claudeTarget = path10.join(claudeCategoryDir, entry.name);
|
|
33609
|
+
const claudeStat = await import_fs_extra7.default.lstat(claudeTarget).catch(() => null);
|
|
33610
|
+
if (!claudeStat) {
|
|
33611
|
+
await platformSymlink(agentsTarget, claudeTarget);
|
|
33612
|
+
result?.symlinked.push(entry.name);
|
|
33613
|
+
} else if (claudeStat.isSymbolicLink()) {
|
|
33614
|
+
await import_fs_extra7.default.remove(claudeTarget);
|
|
33615
|
+
await platformSymlink(agentsTarget, claudeTarget);
|
|
33616
|
+
result?.symlinked.push(entry.name);
|
|
33617
|
+
} else {
|
|
33618
|
+
const reason = `Real directory at ${claudeTarget} - skipped to avoid destruction`;
|
|
33619
|
+
result?.skipped.push({ name: entry.name, reason });
|
|
33620
|
+
if (!silent) {
|
|
33621
|
+
console.log(source_default.yellow(` ⚠️ ${entry.name}: existing real ${category.slice(0, -1)} kept in place (not symlinked)`));
|
|
33622
|
+
}
|
|
33623
|
+
}
|
|
33624
|
+
}
|
|
33625
|
+
if (await import_fs_extra7.default.pathExists(claudeCategoryDir)) {
|
|
33626
|
+
const claudeEntries = await import_fs_extra7.default.readdir(claudeCategoryDir, { withFileTypes: true });
|
|
33627
|
+
for (const entry of claudeEntries) {
|
|
33628
|
+
const claudeTarget = path10.join(claudeCategoryDir, entry.name);
|
|
33629
|
+
const stat = await import_fs_extra7.default.lstat(claudeTarget).catch(() => null);
|
|
33630
|
+
if (stat?.isSymbolicLink()) {
|
|
33631
|
+
const exists = await import_fs_extra7.default.pathExists(claudeTarget);
|
|
33632
|
+
if (!exists) {
|
|
33633
|
+
await import_fs_extra7.default.remove(claudeTarget);
|
|
33634
|
+
}
|
|
33635
|
+
}
|
|
33636
|
+
}
|
|
33637
|
+
}
|
|
33638
|
+
}
|
|
33639
|
+
function isAgentCategory(category) {
|
|
33640
|
+
return AGENT_CATEGORIES.includes(category);
|
|
33641
|
+
}
|
|
33642
|
+
|
|
33558
33643
|
// src/commands/setup.ts
|
|
33559
33644
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
33560
33645
|
var __dirname2 = dirname2(__filename2);
|
|
@@ -33563,6 +33648,7 @@ async function setupCommand(params = {}) {
|
|
|
33563
33648
|
claudeCodeFolder: customClaudeCodeFolder,
|
|
33564
33649
|
codexFolder: customCodexFolder,
|
|
33565
33650
|
openCodeFolder: customOpenCodeFolder,
|
|
33651
|
+
agentsFolder: customAgentsFolder,
|
|
33566
33652
|
skipInteractive
|
|
33567
33653
|
} = params;
|
|
33568
33654
|
let repoPath = null;
|
|
@@ -33575,12 +33661,10 @@ async function setupCommand(params = {}) {
|
|
|
33575
33661
|
if (skipInteractive) {
|
|
33576
33662
|
features = [
|
|
33577
33663
|
"shellShortcuts",
|
|
33578
|
-
"commandValidation",
|
|
33579
33664
|
"customStatusline",
|
|
33580
33665
|
"aiblueprintCommands",
|
|
33581
33666
|
"aiblueprintAgents",
|
|
33582
33667
|
"aiblueprintSkills",
|
|
33583
|
-
"notificationSounds",
|
|
33584
33668
|
"codexSymlink",
|
|
33585
33669
|
"openCodeSymlink"
|
|
33586
33670
|
];
|
|
@@ -33597,11 +33681,6 @@ async function setupCommand(params = {}) {
|
|
|
33597
33681
|
name: "Shell shortcuts (cc, ccc aliases) - Quick access to Claude Code",
|
|
33598
33682
|
checked: true
|
|
33599
33683
|
},
|
|
33600
|
-
{
|
|
33601
|
-
value: "commandValidation",
|
|
33602
|
-
name: "Command validation - Security hook for bash commands",
|
|
33603
|
-
checked: true
|
|
33604
|
-
},
|
|
33605
33684
|
{
|
|
33606
33685
|
value: "customStatusline",
|
|
33607
33686
|
name: "Custom statusline - Shows git, costs, tokens info",
|
|
@@ -33617,11 +33696,6 @@ async function setupCommand(params = {}) {
|
|
|
33617
33696
|
name: "AIBlueprint agents - Specialized AI agents",
|
|
33618
33697
|
checked: true
|
|
33619
33698
|
},
|
|
33620
|
-
{
|
|
33621
|
-
value: "notificationSounds",
|
|
33622
|
-
name: "Notification sounds - Audio alerts for events",
|
|
33623
|
-
checked: true
|
|
33624
|
-
},
|
|
33625
33699
|
{
|
|
33626
33700
|
value: "aiblueprintSkills",
|
|
33627
33701
|
name: "AIBlueprint skills - Pre-built skills (apex, commit, oneshot, etc.)",
|
|
@@ -33648,22 +33722,23 @@ async function setupCommand(params = {}) {
|
|
|
33648
33722
|
}
|
|
33649
33723
|
const options = {
|
|
33650
33724
|
shellShortcuts: features.includes("shellShortcuts"),
|
|
33651
|
-
commandValidation: features.includes("commandValidation"),
|
|
33652
33725
|
customStatusline: features.includes("customStatusline"),
|
|
33653
33726
|
aiblueprintCommands: features.includes("aiblueprintCommands"),
|
|
33654
33727
|
aiblueprintAgents: features.includes("aiblueprintAgents"),
|
|
33655
33728
|
aiblueprintSkills: features.includes("aiblueprintSkills"),
|
|
33656
|
-
notificationSounds: features.includes("notificationSounds"),
|
|
33657
33729
|
codexSymlink: features.includes("codexSymlink"),
|
|
33658
33730
|
openCodeSymlink: features.includes("openCodeSymlink"),
|
|
33659
33731
|
skipInteractive
|
|
33660
33732
|
};
|
|
33661
33733
|
const s = new SimpleSpinner;
|
|
33662
|
-
const claudeDir = customClaudeCodeFolder ?
|
|
33734
|
+
const claudeDir = customClaudeCodeFolder ? path11.resolve(customClaudeCodeFolder) : path11.join(os11.homedir(), ".claude");
|
|
33735
|
+
const agentsDir = getAgentsDir(customAgentsFolder);
|
|
33663
33736
|
console.log(source_default.gray(`Installing to: ${claudeDir}`));
|
|
33664
|
-
|
|
33737
|
+
console.log(source_default.gray(`Skills source: ${agentsDir}/skills`));
|
|
33738
|
+
await import_fs_extra8.default.ensureDir(claudeDir);
|
|
33739
|
+
await import_fs_extra8.default.ensureDir(agentsDir);
|
|
33665
33740
|
s.start("Creating backup of existing configuration");
|
|
33666
|
-
const backupPath = await createBackup(claudeDir);
|
|
33741
|
+
const backupPath = await createBackup(claudeDir, agentsDir);
|
|
33667
33742
|
if (backupPath) {
|
|
33668
33743
|
s.stop(`Backup created: ${source_default.gray(backupPath)}`);
|
|
33669
33744
|
} else {
|
|
@@ -33674,10 +33749,10 @@ async function setupCommand(params = {}) {
|
|
|
33674
33749
|
if (!repoPath) {
|
|
33675
33750
|
throw new Error("Failed to clone repository. Please check your internet connection and try again.");
|
|
33676
33751
|
}
|
|
33677
|
-
const sourceDir =
|
|
33678
|
-
if (!
|
|
33752
|
+
const sourceDir = await resolveConfigDir(repoPath);
|
|
33753
|
+
if (!sourceDir) {
|
|
33679
33754
|
await cleanupRepository(repoPath);
|
|
33680
|
-
throw new Error("Configuration directory not found in cloned repository");
|
|
33755
|
+
throw new Error("Configuration directory not found in cloned repository (looked for ai-config/ and claude-code-config/)");
|
|
33681
33756
|
}
|
|
33682
33757
|
s.stop("Repository cloned successfully");
|
|
33683
33758
|
if (options.shellShortcuts) {
|
|
@@ -33685,21 +33760,21 @@ async function setupCommand(params = {}) {
|
|
|
33685
33760
|
await setupShellShortcuts();
|
|
33686
33761
|
s.stop("Shell shortcuts configured");
|
|
33687
33762
|
}
|
|
33688
|
-
if (options.
|
|
33763
|
+
if (options.customStatusline) {
|
|
33689
33764
|
s.start("Setting up scripts");
|
|
33690
|
-
await
|
|
33691
|
-
await replacePathPlaceholdersInDir(
|
|
33765
|
+
await import_fs_extra8.default.copy(path11.join(sourceDir, "scripts"), path11.join(claudeDir, "scripts"), { overwrite: true });
|
|
33766
|
+
await replacePathPlaceholdersInDir(path11.join(claudeDir, "scripts"), claudeDir);
|
|
33692
33767
|
if (options.customStatusline) {
|
|
33693
|
-
await
|
|
33768
|
+
await import_fs_extra8.default.ensureDir(path11.join(claudeDir, "scripts/statusline/data"));
|
|
33694
33769
|
}
|
|
33695
33770
|
s.stop("Scripts installed");
|
|
33696
33771
|
}
|
|
33697
33772
|
if (options.aiblueprintCommands) {
|
|
33698
33773
|
s.start("Setting up AIBlueprint commands");
|
|
33699
|
-
const commandsSourcePath =
|
|
33700
|
-
if (await
|
|
33701
|
-
await
|
|
33702
|
-
await replacePathPlaceholdersInDir(
|
|
33774
|
+
const commandsSourcePath = path11.join(sourceDir, "commands");
|
|
33775
|
+
if (await import_fs_extra8.default.pathExists(commandsSourcePath)) {
|
|
33776
|
+
await import_fs_extra8.default.copy(commandsSourcePath, path11.join(claudeDir, "commands"), { overwrite: true });
|
|
33777
|
+
await replacePathPlaceholdersInDir(path11.join(claudeDir, "commands"), claudeDir);
|
|
33703
33778
|
s.stop("Commands installed");
|
|
33704
33779
|
} else {
|
|
33705
33780
|
s.stop("Commands not available in repository");
|
|
@@ -33717,26 +33792,31 @@ async function setupCommand(params = {}) {
|
|
|
33717
33792
|
}
|
|
33718
33793
|
if (options.aiblueprintAgents) {
|
|
33719
33794
|
s.start("Setting up AIBlueprint agents");
|
|
33720
|
-
await
|
|
33721
|
-
await replacePathPlaceholdersInDir(
|
|
33795
|
+
await import_fs_extra8.default.copy(path11.join(sourceDir, "agents"), path11.join(claudeDir, "agents"), { overwrite: true });
|
|
33796
|
+
await replacePathPlaceholdersInDir(path11.join(claudeDir, "agents"), claudeDir);
|
|
33722
33797
|
s.stop("Agents installed");
|
|
33723
33798
|
}
|
|
33724
33799
|
if (options.aiblueprintSkills) {
|
|
33725
33800
|
s.start("Setting up AIBlueprint Skills");
|
|
33726
|
-
const skillsSourcePath =
|
|
33727
|
-
if (await
|
|
33728
|
-
await
|
|
33729
|
-
|
|
33730
|
-
|
|
33801
|
+
const skillsSourcePath = path11.join(sourceDir, "skills");
|
|
33802
|
+
if (await import_fs_extra8.default.pathExists(skillsSourcePath)) {
|
|
33803
|
+
const installResult = await installCategoryToAgents(skillsSourcePath, "skills", agentsDir, claudeDir, { migrateClaudeDirs: true, silent: true });
|
|
33804
|
+
const summary = [
|
|
33805
|
+
installResult.copied.length && `${installResult.copied.length} copied`,
|
|
33806
|
+
installResult.migrated.length && `${installResult.migrated.length} migrated`,
|
|
33807
|
+
installResult.symlinked.length && `${installResult.symlinked.length} linked`,
|
|
33808
|
+
installResult.skipped.length && `${installResult.skipped.length} skipped`
|
|
33809
|
+
].filter(Boolean).join(", ");
|
|
33810
|
+
s.stop(`Skills installed${summary ? ` (${summary})` : ""}`);
|
|
33811
|
+
if (installResult.skipped.length > 0) {
|
|
33812
|
+
for (const sk of installResult.skipped) {
|
|
33813
|
+
console.log(source_default.yellow(` ⚠️ ${sk.name}: ${sk.reason}`));
|
|
33814
|
+
}
|
|
33815
|
+
}
|
|
33731
33816
|
} else {
|
|
33732
33817
|
s.stop("Skills not available in repository");
|
|
33733
33818
|
}
|
|
33734
33819
|
}
|
|
33735
|
-
if (options.notificationSounds) {
|
|
33736
|
-
s.start("Setting up notification sounds");
|
|
33737
|
-
await import_fs_extra7.default.copy(path9.join(sourceDir, "song"), path9.join(claudeDir, "song"), { overwrite: true });
|
|
33738
|
-
s.stop("Notification sounds installed");
|
|
33739
|
-
}
|
|
33740
33820
|
if (options.customStatusline) {
|
|
33741
33821
|
s.start("Checking dependencies");
|
|
33742
33822
|
await checkAndInstallDependencies();
|
|
@@ -33773,7 +33853,7 @@ async function setupCommand(params = {}) {
|
|
|
33773
33853
|
console.log(source_default.gray(`
|
|
33774
33854
|
Next steps:`));
|
|
33775
33855
|
if (options.shellShortcuts) {
|
|
33776
|
-
const platform =
|
|
33856
|
+
const platform = os11.platform();
|
|
33777
33857
|
if (platform === "win32") {
|
|
33778
33858
|
console.log(source_default.gray(" • Restart PowerShell to load the new functions"));
|
|
33779
33859
|
} else {
|
|
@@ -33799,9 +33879,9 @@ Next steps:`));
|
|
|
33799
33879
|
}
|
|
33800
33880
|
|
|
33801
33881
|
// src/commands/setup-terminal.ts
|
|
33802
|
-
var
|
|
33803
|
-
import
|
|
33804
|
-
import
|
|
33882
|
+
var import_fs_extra9 = __toESM(require_lib4(), 1);
|
|
33883
|
+
import path12 from "path";
|
|
33884
|
+
import os12 from "os";
|
|
33805
33885
|
import { execSync as execSync3, exec as exec2 } from "child_process";
|
|
33806
33886
|
var OHMYZSH_INSTALL_URL = "https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh";
|
|
33807
33887
|
var INSTALL_TIMEOUT = 120000;
|
|
@@ -33835,16 +33915,16 @@ function commandExists(cmd) {
|
|
|
33835
33915
|
}
|
|
33836
33916
|
}
|
|
33837
33917
|
function isOhMyZshInstalled(homeDir) {
|
|
33838
|
-
const ohMyZshDir =
|
|
33839
|
-
return
|
|
33918
|
+
const ohMyZshDir = path12.join(homeDir, ".oh-my-zsh");
|
|
33919
|
+
return import_fs_extra9.default.existsSync(ohMyZshDir);
|
|
33840
33920
|
}
|
|
33841
33921
|
function backupFile(filePath) {
|
|
33842
|
-
if (!
|
|
33922
|
+
if (!import_fs_extra9.default.existsSync(filePath))
|
|
33843
33923
|
return null;
|
|
33844
33924
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
33845
33925
|
const backupPath = `${filePath}.backup-${timestamp}`;
|
|
33846
33926
|
try {
|
|
33847
|
-
|
|
33927
|
+
import_fs_extra9.default.copyFileSync(filePath, backupPath);
|
|
33848
33928
|
return backupPath;
|
|
33849
33929
|
} catch (error) {
|
|
33850
33930
|
throw new Error(`Failed to create backup: ${error.message}`);
|
|
@@ -33883,7 +33963,7 @@ function installPrerequisiteSync(packageName, installCmd) {
|
|
|
33883
33963
|
async function installOhMyZsh(homeDir) {
|
|
33884
33964
|
return new Promise((resolve, reject) => {
|
|
33885
33965
|
const installCmd = `sh -c "$(curl -fsSL ${OHMYZSH_INSTALL_URL})" "" --unattended`;
|
|
33886
|
-
const env2 = { ...process.env, HOME: homeDir, ZSH:
|
|
33966
|
+
const env2 = { ...process.env, HOME: homeDir, ZSH: path12.join(homeDir, ".oh-my-zsh") };
|
|
33887
33967
|
exec2(installCmd, { timeout: INSTALL_TIMEOUT, env: env2 }, (error, stdout, stderr) => {
|
|
33888
33968
|
if (error) {
|
|
33889
33969
|
if ("killed" in error && error.killed) {
|
|
@@ -33904,8 +33984,8 @@ async function installPlugin(pluginName, repoUrl, homeDir) {
|
|
|
33904
33984
|
if (!/^https:\/\/github\.com\/[\w-]+\/[\w-]+$/.test(repoUrl)) {
|
|
33905
33985
|
throw new Error(`Invalid repository URL: ${repoUrl}`);
|
|
33906
33986
|
}
|
|
33907
|
-
const customPluginsDir =
|
|
33908
|
-
if (
|
|
33987
|
+
const customPluginsDir = path12.join(homeDir, ".oh-my-zsh/custom/plugins", pluginName);
|
|
33988
|
+
if (import_fs_extra9.default.existsSync(customPluginsDir)) {
|
|
33909
33989
|
return;
|
|
33910
33990
|
}
|
|
33911
33991
|
return new Promise((resolve, reject) => {
|
|
@@ -33923,20 +34003,20 @@ async function installPlugin(pluginName, repoUrl, homeDir) {
|
|
|
33923
34003
|
});
|
|
33924
34004
|
}
|
|
33925
34005
|
function updateZshrcTheme(theme, homeDir) {
|
|
33926
|
-
const zshrcPath =
|
|
34006
|
+
const zshrcPath = path12.join(homeDir, ".zshrc");
|
|
33927
34007
|
const sanitizedTheme = sanitizeThemeName(theme);
|
|
33928
|
-
if (!
|
|
34008
|
+
if (!import_fs_extra9.default.existsSync(zshrcPath)) {
|
|
33929
34009
|
throw new Error(".zshrc file not found. Please ensure Oh My ZSH is installed correctly.");
|
|
33930
34010
|
}
|
|
33931
34011
|
try {
|
|
33932
|
-
let content =
|
|
34012
|
+
let content = import_fs_extra9.default.readFileSync(zshrcPath, "utf-8");
|
|
33933
34013
|
if (content.match(/^ZSH_THEME=/m)) {
|
|
33934
34014
|
content = content.replace(/^ZSH_THEME=.*/m, `ZSH_THEME="${sanitizedTheme}"`);
|
|
33935
34015
|
} else {
|
|
33936
34016
|
content = `ZSH_THEME="${sanitizedTheme}"
|
|
33937
34017
|
${content}`;
|
|
33938
34018
|
}
|
|
33939
|
-
|
|
34019
|
+
import_fs_extra9.default.writeFileSync(zshrcPath, content);
|
|
33940
34020
|
} catch (error) {
|
|
33941
34021
|
if (error.message.includes(".zshrc file not found")) {
|
|
33942
34022
|
throw error;
|
|
@@ -33945,12 +34025,12 @@ ${content}`;
|
|
|
33945
34025
|
}
|
|
33946
34026
|
}
|
|
33947
34027
|
function updateZshrcPlugins(plugins, homeDir) {
|
|
33948
|
-
const zshrcPath =
|
|
33949
|
-
if (!
|
|
34028
|
+
const zshrcPath = path12.join(homeDir, ".zshrc");
|
|
34029
|
+
if (!import_fs_extra9.default.existsSync(zshrcPath)) {
|
|
33950
34030
|
throw new Error(".zshrc file not found. Please ensure Oh My ZSH is installed correctly.");
|
|
33951
34031
|
}
|
|
33952
34032
|
try {
|
|
33953
|
-
let content =
|
|
34033
|
+
let content = import_fs_extra9.default.readFileSync(zshrcPath, "utf-8");
|
|
33954
34034
|
const pluginsString = plugins.join(" ");
|
|
33955
34035
|
if (content.match(/^plugins=\(/m)) {
|
|
33956
34036
|
content = content.replace(/^plugins=\([^)]*\)/m, `plugins=(${pluginsString})`);
|
|
@@ -33958,7 +34038,7 @@ function updateZshrcPlugins(plugins, homeDir) {
|
|
|
33958
34038
|
content = `${content}
|
|
33959
34039
|
plugins=(${pluginsString})`;
|
|
33960
34040
|
}
|
|
33961
|
-
|
|
34041
|
+
import_fs_extra9.default.writeFileSync(zshrcPath, content);
|
|
33962
34042
|
} catch (error) {
|
|
33963
34043
|
if (error.message.includes(".zshrc file not found")) {
|
|
33964
34044
|
throw error;
|
|
@@ -33968,7 +34048,7 @@ plugins=(${pluginsString})`;
|
|
|
33968
34048
|
}
|
|
33969
34049
|
async function setupTerminalCommand(options = {}) {
|
|
33970
34050
|
const { skipInteractive, homeDir: customHomeDir } = options;
|
|
33971
|
-
const homeDir = customHomeDir ||
|
|
34051
|
+
const homeDir = customHomeDir || os12.homedir();
|
|
33972
34052
|
try {
|
|
33973
34053
|
console.log(source_default.blue.bold(`
|
|
33974
34054
|
\uD83D\uDDA5️ AIBlueprint Terminal Setup ${source_default.gray(`v${getVersion()}`)}
|
|
@@ -34065,8 +34145,8 @@ Installing missing prerequisites: ${missingPrereqs.join(", ")}`));
|
|
|
34065
34145
|
selectedTheme = themeAnswer.theme;
|
|
34066
34146
|
}
|
|
34067
34147
|
}
|
|
34068
|
-
const zshrcPath =
|
|
34069
|
-
if (
|
|
34148
|
+
const zshrcPath = path12.join(homeDir, ".zshrc");
|
|
34149
|
+
if (import_fs_extra9.default.existsSync(zshrcPath)) {
|
|
34070
34150
|
s.start("Backing up .zshrc");
|
|
34071
34151
|
const backupPath = backupFile(zshrcPath);
|
|
34072
34152
|
if (backupPath) {
|
|
@@ -34997,20 +35077,27 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
34997
35077
|
};
|
|
34998
35078
|
|
|
34999
35079
|
// src/commands/pro.ts
|
|
35000
|
-
import
|
|
35001
|
-
import
|
|
35080
|
+
import os15 from "os";
|
|
35081
|
+
import path15 from "path";
|
|
35002
35082
|
|
|
35003
35083
|
// src/lib/pro-installer.ts
|
|
35004
|
-
var
|
|
35005
|
-
import
|
|
35006
|
-
import
|
|
35084
|
+
var import_fs_extra10 = __toESM(require_lib4(), 1);
|
|
35085
|
+
import os13 from "os";
|
|
35086
|
+
import path13 from "path";
|
|
35007
35087
|
import { exec as exec3 } from "child_process";
|
|
35008
35088
|
import { promisify as promisify2 } from "util";
|
|
35009
35089
|
var execAsync2 = promisify2(exec3);
|
|
35010
35090
|
var PREMIUM_REPO = "Melvynx/aiblueprint-cli-premium";
|
|
35011
35091
|
var PREMIUM_BRANCH = "main";
|
|
35092
|
+
function resolveBaseDir(relativePath, claudeDir, agentsDir) {
|
|
35093
|
+
const firstSeg = relativePath.split(path13.sep)[0];
|
|
35094
|
+
if (isAgentCategory(firstSeg)) {
|
|
35095
|
+
return { base: agentsDir, isAgentTarget: true };
|
|
35096
|
+
}
|
|
35097
|
+
return { base: claudeDir, isAgentTarget: false };
|
|
35098
|
+
}
|
|
35012
35099
|
function getCacheRepoDir() {
|
|
35013
|
-
return
|
|
35100
|
+
return path13.join(os13.homedir(), ".config", "aiblueprint", "pro-repos", "aiblueprint-cli-premium");
|
|
35014
35101
|
}
|
|
35015
35102
|
async function execGitWithAuth(command, token, repoUrl, cwd) {
|
|
35016
35103
|
const authenticatedUrl = `https://x-access-token:${token}@${repoUrl.replace(/^https?:\/\//, "")}`;
|
|
@@ -35024,43 +35111,61 @@ async function execGitWithAuth(command, token, repoUrl, cwd) {
|
|
|
35024
35111
|
async function cloneOrUpdateRepo(token) {
|
|
35025
35112
|
const cacheDir = getCacheRepoDir();
|
|
35026
35113
|
const repoUrl = `https://github.com/${PREMIUM_REPO}.git`;
|
|
35027
|
-
if (await
|
|
35114
|
+
if (await import_fs_extra10.default.pathExists(path13.join(cacheDir, ".git"))) {
|
|
35028
35115
|
try {
|
|
35029
35116
|
await execGitWithAuth("pull", token, repoUrl, cacheDir);
|
|
35030
35117
|
} catch (error) {
|
|
35031
|
-
await
|
|
35032
|
-
await
|
|
35118
|
+
await import_fs_extra10.default.remove(cacheDir);
|
|
35119
|
+
await import_fs_extra10.default.ensureDir(path13.dirname(cacheDir));
|
|
35033
35120
|
await execGitWithAuth(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
35034
35121
|
}
|
|
35035
35122
|
} else {
|
|
35036
|
-
await
|
|
35123
|
+
await import_fs_extra10.default.ensureDir(path13.dirname(cacheDir));
|
|
35037
35124
|
await execGitWithAuth(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
35038
35125
|
}
|
|
35039
|
-
|
|
35126
|
+
for (const candidate of ["ai-config", "claude-code-config"]) {
|
|
35127
|
+
const candidatePath = path13.join(cacheDir, candidate);
|
|
35128
|
+
if (await import_fs_extra10.default.pathExists(candidatePath)) {
|
|
35129
|
+
return candidatePath;
|
|
35130
|
+
}
|
|
35131
|
+
}
|
|
35132
|
+
throw new Error("Premium repo missing config folder (ai-config or claude-code-config)");
|
|
35040
35133
|
}
|
|
35041
|
-
async function copyConfigFromCache(cacheConfigDir,
|
|
35134
|
+
async function copyConfigFromCache(cacheConfigDir, claudeDir, agentsDir, onProgress) {
|
|
35042
35135
|
const walk = async (dir, baseDir = dir) => {
|
|
35043
|
-
const entries = await
|
|
35136
|
+
const entries = await import_fs_extra10.default.readdir(dir, { withFileTypes: true });
|
|
35044
35137
|
for (const entry of entries) {
|
|
35045
|
-
const sourcePath =
|
|
35046
|
-
const relativePath =
|
|
35138
|
+
const sourcePath = path13.join(dir, entry.name);
|
|
35139
|
+
const relativePath = path13.relative(baseDir, sourcePath);
|
|
35047
35140
|
if (entry.isDirectory() && entry.name === ".claude" && dir === baseDir) {
|
|
35048
35141
|
await walk(sourcePath, sourcePath);
|
|
35049
35142
|
continue;
|
|
35050
35143
|
}
|
|
35051
|
-
const
|
|
35144
|
+
const { base, isAgentTarget } = resolveBaseDir(relativePath, claudeDir, agentsDir);
|
|
35145
|
+
const targetPath = path13.join(base, relativePath);
|
|
35146
|
+
if (isAgentTarget) {
|
|
35147
|
+
const segments = relativePath.split(path13.sep);
|
|
35148
|
+
if (segments.length >= 2) {
|
|
35149
|
+
const claudeTop = path13.join(claudeDir, segments[0], segments[1]);
|
|
35150
|
+
const claudeStat = await import_fs_extra10.default.lstat(claudeTop).catch(() => null);
|
|
35151
|
+
if (claudeStat && !claudeStat.isSymbolicLink()) {
|
|
35152
|
+
onProgress?.(`${relativePath} (skipped - real dir)`, "file");
|
|
35153
|
+
continue;
|
|
35154
|
+
}
|
|
35155
|
+
}
|
|
35156
|
+
}
|
|
35052
35157
|
if (entry.isDirectory()) {
|
|
35053
|
-
await
|
|
35158
|
+
await import_fs_extra10.default.ensureDir(targetPath);
|
|
35054
35159
|
onProgress?.(relativePath, "directory");
|
|
35055
35160
|
await walk(sourcePath, baseDir);
|
|
35056
35161
|
} else if (isTextFile(entry.name)) {
|
|
35057
|
-
const content = await
|
|
35058
|
-
const replaced = replaceClaudePathPlaceholder(content,
|
|
35059
|
-
await
|
|
35060
|
-
await
|
|
35162
|
+
const content = await import_fs_extra10.default.readFile(sourcePath, "utf-8");
|
|
35163
|
+
const replaced = replaceClaudePathPlaceholder(content, claudeDir);
|
|
35164
|
+
await import_fs_extra10.default.ensureDir(path13.dirname(targetPath));
|
|
35165
|
+
await import_fs_extra10.default.writeFile(targetPath, replaced, "utf-8");
|
|
35061
35166
|
onProgress?.(relativePath, "file");
|
|
35062
35167
|
} else {
|
|
35063
|
-
await
|
|
35168
|
+
await import_fs_extra10.default.copy(sourcePath, targetPath, { overwrite: true });
|
|
35064
35169
|
onProgress?.(relativePath, "file");
|
|
35065
35170
|
}
|
|
35066
35171
|
}
|
|
@@ -35081,8 +35186,8 @@ async function downloadFromPrivateGitHub(repo, branch, relativePath, targetPath,
|
|
|
35081
35186
|
return false;
|
|
35082
35187
|
}
|
|
35083
35188
|
const content = await response.arrayBuffer();
|
|
35084
|
-
await
|
|
35085
|
-
await
|
|
35189
|
+
await import_fs_extra10.default.ensureDir(path13.dirname(targetPath));
|
|
35190
|
+
await import_fs_extra10.default.writeFile(targetPath, Buffer.from(content));
|
|
35086
35191
|
return true;
|
|
35087
35192
|
} catch (error) {
|
|
35088
35193
|
console.error(`Error downloading ${relativePath}:`, error);
|
|
@@ -35107,11 +35212,11 @@ async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetD
|
|
|
35107
35212
|
console.error(`Unexpected response for directory ${dirPath}`);
|
|
35108
35213
|
return false;
|
|
35109
35214
|
}
|
|
35110
|
-
await
|
|
35215
|
+
await import_fs_extra10.default.ensureDir(targetDir);
|
|
35111
35216
|
for (const file of files) {
|
|
35112
35217
|
const relativePath = dirPath ? `${dirPath}/${file.name}` : file.name;
|
|
35113
|
-
const targetPath =
|
|
35114
|
-
const displayPath = relativePath.replace("
|
|
35218
|
+
const targetPath = path13.join(targetDir, file.name);
|
|
35219
|
+
const displayPath = relativePath.replace("ai-config/", "");
|
|
35115
35220
|
if (file.type === "file") {
|
|
35116
35221
|
onProgress?.(displayPath, "file");
|
|
35117
35222
|
await downloadFromPrivateGitHub(repo, branch, relativePath, targetPath, githubToken);
|
|
@@ -35126,60 +35231,102 @@ async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetD
|
|
|
35126
35231
|
}
|
|
35127
35232
|
}
|
|
35128
35233
|
async function installProConfigs(options) {
|
|
35129
|
-
const { githubToken, claudeCodeFolder, onProgress } = options;
|
|
35130
|
-
const claudeFolder = claudeCodeFolder ||
|
|
35234
|
+
const { githubToken, claudeCodeFolder, agentsFolder, onProgress } = options;
|
|
35235
|
+
const claudeFolder = claudeCodeFolder || path13.join(os13.homedir(), ".claude");
|
|
35236
|
+
const agentsDir = getAgentsDir(agentsFolder);
|
|
35237
|
+
await import_fs_extra10.default.ensureDir(claudeFolder);
|
|
35238
|
+
await import_fs_extra10.default.ensureDir(agentsDir);
|
|
35131
35239
|
try {
|
|
35132
35240
|
const cacheConfigDir = await cloneOrUpdateRepo(githubToken);
|
|
35133
|
-
await copyConfigFromCache(cacheConfigDir, claudeFolder, onProgress);
|
|
35241
|
+
await copyConfigFromCache(cacheConfigDir, claudeFolder, agentsDir, onProgress);
|
|
35242
|
+
await syncAllAgentSymlinks(agentsDir, claudeFolder);
|
|
35134
35243
|
return;
|
|
35135
35244
|
} catch (error) {
|
|
35136
35245
|
console.warn("Git caching failed, falling back to API download");
|
|
35137
35246
|
}
|
|
35138
|
-
const tempDir =
|
|
35247
|
+
const tempDir = path13.join(os13.tmpdir(), `aiblueprint-premium-${Date.now()}`);
|
|
35139
35248
|
try {
|
|
35140
|
-
|
|
35249
|
+
let success = false;
|
|
35250
|
+
for (const candidate of ["ai-config", "claude-code-config"]) {
|
|
35251
|
+
success = await downloadDirectoryFromPrivateGitHub(PREMIUM_REPO, PREMIUM_BRANCH, candidate, tempDir, githubToken, onProgress);
|
|
35252
|
+
if (success)
|
|
35253
|
+
break;
|
|
35254
|
+
}
|
|
35141
35255
|
if (!success) {
|
|
35142
35256
|
throw new Error("Failed to download premium configurations");
|
|
35143
35257
|
}
|
|
35144
|
-
const dotClaudeDir =
|
|
35145
|
-
if (await
|
|
35146
|
-
await
|
|
35147
|
-
await
|
|
35258
|
+
const dotClaudeDir = path13.join(tempDir, ".claude");
|
|
35259
|
+
if (await import_fs_extra10.default.pathExists(dotClaudeDir)) {
|
|
35260
|
+
await import_fs_extra10.default.copy(dotClaudeDir, tempDir, { overwrite: true });
|
|
35261
|
+
await import_fs_extra10.default.remove(dotClaudeDir);
|
|
35148
35262
|
}
|
|
35149
|
-
await
|
|
35150
|
-
|
|
35151
|
-
|
|
35263
|
+
await copyTreeWithRouting(tempDir, claudeFolder, agentsDir);
|
|
35264
|
+
await replacePathPlaceholdersInDir(claudeFolder, claudeFolder);
|
|
35265
|
+
for (const category of AGENT_CATEGORIES) {
|
|
35266
|
+
const agentsCategoryDir = path13.join(agentsDir, category);
|
|
35267
|
+
if (await import_fs_extra10.default.pathExists(agentsCategoryDir)) {
|
|
35268
|
+
await replacePathPlaceholdersInDir(agentsCategoryDir, claudeFolder);
|
|
35269
|
+
}
|
|
35270
|
+
}
|
|
35271
|
+
await syncAllAgentSymlinks(agentsDir, claudeFolder);
|
|
35152
35272
|
} catch (error) {
|
|
35153
35273
|
throw new Error(`Failed to install premium configs: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
35154
35274
|
} finally {
|
|
35155
35275
|
try {
|
|
35156
|
-
await
|
|
35276
|
+
await import_fs_extra10.default.remove(tempDir);
|
|
35157
35277
|
} catch {}
|
|
35158
35278
|
}
|
|
35159
35279
|
}
|
|
35280
|
+
async function copyTreeWithRouting(source, claudeDir, agentsDir) {
|
|
35281
|
+
const entries = await import_fs_extra10.default.readdir(source, { withFileTypes: true });
|
|
35282
|
+
for (const entry of entries) {
|
|
35283
|
+
const src = path13.join(source, entry.name);
|
|
35284
|
+
const { base } = resolveBaseDir(entry.name, claudeDir, agentsDir);
|
|
35285
|
+
const dst = path13.join(base, entry.name);
|
|
35286
|
+
if (entry.isDirectory() && isAgentCategory(entry.name)) {
|
|
35287
|
+
const inner = await import_fs_extra10.default.readdir(src, { withFileTypes: true });
|
|
35288
|
+
for (const innerEntry of inner) {
|
|
35289
|
+
const innerSrc = path13.join(src, innerEntry.name);
|
|
35290
|
+
const innerDst = path13.join(dst, innerEntry.name);
|
|
35291
|
+
const claudeTop = path13.join(claudeDir, entry.name, innerEntry.name);
|
|
35292
|
+
const claudeStat = await import_fs_extra10.default.lstat(claudeTop).catch(() => null);
|
|
35293
|
+
if (claudeStat && !claudeStat.isSymbolicLink())
|
|
35294
|
+
continue;
|
|
35295
|
+
await import_fs_extra10.default.copy(innerSrc, innerDst, { overwrite: true });
|
|
35296
|
+
}
|
|
35297
|
+
} else {
|
|
35298
|
+
await import_fs_extra10.default.copy(src, dst, { overwrite: true });
|
|
35299
|
+
}
|
|
35300
|
+
}
|
|
35301
|
+
}
|
|
35302
|
+
async function syncAllAgentSymlinks(agentsDir, claudeDir) {
|
|
35303
|
+
for (const category of AGENT_CATEGORIES) {
|
|
35304
|
+
await syncCategorySymlinks(category, agentsDir, claudeDir, undefined, true);
|
|
35305
|
+
}
|
|
35306
|
+
}
|
|
35160
35307
|
|
|
35161
35308
|
// src/lib/token-storage.ts
|
|
35162
|
-
var
|
|
35163
|
-
import
|
|
35164
|
-
import
|
|
35309
|
+
var import_fs_extra11 = __toESM(require_lib4(), 1);
|
|
35310
|
+
import os14 from "os";
|
|
35311
|
+
import path14 from "path";
|
|
35165
35312
|
function getConfigDir() {
|
|
35166
|
-
const platform =
|
|
35313
|
+
const platform = os14.platform();
|
|
35167
35314
|
if (platform === "win32") {
|
|
35168
|
-
const appData = process.env.APPDATA ||
|
|
35169
|
-
return
|
|
35315
|
+
const appData = process.env.APPDATA || path14.join(os14.homedir(), "AppData", "Roaming");
|
|
35316
|
+
return path14.join(appData, "aiblueprint");
|
|
35170
35317
|
} else {
|
|
35171
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
35172
|
-
return
|
|
35318
|
+
const configHome = process.env.XDG_CONFIG_HOME || path14.join(os14.homedir(), ".config");
|
|
35319
|
+
return path14.join(configHome, "aiblueprint");
|
|
35173
35320
|
}
|
|
35174
35321
|
}
|
|
35175
|
-
function
|
|
35176
|
-
return
|
|
35322
|
+
function getTokenFilePath2() {
|
|
35323
|
+
return path14.join(getConfigDir(), "token.txt");
|
|
35177
35324
|
}
|
|
35178
35325
|
async function saveToken(githubToken) {
|
|
35179
|
-
const tokenFile =
|
|
35180
|
-
const configDir =
|
|
35326
|
+
const tokenFile = getTokenFilePath2();
|
|
35327
|
+
const configDir = path14.dirname(tokenFile);
|
|
35181
35328
|
try {
|
|
35182
|
-
await
|
|
35329
|
+
await import_fs_extra11.default.ensureDir(configDir);
|
|
35183
35330
|
} catch (error) {
|
|
35184
35331
|
if (error.code === "EACCES") {
|
|
35185
35332
|
throw new Error(`Permission denied creating config directory: ${configDir}
|
|
@@ -35187,15 +35334,15 @@ async function saveToken(githubToken) {
|
|
|
35187
35334
|
}
|
|
35188
35335
|
throw error;
|
|
35189
35336
|
}
|
|
35190
|
-
await
|
|
35337
|
+
await import_fs_extra11.default.writeFile(tokenFile, githubToken, { mode: 384 });
|
|
35191
35338
|
}
|
|
35192
35339
|
async function getToken() {
|
|
35193
|
-
const tokenFile =
|
|
35194
|
-
if (!await
|
|
35340
|
+
const tokenFile = getTokenFilePath2();
|
|
35341
|
+
if (!await import_fs_extra11.default.pathExists(tokenFile)) {
|
|
35195
35342
|
return null;
|
|
35196
35343
|
}
|
|
35197
35344
|
try {
|
|
35198
|
-
const token = await
|
|
35345
|
+
const token = await import_fs_extra11.default.readFile(tokenFile, "utf-8");
|
|
35199
35346
|
return token.trim();
|
|
35200
35347
|
} catch (error) {
|
|
35201
35348
|
return null;
|
|
@@ -35203,13 +35350,13 @@ async function getToken() {
|
|
|
35203
35350
|
}
|
|
35204
35351
|
function getTokenInfo() {
|
|
35205
35352
|
return {
|
|
35206
|
-
path:
|
|
35207
|
-
platform:
|
|
35353
|
+
path: getTokenFilePath2(),
|
|
35354
|
+
platform: os14.platform()
|
|
35208
35355
|
};
|
|
35209
35356
|
}
|
|
35210
35357
|
|
|
35211
35358
|
// src/commands/pro.ts
|
|
35212
|
-
var
|
|
35359
|
+
var import_fs_extra12 = __toESM(require_lib4(), 1);
|
|
35213
35360
|
var API_URL = "https://codeline.app/api/products";
|
|
35214
35361
|
var PRODUCT_IDS = ["prd_XJVgxVPbGG", "prd_NKabAkdOkw"];
|
|
35215
35362
|
async function countInstalledItems(claudeDir) {
|
|
@@ -35219,29 +35366,29 @@ async function countInstalledItems(claudeDir) {
|
|
|
35219
35366
|
skills: 0
|
|
35220
35367
|
};
|
|
35221
35368
|
try {
|
|
35222
|
-
const commandsDir =
|
|
35223
|
-
if (await
|
|
35224
|
-
const files = await
|
|
35369
|
+
const commandsDir = path15.join(claudeDir, "commands");
|
|
35370
|
+
if (await import_fs_extra12.default.pathExists(commandsDir)) {
|
|
35371
|
+
const files = await import_fs_extra12.default.readdir(commandsDir);
|
|
35225
35372
|
counts.commands = files.filter((f) => f.endsWith(".md")).length;
|
|
35226
35373
|
}
|
|
35227
35374
|
} catch (error) {
|
|
35228
35375
|
console.error("Failed to count commands:", error instanceof Error ? error.message : error);
|
|
35229
35376
|
}
|
|
35230
35377
|
try {
|
|
35231
|
-
const agentsDir =
|
|
35232
|
-
if (await
|
|
35233
|
-
const files = await
|
|
35378
|
+
const agentsDir = path15.join(claudeDir, "agents");
|
|
35379
|
+
if (await import_fs_extra12.default.pathExists(agentsDir)) {
|
|
35380
|
+
const files = await import_fs_extra12.default.readdir(agentsDir);
|
|
35234
35381
|
counts.agents = files.filter((f) => f.endsWith(".md")).length;
|
|
35235
35382
|
}
|
|
35236
35383
|
} catch (error) {
|
|
35237
35384
|
console.error("Failed to count agents:", error instanceof Error ? error.message : error);
|
|
35238
35385
|
}
|
|
35239
35386
|
try {
|
|
35240
|
-
const skillsDir =
|
|
35241
|
-
if (await
|
|
35242
|
-
const items = await
|
|
35387
|
+
const skillsDir = path15.join(claudeDir, "skills");
|
|
35388
|
+
if (await import_fs_extra12.default.pathExists(skillsDir)) {
|
|
35389
|
+
const items = await import_fs_extra12.default.readdir(skillsDir);
|
|
35243
35390
|
const dirs = await Promise.all(items.map(async (item) => {
|
|
35244
|
-
const stat = await
|
|
35391
|
+
const stat = await import_fs_extra12.default.stat(path15.join(skillsDir, item));
|
|
35245
35392
|
return stat.isDirectory();
|
|
35246
35393
|
}));
|
|
35247
35394
|
counts.skills = dirs.filter(Boolean).length;
|
|
@@ -35357,7 +35504,7 @@ async function proSetupCommand(options = {}) {
|
|
|
35357
35504
|
Se(source_default.red("❌ Not activated"));
|
|
35358
35505
|
process.exit(1);
|
|
35359
35506
|
}
|
|
35360
|
-
const claudeDir = options.folder ?
|
|
35507
|
+
const claudeDir = options.folder ? path15.resolve(options.folder) : path15.join(os15.homedir(), ".claude");
|
|
35361
35508
|
const spinner = Y2();
|
|
35362
35509
|
const onProgress = (file, type) => {
|
|
35363
35510
|
spinner.message(`Installing: ${source_default.cyan(file)} ${source_default.gray(`(${type})`)}`);
|
|
@@ -35366,6 +35513,7 @@ async function proSetupCommand(options = {}) {
|
|
|
35366
35513
|
await installProConfigs({
|
|
35367
35514
|
githubToken,
|
|
35368
35515
|
claudeCodeFolder: claudeDir,
|
|
35516
|
+
agentsFolder: options.agentsFolder,
|
|
35369
35517
|
onProgress
|
|
35370
35518
|
});
|
|
35371
35519
|
spinner.stop("Premium configurations installed");
|
|
@@ -35381,12 +35529,10 @@ async function proSetupCommand(options = {}) {
|
|
|
35381
35529
|
spinner.start("Updating settings.json...");
|
|
35382
35530
|
await updateSettings({
|
|
35383
35531
|
shellShortcuts: false,
|
|
35384
|
-
commandValidation: true,
|
|
35385
35532
|
customStatusline: true,
|
|
35386
35533
|
aiblueprintCommands: false,
|
|
35387
35534
|
aiblueprintAgents: false,
|
|
35388
35535
|
aiblueprintSkills: false,
|
|
35389
|
-
notificationSounds: true,
|
|
35390
35536
|
codexSymlink: false,
|
|
35391
35537
|
openCodeSymlink: false
|
|
35392
35538
|
}, claudeDir);
|
|
@@ -35406,7 +35552,7 @@ async function proSetupCommand(options = {}) {
|
|
|
35406
35552
|
M2.info(` • Premium Skills (${counts.skills})`);
|
|
35407
35553
|
M2.info(" • Premium statusline (advanced)");
|
|
35408
35554
|
M2.info(" • Shell shortcuts (cc, ccc)");
|
|
35409
|
-
M2.info(" • Settings.json with
|
|
35555
|
+
M2.info(" • Settings.json with statusline");
|
|
35410
35556
|
Se(source_default.green("\uD83D\uDE80 Ready to use!"));
|
|
35411
35557
|
} catch (error) {
|
|
35412
35558
|
trackError(error, { command: "pro-setup" });
|
|
@@ -35432,7 +35578,8 @@ async function proUpdateCommand(options = {}) {
|
|
|
35432
35578
|
spinner.start("Updating premium configurations...");
|
|
35433
35579
|
await installProConfigs({
|
|
35434
35580
|
githubToken,
|
|
35435
|
-
claudeCodeFolder: options.folder
|
|
35581
|
+
claudeCodeFolder: options.folder,
|
|
35582
|
+
agentsFolder: options.agentsFolder
|
|
35436
35583
|
});
|
|
35437
35584
|
spinner.stop("Premium configurations updated");
|
|
35438
35585
|
trackEvent("pro-update");
|
|
@@ -35449,12 +35596,12 @@ async function proUpdateCommand(options = {}) {
|
|
|
35449
35596
|
}
|
|
35450
35597
|
|
|
35451
35598
|
// src/commands/sync.ts
|
|
35452
|
-
import
|
|
35453
|
-
import
|
|
35599
|
+
import os16 from "os";
|
|
35600
|
+
import path17 from "path";
|
|
35454
35601
|
|
|
35455
35602
|
// src/lib/sync-utils.ts
|
|
35456
|
-
var
|
|
35457
|
-
import
|
|
35603
|
+
var import_fs_extra13 = __toESM(require_lib4(), 1);
|
|
35604
|
+
import path16 from "path";
|
|
35458
35605
|
import crypto from "crypto";
|
|
35459
35606
|
var PREMIUM_REPO2 = "Melvynx/aiblueprint-cli-premium";
|
|
35460
35607
|
var PREMIUM_BRANCH2 = "main";
|
|
@@ -35464,8 +35611,29 @@ function computeFileSha(content) {
|
|
|
35464
35611
|
const fullContent = Buffer.concat([Buffer.from(header), content]);
|
|
35465
35612
|
return crypto.createHash("sha1").update(fullContent).digest("hex");
|
|
35466
35613
|
}
|
|
35614
|
+
var resolvedConfigFolder = null;
|
|
35615
|
+
async function resolveRemoteConfigFolder(githubToken) {
|
|
35616
|
+
if (resolvedConfigFolder)
|
|
35617
|
+
return resolvedConfigFolder;
|
|
35618
|
+
for (const candidate of ["ai-config", "claude-code-config"]) {
|
|
35619
|
+
const apiUrl = `https://api.github.com/repos/${PREMIUM_REPO2}/contents/${candidate}?ref=${PREMIUM_BRANCH2}`;
|
|
35620
|
+
const response = await fetch(apiUrl, {
|
|
35621
|
+
headers: {
|
|
35622
|
+
Authorization: `token ${githubToken}`,
|
|
35623
|
+
Accept: "application/vnd.github.v3+json"
|
|
35624
|
+
}
|
|
35625
|
+
});
|
|
35626
|
+
if (response.ok) {
|
|
35627
|
+
resolvedConfigFolder = candidate;
|
|
35628
|
+
return candidate;
|
|
35629
|
+
}
|
|
35630
|
+
}
|
|
35631
|
+
resolvedConfigFolder = "ai-config";
|
|
35632
|
+
return "ai-config";
|
|
35633
|
+
}
|
|
35467
35634
|
async function listRemoteDirectory(dirPath, githubToken) {
|
|
35468
|
-
const
|
|
35635
|
+
const configFolder = await resolveRemoteConfigFolder(githubToken);
|
|
35636
|
+
const apiUrl = `https://api.github.com/repos/${PREMIUM_REPO2}/contents/${configFolder}/${dirPath}?ref=${PREMIUM_BRANCH2}`;
|
|
35469
35637
|
const response = await fetch(apiUrl, {
|
|
35470
35638
|
headers: {
|
|
35471
35639
|
Authorization: `token ${githubToken}`,
|
|
@@ -35503,7 +35671,7 @@ async function listRemoteFilesRecursive(dirPath, githubToken, basePath = "") {
|
|
|
35503
35671
|
}
|
|
35504
35672
|
async function computeLocalFileSha(filePath) {
|
|
35505
35673
|
try {
|
|
35506
|
-
const content = await
|
|
35674
|
+
const content = await import_fs_extra13.default.readFile(filePath);
|
|
35507
35675
|
return computeFileSha(content);
|
|
35508
35676
|
} catch {
|
|
35509
35677
|
return null;
|
|
@@ -35511,15 +35679,17 @@ async function computeLocalFileSha(filePath) {
|
|
|
35511
35679
|
}
|
|
35512
35680
|
async function listLocalFiles(dir) {
|
|
35513
35681
|
const files = [];
|
|
35514
|
-
if (!await
|
|
35682
|
+
if (!await import_fs_extra13.default.pathExists(dir)) {
|
|
35515
35683
|
return files;
|
|
35516
35684
|
}
|
|
35517
|
-
const items = await
|
|
35685
|
+
const items = await import_fs_extra13.default.readdir(dir);
|
|
35518
35686
|
for (const item of items) {
|
|
35519
35687
|
if (item === "node_modules" || item === ".DS_Store")
|
|
35520
35688
|
continue;
|
|
35521
|
-
const fullPath =
|
|
35522
|
-
const stat = await
|
|
35689
|
+
const fullPath = path16.join(dir, item);
|
|
35690
|
+
const stat = await import_fs_extra13.default.stat(fullPath).catch(() => null);
|
|
35691
|
+
if (!stat)
|
|
35692
|
+
continue;
|
|
35523
35693
|
if (stat.isDirectory()) {
|
|
35524
35694
|
files.push(item);
|
|
35525
35695
|
const subFiles = await listLocalFilesRecursive(fullPath, item);
|
|
@@ -35532,13 +35702,15 @@ async function listLocalFiles(dir) {
|
|
|
35532
35702
|
}
|
|
35533
35703
|
async function listLocalFilesRecursive(dir, basePath) {
|
|
35534
35704
|
const files = [];
|
|
35535
|
-
const items = await
|
|
35705
|
+
const items = await import_fs_extra13.default.readdir(dir).catch(() => []);
|
|
35536
35706
|
for (const item of items) {
|
|
35537
35707
|
if (item === "node_modules" || item === ".DS_Store")
|
|
35538
35708
|
continue;
|
|
35539
|
-
const fullPath =
|
|
35709
|
+
const fullPath = path16.join(dir, item);
|
|
35540
35710
|
const relativePath = `${basePath}/${item}`;
|
|
35541
|
-
const stat = await
|
|
35711
|
+
const stat = await import_fs_extra13.default.stat(fullPath).catch(() => null);
|
|
35712
|
+
if (!stat)
|
|
35713
|
+
continue;
|
|
35542
35714
|
if (stat.isDirectory()) {
|
|
35543
35715
|
files.push(relativePath);
|
|
35544
35716
|
const subFiles = await listLocalFilesRecursive(fullPath, relativePath);
|
|
@@ -35549,18 +35721,40 @@ async function listLocalFilesRecursive(dir, basePath) {
|
|
|
35549
35721
|
}
|
|
35550
35722
|
return files;
|
|
35551
35723
|
}
|
|
35552
|
-
async function
|
|
35724
|
+
async function listClaudeRealTopLevel(claudeCategoryDir) {
|
|
35725
|
+
if (!await import_fs_extra13.default.pathExists(claudeCategoryDir))
|
|
35726
|
+
return [];
|
|
35727
|
+
const entries = await import_fs_extra13.default.readdir(claudeCategoryDir).catch(() => []);
|
|
35728
|
+
const real = [];
|
|
35729
|
+
for (const name of entries) {
|
|
35730
|
+
if (name === "node_modules" || name === ".DS_Store")
|
|
35731
|
+
continue;
|
|
35732
|
+
const stat = await import_fs_extra13.default.lstat(path16.join(claudeCategoryDir, name)).catch(() => null);
|
|
35733
|
+
if (!stat)
|
|
35734
|
+
continue;
|
|
35735
|
+
if (stat.isDirectory())
|
|
35736
|
+
real.push(name);
|
|
35737
|
+
}
|
|
35738
|
+
return real;
|
|
35739
|
+
}
|
|
35740
|
+
async function analyzeCategory(category, claudeDir, agentsDir, githubToken) {
|
|
35553
35741
|
const items = [];
|
|
35554
|
-
const
|
|
35742
|
+
const useAgents = isAgentCategory(category);
|
|
35743
|
+
const localBase = useAgents ? agentsDir : claudeDir;
|
|
35744
|
+
const localDir = path16.join(localBase, category);
|
|
35555
35745
|
const remoteFiles = await listRemoteFilesRecursive(category, githubToken);
|
|
35556
35746
|
const localFiles = await listLocalFiles(localDir);
|
|
35557
35747
|
const remoteSet = new Map;
|
|
35558
35748
|
for (const rf of remoteFiles) {
|
|
35559
35749
|
remoteSet.set(rf.path, { sha: rf.sha, isFolder: rf.isFolder });
|
|
35560
35750
|
}
|
|
35751
|
+
const remoteTopLevels = new Set;
|
|
35752
|
+
for (const remotePath of remoteSet.keys()) {
|
|
35753
|
+
remoteTopLevels.add(remotePath.split("/")[0]);
|
|
35754
|
+
}
|
|
35561
35755
|
const localSet = new Set(localFiles);
|
|
35562
35756
|
for (const [remotePath, { sha, isFolder }] of remoteSet) {
|
|
35563
|
-
const localPath =
|
|
35757
|
+
const localPath = path16.join(localDir, remotePath);
|
|
35564
35758
|
if (isFolder) {
|
|
35565
35759
|
continue;
|
|
35566
35760
|
}
|
|
@@ -35590,102 +35784,85 @@ async function analyzeCategory(category, claudeDir, githubToken) {
|
|
|
35590
35784
|
}
|
|
35591
35785
|
}
|
|
35592
35786
|
}
|
|
35593
|
-
const
|
|
35594
|
-
|
|
35595
|
-
|
|
35596
|
-
|
|
35597
|
-
|
|
35598
|
-
|
|
35599
|
-
|
|
35600
|
-
|
|
35601
|
-
|
|
35787
|
+
const migrationTopLevels = new Set;
|
|
35788
|
+
if (useAgents) {
|
|
35789
|
+
const agentsTopLevels = new Set;
|
|
35790
|
+
for (const localPath of localSet) {
|
|
35791
|
+
agentsTopLevels.add(localPath.split("/")[0]);
|
|
35792
|
+
}
|
|
35793
|
+
for (const top of agentsTopLevels) {
|
|
35794
|
+
if (remoteTopLevels.has(top))
|
|
35795
|
+
continue;
|
|
35796
|
+
if (migrationTopLevels.has(top))
|
|
35797
|
+
continue;
|
|
35798
|
+
const fullPath = path16.join(localDir, top);
|
|
35799
|
+
const stat = await import_fs_extra13.default.stat(fullPath).catch(() => null);
|
|
35800
|
+
if (!stat)
|
|
35801
|
+
continue;
|
|
35802
|
+
migrationTopLevels.add(top);
|
|
35803
|
+
items.push({
|
|
35804
|
+
name: top,
|
|
35805
|
+
relativePath: `${category}/${top}`,
|
|
35806
|
+
status: "migration",
|
|
35807
|
+
category,
|
|
35808
|
+
isFolder: stat.isDirectory(),
|
|
35809
|
+
migrationKind: "preserve-in-agents"
|
|
35602
35810
|
});
|
|
35603
|
-
|
|
35811
|
+
}
|
|
35812
|
+
const claudeCategoryDir = path16.join(claudeDir, category);
|
|
35813
|
+
const claudeRealEntries = await listClaudeRealTopLevel(claudeCategoryDir);
|
|
35814
|
+
for (const top of claudeRealEntries) {
|
|
35815
|
+
if (agentsTopLevels.has(top))
|
|
35604
35816
|
continue;
|
|
35605
|
-
|
|
35606
|
-
|
|
35607
|
-
|
|
35608
|
-
|
|
35609
|
-
|
|
35610
|
-
|
|
35611
|
-
|
|
35612
|
-
|
|
35613
|
-
|
|
35614
|
-
|
|
35615
|
-
|
|
35616
|
-
});
|
|
35617
|
-
if (isFolder) {
|
|
35618
|
-
deletedPaths.add(localPath);
|
|
35619
|
-
}
|
|
35620
|
-
}
|
|
35817
|
+
if (migrationTopLevels.has(top))
|
|
35818
|
+
continue;
|
|
35819
|
+
migrationTopLevels.add(top);
|
|
35820
|
+
items.push({
|
|
35821
|
+
name: top,
|
|
35822
|
+
relativePath: `${category}/${top}`,
|
|
35823
|
+
status: "migration",
|
|
35824
|
+
category,
|
|
35825
|
+
isFolder: true,
|
|
35826
|
+
migrationKind: "move-from-claude"
|
|
35827
|
+
});
|
|
35621
35828
|
}
|
|
35622
35829
|
}
|
|
35623
|
-
|
|
35624
|
-
|
|
35625
|
-
|
|
35626
|
-
|
|
35627
|
-
const
|
|
35628
|
-
|
|
35629
|
-
|
|
35630
|
-
|
|
35631
|
-
|
|
35632
|
-
|
|
35830
|
+
const deletedPaths = new Set;
|
|
35831
|
+
for (const localPath of localSet) {
|
|
35832
|
+
if (remoteSet.has(localPath))
|
|
35833
|
+
continue;
|
|
35834
|
+
const topLevel = localPath.split("/")[0];
|
|
35835
|
+
if (migrationTopLevels.has(topLevel))
|
|
35836
|
+
continue;
|
|
35837
|
+
const pathParts = localPath.split("/");
|
|
35838
|
+
const parentAlreadyDeleted = pathParts.some((_4, idx) => {
|
|
35839
|
+
if (idx === 0)
|
|
35840
|
+
return false;
|
|
35841
|
+
const parentPath = pathParts.slice(0, idx).join("/");
|
|
35842
|
+
return deletedPaths.has(parentPath);
|
|
35633
35843
|
});
|
|
35634
|
-
if (
|
|
35635
|
-
return null;
|
|
35636
|
-
}
|
|
35637
|
-
return await response.json();
|
|
35638
|
-
} catch {
|
|
35639
|
-
return null;
|
|
35640
|
-
}
|
|
35641
|
-
}
|
|
35642
|
-
async function getLocalSettings(claudeDir) {
|
|
35643
|
-
const settingsPath = path14.join(claudeDir, "settings.json");
|
|
35644
|
-
try {
|
|
35645
|
-
const content = await import_fs_extra12.default.readFile(settingsPath, "utf-8");
|
|
35646
|
-
return JSON.parse(content);
|
|
35647
|
-
} catch {
|
|
35648
|
-
return {};
|
|
35649
|
-
}
|
|
35650
|
-
}
|
|
35651
|
-
function analyzeHooksChanges(remoteSettings, localSettings) {
|
|
35652
|
-
const hookItems = [];
|
|
35653
|
-
if (!remoteSettings?.hooks) {
|
|
35654
|
-
return hookItems;
|
|
35655
|
-
}
|
|
35656
|
-
const localHooks = localSettings?.hooks || {};
|
|
35657
|
-
for (const [hookType, remoteHookArray] of Object.entries(remoteSettings.hooks)) {
|
|
35658
|
-
if (!Array.isArray(remoteHookArray))
|
|
35844
|
+
if (parentAlreadyDeleted) {
|
|
35659
35845
|
continue;
|
|
35660
|
-
|
|
35661
|
-
|
|
35662
|
-
|
|
35663
|
-
|
|
35664
|
-
|
|
35665
|
-
|
|
35666
|
-
|
|
35667
|
-
|
|
35668
|
-
|
|
35669
|
-
|
|
35670
|
-
|
|
35671
|
-
}
|
|
35672
|
-
|
|
35673
|
-
|
|
35674
|
-
if (remoteStr !== localStr) {
|
|
35675
|
-
hookItems.push({
|
|
35676
|
-
hookType,
|
|
35677
|
-
matcher,
|
|
35678
|
-
status: "modified",
|
|
35679
|
-
remoteHook,
|
|
35680
|
-
localHook: existingLocal
|
|
35681
|
-
});
|
|
35682
|
-
}
|
|
35846
|
+
}
|
|
35847
|
+
const fullPath = path16.join(localDir, localPath);
|
|
35848
|
+
const stat = await import_fs_extra13.default.stat(fullPath).catch(() => null);
|
|
35849
|
+
if (stat) {
|
|
35850
|
+
const isFolder = stat.isDirectory();
|
|
35851
|
+
items.push({
|
|
35852
|
+
name: localPath,
|
|
35853
|
+
relativePath: `${category}/${localPath}`,
|
|
35854
|
+
status: "deleted",
|
|
35855
|
+
category,
|
|
35856
|
+
isFolder
|
|
35857
|
+
});
|
|
35858
|
+
if (isFolder) {
|
|
35859
|
+
deletedPaths.add(localPath);
|
|
35683
35860
|
}
|
|
35684
35861
|
}
|
|
35685
35862
|
}
|
|
35686
|
-
return
|
|
35863
|
+
return items;
|
|
35687
35864
|
}
|
|
35688
|
-
async function analyzeSyncChanges(claudeDir, githubToken) {
|
|
35865
|
+
async function analyzeSyncChanges(claudeDir, githubToken, agentsDir) {
|
|
35689
35866
|
const allItems = [];
|
|
35690
35867
|
const categories = [
|
|
35691
35868
|
"commands",
|
|
@@ -35694,26 +35871,22 @@ async function analyzeSyncChanges(claudeDir, githubToken) {
|
|
|
35694
35871
|
"scripts"
|
|
35695
35872
|
];
|
|
35696
35873
|
for (const category of categories) {
|
|
35697
|
-
const items = await analyzeCategory(category, claudeDir, githubToken);
|
|
35874
|
+
const items = await analyzeCategory(category, claudeDir, agentsDir, githubToken);
|
|
35698
35875
|
allItems.push(...items);
|
|
35699
35876
|
}
|
|
35700
|
-
const remoteSettings = await fetchRemoteSettings(githubToken);
|
|
35701
|
-
const localSettings = await getLocalSettings(claudeDir);
|
|
35702
|
-
const hooks = remoteSettings ? analyzeHooksChanges(remoteSettings, localSettings) : [];
|
|
35703
|
-
const hooksNewCount = hooks.filter((h2) => h2.status === "new").length;
|
|
35704
|
-
const hooksModifiedCount = hooks.filter((h2) => h2.status === "modified").length;
|
|
35705
35877
|
return {
|
|
35706
35878
|
items: allItems,
|
|
35707
|
-
|
|
35708
|
-
|
|
35709
|
-
modifiedCount: allItems.filter((i) => i.status === "modified").length + hooksModifiedCount,
|
|
35879
|
+
newCount: allItems.filter((i) => i.status === "new").length,
|
|
35880
|
+
modifiedCount: allItems.filter((i) => i.status === "modified").length,
|
|
35710
35881
|
deletedCount: allItems.filter((i) => i.status === "deleted").length,
|
|
35711
|
-
unchangedCount: allItems.filter((i) => i.status === "unchanged").length
|
|
35882
|
+
unchangedCount: allItems.filter((i) => i.status === "unchanged").length,
|
|
35883
|
+
migrationCount: allItems.filter((i) => i.status === "migration").length
|
|
35712
35884
|
};
|
|
35713
35885
|
}
|
|
35714
35886
|
async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken, claudeDir) {
|
|
35715
35887
|
try {
|
|
35716
|
-
const
|
|
35888
|
+
const configFolder = await resolveRemoteConfigFolder(githubToken);
|
|
35889
|
+
const url = `https://raw.githubusercontent.com/${PREMIUM_REPO2}/${PREMIUM_BRANCH2}/${configFolder}/${relativePath}`;
|
|
35717
35890
|
const response = await fetch(url, {
|
|
35718
35891
|
headers: {
|
|
35719
35892
|
Authorization: `token ${githubToken}`,
|
|
@@ -35724,68 +35897,83 @@ async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken,
|
|
|
35724
35897
|
return false;
|
|
35725
35898
|
}
|
|
35726
35899
|
const content = await response.arrayBuffer();
|
|
35727
|
-
await
|
|
35900
|
+
await import_fs_extra13.default.ensureDir(path16.dirname(targetPath));
|
|
35728
35901
|
if (isTextFile(relativePath)) {
|
|
35729
35902
|
const textContent = Buffer.from(content).toString("utf-8");
|
|
35730
35903
|
const transformedContent = transformFileContent(textContent, claudeDir);
|
|
35731
|
-
await
|
|
35904
|
+
await import_fs_extra13.default.writeFile(targetPath, transformedContent, "utf-8");
|
|
35732
35905
|
} else {
|
|
35733
|
-
await
|
|
35906
|
+
await import_fs_extra13.default.writeFile(targetPath, Buffer.from(content));
|
|
35734
35907
|
}
|
|
35735
35908
|
return true;
|
|
35736
35909
|
} catch {
|
|
35737
35910
|
return false;
|
|
35738
35911
|
}
|
|
35739
35912
|
}
|
|
35740
|
-
async function
|
|
35741
|
-
if (hooks.length === 0) {
|
|
35742
|
-
return { success: 0, failed: 0 };
|
|
35743
|
-
}
|
|
35744
|
-
const settingsPath = path14.join(claudeDir, "settings.json");
|
|
35745
|
-
let settings = {};
|
|
35746
|
-
try {
|
|
35747
|
-
const content = await import_fs_extra12.default.readFile(settingsPath, "utf-8");
|
|
35748
|
-
settings = JSON.parse(content);
|
|
35749
|
-
} catch {
|
|
35750
|
-
settings = {};
|
|
35751
|
-
}
|
|
35752
|
-
if (!settings.hooks) {
|
|
35753
|
-
settings.hooks = {};
|
|
35754
|
-
}
|
|
35913
|
+
async function syncSelectedItems(claudeDir, items, githubToken, agentsDir, onProgress) {
|
|
35755
35914
|
let success = 0;
|
|
35756
35915
|
let failed = 0;
|
|
35757
|
-
|
|
35758
|
-
|
|
35759
|
-
|
|
35760
|
-
|
|
35761
|
-
|
|
35916
|
+
let deleted = 0;
|
|
35917
|
+
let migrated = 0;
|
|
35918
|
+
const touchedAgentCategories = new Set;
|
|
35919
|
+
for (const item of items) {
|
|
35920
|
+
const useAgents = isAgentCategory(item.category);
|
|
35921
|
+
const baseDir = useAgents ? agentsDir : claudeDir;
|
|
35922
|
+
const targetPath = path16.join(baseDir, item.relativePath);
|
|
35923
|
+
if (item.status === "migration" && useAgents) {
|
|
35924
|
+
const topName = item.name.split("/")[0];
|
|
35925
|
+
const agentsTop = path16.join(agentsDir, item.category, topName);
|
|
35926
|
+
const claudeTop = path16.join(claudeDir, item.category, topName);
|
|
35927
|
+
try {
|
|
35928
|
+
if (item.migrationKind === "move-from-claude") {
|
|
35929
|
+
const claudeStat = await import_fs_extra13.default.lstat(claudeTop).catch(() => null);
|
|
35930
|
+
if (!claudeStat || claudeStat.isSymbolicLink()) {
|
|
35931
|
+
onProgress?.(item.relativePath, "skipping (no real dir to migrate)");
|
|
35932
|
+
failed++;
|
|
35933
|
+
continue;
|
|
35934
|
+
}
|
|
35935
|
+
const agentsExists = await import_fs_extra13.default.pathExists(agentsTop);
|
|
35936
|
+
if (agentsExists) {
|
|
35937
|
+
onProgress?.(item.relativePath, "skipping (already in .agents)");
|
|
35938
|
+
failed++;
|
|
35939
|
+
continue;
|
|
35940
|
+
}
|
|
35941
|
+
onProgress?.(item.relativePath, "moving to .agents");
|
|
35942
|
+
await import_fs_extra13.default.ensureDir(path16.dirname(agentsTop));
|
|
35943
|
+
await import_fs_extra13.default.move(claudeTop, agentsTop);
|
|
35944
|
+
} else {
|
|
35945
|
+
const claudeStat = await import_fs_extra13.default.lstat(claudeTop).catch(() => null);
|
|
35946
|
+
if (claudeStat && !claudeStat.isSymbolicLink()) {
|
|
35947
|
+
onProgress?.(item.relativePath, "skipping (real dir in .claude)");
|
|
35948
|
+
failed++;
|
|
35949
|
+
continue;
|
|
35950
|
+
}
|
|
35951
|
+
onProgress?.(item.relativePath, "preserving in .agents");
|
|
35952
|
+
}
|
|
35953
|
+
migrated++;
|
|
35954
|
+
touchedAgentCategories.add(item.category);
|
|
35955
|
+
} catch {
|
|
35956
|
+
failed++;
|
|
35762
35957
|
}
|
|
35763
|
-
|
|
35764
|
-
|
|
35765
|
-
|
|
35766
|
-
|
|
35767
|
-
|
|
35768
|
-
|
|
35958
|
+
continue;
|
|
35959
|
+
}
|
|
35960
|
+
if (useAgents) {
|
|
35961
|
+
const topName = item.name.split("/")[0];
|
|
35962
|
+
const claudeTop = path16.join(claudeDir, item.category, topName);
|
|
35963
|
+
const claudeTopStat = await import_fs_extra13.default.lstat(claudeTop).catch(() => null);
|
|
35964
|
+
if (claudeTopStat && !claudeTopStat.isSymbolicLink()) {
|
|
35965
|
+
onProgress?.(item.relativePath, "skipping (real dir in .claude)");
|
|
35966
|
+
failed++;
|
|
35967
|
+
continue;
|
|
35769
35968
|
}
|
|
35770
|
-
success++;
|
|
35771
|
-
} catch {
|
|
35772
|
-
failed++;
|
|
35773
35969
|
}
|
|
35774
|
-
}
|
|
35775
|
-
await import_fs_extra12.default.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
35776
|
-
return { success, failed };
|
|
35777
|
-
}
|
|
35778
|
-
async function syncSelectedItems(claudeDir, items, githubToken, onProgress) {
|
|
35779
|
-
let success = 0;
|
|
35780
|
-
let failed = 0;
|
|
35781
|
-
let deleted = 0;
|
|
35782
|
-
for (const item of items) {
|
|
35783
|
-
const targetPath = path14.join(claudeDir, item.relativePath);
|
|
35784
35970
|
if (item.status === "deleted") {
|
|
35785
35971
|
onProgress?.(item.relativePath, "deleting");
|
|
35786
35972
|
try {
|
|
35787
|
-
await
|
|
35973
|
+
await import_fs_extra13.default.remove(targetPath);
|
|
35788
35974
|
deleted++;
|
|
35975
|
+
if (useAgents)
|
|
35976
|
+
touchedAgentCategories.add(item.category);
|
|
35789
35977
|
} catch {
|
|
35790
35978
|
failed++;
|
|
35791
35979
|
}
|
|
@@ -35794,12 +35982,19 @@ async function syncSelectedItems(claudeDir, items, githubToken, onProgress) {
|
|
|
35794
35982
|
const ok = await downloadFromPrivateGitHub2(item.relativePath, targetPath, githubToken, claudeDir);
|
|
35795
35983
|
if (ok) {
|
|
35796
35984
|
success++;
|
|
35985
|
+
if (useAgents)
|
|
35986
|
+
touchedAgentCategories.add(item.category);
|
|
35797
35987
|
} else {
|
|
35798
35988
|
failed++;
|
|
35799
35989
|
}
|
|
35800
35990
|
}
|
|
35801
35991
|
}
|
|
35802
|
-
|
|
35992
|
+
for (const category of touchedAgentCategories) {
|
|
35993
|
+
if (isAgentCategory(category)) {
|
|
35994
|
+
await syncCategorySymlinks(category, agentsDir, claudeDir, undefined, true);
|
|
35995
|
+
}
|
|
35996
|
+
}
|
|
35997
|
+
return { success, failed, deleted, migrated };
|
|
35803
35998
|
}
|
|
35804
35999
|
|
|
35805
36000
|
// src/commands/sync.ts
|
|
@@ -35808,16 +36003,19 @@ function formatItem(item) {
|
|
|
35808
36003
|
new: "\uD83C\uDD95",
|
|
35809
36004
|
modified: "\uD83D\uDCDD",
|
|
35810
36005
|
deleted: "\uD83D\uDDD1️",
|
|
35811
|
-
unchanged: "✅"
|
|
36006
|
+
unchanged: "✅",
|
|
36007
|
+
migration: "\uD83D\uDCE6"
|
|
35812
36008
|
};
|
|
35813
36009
|
const colors12 = {
|
|
35814
36010
|
new: source_default.green,
|
|
35815
36011
|
modified: source_default.yellow,
|
|
35816
36012
|
deleted: source_default.red,
|
|
35817
|
-
unchanged: source_default.gray
|
|
36013
|
+
unchanged: source_default.gray,
|
|
36014
|
+
migration: source_default.blue
|
|
35818
36015
|
};
|
|
35819
36016
|
const folderPrefix = item.isFolder ? "\uD83D\uDCC1 " : "";
|
|
35820
|
-
|
|
36017
|
+
const suffix = item.status === "migration" && item.migrationKind === "move-from-claude" ? source_default.gray(" (move .claude → .agents)") : item.status === "migration" ? source_default.gray(" (preserve in .agents)") : "";
|
|
36018
|
+
return `${icons[item.status]} ${folderPrefix}${colors12[item.status](item.relativePath)}${suffix}`;
|
|
35821
36019
|
}
|
|
35822
36020
|
function groupByCategory(items) {
|
|
35823
36021
|
const grouped = new Map;
|
|
@@ -35834,7 +36032,13 @@ function aggregateByTopLevelFolder(items) {
|
|
|
35834
36032
|
const parts = item.name.split("/");
|
|
35835
36033
|
const topLevel = parts[0];
|
|
35836
36034
|
if (!folderMap.has(topLevel)) {
|
|
35837
|
-
folderMap.set(topLevel, {
|
|
36035
|
+
folderMap.set(topLevel, {
|
|
36036
|
+
name: topLevel,
|
|
36037
|
+
newCount: 0,
|
|
36038
|
+
modifiedCount: 0,
|
|
36039
|
+
deletedCount: 0,
|
|
36040
|
+
migrationCount: 0
|
|
36041
|
+
});
|
|
35838
36042
|
}
|
|
35839
36043
|
const summary = folderMap.get(topLevel);
|
|
35840
36044
|
if (item.status === "new")
|
|
@@ -35843,6 +36047,8 @@ function aggregateByTopLevelFolder(items) {
|
|
|
35843
36047
|
summary.modifiedCount++;
|
|
35844
36048
|
else if (item.status === "deleted")
|
|
35845
36049
|
summary.deletedCount++;
|
|
36050
|
+
else if (item.status === "migration")
|
|
36051
|
+
summary.migrationCount++;
|
|
35846
36052
|
}
|
|
35847
36053
|
return Array.from(folderMap.values());
|
|
35848
36054
|
}
|
|
@@ -35854,10 +36060,12 @@ function formatFolderSummary(summary) {
|
|
|
35854
36060
|
parts.push(source_default.yellow(`~${summary.modifiedCount}`));
|
|
35855
36061
|
if (summary.deletedCount > 0)
|
|
35856
36062
|
parts.push(source_default.red(`-${summary.deletedCount}`));
|
|
36063
|
+
if (summary.migrationCount > 0)
|
|
36064
|
+
parts.push(source_default.blue(`→${summary.migrationCount}`));
|
|
35857
36065
|
const countStr = parts.length > 0 ? ` (${parts.join(", ")})` : "";
|
|
35858
36066
|
return `\uD83D\uDCC1 ${summary.name}${countStr}`;
|
|
35859
36067
|
}
|
|
35860
|
-
function createSelectionChoices(changedItems
|
|
36068
|
+
function createSelectionChoices(changedItems) {
|
|
35861
36069
|
const choices = [];
|
|
35862
36070
|
const folderedCategories = ["scripts", "skills"];
|
|
35863
36071
|
const grouped = groupByCategory(changedItems);
|
|
@@ -35880,8 +36088,20 @@ function createSelectionChoices(changedItems, hooks = []) {
|
|
|
35880
36088
|
}
|
|
35881
36089
|
} else {
|
|
35882
36090
|
for (const item of items) {
|
|
35883
|
-
const icons = {
|
|
35884
|
-
|
|
36091
|
+
const icons = {
|
|
36092
|
+
new: "\uD83C\uDD95",
|
|
36093
|
+
modified: "\uD83D\uDCDD",
|
|
36094
|
+
deleted: "\uD83D\uDDD1️",
|
|
36095
|
+
unchanged: "",
|
|
36096
|
+
migration: "\uD83D\uDCE6"
|
|
36097
|
+
};
|
|
36098
|
+
const actions = {
|
|
36099
|
+
new: "add",
|
|
36100
|
+
modified: "update",
|
|
36101
|
+
deleted: "remove",
|
|
36102
|
+
unchanged: "",
|
|
36103
|
+
migration: "migrate"
|
|
36104
|
+
};
|
|
35885
36105
|
choices.push({
|
|
35886
36106
|
value: { type: "file", item },
|
|
35887
36107
|
label: `${icons[item.status]} ${item.relativePath}`,
|
|
@@ -35890,16 +36110,6 @@ function createSelectionChoices(changedItems, hooks = []) {
|
|
|
35890
36110
|
}
|
|
35891
36111
|
}
|
|
35892
36112
|
}
|
|
35893
|
-
for (const hook of hooks) {
|
|
35894
|
-
const icon = hook.status === "new" ? "\uD83C\uDD95" : "\uD83D\uDCDD";
|
|
35895
|
-
const action = hook.status === "new" ? "add" : "update";
|
|
35896
|
-
const matcherDisplay = hook.matcher || "*";
|
|
35897
|
-
choices.push({
|
|
35898
|
-
value: { type: "hook", hook },
|
|
35899
|
-
label: `${icon} settings.json → ${hook.hookType}[${matcherDisplay}]`,
|
|
35900
|
-
hint: action
|
|
35901
|
-
});
|
|
35902
|
-
}
|
|
35903
36113
|
return choices;
|
|
35904
36114
|
}
|
|
35905
36115
|
function formatFolderHint(summary) {
|
|
@@ -35910,21 +36120,20 @@ function formatFolderHint(summary) {
|
|
|
35910
36120
|
parts.push(`~${summary.modifiedCount}`);
|
|
35911
36121
|
if (summary.deletedCount > 0)
|
|
35912
36122
|
parts.push(`-${summary.deletedCount}`);
|
|
36123
|
+
if (summary.migrationCount > 0)
|
|
36124
|
+
parts.push(`→${summary.migrationCount}`);
|
|
35913
36125
|
return parts.join(", ");
|
|
35914
36126
|
}
|
|
35915
36127
|
function expandSelections(selections) {
|
|
35916
36128
|
const items = [];
|
|
35917
|
-
const hooks = [];
|
|
35918
36129
|
for (const sel of selections) {
|
|
35919
36130
|
if (sel.type === "file") {
|
|
35920
36131
|
items.push(sel.item);
|
|
35921
36132
|
} else if (sel.type === "folder") {
|
|
35922
36133
|
items.push(...sel.items);
|
|
35923
|
-
} else if (sel.type === "hook") {
|
|
35924
|
-
hooks.push(sel.hook);
|
|
35925
36134
|
}
|
|
35926
36135
|
}
|
|
35927
|
-
return { items
|
|
36136
|
+
return { items };
|
|
35928
36137
|
}
|
|
35929
36138
|
async function proSyncCommand(options = {}) {
|
|
35930
36139
|
Ie(source_default.blue(`\uD83D\uDD04 Sync Premium Configurations ${source_default.gray(`v${getVersion()}`)}`));
|
|
@@ -35936,19 +36145,28 @@ async function proSyncCommand(options = {}) {
|
|
|
35936
36145
|
Se(source_default.red("❌ Not activated"));
|
|
35937
36146
|
process.exit(1);
|
|
35938
36147
|
}
|
|
35939
|
-
const claudeDir = options.folder ?
|
|
36148
|
+
const claudeDir = options.folder ? path17.resolve(options.folder) : path17.join(os16.homedir(), ".claude");
|
|
36149
|
+
const agentsDir = getAgentsDir(options.agentsFolder);
|
|
35940
36150
|
const spinner = Y2();
|
|
35941
36151
|
spinner.start("Analyzing changes...");
|
|
35942
|
-
const result = await analyzeSyncChanges(claudeDir, githubToken);
|
|
36152
|
+
const result = await analyzeSyncChanges(claudeDir, githubToken, agentsDir);
|
|
35943
36153
|
spinner.stop("Analysis complete");
|
|
35944
36154
|
const changedItems = result.items.filter((i) => i.status !== "unchanged");
|
|
35945
|
-
|
|
35946
|
-
if (changedItems.length === 0 && changedHooks.length === 0) {
|
|
36155
|
+
if (changedItems.length === 0) {
|
|
35947
36156
|
M2.success("Everything is up to date!");
|
|
35948
36157
|
Se(source_default.green("✅ No changes needed"));
|
|
35949
36158
|
return;
|
|
35950
36159
|
}
|
|
35951
|
-
|
|
36160
|
+
const summaryParts = [
|
|
36161
|
+
source_default.green(`${result.newCount} new`),
|
|
36162
|
+
source_default.yellow(`${result.modifiedCount} modified`)
|
|
36163
|
+
];
|
|
36164
|
+
if (result.migrationCount > 0) {
|
|
36165
|
+
summaryParts.push(source_default.blue(`${result.migrationCount} to migrate`));
|
|
36166
|
+
}
|
|
36167
|
+
summaryParts.push(source_default.red(`${result.deletedCount} to remove`));
|
|
36168
|
+
summaryParts.push(source_default.gray(`${result.unchangedCount} unchanged`));
|
|
36169
|
+
M2.info(`Found: ${summaryParts.join(", ")}`);
|
|
35952
36170
|
M2.message("");
|
|
35953
36171
|
M2.message(source_default.bold("Changes by category:"));
|
|
35954
36172
|
const grouped = groupByCategory(changedItems);
|
|
@@ -35967,36 +36185,34 @@ async function proSyncCommand(options = {}) {
|
|
|
35967
36185
|
}
|
|
35968
36186
|
}
|
|
35969
36187
|
}
|
|
35970
|
-
if (changedHooks.length > 0) {
|
|
35971
|
-
M2.message("");
|
|
35972
|
-
M2.message(source_default.cyan.bold(` SETTINGS (hooks)`));
|
|
35973
|
-
for (const hook of changedHooks) {
|
|
35974
|
-
const icon = hook.status === "new" ? "\uD83C\uDD95" : "\uD83D\uDCDD";
|
|
35975
|
-
const color = hook.status === "new" ? source_default.green : source_default.yellow;
|
|
35976
|
-
const matcherDisplay = hook.matcher || "*";
|
|
35977
|
-
M2.message(` ${icon} ${color(`${hook.hookType}[${matcherDisplay}]`)}`);
|
|
35978
|
-
}
|
|
35979
|
-
}
|
|
35980
36188
|
M2.message("");
|
|
35981
|
-
const choices = createSelectionChoices(changedItems
|
|
36189
|
+
const choices = createSelectionChoices(changedItems);
|
|
35982
36190
|
const newItems = changedItems.filter((i) => i.status === "new");
|
|
35983
36191
|
const modifiedItems = changedItems.filter((i) => i.status === "modified");
|
|
35984
36192
|
const deletedItems = changedItems.filter((i) => i.status === "deleted");
|
|
35985
|
-
const
|
|
35986
|
-
const modifiedHooks = changedHooks.filter((h2) => h2.status === "modified");
|
|
36193
|
+
const migrationItems = changedItems.filter((i) => i.status === "migration");
|
|
35987
36194
|
const hasDeletions = deletedItems.length > 0;
|
|
36195
|
+
const hasMigrations = migrationItems.length > 0;
|
|
36196
|
+
const updatesHintParts = [
|
|
36197
|
+
`add ${newItems.length}`,
|
|
36198
|
+
`update ${modifiedItems.length}`
|
|
36199
|
+
];
|
|
36200
|
+
if (hasMigrations) {
|
|
36201
|
+
updatesHintParts.push(`migrate ${migrationItems.length}`);
|
|
36202
|
+
}
|
|
35988
36203
|
const syncModeOptions = [
|
|
35989
36204
|
{
|
|
35990
36205
|
value: "updates",
|
|
35991
36206
|
label: "Import all updates",
|
|
35992
|
-
hint:
|
|
36207
|
+
hint: `${updatesHintParts.join(" + ")} files`
|
|
35993
36208
|
}
|
|
35994
36209
|
];
|
|
35995
36210
|
if (hasDeletions) {
|
|
36211
|
+
const deleteHintParts = [...updatesHintParts, `delete ${deletedItems.length}`];
|
|
35996
36212
|
syncModeOptions.push({
|
|
35997
36213
|
value: "updates_and_delete",
|
|
35998
36214
|
label: "Import all updates and delete files",
|
|
35999
|
-
hint:
|
|
36215
|
+
hint: `${deleteHintParts.join(" + ")} files`
|
|
36000
36216
|
});
|
|
36001
36217
|
}
|
|
36002
36218
|
syncModeOptions.push({
|
|
@@ -36013,16 +36229,17 @@ async function proSyncCommand(options = {}) {
|
|
|
36013
36229
|
process.exit(0);
|
|
36014
36230
|
}
|
|
36015
36231
|
let selectedItems = [];
|
|
36016
|
-
let selectedHooks = [];
|
|
36017
36232
|
if (syncMode === "updates") {
|
|
36018
|
-
selectedItems = [...newItems, ...modifiedItems];
|
|
36233
|
+
selectedItems = [...newItems, ...modifiedItems, ...migrationItems];
|
|
36019
36234
|
} else if (syncMode === "updates_and_delete") {
|
|
36020
36235
|
M2.message("");
|
|
36021
36236
|
M2.message(source_default.red.bold("⚠️ WARNING: DESTRUCTIVE ACTION"));
|
|
36022
36237
|
M2.message(source_default.red("━".repeat(50)));
|
|
36023
|
-
M2.message(source_default.red(
|
|
36024
|
-
M2.message(source_default.red("
|
|
36025
|
-
|
|
36238
|
+
M2.message(source_default.red(`${deletedItems.length} commands/agents/scripts not in the premium version`));
|
|
36239
|
+
M2.message(source_default.red("will be PERMANENTLY DELETED and replaced by the new version."));
|
|
36240
|
+
if (hasMigrations) {
|
|
36241
|
+
M2.message(source_default.gray(`(Skills are NOT deleted - they will be migrated to ~/.agents instead.)`));
|
|
36242
|
+
}
|
|
36026
36243
|
M2.message(source_default.red("━".repeat(50)));
|
|
36027
36244
|
M2.message("");
|
|
36028
36245
|
const deleteConfirm = await ye({
|
|
@@ -36033,9 +36250,9 @@ async function proSyncCommand(options = {}) {
|
|
|
36033
36250
|
xe("Sync cancelled");
|
|
36034
36251
|
process.exit(0);
|
|
36035
36252
|
}
|
|
36036
|
-
selectedItems = [...newItems, ...modifiedItems, ...deletedItems];
|
|
36253
|
+
selectedItems = [...newItems, ...modifiedItems, ...migrationItems, ...deletedItems];
|
|
36037
36254
|
} else {
|
|
36038
|
-
const fileChoices = choices
|
|
36255
|
+
const fileChoices = choices;
|
|
36039
36256
|
const nonDeleteChoices = fileChoices.filter((c) => {
|
|
36040
36257
|
if (c.value.type === "file")
|
|
36041
36258
|
return c.value.item.status !== "deleted";
|
|
@@ -36065,12 +36282,15 @@ async function proSyncCommand(options = {}) {
|
|
|
36065
36282
|
const toAdd = selectedItems.filter((i) => i.status === "new").length;
|
|
36066
36283
|
const toUpdate = selectedItems.filter((i) => i.status === "modified").length;
|
|
36067
36284
|
const toRemove = selectedItems.filter((i) => i.status === "deleted").length;
|
|
36285
|
+
const toMigrate = selectedItems.filter((i) => i.status === "migration").length;
|
|
36068
36286
|
M2.message("");
|
|
36069
36287
|
M2.message(source_default.bold("What will happen:"));
|
|
36070
36288
|
if (toAdd > 0)
|
|
36071
36289
|
M2.message(source_default.green(` ✓ Add ${toAdd} new file${toAdd > 1 ? "s" : ""}`));
|
|
36072
36290
|
if (toUpdate > 0)
|
|
36073
36291
|
M2.message(source_default.yellow(` ✓ Update ${toUpdate} file${toUpdate > 1 ? "s" : ""}`));
|
|
36292
|
+
if (toMigrate > 0)
|
|
36293
|
+
M2.message(source_default.blue(` ✓ Migrate ${toMigrate} item${toMigrate > 1 ? "s" : ""} to .agents (preserve, no data loss)`));
|
|
36074
36294
|
if (toRemove > 0)
|
|
36075
36295
|
M2.message(source_default.red(` ✓ Delete ${toRemove} file${toRemove > 1 ? "s" : ""}`));
|
|
36076
36296
|
M2.message(source_default.gray(` ✓ Backup current config to ~/.config/aiblueprint/backup/`));
|
|
@@ -36084,86 +36304,27 @@ async function proSyncCommand(options = {}) {
|
|
|
36084
36304
|
process.exit(0);
|
|
36085
36305
|
}
|
|
36086
36306
|
spinner.start("Creating backup...");
|
|
36087
|
-
const backupPath = await createBackup(claudeDir);
|
|
36307
|
+
const backupPath = await createBackup(claudeDir, agentsDir);
|
|
36088
36308
|
if (backupPath) {
|
|
36089
36309
|
spinner.stop(`Backup created: ${source_default.gray(backupPath)}`);
|
|
36090
36310
|
} else {
|
|
36091
36311
|
spinner.stop("No existing config to backup");
|
|
36092
36312
|
}
|
|
36093
36313
|
spinner.start("Syncing...");
|
|
36094
|
-
const syncResult = await syncSelectedItems(claudeDir, selectedItems, githubToken, (file, action) => {
|
|
36314
|
+
const syncResult = await syncSelectedItems(claudeDir, selectedItems, githubToken, agentsDir, (file, action) => {
|
|
36095
36315
|
spinner.message(`${action}: ${source_default.cyan(file)}`);
|
|
36096
36316
|
});
|
|
36097
36317
|
spinner.stop("Files synced");
|
|
36098
36318
|
const results = [];
|
|
36099
36319
|
if (syncResult.success > 0)
|
|
36100
36320
|
results.push(source_default.green(`${syncResult.success} added/updated`));
|
|
36321
|
+
if (syncResult.migrated > 0)
|
|
36322
|
+
results.push(source_default.blue(`${syncResult.migrated} migrated`));
|
|
36101
36323
|
if (syncResult.deleted > 0)
|
|
36102
36324
|
results.push(source_default.red(`${syncResult.deleted} removed`));
|
|
36103
36325
|
if (syncResult.failed > 0)
|
|
36104
36326
|
results.push(source_default.yellow(`${syncResult.failed} failed`));
|
|
36105
36327
|
M2.success(results.join(", "));
|
|
36106
|
-
if (changedHooks.length > 0) {
|
|
36107
|
-
const hookDescriptions = {
|
|
36108
|
-
Stop: "Play sound when Claude finishes a task",
|
|
36109
|
-
Notification: "Play sound when Claude needs human input",
|
|
36110
|
-
PreToolUse: "Run before Claude uses a tool (e.g., command validation)",
|
|
36111
|
-
PostToolUse: "Run after Claude uses a tool (e.g., auto-format)"
|
|
36112
|
-
};
|
|
36113
|
-
const getHookCommand = (hookData) => {
|
|
36114
|
-
if (hookData?.hooks?.[0]?.command)
|
|
36115
|
-
return hookData.hooks[0].command;
|
|
36116
|
-
if (hookData?.command)
|
|
36117
|
-
return hookData.command;
|
|
36118
|
-
return null;
|
|
36119
|
-
};
|
|
36120
|
-
M2.message("");
|
|
36121
|
-
M2.message(source_default.bold.yellow("⚠️ Settings.json Sync (Optional)"));
|
|
36122
|
-
M2.message(source_default.gray("The following hooks can be synced to your settings.json:"));
|
|
36123
|
-
M2.message("");
|
|
36124
|
-
for (const hook of changedHooks) {
|
|
36125
|
-
const icon = hook.status === "new" ? "\uD83C\uDD95" : "\uD83D\uDCDD";
|
|
36126
|
-
const color = hook.status === "new" ? source_default.green : source_default.yellow;
|
|
36127
|
-
const matcherDisplay = hook.matcher ? `[${hook.matcher}]` : "";
|
|
36128
|
-
const description = hookDescriptions[hook.hookType] || "";
|
|
36129
|
-
M2.message(` ${icon} ${color(`${hook.hookType}${matcherDisplay}`)} ${source_default.gray(description)}`);
|
|
36130
|
-
const transformedHook = transformHook(hook.remoteHook, claudeDir);
|
|
36131
|
-
const newCommand = getHookCommand(transformedHook);
|
|
36132
|
-
if (hook.status === "modified" && hook.localHook) {
|
|
36133
|
-
const oldCommand = getHookCommand(hook.localHook);
|
|
36134
|
-
if (oldCommand) {
|
|
36135
|
-
M2.message(source_default.red(` - ${oldCommand}`));
|
|
36136
|
-
}
|
|
36137
|
-
}
|
|
36138
|
-
if (newCommand) {
|
|
36139
|
-
M2.message(source_default.green(` + ${newCommand}`));
|
|
36140
|
-
}
|
|
36141
|
-
M2.message("");
|
|
36142
|
-
}
|
|
36143
|
-
M2.message(source_default.gray("This will add/update hooks in ~/.claude/settings.json"));
|
|
36144
|
-
M2.message("");
|
|
36145
|
-
const syncSettingsResult = await ye({
|
|
36146
|
-
message: "Do you want to sync these hooks to settings.json?",
|
|
36147
|
-
initialValue: false
|
|
36148
|
-
});
|
|
36149
|
-
if (!pD(syncSettingsResult) && syncSettingsResult) {
|
|
36150
|
-
const spinner2 = Y2();
|
|
36151
|
-
spinner2.start("Syncing hooks to settings.json...");
|
|
36152
|
-
selectedHooks = [...changedHooks];
|
|
36153
|
-
const hooksResult = await syncSelectedHooks(claudeDir, selectedHooks, (hook, action) => {
|
|
36154
|
-
spinner2.message(`${action}: ${source_default.cyan(hook)}`);
|
|
36155
|
-
});
|
|
36156
|
-
spinner2.stop("Hooks synced to settings.json");
|
|
36157
|
-
if (hooksResult.success > 0) {
|
|
36158
|
-
M2.success(source_default.green(`${hooksResult.success} hook${hooksResult.success > 1 ? "s" : ""} synced`));
|
|
36159
|
-
}
|
|
36160
|
-
if (hooksResult.failed > 0) {
|
|
36161
|
-
M2.warn(source_default.yellow(`${hooksResult.failed} hook${hooksResult.failed > 1 ? "s" : ""} failed`));
|
|
36162
|
-
}
|
|
36163
|
-
} else {
|
|
36164
|
-
M2.info(source_default.gray("Skipped settings.json sync"));
|
|
36165
|
-
}
|
|
36166
|
-
}
|
|
36167
36328
|
const scriptsWereSynced = selectedItems.some((i) => i.category === "scripts");
|
|
36168
36329
|
if (scriptsWereSynced) {
|
|
36169
36330
|
spinner.start("Installing scripts dependencies...");
|
|
@@ -36172,9 +36333,9 @@ async function proSyncCommand(options = {}) {
|
|
|
36172
36333
|
}
|
|
36173
36334
|
trackEvent("pro-sync", {
|
|
36174
36335
|
added: syncResult.success,
|
|
36336
|
+
migrated: syncResult.migrated,
|
|
36175
36337
|
deleted: syncResult.deleted,
|
|
36176
|
-
failed: syncResult.failed
|
|
36177
|
-
hookssynced: selectedHooks.length
|
|
36338
|
+
failed: syncResult.failed
|
|
36178
36339
|
});
|
|
36179
36340
|
Se(source_default.green("✅ Sync completed"));
|
|
36180
36341
|
} catch (error) {
|
|
@@ -36189,8 +36350,8 @@ async function proSyncCommand(options = {}) {
|
|
|
36189
36350
|
}
|
|
36190
36351
|
|
|
36191
36352
|
// src/commands/backup.ts
|
|
36192
|
-
import
|
|
36193
|
-
import
|
|
36353
|
+
import os17 from "os";
|
|
36354
|
+
import path18 from "path";
|
|
36194
36355
|
function formatBackupDate(date) {
|
|
36195
36356
|
const now = new Date;
|
|
36196
36357
|
const diffMs = now.getTime() - date.getTime();
|
|
@@ -36210,7 +36371,8 @@ function formatBackupDate(date) {
|
|
|
36210
36371
|
return `${date.toLocaleString()} (${relative})`;
|
|
36211
36372
|
}
|
|
36212
36373
|
async function backupLoadCommand(options = {}) {
|
|
36213
|
-
const claudeDir = options.folder ||
|
|
36374
|
+
const claudeDir = options.folder || path18.join(os17.homedir(), ".claude");
|
|
36375
|
+
const agentsDir = getAgentsDir(options.agentsFolder);
|
|
36214
36376
|
Ie(source_default.blue("\uD83D\uDCE6 Load Backup"));
|
|
36215
36377
|
const spinner = Y2();
|
|
36216
36378
|
spinner.start("Scanning for backups...");
|
|
@@ -36246,7 +36408,7 @@ async function backupLoadCommand(options = {}) {
|
|
|
36246
36408
|
process.exit(0);
|
|
36247
36409
|
}
|
|
36248
36410
|
spinner.start("Creating backup of current configuration...");
|
|
36249
|
-
const currentBackup = await createBackup(claudeDir);
|
|
36411
|
+
const currentBackup = await createBackup(claudeDir, agentsDir);
|
|
36250
36412
|
if (currentBackup) {
|
|
36251
36413
|
spinner.stop(`Current config backed up to: ${source_default.gray(currentBackup)}`);
|
|
36252
36414
|
} else {
|
|
@@ -36254,7 +36416,7 @@ async function backupLoadCommand(options = {}) {
|
|
|
36254
36416
|
}
|
|
36255
36417
|
spinner.start("Restoring backup...");
|
|
36256
36418
|
try {
|
|
36257
|
-
await loadBackup(selected.path, claudeDir);
|
|
36419
|
+
await loadBackup(selected.path, claudeDir, agentsDir);
|
|
36258
36420
|
spinner.stop("Backup restored successfully");
|
|
36259
36421
|
M2.success(`Restored configuration from ${source_default.cyan(selected.name)}`);
|
|
36260
36422
|
Se(source_default.green("✅ Backup loaded successfully"));
|
|
@@ -36266,19 +36428,19 @@ async function backupLoadCommand(options = {}) {
|
|
|
36266
36428
|
}
|
|
36267
36429
|
|
|
36268
36430
|
// src/commands/openclaw-pro.ts
|
|
36269
|
-
import
|
|
36270
|
-
import
|
|
36431
|
+
import os20 from "os";
|
|
36432
|
+
import path21 from "path";
|
|
36271
36433
|
|
|
36272
36434
|
// src/lib/openclaw-installer.ts
|
|
36273
|
-
var
|
|
36274
|
-
import
|
|
36275
|
-
import
|
|
36435
|
+
var import_fs_extra14 = __toESM(require_lib4(), 1);
|
|
36436
|
+
import os18 from "os";
|
|
36437
|
+
import path19 from "path";
|
|
36276
36438
|
import { exec as exec4 } from "child_process";
|
|
36277
36439
|
import { promisify as promisify3 } from "util";
|
|
36278
36440
|
var execAsync3 = promisify3(exec4);
|
|
36279
36441
|
var OPENCLAW_PRO_REPO = "Melvynx/openclawpro";
|
|
36280
36442
|
function getCacheRepoDir2() {
|
|
36281
|
-
return
|
|
36443
|
+
return path19.join(os18.homedir(), ".config", "openclaw", "pro-repos", "openclawpro");
|
|
36282
36444
|
}
|
|
36283
36445
|
async function execGitWithAuth2(command, token, repoUrl, cwd) {
|
|
36284
36446
|
const authenticatedUrl = `https://x-access-token:${token}@${repoUrl.replace(/^https?:\/\//, "")}`;
|
|
@@ -36292,33 +36454,33 @@ async function execGitWithAuth2(command, token, repoUrl, cwd) {
|
|
|
36292
36454
|
async function cloneOrUpdateRepo2(token) {
|
|
36293
36455
|
const cacheDir = getCacheRepoDir2();
|
|
36294
36456
|
const repoUrl = `https://github.com/${OPENCLAW_PRO_REPO}.git`;
|
|
36295
|
-
if (await
|
|
36457
|
+
if (await import_fs_extra14.default.pathExists(path19.join(cacheDir, ".git"))) {
|
|
36296
36458
|
try {
|
|
36297
36459
|
await execGitWithAuth2("pull", token, repoUrl, cacheDir);
|
|
36298
36460
|
} catch (error) {
|
|
36299
|
-
await
|
|
36300
|
-
await
|
|
36461
|
+
await import_fs_extra14.default.remove(cacheDir);
|
|
36462
|
+
await import_fs_extra14.default.ensureDir(path19.dirname(cacheDir));
|
|
36301
36463
|
await execGitWithAuth2(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
36302
36464
|
}
|
|
36303
36465
|
} else {
|
|
36304
|
-
await
|
|
36466
|
+
await import_fs_extra14.default.ensureDir(path19.dirname(cacheDir));
|
|
36305
36467
|
await execGitWithAuth2(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
36306
36468
|
}
|
|
36307
|
-
return
|
|
36469
|
+
return path19.join(cacheDir, "openclaw-config");
|
|
36308
36470
|
}
|
|
36309
36471
|
async function copyConfigFromCache2(cacheConfigDir, targetDir, onProgress) {
|
|
36310
36472
|
const walk = async (dir, baseDir = dir) => {
|
|
36311
|
-
const entries = await
|
|
36473
|
+
const entries = await import_fs_extra14.default.readdir(dir, { withFileTypes: true });
|
|
36312
36474
|
for (const entry of entries) {
|
|
36313
|
-
const sourcePath =
|
|
36314
|
-
const relativePath =
|
|
36315
|
-
const targetPath =
|
|
36475
|
+
const sourcePath = path19.join(dir, entry.name);
|
|
36476
|
+
const relativePath = path19.relative(baseDir, sourcePath);
|
|
36477
|
+
const targetPath = path19.join(targetDir, relativePath);
|
|
36316
36478
|
if (entry.isDirectory()) {
|
|
36317
|
-
await
|
|
36479
|
+
await import_fs_extra14.default.ensureDir(targetPath);
|
|
36318
36480
|
onProgress?.(relativePath, "directory");
|
|
36319
36481
|
await walk(sourcePath, baseDir);
|
|
36320
36482
|
} else {
|
|
36321
|
-
await
|
|
36483
|
+
await import_fs_extra14.default.copy(sourcePath, targetPath, { overwrite: true });
|
|
36322
36484
|
onProgress?.(relativePath, "file");
|
|
36323
36485
|
}
|
|
36324
36486
|
}
|
|
@@ -36327,7 +36489,7 @@ async function copyConfigFromCache2(cacheConfigDir, targetDir, onProgress) {
|
|
|
36327
36489
|
}
|
|
36328
36490
|
async function installOpenclawProConfigs(options) {
|
|
36329
36491
|
const { githubToken, openclawFolder, onProgress } = options;
|
|
36330
|
-
const targetFolder = openclawFolder ||
|
|
36492
|
+
const targetFolder = openclawFolder || path19.join(os18.homedir(), ".openclaw");
|
|
36331
36493
|
try {
|
|
36332
36494
|
const cacheConfigDir = await cloneOrUpdateRepo2(githubToken);
|
|
36333
36495
|
await copyConfigFromCache2(cacheConfigDir, targetFolder, onProgress);
|
|
@@ -36338,28 +36500,28 @@ async function installOpenclawProConfigs(options) {
|
|
|
36338
36500
|
}
|
|
36339
36501
|
|
|
36340
36502
|
// src/lib/openclaw-token-storage.ts
|
|
36341
|
-
var
|
|
36342
|
-
import
|
|
36343
|
-
import
|
|
36503
|
+
var import_fs_extra15 = __toESM(require_lib4(), 1);
|
|
36504
|
+
import os19 from "os";
|
|
36505
|
+
import path20 from "path";
|
|
36344
36506
|
function getConfigDir2() {
|
|
36345
|
-
const platform =
|
|
36507
|
+
const platform = os19.platform();
|
|
36346
36508
|
if (platform === "win32") {
|
|
36347
|
-
return
|
|
36509
|
+
return path20.join(process.env.APPDATA || os19.homedir(), "openclaw");
|
|
36348
36510
|
}
|
|
36349
|
-
return
|
|
36511
|
+
return path20.join(os19.homedir(), ".config", "openclaw");
|
|
36350
36512
|
}
|
|
36351
36513
|
function getTokenPath() {
|
|
36352
|
-
return
|
|
36514
|
+
return path20.join(getConfigDir2(), "token.txt");
|
|
36353
36515
|
}
|
|
36354
36516
|
async function saveOpenclawToken(githubToken) {
|
|
36355
36517
|
const configDir = getConfigDir2();
|
|
36356
|
-
await
|
|
36357
|
-
await
|
|
36518
|
+
await import_fs_extra15.default.ensureDir(configDir);
|
|
36519
|
+
await import_fs_extra15.default.writeFile(getTokenPath(), githubToken, { mode: 384 });
|
|
36358
36520
|
}
|
|
36359
36521
|
async function getOpenclawToken() {
|
|
36360
36522
|
const tokenPath = getTokenPath();
|
|
36361
|
-
if (await
|
|
36362
|
-
const token = await
|
|
36523
|
+
if (await import_fs_extra15.default.pathExists(tokenPath)) {
|
|
36524
|
+
const token = await import_fs_extra15.default.readFile(tokenPath, "utf8");
|
|
36363
36525
|
return token.trim();
|
|
36364
36526
|
}
|
|
36365
36527
|
return null;
|
|
@@ -36367,12 +36529,12 @@ async function getOpenclawToken() {
|
|
|
36367
36529
|
function getOpenclawTokenInfo() {
|
|
36368
36530
|
return {
|
|
36369
36531
|
path: getTokenPath(),
|
|
36370
|
-
platform:
|
|
36532
|
+
platform: os19.platform()
|
|
36371
36533
|
};
|
|
36372
36534
|
}
|
|
36373
36535
|
|
|
36374
36536
|
// src/commands/openclaw-pro.ts
|
|
36375
|
-
var
|
|
36537
|
+
var import_fs_extra16 = __toESM(require_lib4(), 1);
|
|
36376
36538
|
var API_URL2 = "https://codeline.app/api/products";
|
|
36377
36539
|
var OPENCLAW_PRODUCT_ID = "prd_t2GRwX3aH1";
|
|
36378
36540
|
var CLAUDE_CODE_TOOLS_INSTRUCTIONS = `
|
|
@@ -36479,7 +36641,7 @@ async function openclawProSetupCommand(options = {}) {
|
|
|
36479
36641
|
Se(source_default.red("❌ Not activated"));
|
|
36480
36642
|
process.exit(1);
|
|
36481
36643
|
}
|
|
36482
|
-
const openclawDir = options.folder ?
|
|
36644
|
+
const openclawDir = options.folder ? path21.resolve(options.folder) : path21.join(os20.homedir(), ".openclaw");
|
|
36483
36645
|
const spinner = Y2();
|
|
36484
36646
|
const onProgress = (file, type) => {
|
|
36485
36647
|
spinner.message(`Installing: ${source_default.cyan(file)} ${source_default.gray(`(${type})`)}`);
|
|
@@ -36492,23 +36654,23 @@ async function openclawProSetupCommand(options = {}) {
|
|
|
36492
36654
|
});
|
|
36493
36655
|
spinner.stop("OpenClaw Pro configurations installed");
|
|
36494
36656
|
let skillCount = 0;
|
|
36495
|
-
const skillsDir =
|
|
36496
|
-
if (await
|
|
36497
|
-
const items = await
|
|
36657
|
+
const skillsDir = path21.join(openclawDir, "skills");
|
|
36658
|
+
if (await import_fs_extra16.default.pathExists(skillsDir)) {
|
|
36659
|
+
const items = await import_fs_extra16.default.readdir(skillsDir);
|
|
36498
36660
|
const dirs = await Promise.all(items.map(async (item) => {
|
|
36499
|
-
const stat = await
|
|
36661
|
+
const stat = await import_fs_extra16.default.stat(path21.join(skillsDir, item));
|
|
36500
36662
|
return stat.isDirectory();
|
|
36501
36663
|
}));
|
|
36502
36664
|
skillCount = dirs.filter(Boolean).length;
|
|
36503
36665
|
}
|
|
36504
36666
|
spinner.start("Setting up workspace TOOLS.md...");
|
|
36505
|
-
const workspaceDir =
|
|
36506
|
-
const toolsPath =
|
|
36507
|
-
await
|
|
36508
|
-
if (await
|
|
36509
|
-
const existingContent = await
|
|
36667
|
+
const workspaceDir = path21.join(openclawDir, "workspace");
|
|
36668
|
+
const toolsPath = path21.join(workspaceDir, "TOOLS.md");
|
|
36669
|
+
await import_fs_extra16.default.ensureDir(workspaceDir);
|
|
36670
|
+
if (await import_fs_extra16.default.pathExists(toolsPath)) {
|
|
36671
|
+
const existingContent = await import_fs_extra16.default.readFile(toolsPath, "utf-8");
|
|
36510
36672
|
if (!existingContent.includes("Claude Code CLI")) {
|
|
36511
|
-
await
|
|
36673
|
+
await import_fs_extra16.default.appendFile(toolsPath, `
|
|
36512
36674
|
|
|
36513
36675
|
` + CLAUDE_CODE_TOOLS_INSTRUCTIONS);
|
|
36514
36676
|
spinner.stop("TOOLS.md updated with Claude Code instructions");
|
|
@@ -36522,7 +36684,7 @@ Skills define _how_ tools work. This file is for _your_ specifics — the stuff
|
|
|
36522
36684
|
|
|
36523
36685
|
${CLAUDE_CODE_TOOLS_INSTRUCTIONS}
|
|
36524
36686
|
`;
|
|
36525
|
-
await
|
|
36687
|
+
await import_fs_extra16.default.writeFile(toolsPath, defaultToolsMd);
|
|
36526
36688
|
spinner.stop("TOOLS.md created with Claude Code instructions");
|
|
36527
36689
|
}
|
|
36528
36690
|
spinner.start("Creating claude-run wrapper...");
|
|
@@ -36533,9 +36695,9 @@ ${CLAUDE_CODE_TOOLS_INSTRUCTIONS}
|
|
|
36533
36695
|
script -q -c "claude $*" /dev/null
|
|
36534
36696
|
`;
|
|
36535
36697
|
const binDir = "/usr/local/bin";
|
|
36536
|
-
const wrapperPath =
|
|
36698
|
+
const wrapperPath = path21.join(binDir, "claude-run");
|
|
36537
36699
|
try {
|
|
36538
|
-
await
|
|
36700
|
+
await import_fs_extra16.default.writeFile(wrapperPath, claudeRunWrapper, { mode: 493 });
|
|
36539
36701
|
spinner.stop("claude-run wrapper created");
|
|
36540
36702
|
} catch {
|
|
36541
36703
|
spinner.stop("claude-run wrapper skipped (no write access to /usr/local/bin)");
|
|
@@ -36584,12 +36746,12 @@ async function openclawProUpdateCommand(options = {}) {
|
|
|
36584
36746
|
}
|
|
36585
36747
|
|
|
36586
36748
|
// src/commands/dynamic-scripts.ts
|
|
36587
|
-
import
|
|
36749
|
+
import path24 from "path";
|
|
36588
36750
|
import { homedir } from "os";
|
|
36589
36751
|
|
|
36590
36752
|
// src/lib/script-parser.ts
|
|
36591
|
-
var
|
|
36592
|
-
import
|
|
36753
|
+
var import_fs_extra17 = __toESM(require_lib4(), 1);
|
|
36754
|
+
import path22 from "path";
|
|
36593
36755
|
var EXCLUDED_SCRIPTS = ["test", "lint", "format", "start"];
|
|
36594
36756
|
var EXCLUDED_SUFFIXES = [":test", ":lint", ":test-fixtures", ":start"];
|
|
36595
36757
|
function shouldIncludeScript(scriptName) {
|
|
@@ -36600,12 +36762,12 @@ function shouldIncludeScript(scriptName) {
|
|
|
36600
36762
|
return true;
|
|
36601
36763
|
}
|
|
36602
36764
|
async function readScriptsPackageJson(claudeDir) {
|
|
36603
|
-
const packageJsonPath =
|
|
36765
|
+
const packageJsonPath = path22.join(claudeDir, "scripts", "package.json");
|
|
36604
36766
|
try {
|
|
36605
|
-
if (!await
|
|
36767
|
+
if (!await import_fs_extra17.default.pathExists(packageJsonPath)) {
|
|
36606
36768
|
return null;
|
|
36607
36769
|
}
|
|
36608
|
-
const content = await
|
|
36770
|
+
const content = await import_fs_extra17.default.readFile(packageJsonPath, "utf-8");
|
|
36609
36771
|
const parsed = JSON.parse(content);
|
|
36610
36772
|
return parsed.scripts || null;
|
|
36611
36773
|
} catch (error) {
|
|
@@ -36649,14 +36811,14 @@ function groupScriptsByPrefix(commands) {
|
|
|
36649
36811
|
}
|
|
36650
36812
|
|
|
36651
36813
|
// src/commands/script-runner.ts
|
|
36652
|
-
var
|
|
36814
|
+
var import_fs_extra18 = __toESM(require_lib4(), 1);
|
|
36653
36815
|
import { spawn as spawn2 } from "child_process";
|
|
36654
36816
|
import { execSync as execSync4 } from "child_process";
|
|
36655
|
-
import
|
|
36656
|
-
import
|
|
36817
|
+
import path23 from "path";
|
|
36818
|
+
import os21 from "os";
|
|
36657
36819
|
function checkCommand2(cmd) {
|
|
36658
36820
|
try {
|
|
36659
|
-
const isWindows2 =
|
|
36821
|
+
const isWindows2 = os21.platform() === "win32";
|
|
36660
36822
|
const whichCmd = isWindows2 ? `where ${cmd}` : `which ${cmd}`;
|
|
36661
36823
|
execSync4(whichCmd, { stdio: "ignore" });
|
|
36662
36824
|
return true;
|
|
@@ -36682,18 +36844,18 @@ async function executeScript(scriptName, claudeDir) {
|
|
|
36682
36844
|
console.error(source_default.red("Bun is not installed. Install with: npm install -g bun"));
|
|
36683
36845
|
return 1;
|
|
36684
36846
|
}
|
|
36685
|
-
const scriptsDir =
|
|
36686
|
-
if (!await
|
|
36847
|
+
const scriptsDir = path23.join(claudeDir, "scripts");
|
|
36848
|
+
if (!await import_fs_extra18.default.pathExists(scriptsDir)) {
|
|
36687
36849
|
console.error(source_default.red(`Scripts directory not found at ${scriptsDir}`));
|
|
36688
36850
|
console.log(source_default.gray("Run: aiblueprint claude-code setup"));
|
|
36689
36851
|
return 1;
|
|
36690
36852
|
}
|
|
36691
|
-
const packageJsonPath =
|
|
36692
|
-
if (!await
|
|
36853
|
+
const packageJsonPath = path23.join(scriptsDir, "package.json");
|
|
36854
|
+
if (!await import_fs_extra18.default.pathExists(packageJsonPath)) {
|
|
36693
36855
|
console.error(source_default.red(`package.json not found in ${scriptsDir}`));
|
|
36694
36856
|
return 1;
|
|
36695
36857
|
}
|
|
36696
|
-
const packageJson = await
|
|
36858
|
+
const packageJson = await import_fs_extra18.default.readJson(packageJsonPath);
|
|
36697
36859
|
if (!packageJson.scripts || !packageJson.scripts[scriptName]) {
|
|
36698
36860
|
console.error(source_default.red(`Script "${scriptName}" not found in package.json`));
|
|
36699
36861
|
return 1;
|
|
@@ -36716,7 +36878,7 @@ async function executeScript(scriptName, claudeDir) {
|
|
|
36716
36878
|
|
|
36717
36879
|
// src/commands/dynamic-scripts.ts
|
|
36718
36880
|
function getClaudeDir(parentOptions) {
|
|
36719
|
-
return parentOptions.claudeCodeFolder || parentOptions.folder ?
|
|
36881
|
+
return parentOptions.claudeCodeFolder || parentOptions.folder ? path24.resolve(parentOptions.claudeCodeFolder || parentOptions.folder) : path24.join(homedir(), ".claude");
|
|
36720
36882
|
}
|
|
36721
36883
|
async function registerDynamicScriptCommands(claudeCodeCmd, claudeDir) {
|
|
36722
36884
|
const scripts = await readScriptsPackageJson(claudeDir);
|
|
@@ -36751,13 +36913,14 @@ var __dirname3 = dirname3(fileURLToPath3(import.meta.url));
|
|
|
36751
36913
|
var packageJson = JSON.parse(readFileSync3(join2(__dirname3, "../package.json"), "utf8"));
|
|
36752
36914
|
var program2 = new Command;
|
|
36753
36915
|
program2.name("aiblueprint").description("AIBlueprint CLI for setting up Claude Code configurations").version(packageJson.version);
|
|
36754
|
-
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");
|
|
36916
|
+
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("--agentsFolder <path>", "Specify custom agents folder path (default: ~/.agents)").option("-s, --skip", "Skip interactive prompts and install all features");
|
|
36755
36917
|
claudeCodeCmd.command("setup").description("Setup Claude Code configuration with AIBlueprint defaults").action((options, command) => {
|
|
36756
36918
|
const parentOptions = command.parent.opts();
|
|
36757
36919
|
setupCommand({
|
|
36758
36920
|
claudeCodeFolder: parentOptions.claudeCodeFolder || parentOptions.folder,
|
|
36759
36921
|
codexFolder: parentOptions.codexFolder,
|
|
36760
36922
|
openCodeFolder: parentOptions.openCodeFolder,
|
|
36923
|
+
agentsFolder: parentOptions.agentsFolder,
|
|
36761
36924
|
skipInteractive: parentOptions.skip
|
|
36762
36925
|
});
|
|
36763
36926
|
});
|
|
@@ -36787,23 +36950,26 @@ proCmd.command("status").description("Check your Premium token status").action((
|
|
|
36787
36950
|
proCmd.command("setup").description("Install premium configurations (requires activation)").action((options, command) => {
|
|
36788
36951
|
const parentOptions = command.parent.parent.opts();
|
|
36789
36952
|
const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
|
|
36790
|
-
proSetupCommand({ folder: claudeCodeFolder });
|
|
36953
|
+
proSetupCommand({ folder: claudeCodeFolder, agentsFolder: parentOptions.agentsFolder });
|
|
36791
36954
|
});
|
|
36792
36955
|
proCmd.command("update").description("Update premium configurations").action((options, command) => {
|
|
36793
36956
|
const parentOptions = command.parent.parent.opts();
|
|
36794
36957
|
const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
|
|
36795
|
-
proUpdateCommand({ folder: claudeCodeFolder });
|
|
36958
|
+
proUpdateCommand({ folder: claudeCodeFolder, agentsFolder: parentOptions.agentsFolder });
|
|
36796
36959
|
});
|
|
36797
36960
|
proCmd.command("sync").description("Sync premium configurations with selective update").action((options, command) => {
|
|
36798
36961
|
const parentOptions = command.parent.parent.opts();
|
|
36799
36962
|
const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
|
|
36800
|
-
proSyncCommand({ folder: claudeCodeFolder });
|
|
36963
|
+
proSyncCommand({ folder: claudeCodeFolder, agentsFolder: parentOptions.agentsFolder });
|
|
36801
36964
|
});
|
|
36802
36965
|
var backupCmd = claudeCodeCmd.command("backup").description("Manage Claude Code configuration backups");
|
|
36803
36966
|
backupCmd.command("load").description("Load a previous backup interactively").action((options, command) => {
|
|
36804
36967
|
const parentOptions = command.parent.parent.opts();
|
|
36805
36968
|
const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
|
|
36806
|
-
backupLoadCommand({
|
|
36969
|
+
backupLoadCommand({
|
|
36970
|
+
folder: claudeCodeFolder,
|
|
36971
|
+
agentsFolder: parentOptions.agentsFolder
|
|
36972
|
+
});
|
|
36807
36973
|
});
|
|
36808
36974
|
var openclawCmd = program2.command("openclaw").description("OpenClaw configuration commands").option("-f, --folder <path>", "Specify custom OpenClaw folder path (default: ~/.openclaw)");
|
|
36809
36975
|
var openclawProCmd = openclawCmd.command("pro").description("Manage OpenClaw Pro features");
|