@relipa/ai-flow-kit 0.0.1

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 (204) hide show
  1. package/AIFLOW.md +432 -0
  2. package/CHANGELOG.md +78 -0
  3. package/CONTRIBUTING.md +351 -0
  4. package/IMPLEMENTATION_SUMMARY.md +348 -0
  5. package/QUICK_START.md +392 -0
  6. package/README.md +323 -0
  7. package/bin/aiflow.js +178 -0
  8. package/custom/mcp-presets/README.md +138 -0
  9. package/custom/mcp-presets/backlog.json +15 -0
  10. package/custom/mcp-presets/figma.json +15 -0
  11. package/custom/mcp-presets/google-sheets.json +14 -0
  12. package/custom/mcp-presets/jira.json +16 -0
  13. package/custom/prompts/bug-fix.md +149 -0
  14. package/custom/prompts/feature.md +190 -0
  15. package/custom/prompts/investigation.md +164 -0
  16. package/custom/rules/code-style.md +7 -0
  17. package/custom/rules/java/code-style.md +11 -0
  18. package/custom/rules/java/naming.md +17 -0
  19. package/custom/rules/java/review-checklist.md +36 -0
  20. package/custom/rules/javascript/code-style.md +12 -0
  21. package/custom/rules/javascript/naming.md +14 -0
  22. package/custom/rules/naming.md +9 -0
  23. package/custom/rules/php/code-style.md +10 -0
  24. package/custom/rules/php/naming.md +15 -0
  25. package/custom/rules/review-checklist.md +9 -0
  26. package/custom/skills/figma-to-component/SKILL.md +207 -0
  27. package/custom/skills/generate-spec/SKILL.md +97 -0
  28. package/custom/skills/impact-analysis/SKILL.md +94 -0
  29. package/custom/skills/investigate-bug/SKILL.md +93 -0
  30. package/custom/skills/report-customer/SKILL.md +95 -0
  31. package/custom/skills/review-plan/SKILL.md +158 -0
  32. package/custom/skills/validate-ticket/SKILL.md +240 -0
  33. package/custom/templates/laravel.md +90 -0
  34. package/custom/templates/nextjs.md +89 -0
  35. package/custom/templates/reactjs.md +567 -0
  36. package/custom/templates/spring-boot.md +598 -0
  37. package/custom/templates/vue-nuxt.md +89 -0
  38. package/docs/architecture.md +395 -0
  39. package/docs/cli-reference.md +438 -0
  40. package/docs/configuration.md +412 -0
  41. package/docs/getting-started.md +248 -0
  42. package/docs/troubleshooting.md +587 -0
  43. package/docs/workflows/bug-fix.md +126 -0
  44. package/docs/workflows/feature.md +123 -0
  45. package/docs/workflows/impact-analysis.md +13 -0
  46. package/docs/workflows/investigation.md +13 -0
  47. package/docs/workflows/refactor.md +13 -0
  48. package/index.js +27 -0
  49. package/package.json +70 -0
  50. package/scripts/config.js +317 -0
  51. package/scripts/context.js +117 -0
  52. package/scripts/detect.js +239 -0
  53. package/scripts/doctor.js +48 -0
  54. package/scripts/guide.js +282 -0
  55. package/scripts/hooks/session-start.js +140 -0
  56. package/scripts/init.js +453 -0
  57. package/scripts/memory.js +247 -0
  58. package/scripts/prompt.js +392 -0
  59. package/scripts/remove.js +170 -0
  60. package/scripts/update.js +111 -0
  61. package/scripts/use.js +570 -0
  62. package/scripts/validate.js +303 -0
  63. package/upstream/.claude-plugin/marketplace.json +20 -0
  64. package/upstream/.claude-plugin/plugin.json +20 -0
  65. package/upstream/.codex/INSTALL.md +67 -0
  66. package/upstream/.cursor-plugin/plugin.json +25 -0
  67. package/upstream/.gitattributes +18 -0
  68. package/upstream/.github/FUNDING.yml +3 -0
  69. package/upstream/.github/ISSUE_TEMPLATE/bug_report.md +52 -0
  70. package/upstream/.github/ISSUE_TEMPLATE/config.yml +5 -0
  71. package/upstream/.github/ISSUE_TEMPLATE/feature_request.md +34 -0
  72. package/upstream/.github/ISSUE_TEMPLATE/platform_support.md +23 -0
  73. package/upstream/.github/PULL_REQUEST_TEMPLATE.md +87 -0
  74. package/upstream/.opencode/INSTALL.md +83 -0
  75. package/upstream/.opencode/plugins/superpowers.js +112 -0
  76. package/upstream/.version-bump.json +19 -0
  77. package/upstream/AGENTS.md +1 -0
  78. package/upstream/CHANGELOG.md +13 -0
  79. package/upstream/CLAUDE.md +85 -0
  80. package/upstream/CODE_OF_CONDUCT.md +128 -0
  81. package/upstream/GEMINI.md +2 -0
  82. package/upstream/LICENSE +21 -0
  83. package/upstream/README.md +190 -0
  84. package/upstream/RELEASE-NOTES.md +1096 -0
  85. package/upstream/agents/code-reviewer.md +48 -0
  86. package/upstream/commands/brainstorm.md +5 -0
  87. package/upstream/commands/execute-plan.md +5 -0
  88. package/upstream/commands/write-plan.md +5 -0
  89. package/upstream/docs/README.codex.md +126 -0
  90. package/upstream/docs/README.opencode.md +130 -0
  91. package/upstream/docs/plans/2025-11-22-opencode-support-design.md +294 -0
  92. package/upstream/docs/plans/2025-11-22-opencode-support-implementation.md +1095 -0
  93. package/upstream/docs/plans/2025-11-28-skills-improvements-from-user-feedback.md +711 -0
  94. package/upstream/docs/plans/2026-01-17-visual-brainstorming.md +571 -0
  95. package/upstream/docs/superpowers/plans/2026-01-22-document-review-system.md +301 -0
  96. package/upstream/docs/superpowers/plans/2026-02-19-visual-brainstorming-refactor.md +523 -0
  97. package/upstream/docs/superpowers/plans/2026-03-11-zero-dep-brainstorm-server.md +479 -0
  98. package/upstream/docs/superpowers/plans/2026-03-23-codex-app-compatibility.md +564 -0
  99. package/upstream/docs/superpowers/specs/2026-01-22-document-review-system-design.md +136 -0
  100. package/upstream/docs/superpowers/specs/2026-02-19-visual-brainstorming-refactor-design.md +162 -0
  101. package/upstream/docs/superpowers/specs/2026-03-11-zero-dep-brainstorm-server-design.md +118 -0
  102. package/upstream/docs/superpowers/specs/2026-03-23-codex-app-compatibility-design.md +244 -0
  103. package/upstream/docs/testing.md +303 -0
  104. package/upstream/docs/windows/polyglot-hooks.md +212 -0
  105. package/upstream/gemini-extension.json +6 -0
  106. package/upstream/hooks/hooks-cursor.json +10 -0
  107. package/upstream/hooks/hooks.json +16 -0
  108. package/upstream/hooks/run-hook.cmd +46 -0
  109. package/upstream/hooks/session-start +57 -0
  110. package/upstream/package.json +6 -0
  111. package/upstream/scripts/bump-version.sh +220 -0
  112. package/upstream/skills/brainstorming/SKILL.md +164 -0
  113. package/upstream/skills/brainstorming/scripts/frame-template.html +214 -0
  114. package/upstream/skills/brainstorming/scripts/helper.js +88 -0
  115. package/upstream/skills/brainstorming/scripts/server.cjs +354 -0
  116. package/upstream/skills/brainstorming/scripts/start-server.sh +148 -0
  117. package/upstream/skills/brainstorming/scripts/stop-server.sh +56 -0
  118. package/upstream/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  119. package/upstream/skills/brainstorming/visual-companion.md +287 -0
  120. package/upstream/skills/dispatching-parallel-agents/SKILL.md +182 -0
  121. package/upstream/skills/executing-plans/SKILL.md +70 -0
  122. package/upstream/skills/finishing-a-development-branch/SKILL.md +200 -0
  123. package/upstream/skills/receiving-code-review/SKILL.md +213 -0
  124. package/upstream/skills/requesting-code-review/SKILL.md +105 -0
  125. package/upstream/skills/requesting-code-review/code-reviewer.md +146 -0
  126. package/upstream/skills/subagent-driven-development/SKILL.md +277 -0
  127. package/upstream/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
  128. package/upstream/skills/subagent-driven-development/implementer-prompt.md +113 -0
  129. package/upstream/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  130. package/upstream/skills/systematic-debugging/CREATION-LOG.md +119 -0
  131. package/upstream/skills/systematic-debugging/SKILL.md +296 -0
  132. package/upstream/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  133. package/upstream/skills/systematic-debugging/condition-based-waiting.md +115 -0
  134. package/upstream/skills/systematic-debugging/defense-in-depth.md +122 -0
  135. package/upstream/skills/systematic-debugging/find-polluter.sh +63 -0
  136. package/upstream/skills/systematic-debugging/root-cause-tracing.md +169 -0
  137. package/upstream/skills/systematic-debugging/test-academic.md +14 -0
  138. package/upstream/skills/systematic-debugging/test-pressure-1.md +58 -0
  139. package/upstream/skills/systematic-debugging/test-pressure-2.md +68 -0
  140. package/upstream/skills/systematic-debugging/test-pressure-3.md +69 -0
  141. package/upstream/skills/test-driven-development/SKILL.md +371 -0
  142. package/upstream/skills/test-driven-development/testing-anti-patterns.md +299 -0
  143. package/upstream/skills/using-git-worktrees/SKILL.md +218 -0
  144. package/upstream/skills/using-superpowers/SKILL.md +117 -0
  145. package/upstream/skills/using-superpowers/references/codex-tools.md +100 -0
  146. package/upstream/skills/using-superpowers/references/copilot-tools.md +52 -0
  147. package/upstream/skills/using-superpowers/references/gemini-tools.md +33 -0
  148. package/upstream/skills/verification-before-completion/SKILL.md +139 -0
  149. package/upstream/skills/writing-plans/SKILL.md +152 -0
  150. package/upstream/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
  151. package/upstream/skills/writing-skills/SKILL.md +655 -0
  152. package/upstream/skills/writing-skills/anthropic-best-practices.md +1150 -0
  153. package/upstream/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  154. package/upstream/skills/writing-skills/graphviz-conventions.dot +172 -0
  155. package/upstream/skills/writing-skills/persuasion-principles.md +187 -0
  156. package/upstream/skills/writing-skills/render-graphs.js +168 -0
  157. package/upstream/skills/writing-skills/testing-skills-with-subagents.md +384 -0
  158. package/upstream/tests/brainstorm-server/package-lock.json +36 -0
  159. package/upstream/tests/brainstorm-server/package.json +10 -0
  160. package/upstream/tests/brainstorm-server/server.test.js +427 -0
  161. package/upstream/tests/brainstorm-server/windows-lifecycle.test.sh +351 -0
  162. package/upstream/tests/brainstorm-server/ws-protocol.test.js +392 -0
  163. package/upstream/tests/claude-code/README.md +158 -0
  164. package/upstream/tests/claude-code/analyze-token-usage.py +168 -0
  165. package/upstream/tests/claude-code/run-skill-tests.sh +187 -0
  166. package/upstream/tests/claude-code/test-document-review-system.sh +177 -0
  167. package/upstream/tests/claude-code/test-helpers.sh +202 -0
  168. package/upstream/tests/claude-code/test-subagent-driven-development-integration.sh +314 -0
  169. package/upstream/tests/claude-code/test-subagent-driven-development.sh +165 -0
  170. package/upstream/tests/explicit-skill-requests/prompts/action-oriented.txt +3 -0
  171. package/upstream/tests/explicit-skill-requests/prompts/after-planning-flow.txt +17 -0
  172. package/upstream/tests/explicit-skill-requests/prompts/claude-suggested-it.txt +11 -0
  173. package/upstream/tests/explicit-skill-requests/prompts/i-know-what-sdd-means.txt +8 -0
  174. package/upstream/tests/explicit-skill-requests/prompts/mid-conversation-execute-plan.txt +3 -0
  175. package/upstream/tests/explicit-skill-requests/prompts/please-use-brainstorming.txt +1 -0
  176. package/upstream/tests/explicit-skill-requests/prompts/skip-formalities.txt +3 -0
  177. package/upstream/tests/explicit-skill-requests/prompts/subagent-driven-development-please.txt +1 -0
  178. package/upstream/tests/explicit-skill-requests/prompts/use-systematic-debugging.txt +1 -0
  179. package/upstream/tests/explicit-skill-requests/run-all.sh +70 -0
  180. package/upstream/tests/explicit-skill-requests/run-claude-describes-sdd.sh +100 -0
  181. package/upstream/tests/explicit-skill-requests/run-extended-multiturn-test.sh +113 -0
  182. package/upstream/tests/explicit-skill-requests/run-haiku-test.sh +144 -0
  183. package/upstream/tests/explicit-skill-requests/run-multiturn-test.sh +143 -0
  184. package/upstream/tests/explicit-skill-requests/run-test.sh +136 -0
  185. package/upstream/tests/opencode/run-tests.sh +163 -0
  186. package/upstream/tests/opencode/setup.sh +88 -0
  187. package/upstream/tests/opencode/test-plugin-loading.sh +82 -0
  188. package/upstream/tests/opencode/test-priority.sh +198 -0
  189. package/upstream/tests/opencode/test-tools.sh +104 -0
  190. package/upstream/tests/skill-triggering/prompts/dispatching-parallel-agents.txt +8 -0
  191. package/upstream/tests/skill-triggering/prompts/executing-plans.txt +1 -0
  192. package/upstream/tests/skill-triggering/prompts/requesting-code-review.txt +3 -0
  193. package/upstream/tests/skill-triggering/prompts/systematic-debugging.txt +11 -0
  194. package/upstream/tests/skill-triggering/prompts/test-driven-development.txt +7 -0
  195. package/upstream/tests/skill-triggering/prompts/writing-plans.txt +10 -0
  196. package/upstream/tests/skill-triggering/run-all.sh +60 -0
  197. package/upstream/tests/skill-triggering/run-test.sh +88 -0
  198. package/upstream/tests/subagent-driven-dev/go-fractals/design.md +81 -0
  199. package/upstream/tests/subagent-driven-dev/go-fractals/plan.md +172 -0
  200. package/upstream/tests/subagent-driven-dev/go-fractals/scaffold.sh +45 -0
  201. package/upstream/tests/subagent-driven-dev/run-test.sh +106 -0
  202. package/upstream/tests/subagent-driven-dev/svelte-todo/design.md +70 -0
  203. package/upstream/tests/subagent-driven-dev/svelte-todo/plan.md +222 -0
  204. package/upstream/tests/subagent-driven-dev/svelte-todo/scaffold.sh +46 -0
@@ -0,0 +1,170 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const { confirm } = require('@inquirer/prompts');
5
+
6
+ const PROJECT_DIR = process.cwd();
7
+ const AIFLOW_DIR = path.join(PROJECT_DIR, '.aiflow');
8
+ const STATE_FILE = path.join(AIFLOW_DIR, 'state.json');
9
+
10
+ // ──────────────────────────────────────────────────────────────
11
+ // Entry point
12
+ // ──────────────────────────────────────────────────────────────
13
+
14
+ module.exports = async function remove(options = {}) {
15
+ try {
16
+ if (options.global) return await removeGlobal();
17
+ if (options.version) return await removeVersion(options.version);
18
+ return await removeFromProject();
19
+ } catch (err) {
20
+ console.error(chalk.red(`Error: ${err.message}`));
21
+ }
22
+ };
23
+
24
+ // ──────────────────────────────────────────────────────────────
25
+ // Case 1: Remove ai-flow-kit setup from current project
26
+ // Deletes .aiflow/, .claude/skills, .claude/hooks, .claude/settings.json, .rules/
27
+ // Does NOT delete CLAUDE.md or .mcp.json (user content)
28
+ // ──────────────────────────────────────────────────────────────
29
+
30
+ async function removeFromProject() {
31
+ if (!(await fs.pathExists(AIFLOW_DIR))) {
32
+ console.log(chalk.yellow('ai-flow-kit is not initialized in this project.'));
33
+ return;
34
+ }
35
+
36
+ console.log(chalk.yellow('\nThis will remove ai-flow-kit from the current project:'));
37
+ console.log(chalk.gray(' • .aiflow/ (state, versions, context, memory)'));
38
+ console.log(chalk.gray(' • .claude/skills/ (superpowers + custom skills)'));
39
+ console.log(chalk.gray(' • .claude/hooks/ (SessionStart hook)'));
40
+ console.log(chalk.gray(' • .claude/settings.json (hook config)'));
41
+ console.log(chalk.gray(' • .rules/ (team rules)'));
42
+ console.log(chalk.gray(' ✗ CLAUDE.md and .mcp.json are NOT removed (your content)\n'));
43
+
44
+ const ok = await confirm({ message: 'Continue?' });
45
+ if (!ok) {
46
+ console.log(chalk.gray('Cancelled.'));
47
+ return;
48
+ }
49
+
50
+ // Remove .aiflow/
51
+ await fs.remove(AIFLOW_DIR);
52
+ console.log(chalk.green('✓ Removed .aiflow/'));
53
+
54
+ // Remove .claude/skills, hooks, settings.json — but keep the rest (e.g. context user may want)
55
+ const claudeDir = path.join(PROJECT_DIR, '.claude');
56
+ const skillsDir = path.join(claudeDir, 'skills');
57
+ const hooksDir = path.join(claudeDir, 'hooks');
58
+ const settingsFile = path.join(claudeDir, 'settings.json');
59
+
60
+ if (await fs.pathExists(skillsDir)) {
61
+ await fs.remove(skillsDir);
62
+ console.log(chalk.green('✓ Removed .claude/skills/'));
63
+ }
64
+
65
+ if (await fs.pathExists(hooksDir)) {
66
+ await fs.remove(hooksDir);
67
+ console.log(chalk.green('✓ Removed .claude/hooks/'));
68
+ }
69
+
70
+ if (await fs.pathExists(settingsFile)) {
71
+ // Only remove the _aiflowKit hook entry, not the whole file
72
+ const settings = await fs.readJson(settingsFile).catch(() => ({}));
73
+ if (settings.hooks?.SessionStart) {
74
+ settings.hooks.SessionStart = settings.hooks.SessionStart.filter(
75
+ h => !h._aiflowKit
76
+ );
77
+ if (settings.hooks.SessionStart.length === 0) {
78
+ delete settings.hooks.SessionStart;
79
+ }
80
+ await fs.writeJson(settingsFile, settings, { spaces: 2 });
81
+ console.log(chalk.green('✓ Removed ai-flow-kit hook from .claude/settings.json'));
82
+ }
83
+ }
84
+
85
+ // Remove .rules/
86
+ const rulesDir = path.join(PROJECT_DIR, '.rules');
87
+ if (await fs.pathExists(rulesDir)) {
88
+ await fs.remove(rulesDir);
89
+ console.log(chalk.green('✓ Removed .rules/'));
90
+ }
91
+
92
+ console.log(chalk.green('\n✨ ai-flow-kit removed from project.'));
93
+ console.log(chalk.gray('To reinstall: aiflow init'));
94
+ }
95
+
96
+ // ──────────────────────────────────────────────────────────────
97
+ // Case 2: Uninstall the global npm package
98
+ // ──────────────────────────────────────────────────────────────
99
+
100
+ async function removeGlobal() {
101
+ console.log(chalk.yellow('\nThis will uninstall ai-flow-kit globally from your system.'));
102
+ console.log(chalk.gray('Project files (.aiflow/, .claude/, .rules/) are NOT affected.\n'));
103
+
104
+ const ok = await confirm({ message: 'Uninstall global package?' });
105
+ if (!ok) {
106
+ console.log(chalk.gray('Cancelled.'));
107
+ return;
108
+ }
109
+
110
+ const { execSync } = require('child_process');
111
+ try {
112
+ console.log(chalk.blue('Running: npm uninstall -g ai-flow-kit ...'));
113
+ execSync('npm uninstall -g ai-flow-kit', { stdio: 'inherit' });
114
+ console.log(chalk.green('\n✨ ai-flow-kit uninstalled globally.'));
115
+ console.log(chalk.gray('The `aiflow` command is no longer available.'));
116
+ } catch (err) {
117
+ // execSync throws on non-zero exit; message already printed via stdio: inherit
118
+ console.log(chalk.red('\nFailed to uninstall. Try manually: npm uninstall -g ai-flow-kit'));
119
+ }
120
+ }
121
+
122
+ // ──────────────────────────────────────────────────────────────
123
+ // Case 3: Remove a specific cached version from .aiflow/versions/
124
+ // ──────────────────────────────────────────────────────────────
125
+
126
+ async function removeVersion(version) {
127
+ if (!(await fs.pathExists(STATE_FILE))) {
128
+ console.log(chalk.red('Project is not initialized. Run `aiflow init` first.'));
129
+ return;
130
+ }
131
+
132
+ const versionsDir = path.join(AIFLOW_DIR, 'versions');
133
+ const targetDir = path.join(versionsDir, version);
134
+
135
+ if (!(await fs.pathExists(targetDir))) {
136
+ console.log(chalk.red(`Version v${version} is not cached in this project.`));
137
+
138
+ // Show what's available
139
+ if (await fs.pathExists(versionsDir)) {
140
+ const available = await fs.readdir(versionsDir);
141
+ if (available.length) {
142
+ console.log(chalk.gray(`Cached versions: ${available.map(v => `v${v}`).join(', ')}`));
143
+ }
144
+ }
145
+ return;
146
+ }
147
+
148
+ // Prevent removing the currently active version
149
+ const state = await fs.readJson(STATE_FILE);
150
+ if (state.current_version === version) {
151
+ console.log(chalk.red(`v${version} is currently active — cannot remove it.`));
152
+ console.log(chalk.gray('Switch to another version first: aiflow use <version>'));
153
+ return;
154
+ }
155
+
156
+ const ok = await confirm({ message: `Delete cached version v${version}?` });
157
+ if (!ok) {
158
+ console.log(chalk.gray('Cancelled.'));
159
+ return;
160
+ }
161
+
162
+ await fs.remove(targetDir);
163
+ console.log(chalk.green(`✓ Removed cached version v${version}.`));
164
+
165
+ // Show remaining versions
166
+ const remaining = await fs.readdir(versionsDir).catch(() => []);
167
+ if (remaining.length) {
168
+ console.log(chalk.gray(`Remaining: ${remaining.map(v => `v${v}`).join(', ')}`));
169
+ }
170
+ }
@@ -0,0 +1,111 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const { confirm, select } = require('@inquirer/prompts');
5
+
6
+ const PKG_DIR = path.join(__dirname, '..');
7
+ const PKG_VERSION = require('../package.json').version;
8
+
9
+ // Same language map as init.js
10
+ const FRAMEWORK_LANGUAGE = {
11
+ 'laravel': 'php',
12
+ 'spring-boot': 'java',
13
+ 'reactjs': 'javascript',
14
+ 'nextjs': 'javascript',
15
+ 'vue-nuxt': 'javascript',
16
+ };
17
+
18
+ module.exports = async function update(options = {}) {
19
+ const projectDir = process.cwd();
20
+ const aiflowDir = path.join(projectDir, '.aiflow');
21
+ const stateFile = path.join(aiflowDir, 'state.json');
22
+
23
+ if (!(await fs.pathExists(stateFile))) {
24
+ console.log(chalk.red('Project is not initialized. Please run `aiflow init` first.'));
25
+ return;
26
+ }
27
+
28
+ const state = await fs.readJson(stateFile);
29
+ const currentVersion = state.current_version;
30
+
31
+ if (currentVersion === PKG_VERSION && !options.force) {
32
+ console.log(chalk.green(`Already on v${PKG_VERSION}. Use --force to re-copy assets anyway.`));
33
+ return;
34
+ }
35
+
36
+ console.log(chalk.blue(`Updating from v${currentVersion} to v${PKG_VERSION}...`));
37
+
38
+ const newVersionDir = path.join(aiflowDir, 'versions', PKG_VERSION);
39
+ await fs.ensureDir(newVersionDir);
40
+
41
+ // Merge skills
42
+ const upstreamSkills = path.join(PKG_DIR, 'upstream', 'skills');
43
+ const customSkills = path.join(PKG_DIR, 'custom', 'skills');
44
+
45
+ await fs.ensureDir(path.join(newVersionDir, 'skills'));
46
+ if (await fs.pathExists(upstreamSkills)) {
47
+ await fs.copy(upstreamSkills, path.join(newVersionDir, 'skills'), { overwrite: true });
48
+ }
49
+ if (await fs.pathExists(customSkills)) {
50
+ await fs.copy(customSkills, path.join(newVersionDir, 'skills'), { overwrite: true });
51
+ }
52
+
53
+ // Copy rules: common first, then language-specific overlay (mirrors init.js logic)
54
+ const rulesTarget = path.join(newVersionDir, 'rules');
55
+ const commonRules = path.join(PKG_DIR, 'custom', 'rules', 'common');
56
+ const allRules = path.join(PKG_DIR, 'custom', 'rules');
57
+ const primaryFramework = (state.frameworks || [])[0] || null;
58
+
59
+ await fs.ensureDir(rulesTarget);
60
+ if (await fs.pathExists(commonRules)) {
61
+ await fs.copy(commonRules, rulesTarget, { overwrite: true });
62
+ } else if (await fs.pathExists(allRules)) {
63
+ const entries = await fs.readdir(allRules, { withFileTypes: true });
64
+ for (const entry of entries) {
65
+ if (entry.isFile() && entry.name.endsWith('.md')) {
66
+ await fs.copy(path.join(allRules, entry.name), path.join(rulesTarget, entry.name), { overwrite: true });
67
+ }
68
+ }
69
+ }
70
+
71
+ if (primaryFramework) {
72
+ const lang = FRAMEWORK_LANGUAGE[primaryFramework];
73
+ if (lang) {
74
+ const langRules = path.join(PKG_DIR, 'custom', 'rules', lang);
75
+ if (await fs.pathExists(langRules)) {
76
+ await fs.copy(langRules, rulesTarget, { overwrite: true });
77
+ console.log(chalk.gray(` ✓ Applied ${lang} rules`));
78
+ }
79
+ }
80
+ }
81
+
82
+ console.log(chalk.green(`✓ Downloaded assets for v${PKG_VERSION} into the project.`));
83
+
84
+ // Only offer to delete old version when it's a different version.
85
+ // When --force re-copies the same version, old === new === newVersionDir,
86
+ // so deleting "old" would immediately break the copy step below.
87
+ const isSameVersion = currentVersion === PKG_VERSION;
88
+ if (!isSameVersion) {
89
+ const deleteOld = await confirm({ message: `Do you want to delete the old version (v${currentVersion})?` });
90
+ if (deleteOld) {
91
+ await fs.remove(path.join(aiflowDir, 'versions', currentVersion));
92
+ console.log(chalk.gray(`Deleted v${currentVersion}.`));
93
+ } else {
94
+ console.log(chalk.gray(`Kept v${currentVersion}. You can switch back using 'aiflow use ${currentVersion}'.`));
95
+ }
96
+ }
97
+
98
+ // Switch to new version
99
+ const claudeDir = path.join(projectDir, '.claude');
100
+ await fs.emptyDir(claudeDir);
101
+ await fs.copy(path.join(newVersionDir, 'skills'), path.join(claudeDir, 'skills'), { overwrite: true });
102
+
103
+ const rulesDir = path.join(projectDir, '.rules');
104
+ await fs.emptyDir(rulesDir);
105
+ await fs.copy(path.join(newVersionDir, 'rules'), rulesDir, { overwrite: true });
106
+
107
+ state.current_version = PKG_VERSION;
108
+ await fs.writeJson(stateFile, state);
109
+
110
+ console.log(chalk.green(`\n✨ Update completed! Your project is now on v${PKG_VERSION}.`));
111
+ };