aiblueprint-cli 1.4.46 → 1.4.49

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