aiblueprint-cli 1.4.45 → 1.4.48

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