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