agileflow 2.30.0

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 (133) hide show
  1. package/package.json +61 -0
  2. package/src/core/agents/accessibility.md +445 -0
  3. package/src/core/agents/adr-writer.md +215 -0
  4. package/src/core/agents/analytics.md +523 -0
  5. package/src/core/agents/api.md +484 -0
  6. package/src/core/agents/ci.md +452 -0
  7. package/src/core/agents/compliance.md +401 -0
  8. package/src/core/agents/context7.md +164 -0
  9. package/src/core/agents/database.md +377 -0
  10. package/src/core/agents/datamigration.md +565 -0
  11. package/src/core/agents/design.md +400 -0
  12. package/src/core/agents/devops.md +576 -0
  13. package/src/core/agents/documentation.md +229 -0
  14. package/src/core/agents/epic-planner.md +277 -0
  15. package/src/core/agents/integrations.md +459 -0
  16. package/src/core/agents/mentor.md +375 -0
  17. package/src/core/agents/mobile.md +391 -0
  18. package/src/core/agents/monitoring.md +430 -0
  19. package/src/core/agents/performance.md +390 -0
  20. package/src/core/agents/product.md +311 -0
  21. package/src/core/agents/qa.md +647 -0
  22. package/src/core/agents/readme-updater.md +325 -0
  23. package/src/core/agents/refactor.md +432 -0
  24. package/src/core/agents/research.md +250 -0
  25. package/src/core/agents/security.md +379 -0
  26. package/src/core/agents/testing.md +397 -0
  27. package/src/core/agents/ui.md +999 -0
  28. package/src/core/commands/adr.md +32 -0
  29. package/src/core/commands/agent.md +23 -0
  30. package/src/core/commands/assign.md +34 -0
  31. package/src/core/commands/auto.md +364 -0
  32. package/src/core/commands/babysit.md +1357 -0
  33. package/src/core/commands/baseline.md +520 -0
  34. package/src/core/commands/blockers.md +343 -0
  35. package/src/core/commands/board.md +241 -0
  36. package/src/core/commands/changelog.md +321 -0
  37. package/src/core/commands/ci.md +36 -0
  38. package/src/core/commands/compress.md +270 -0
  39. package/src/core/commands/context.md +222 -0
  40. package/src/core/commands/debt.md +268 -0
  41. package/src/core/commands/deploy.md +544 -0
  42. package/src/core/commands/deps.md +560 -0
  43. package/src/core/commands/diagnose.md +227 -0
  44. package/src/core/commands/docs.md +166 -0
  45. package/src/core/commands/epic.md +40 -0
  46. package/src/core/commands/feedback.md +307 -0
  47. package/src/core/commands/handoff.md +33 -0
  48. package/src/core/commands/help.md +90 -0
  49. package/src/core/commands/impact.md +204 -0
  50. package/src/core/commands/metrics.md +530 -0
  51. package/src/core/commands/packages.md +369 -0
  52. package/src/core/commands/pr.md +35 -0
  53. package/src/core/commands/readme-sync.md +168 -0
  54. package/src/core/commands/research.md +30 -0
  55. package/src/core/commands/resume.md +475 -0
  56. package/src/core/commands/retro.md +538 -0
  57. package/src/core/commands/review.md +364 -0
  58. package/src/core/commands/session-init.md +532 -0
  59. package/src/core/commands/setup.md +708 -0
  60. package/src/core/commands/sprint.md +490 -0
  61. package/src/core/commands/status.md +38 -0
  62. package/src/core/commands/story-validate.md +242 -0
  63. package/src/core/commands/story.md +38 -0
  64. package/src/core/commands/template.md +458 -0
  65. package/src/core/commands/tests.md +359 -0
  66. package/src/core/commands/update.md +407 -0
  67. package/src/core/commands/velocity.md +369 -0
  68. package/src/core/commands/verify.md +283 -0
  69. package/src/core/skills/acceptance-criteria-generator/SKILL.md +46 -0
  70. package/src/core/skills/adr-template/SKILL.md +62 -0
  71. package/src/core/skills/agileflow-acceptance-criteria/SKILL.md +156 -0
  72. package/src/core/skills/agileflow-adr/SKILL.md +147 -0
  73. package/src/core/skills/agileflow-adr/examples/database-choice-example.md +122 -0
  74. package/src/core/skills/agileflow-adr/templates/adr-template.md +69 -0
  75. package/src/core/skills/agileflow-commit-messages/SKILL.md +130 -0
  76. package/src/core/skills/agileflow-commit-messages/reference/bad-examples.md +168 -0
  77. package/src/core/skills/agileflow-commit-messages/reference/good-examples.md +120 -0
  78. package/src/core/skills/agileflow-commit-messages/scripts/check-attribution.sh +15 -0
  79. package/src/core/skills/agileflow-epic-planner/SKILL.md +184 -0
  80. package/src/core/skills/agileflow-retro-facilitator/SKILL.md +281 -0
  81. package/src/core/skills/agileflow-sprint-planner/SKILL.md +212 -0
  82. package/src/core/skills/agileflow-story-writer/SKILL.md +163 -0
  83. package/src/core/skills/agileflow-story-writer/examples/good-story-example.md +63 -0
  84. package/src/core/skills/agileflow-story-writer/templates/story-template.md +44 -0
  85. package/src/core/skills/agileflow-tech-debt/SKILL.md +215 -0
  86. package/src/core/skills/api-documentation-generator/SKILL.md +65 -0
  87. package/src/core/skills/changelog-entry/SKILL.md +55 -0
  88. package/src/core/skills/commit-message-formatter/SKILL.md +50 -0
  89. package/src/core/skills/deployment-guide-generator/SKILL.md +84 -0
  90. package/src/core/skills/diagram-generator/SKILL.md +65 -0
  91. package/src/core/skills/error-handler-template/SKILL.md +78 -0
  92. package/src/core/skills/migration-checklist/SKILL.md +82 -0
  93. package/src/core/skills/pr-description/SKILL.md +65 -0
  94. package/src/core/skills/sql-schema-generator/SKILL.md +69 -0
  95. package/src/core/skills/story-skeleton/SKILL.md +34 -0
  96. package/src/core/skills/test-case-generator/SKILL.md +63 -0
  97. package/src/core/skills/type-definitions/SKILL.md +65 -0
  98. package/src/core/skills/validation-schema-generator/SKILL.md +64 -0
  99. package/src/core/templates/README-template.md +16 -0
  100. package/src/core/templates/adr-template.md +28 -0
  101. package/src/core/templates/agent-profile-template.md +51 -0
  102. package/src/core/templates/agileflow-metadata.json +41 -0
  103. package/src/core/templates/ci-workflow.yml +74 -0
  104. package/src/core/templates/claude-settings.advanced.example.json +71 -0
  105. package/src/core/templates/claude-settings.example.json +26 -0
  106. package/src/core/templates/comms-note-template.md +24 -0
  107. package/src/core/templates/environment.json +18 -0
  108. package/src/core/templates/epic-template.md +27 -0
  109. package/src/core/templates/init.sh +76 -0
  110. package/src/core/templates/research-template.md +44 -0
  111. package/src/core/templates/resume-session.sh +121 -0
  112. package/src/core/templates/session-state.json +20 -0
  113. package/src/core/templates/skill-template.md +75 -0
  114. package/src/core/templates/story-template.md +88 -0
  115. package/src/core/templates/validate-tokens.sh +88 -0
  116. package/src/core/templates/worktree-create.sh +111 -0
  117. package/src/core/templates/worktrees-guide.md +235 -0
  118. package/tools/agileflow-npx.js +40 -0
  119. package/tools/cli/agileflow-cli.js +70 -0
  120. package/tools/cli/commands/doctor.js +243 -0
  121. package/tools/cli/commands/install.js +82 -0
  122. package/tools/cli/commands/status.js +121 -0
  123. package/tools/cli/commands/uninstall.js +110 -0
  124. package/tools/cli/commands/update.js +99 -0
  125. package/tools/cli/installers/core/installer.js +296 -0
  126. package/tools/cli/installers/ide/_base-ide.js +133 -0
  127. package/tools/cli/installers/ide/claude-code.js +174 -0
  128. package/tools/cli/installers/ide/cursor.js +189 -0
  129. package/tools/cli/installers/ide/manager.js +197 -0
  130. package/tools/cli/installers/ide/windsurf.js +192 -0
  131. package/tools/cli/lib/ui.js +203 -0
  132. package/tools/cli/lib/version-checker.js +95 -0
  133. package/tools/postinstall.js +141 -0
@@ -0,0 +1,192 @@
1
+ /**
2
+ * AgileFlow CLI - Windsurf IDE Installer
3
+ *
4
+ * Installs AgileFlow workflows for Windsurf IDE.
5
+ * Windsurf uses markdown files in .windsurf/workflows/
6
+ */
7
+
8
+ const path = require('node:path');
9
+ const fs = require('fs-extra');
10
+ const chalk = require('chalk');
11
+ const { BaseIdeSetup } = require('./_base-ide');
12
+
13
+ /**
14
+ * Windsurf IDE setup handler
15
+ */
16
+ class WindsurfSetup extends BaseIdeSetup {
17
+ constructor() {
18
+ super('windsurf', 'Windsurf', true);
19
+ this.configDir = '.windsurf';
20
+ this.workflowsDir = 'workflows';
21
+ }
22
+
23
+ /**
24
+ * Setup Windsurf IDE configuration
25
+ * @param {string} projectDir - Project directory
26
+ * @param {string} agileflowDir - AgileFlow installation directory
27
+ * @param {Object} options - Setup options
28
+ */
29
+ async setup(projectDir, agileflowDir, options = {}) {
30
+ console.log(chalk.cyan(` Setting up ${this.displayName}...`));
31
+
32
+ // Clean up old installation first
33
+ await this.cleanup(projectDir);
34
+
35
+ // Create .windsurf/workflows/agileflow directory
36
+ const windsurfDir = path.join(projectDir, this.configDir);
37
+ const workflowsDir = path.join(windsurfDir, this.workflowsDir);
38
+ const agileflowWorkflowsDir = path.join(workflowsDir, 'agileflow');
39
+
40
+ await this.ensureDir(agileflowWorkflowsDir);
41
+
42
+ // Get commands from AgileFlow installation
43
+ const commandsSource = path.join(agileflowDir, 'commands');
44
+ let commandCount = 0;
45
+
46
+ if (await this.exists(commandsSource)) {
47
+ const commands = await this.scanDirectory(commandsSource, '.md');
48
+
49
+ for (const command of commands) {
50
+ // Create workflow file
51
+ const workflowContent = await this.createCommandWorkflow(command, agileflowDir, projectDir);
52
+ const targetPath = path.join(agileflowWorkflowsDir, `${command.name}.md`);
53
+
54
+ await this.writeFile(targetPath, workflowContent);
55
+ commandCount++;
56
+ }
57
+ }
58
+
59
+ // Create agents subdirectory
60
+ const agileflowAgentsDir = path.join(agileflowWorkflowsDir, 'agents');
61
+ await this.ensureDir(agileflowAgentsDir);
62
+
63
+ // Get agents from AgileFlow installation
64
+ const agentsSource = path.join(agileflowDir, 'agents');
65
+ let agentCount = 0;
66
+
67
+ if (await this.exists(agentsSource)) {
68
+ const agents = await this.scanDirectory(agentsSource, '.md');
69
+
70
+ for (const agent of agents) {
71
+ // Create workflow file
72
+ const workflowContent = await this.createAgentWorkflow(agent, agileflowDir, projectDir);
73
+ const targetPath = path.join(agileflowAgentsDir, `${agent.name}.md`);
74
+
75
+ await this.writeFile(targetPath, workflowContent);
76
+ agentCount++;
77
+ }
78
+ }
79
+
80
+ console.log(chalk.green(` ✓ ${this.displayName} configured:`));
81
+ console.log(chalk.dim(` - ${commandCount} workflows installed`));
82
+ console.log(chalk.dim(` - ${agentCount} agent workflows installed`));
83
+ console.log(chalk.dim(` - Path: ${path.relative(projectDir, agileflowWorkflowsDir)}`));
84
+
85
+ return {
86
+ success: true,
87
+ commands: commandCount,
88
+ agents: agentCount,
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Cleanup old AgileFlow installation
94
+ * @param {string} projectDir - Project directory
95
+ */
96
+ async cleanup(projectDir) {
97
+ const agileflowPath = path.join(projectDir, this.configDir, this.workflowsDir, 'agileflow');
98
+ if (await this.exists(agileflowPath)) {
99
+ await fs.remove(agileflowPath);
100
+ console.log(chalk.dim(` Removed old AgileFlow workflows from ${this.displayName}`));
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Create a workflow file for a command
106
+ * @param {Object} command - Command info
107
+ * @param {string} agileflowDir - AgileFlow directory
108
+ * @param {string} projectDir - Project directory
109
+ * @returns {Promise<string>} Workflow content
110
+ */
111
+ async createCommandWorkflow(command, agileflowDir, projectDir) {
112
+ // Read the original command file
113
+ const content = await this.readFile(command.path);
114
+
115
+ // Extract description from frontmatter if present
116
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
117
+ let description = command.name;
118
+
119
+ if (frontmatterMatch) {
120
+ const descMatch = frontmatterMatch[1].match(/description:\s*["']?([^"'\n]+)["']?/);
121
+ if (descMatch) {
122
+ description = descMatch[1];
123
+ }
124
+ }
125
+
126
+ // Create Windsurf workflow format
127
+ const relativePath = path.relative(projectDir, command.path);
128
+
129
+ return `---
130
+ description: ${description}
131
+ auto_execution_mode: 2
132
+ ---
133
+
134
+ # AgileFlow: ${command.name}
135
+
136
+ Load and execute the AgileFlow command.
137
+
138
+ ## Instructions
139
+
140
+ Read and follow the full command from: \`${relativePath}\`
141
+
142
+ Execute the command according to its specifications.
143
+ `;
144
+ }
145
+
146
+ /**
147
+ * Create a workflow file for an agent
148
+ * @param {Object} agent - Agent info
149
+ * @param {string} agileflowDir - AgileFlow directory
150
+ * @param {string} projectDir - Project directory
151
+ * @returns {Promise<string>} Workflow content
152
+ */
153
+ async createAgentWorkflow(agent, agileflowDir, projectDir) {
154
+ // Read the original agent file
155
+ const content = await this.readFile(agent.path);
156
+
157
+ // Extract metadata from frontmatter
158
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
159
+ let description = agent.name;
160
+ let name = agent.name;
161
+
162
+ if (frontmatterMatch) {
163
+ const descMatch = frontmatterMatch[1].match(/description:\s*["']?([^"'\n]+)["']?/);
164
+ const nameMatch = frontmatterMatch[1].match(/name:\s*["']?([^"'\n]+)["']?/);
165
+
166
+ if (descMatch) description = descMatch[1];
167
+ if (nameMatch) name = nameMatch[1];
168
+ }
169
+
170
+ // Create Windsurf workflow format
171
+ const relativePath = path.relative(projectDir, agent.path);
172
+
173
+ return `---
174
+ description: ${description}
175
+ auto_execution_mode: 3
176
+ ---
177
+
178
+ # AgileFlow Agent: ${name}
179
+
180
+ Activate the AgileFlow agent.
181
+
182
+ ## Instructions
183
+
184
+ 1. Read the full agent definition from: \`${relativePath}\`
185
+ 2. Adopt the agent's persona and communication style
186
+ 3. Follow all instructions and use the specified tools
187
+ 4. Maintain the agent's character throughout the session
188
+ `;
189
+ }
190
+ }
191
+
192
+ module.exports = { WindsurfSetup };
@@ -0,0 +1,203 @@
1
+ /**
2
+ * AgileFlow CLI - UI Utilities
3
+ *
4
+ * Provides interactive prompts and display utilities for the CLI.
5
+ */
6
+
7
+ const chalk = require('chalk');
8
+ const inquirer = require('inquirer');
9
+ const path = require('node:path');
10
+ const fs = require('node:fs');
11
+
12
+ // Load package.json for version
13
+ const packageJsonPath = path.join(__dirname, '..', '..', '..', 'package.json');
14
+ const packageJson = require(packageJsonPath);
15
+
16
+ /**
17
+ * Display the AgileFlow ASCII logo
18
+ */
19
+ function displayLogo() {
20
+ const logo = `
21
+ _____ _ __ ________
22
+ / _ \\ ____/ | \\_/ ____/
23
+ / /_\\ \\ / ___\\ | |\\____ \\ ____ _ __
24
+ / | \\ \\___|__|__/ \\/ __ \\/ \\/ /
25
+ \\____|____/\\____/____ /_______/\\____/ \\__/
26
+ `;
27
+ console.log(chalk.cyan(logo));
28
+ console.log(chalk.dim(` AgileFlow v${packageJson.version} - AI-Driven Agile Development\n`));
29
+ }
30
+
31
+ /**
32
+ * Display a section header
33
+ * @param {string} title - Section title
34
+ * @param {string} subtitle - Optional subtitle
35
+ */
36
+ function displaySection(title, subtitle = null) {
37
+ console.log(chalk.bold.cyan(`\n${title}`));
38
+ if (subtitle) {
39
+ console.log(chalk.dim(subtitle));
40
+ }
41
+ console.log();
42
+ }
43
+
44
+ /**
45
+ * Display a success message
46
+ * @param {string} message - Success message
47
+ */
48
+ function success(message) {
49
+ console.log(chalk.green(`✓ ${message}`));
50
+ }
51
+
52
+ /**
53
+ * Display a warning message
54
+ * @param {string} message - Warning message
55
+ */
56
+ function warning(message) {
57
+ console.log(chalk.yellow(`⚠ ${message}`));
58
+ }
59
+
60
+ /**
61
+ * Display an error message
62
+ * @param {string} message - Error message
63
+ */
64
+ function error(message) {
65
+ console.log(chalk.red(`✗ ${message}`));
66
+ }
67
+
68
+ /**
69
+ * Display an info message
70
+ * @param {string} message - Info message
71
+ */
72
+ function info(message) {
73
+ console.log(chalk.dim(` ${message}`));
74
+ }
75
+
76
+ /**
77
+ * Available IDE configurations
78
+ */
79
+ const IDE_CHOICES = [
80
+ {
81
+ name: 'Claude Code',
82
+ value: 'claude-code',
83
+ checked: true,
84
+ configDir: '.claude/commands',
85
+ description: 'Anthropic\'s Claude Code IDE',
86
+ },
87
+ {
88
+ name: 'Cursor',
89
+ value: 'cursor',
90
+ checked: false,
91
+ configDir: '.cursor/rules',
92
+ description: 'AI-powered code editor',
93
+ },
94
+ {
95
+ name: 'Windsurf',
96
+ value: 'windsurf',
97
+ checked: false,
98
+ configDir: '.windsurf/workflows',
99
+ description: 'Codeium\'s AI IDE',
100
+ },
101
+ ];
102
+
103
+ /**
104
+ * Prompt for installation configuration
105
+ * @returns {Promise<Object>} Installation configuration
106
+ */
107
+ async function promptInstall() {
108
+ displayLogo();
109
+
110
+ const answers = await inquirer.prompt([
111
+ {
112
+ type: 'input',
113
+ name: 'directory',
114
+ message: 'Where would you like to install AgileFlow?',
115
+ default: '.',
116
+ validate: (input) => {
117
+ const resolved = path.resolve(input);
118
+ const parent = path.dirname(resolved);
119
+ if (!fs.existsSync(parent)) {
120
+ return `Parent directory does not exist: ${parent}`;
121
+ }
122
+ return true;
123
+ },
124
+ },
125
+ {
126
+ type: 'checkbox',
127
+ name: 'ides',
128
+ message: 'Select your IDE(s):',
129
+ choices: IDE_CHOICES,
130
+ validate: (input) => {
131
+ if (input.length === 0) {
132
+ return 'Please select at least one IDE';
133
+ }
134
+ return true;
135
+ },
136
+ },
137
+ {
138
+ type: 'input',
139
+ name: 'userName',
140
+ message: 'What should agents call you?',
141
+ default: 'Developer',
142
+ },
143
+ {
144
+ type: 'input',
145
+ name: 'agileflowFolder',
146
+ message: 'AgileFlow installation folder name:',
147
+ default: '.agileflow',
148
+ validate: (input) => {
149
+ if (!/^[a-zA-Z0-9._-]+$/.test(input)) {
150
+ return 'Folder name can only contain letters, numbers, dots, underscores, and hyphens';
151
+ }
152
+ return true;
153
+ },
154
+ },
155
+ ]);
156
+
157
+ return {
158
+ directory: path.resolve(answers.directory),
159
+ ides: answers.ides,
160
+ userName: answers.userName,
161
+ agileflowFolder: answers.agileflowFolder,
162
+ };
163
+ }
164
+
165
+ /**
166
+ * Prompt for confirmation
167
+ * @param {string} message - Confirmation message
168
+ * @param {boolean} defaultValue - Default value
169
+ * @returns {Promise<boolean>}
170
+ */
171
+ async function confirm(message, defaultValue = true) {
172
+ const { confirmed } = await inquirer.prompt([
173
+ {
174
+ type: 'confirm',
175
+ name: 'confirmed',
176
+ message,
177
+ default: defaultValue,
178
+ },
179
+ ]);
180
+ return confirmed;
181
+ }
182
+
183
+ /**
184
+ * Get IDE configuration by name
185
+ * @param {string} ideName - IDE name
186
+ * @returns {Object|null}
187
+ */
188
+ function getIdeConfig(ideName) {
189
+ return IDE_CHOICES.find((ide) => ide.value === ideName) || null;
190
+ }
191
+
192
+ module.exports = {
193
+ displayLogo,
194
+ displaySection,
195
+ success,
196
+ warning,
197
+ error,
198
+ info,
199
+ promptInstall,
200
+ confirm,
201
+ getIdeConfig,
202
+ IDE_CHOICES,
203
+ };
@@ -0,0 +1,95 @@
1
+ /**
2
+ * AgileFlow CLI - Version Checker
3
+ *
4
+ * Checks for updates from npm registry.
5
+ */
6
+
7
+ const https = require('node:https');
8
+ const semver = require('semver');
9
+ const path = require('node:path');
10
+
11
+ // Load package.json for current version
12
+ const packageJsonPath = path.join(__dirname, '..', '..', '..', 'package.json');
13
+ const packageJson = require(packageJsonPath);
14
+
15
+ /**
16
+ * Get the latest version from npm registry
17
+ * @param {string} packageName - Package name
18
+ * @returns {Promise<string|null>} Latest version or null
19
+ */
20
+ async function getLatestVersion(packageName = 'agileflow') {
21
+ return new Promise((resolve) => {
22
+ const url = `https://registry.npmjs.org/${packageName}/latest`;
23
+
24
+ const req = https.get(url, { timeout: 5000 }, (res) => {
25
+ if (res.statusCode !== 200) {
26
+ resolve(null);
27
+ return;
28
+ }
29
+
30
+ let data = '';
31
+ res.on('data', (chunk) => {
32
+ data += chunk;
33
+ });
34
+
35
+ res.on('end', () => {
36
+ try {
37
+ const json = JSON.parse(data);
38
+ resolve(json.version || null);
39
+ } catch {
40
+ resolve(null);
41
+ }
42
+ });
43
+ });
44
+
45
+ req.on('error', () => {
46
+ resolve(null);
47
+ });
48
+
49
+ req.on('timeout', () => {
50
+ req.destroy();
51
+ resolve(null);
52
+ });
53
+ });
54
+ }
55
+
56
+ /**
57
+ * Check if an update is available
58
+ * @returns {Promise<Object>} Update info
59
+ */
60
+ async function checkForUpdate() {
61
+ const currentVersion = packageJson.version;
62
+ const latestVersion = await getLatestVersion();
63
+
64
+ if (!latestVersion) {
65
+ return {
66
+ current: currentVersion,
67
+ latest: null,
68
+ updateAvailable: false,
69
+ error: 'Could not check for updates',
70
+ };
71
+ }
72
+
73
+ const updateAvailable = semver.gt(latestVersion, currentVersion);
74
+
75
+ return {
76
+ current: currentVersion,
77
+ latest: latestVersion,
78
+ updateAvailable,
79
+ error: null,
80
+ };
81
+ }
82
+
83
+ /**
84
+ * Get current version
85
+ * @returns {string}
86
+ */
87
+ function getCurrentVersion() {
88
+ return packageJson.version;
89
+ }
90
+
91
+ module.exports = {
92
+ getLatestVersion,
93
+ checkForUpdate,
94
+ getCurrentVersion,
95
+ };
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * AgileFlow Postinstall Script
5
+ *
6
+ * Automatically runs AgileFlow installation after npm install.
7
+ * Includes smart detection to avoid running in inappropriate contexts.
8
+ */
9
+
10
+ const { execSync } = require('node:child_process');
11
+ const path = require('node:path');
12
+ const fs = require('node:fs');
13
+
14
+ // ANSI color codes for terminal output
15
+ const colors = {
16
+ green: '\x1b[32m',
17
+ yellow: '\x1b[33m',
18
+ blue: '\x1b[36m',
19
+ dim: '\x1b[2m',
20
+ reset: '\x1b[0m',
21
+ };
22
+
23
+ function log(message, color = 'reset') {
24
+ console.log(`${colors[color]}${message}${colors.reset}`);
25
+ }
26
+
27
+ function shouldSkipInstall() {
28
+ // Skip if environment variable is set
29
+ if (process.env.AGILEFLOW_SKIP_INSTALL === 'true') {
30
+ log('ℹ️ Skipping auto-install (AGILEFLOW_SKIP_INSTALL=true)', 'dim');
31
+ return true;
32
+ }
33
+
34
+ // Skip if running in npm cache or npx temp directory
35
+ if (__dirname.includes('_npx') || __dirname.includes('.npm')) {
36
+ log('ℹ️ Skipping auto-install (npm cache or npx temp directory)', 'dim');
37
+ return true;
38
+ }
39
+
40
+ // Skip if we're in the AgileFlow monorepo itself (development mode)
41
+ // Check for monorepo structure: packages/cli/tools/postinstall.js
42
+ // __dirname is tools/ so ../ goes to packages/cli/
43
+ const packageJsonPath = path.join(__dirname, '..', 'package.json');
44
+
45
+ if (fs.existsSync(packageJsonPath)) {
46
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
47
+
48
+ if (packageJson.name === 'agileflow') {
49
+ // Check multiple indicators of monorepo development:
50
+ // 1. Parent directory structure (packages/cli pattern)
51
+ const isInPackagesDir = __dirname.includes('/packages/cli/');
52
+
53
+ // 2. Workspace root package.json exists
54
+ // Path from tools/ -> packages/cli -> packages -> AgileFlow
55
+ const rootPackageJson = path.join(__dirname, '..', '..', '..', 'package.json');
56
+ let isWorkspaceRoot = false;
57
+ if (fs.existsSync(rootPackageJson)) {
58
+ try {
59
+ const rootPkg = JSON.parse(fs.readFileSync(rootPackageJson, 'utf-8'));
60
+ isWorkspaceRoot = rootPkg.name === 'agileflow-monorepo' || Boolean(rootPkg.workspaces);
61
+ } catch (e) {
62
+ // Ignore parse errors
63
+ }
64
+ }
65
+
66
+ // 3. Git repository check (look for .git in monorepo root)
67
+ // Path from tools/ -> packages/cli -> packages -> AgileFlow -> .git
68
+ const gitDir = path.join(__dirname, '..', '..', '..', '.git');
69
+ const isGitRepo = fs.existsSync(gitDir);
70
+
71
+ if (isInPackagesDir || isWorkspaceRoot || isGitRepo) {
72
+ log('ℹ️ Skipping auto-install (running in development/monorepo)', 'dim');
73
+ return true;
74
+ }
75
+ }
76
+ }
77
+
78
+ // Get the installation directory (user's project root)
79
+ const installDir = process.cwd();
80
+
81
+ // Skip if .agileflow or .claude/commands/AgileFlow folder already exists
82
+ const agileflowPath = path.join(installDir, '.agileflow');
83
+ const claudeAgileflowPath = path.join(installDir, '.claude', 'commands', 'AgileFlow');
84
+
85
+ if (fs.existsSync(agileflowPath) || fs.existsSync(claudeAgileflowPath)) {
86
+ log('ℹ️ AgileFlow already installed in this project', 'dim');
87
+ return true;
88
+ }
89
+
90
+ return false;
91
+ }
92
+
93
+ function runAutoInstall() {
94
+ try {
95
+ console.log(''); // Blank line for spacing
96
+ log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'blue');
97
+ log(' AgileFlow Auto-Setup', 'blue');
98
+ log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'blue');
99
+ console.log('');
100
+
101
+ log('🚀 Setting up AgileFlow in your project...', 'green');
102
+ console.log('');
103
+
104
+ // Path to the CLI
105
+ const cliPath = path.join(__dirname, 'cli', 'agileflow-cli.js');
106
+
107
+ if (!fs.existsSync(cliPath)) {
108
+ log('⚠️ Could not find AgileFlow CLI. Run "npx agileflow install" manually.', 'yellow');
109
+ return;
110
+ }
111
+
112
+ // Run install command with --yes flag (non-interactive)
113
+ execSync(`node "${cliPath}" install --yes`, {
114
+ stdio: 'inherit',
115
+ cwd: process.cwd(),
116
+ });
117
+
118
+ console.log('');
119
+ log('✨ AgileFlow is ready to use!', 'green');
120
+ console.log('');
121
+ log('To skip auto-install in the future, set: AGILEFLOW_SKIP_INSTALL=true', 'dim');
122
+ console.log('');
123
+
124
+ } catch (error) {
125
+ console.log('');
126
+ log('⚠️ Auto-installation encountered an issue.', 'yellow');
127
+ log(' You can run "npx agileflow install" manually to complete setup.', 'yellow');
128
+ console.log('');
129
+
130
+ if (process.env.DEBUG) {
131
+ console.error(error);
132
+ }
133
+ }
134
+ }
135
+
136
+ // Main execution
137
+ if (shouldSkipInstall()) {
138
+ process.exit(0);
139
+ }
140
+
141
+ runAutoInstall();