agileflow 2.61.0 → 2.62.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 (66) hide show
  1. package/README.md +9 -9
  2. package/package.json +1 -1
  3. package/scripts/lib/counter.js +103 -0
  4. package/src/core/commands/auto.md +1 -0
  5. package/src/core/commands/babysit.md +170 -29
  6. package/src/core/commands/board.md +1 -0
  7. package/src/core/commands/ci.md +1 -0
  8. package/src/core/commands/compress.md +1 -0
  9. package/src/core/commands/deploy.md +1 -0
  10. package/src/core/commands/help.md +1 -0
  11. package/src/core/commands/research.md +1 -0
  12. package/src/core/commands/skill/create.md +566 -0
  13. package/src/core/commands/skill/delete.md +189 -0
  14. package/src/core/commands/skill/edit.md +245 -0
  15. package/src/core/commands/skill/list.md +155 -0
  16. package/src/core/commands/skill/test.md +249 -0
  17. package/src/core/commands/template.md +1 -0
  18. package/src/core/commands/tests.md +1 -0
  19. package/src/core/commands/update.md +1 -0
  20. package/src/core/commands/velocity.md +1 -0
  21. package/src/core/experts/refactor/expertise.yaml +17 -12
  22. package/src/core/templates/claude-settings.advanced.example.json +1 -1
  23. package/src/core/templates/claude-settings.example.json +1 -1
  24. package/tools/cli/commands/list.js +8 -13
  25. package/tools/cli/installers/core/installer.js +20 -19
  26. package/tools/cli/installers/ide/_base-ide.js +18 -4
  27. package/tools/cli/installers/ide/claude-code.js +4 -15
  28. package/tools/cli/installers/ide/codex.js +9 -13
  29. package/tools/cli/lib/content-injector.js +162 -31
  30. package/tools/cli/lib/utils.js +87 -0
  31. package/src/core/skills/acceptance-criteria-generator/SKILL.md +0 -46
  32. package/src/core/skills/adr-template/SKILL.md +0 -62
  33. package/src/core/skills/agileflow-acceptance-criteria/SKILL.md +0 -156
  34. package/src/core/skills/agileflow-adr/SKILL.md +0 -147
  35. package/src/core/skills/agileflow-adr/examples/database-choice-example.md +0 -122
  36. package/src/core/skills/agileflow-adr/templates/adr-template.md +0 -69
  37. package/src/core/skills/agileflow-commit-messages/SKILL.md +0 -130
  38. package/src/core/skills/agileflow-commit-messages/reference/bad-examples.md +0 -168
  39. package/src/core/skills/agileflow-commit-messages/reference/good-examples.md +0 -120
  40. package/src/core/skills/agileflow-commit-messages/scripts/check-attribution.sh +0 -15
  41. package/src/core/skills/agileflow-epic-planner/SKILL.md +0 -184
  42. package/src/core/skills/agileflow-retro-facilitator/SKILL.md +0 -119
  43. package/src/core/skills/agileflow-retro-facilitator/cookbook/4ls.md +0 -86
  44. package/src/core/skills/agileflow-retro-facilitator/cookbook/glad-sad-mad.md +0 -79
  45. package/src/core/skills/agileflow-retro-facilitator/cookbook/start-stop-continue.md +0 -142
  46. package/src/core/skills/agileflow-retro-facilitator/prompts/action-items.md +0 -83
  47. package/src/core/skills/agileflow-sprint-planner/SKILL.md +0 -212
  48. package/src/core/skills/agileflow-story-writer/SKILL.md +0 -163
  49. package/src/core/skills/agileflow-story-writer/examples/good-story-example.md +0 -63
  50. package/src/core/skills/agileflow-story-writer/templates/story-template.md +0 -44
  51. package/src/core/skills/agileflow-tech-debt/SKILL.md +0 -215
  52. package/src/core/skills/api-documentation-generator/SKILL.md +0 -65
  53. package/src/core/skills/changelog-entry/SKILL.md +0 -55
  54. package/src/core/skills/commit-message-formatter/SKILL.md +0 -50
  55. package/src/core/skills/deployment-guide-generator/SKILL.md +0 -84
  56. package/src/core/skills/diagram-generator/SKILL.md +0 -65
  57. package/src/core/skills/error-handler-template/SKILL.md +0 -78
  58. package/src/core/skills/migration-checklist/SKILL.md +0 -82
  59. package/src/core/skills/pr-description/SKILL.md +0 -65
  60. package/src/core/skills/sql-schema-generator/SKILL.md +0 -69
  61. package/src/core/skills/story-skeleton/SKILL.md +0 -34
  62. package/src/core/skills/test-case-generator/SKILL.md +0 -63
  63. package/src/core/skills/type-definitions/SKILL.md +0 -65
  64. package/src/core/skills/validation-schema-generator/SKILL.md +0 -64
  65. package/src/core/skills/writing-skills/SKILL.md +0 -352
  66. package/src/core/skills/writing-skills/testing-skills-with-subagents.md +0 -232
@@ -0,0 +1,249 @@
1
+ ---
2
+ description: Verify a skill works correctly by testing its activation and functionality
3
+ argument-hint: [SKILL_NAME] (optional)
4
+ ---
5
+
6
+ # /agileflow:skill:test
7
+
8
+ Test a skill to verify it activates correctly and produces expected results.
9
+
10
+ ---
11
+
12
+ ## Workflow
13
+
14
+ ### STEP 1: Select skill to test
15
+
16
+ If SKILL_NAME not provided, list available skills:
17
+
18
+ ```bash
19
+ ls -d .claude/skills/*/ 2>/dev/null | xargs -I {} basename {}
20
+ ```
21
+
22
+ Then ask user:
23
+
24
+ ```xml
25
+ <invoke name="AskUserQuestion">
26
+ <parameter name="questions">[{
27
+ "question": "Which skill would you like to test?",
28
+ "header": "Select Skill",
29
+ "multiSelect": false,
30
+ "options": [
31
+ {"label": "<skill-1>", "description": "<description from frontmatter>"},
32
+ {"label": "<skill-2>", "description": "<description from frontmatter>"},
33
+ {"label": "<skill-3>", "description": "<description from frontmatter>"}
34
+ ]
35
+ }]</parameter>
36
+ </invoke>
37
+ ```
38
+
39
+ ### STEP 2: Read skill metadata
40
+
41
+ Read SKILL.md and extract:
42
+ - Name and description
43
+ - "When to Use" section (activation triggers)
44
+ - Cookbook entries (if any)
45
+ - Quick reference section
46
+
47
+ ### STEP 3: Run validation checks
48
+
49
+ ```
50
+ 🧪 Testing: supabase-swift
51
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
52
+
53
+ Structure Validation:
54
+ ✅ SKILL.md exists
55
+ ✅ Frontmatter has name and description
56
+ ✅ references.md exists
57
+ ✅ cookbook/ directory found (2 entries)
58
+ ⚠️ No .mcp.json (MCP not configured)
59
+
60
+ Content Validation:
61
+ ✅ "When to Use" section present
62
+ ✅ Description under 1024 characters
63
+ ✅ SKILL.md under 500 lines (current: 287)
64
+ ✅ All cookbook files referenced in SKILL.md
65
+
66
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
67
+ ```
68
+
69
+ ### STEP 4: Test activation (optional)
70
+
71
+ ```xml
72
+ <invoke name="AskUserQuestion">
73
+ <parameter name="questions">[{
74
+ "question": "Would you like to test skill activation with a sample prompt?",
75
+ "header": "Activation Test",
76
+ "multiSelect": false,
77
+ "options": [
78
+ {"label": "Yes, test activation (Recommended)", "description": "I'll simulate using the skill"},
79
+ {"label": "Skip activation test", "description": "Structure validation is enough"},
80
+ {"label": "View SKILL.md content", "description": "Read the full skill instructions"}
81
+ ]
82
+ }]</parameter>
83
+ </invoke>
84
+ ```
85
+
86
+ If user wants activation test:
87
+
88
+ 1. **Extract sample triggers** from "When to Use" section
89
+ 2. **Present test prompts** based on triggers:
90
+ ```
91
+ Sample prompts that should activate this skill:
92
+
93
+ 1. "Help me set up Supabase authentication in Swift"
94
+ 2. "Create CRUD operations for my database"
95
+ 3. "How do I query Supabase from iOS?"
96
+ ```
97
+ 3. **Ask user to pick one** or provide custom prompt
98
+ 4. **Execute the skill** by reading SKILL.md and following instructions
99
+ 5. **Report results**
100
+
101
+ ### STEP 5: Show test results
102
+
103
+ ```
104
+ 🧪 Test Results: supabase-swift
105
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
106
+
107
+ Structure: ✅ PASS (5/5 checks)
108
+ Content: ✅ PASS (4/4 checks)
109
+ Activation: ✅ PASS (skill triggered correctly)
110
+ MCP Config: ⚠️ NOT CONFIGURED
111
+
112
+ Overall: ✅ SKILL IS FUNCTIONAL
113
+
114
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
115
+ ```
116
+
117
+ ### STEP 6: Offer next actions
118
+
119
+ ```xml
120
+ <invoke name="AskUserQuestion">
121
+ <parameter name="questions">[{
122
+ "question": "What would you like to do?",
123
+ "header": "Next Action",
124
+ "multiSelect": false,
125
+ "options": [
126
+ {"label": "Test another skill", "description": "Validate a different skill"},
127
+ {"label": "Edit this skill", "description": "Fix issues or improve"},
128
+ {"label": "Use this skill now", "description": "Start working with it"},
129
+ {"label": "Done", "description": "Exit skill testing"}
130
+ ]
131
+ }]</parameter>
132
+ </invoke>
133
+ ```
134
+
135
+ ---
136
+
137
+ ## Validation Checks
138
+
139
+ ### Structure Checks
140
+
141
+ | Check | Pass Condition |
142
+ |-------|----------------|
143
+ | SKILL.md exists | File present in skill directory |
144
+ | Frontmatter valid | Has `name:` and `description:` |
145
+ | references.md | File exists (optional but recommended) |
146
+ | cookbook/ | Directory exists if referenced in SKILL.md |
147
+ | .mcp.json | Valid JSON if present |
148
+
149
+ ### Content Checks
150
+
151
+ | Check | Pass Condition |
152
+ |-------|----------------|
153
+ | When to Use | Section present with activation triggers |
154
+ | Description length | Under 1024 characters |
155
+ | SKILL.md size | Under 500 lines |
156
+ | Cookbook references | All referenced files exist |
157
+ | No broken links | All local file references valid |
158
+
159
+ ### MCP Checks (if .mcp.json exists)
160
+
161
+ | Check | Pass Condition |
162
+ |-------|----------------|
163
+ | Valid JSON | Parses without errors |
164
+ | Has mcpServers | Contains mcpServers object |
165
+ | Command exists | Command is npx or valid executable |
166
+ | Env vars documented | Any ${VAR} has comments |
167
+
168
+ ---
169
+
170
+ ## Test Report Format
171
+
172
+ ```
173
+ 🧪 Skill Test Report: <skill-name>
174
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
175
+
176
+ STRUCTURE VALIDATION
177
+ [✅|❌] SKILL.md exists
178
+ [✅|❌] Frontmatter valid (name, description)
179
+ [✅|⚠️] references.md exists
180
+ [✅|⚠️] cookbook/ directory
181
+ [✅|⚠️] .mcp.json present
182
+
183
+ CONTENT VALIDATION
184
+ [✅|❌] "When to Use" section
185
+ [✅|❌] Description < 1024 chars (<current> chars)
186
+ [✅|❌] SKILL.md < 500 lines (<current> lines)
187
+ [✅|❌] All cookbook files exist
188
+
189
+ ACTIVATION TEST
190
+ [✅|❌] Skill triggered on test prompt
191
+ [✅|❌] Produced expected output format
192
+
193
+ ISSUES FOUND
194
+ - <issue 1>
195
+ - <issue 2>
196
+
197
+ RECOMMENDATIONS
198
+ - <suggestion 1>
199
+ - <suggestion 2>
200
+
201
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
202
+ Overall: [✅ PASS | ⚠️ WARNINGS | ❌ FAIL]
203
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
204
+ ```
205
+
206
+ ---
207
+
208
+ ## Error Handling
209
+
210
+ ### Skill Not Found
211
+ ```
212
+ ❌ Skill "<name>" not found.
213
+
214
+ Available skills:
215
+ - ui-components
216
+ - api-integration
217
+
218
+ Use /agileflow:skill:list to see all skills.
219
+ ```
220
+
221
+ ### No Skills Installed
222
+ ```
223
+ ❌ No skills to test.
224
+
225
+ Create a skill first: /agileflow:skill:create
226
+ ```
227
+
228
+ ### Validation Failed
229
+ ```
230
+ ❌ Skill "<name>" has issues:
231
+
232
+ ❌ Missing SKILL.md frontmatter
233
+ ❌ Description exceeds 1024 characters (1523)
234
+ ⚠️ No "When to Use" section
235
+
236
+ Fix with: /agileflow:skill:edit <name>
237
+ ```
238
+
239
+ ---
240
+
241
+ ## Usage
242
+
243
+ ```bash
244
+ # Interactive mode
245
+ /agileflow:skill:test
246
+
247
+ # Test specific skill
248
+ /agileflow:skill:test supabase-swift
249
+ ```
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: Create and manage custom document templates
3
+ argument-hint: (no arguments)
3
4
  ---
4
5
 
5
6
  # custom-template
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: Set up automated testing infrastructure
3
+ argument-hint: (no arguments)
3
4
  ---
4
5
 
5
6
  # setup-tests
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: Generate stakeholder progress report
3
+ argument-hint: (no arguments)
3
4
  ---
4
5
 
5
6
  # stakeholder-update
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: Track velocity and forecast sprint capacity
3
+ argument-hint: (no arguments)
3
4
  model: haiku
4
5
  ---
5
6
 
@@ -26,22 +26,22 @@ files:
26
26
  core_content:
27
27
  - path: packages/cli/src/core/commands/
28
28
  purpose: Slash command markdown files
29
- count: 41
29
+ count: "{{COMMAND_COUNT}}"
30
30
  pattern: "<command>.md with frontmatter"
31
31
 
32
32
  - path: packages/cli/src/core/agents/
33
33
  purpose: Agent prompt markdown files
34
- count: 26
34
+ count: "{{AGENT_COUNT}}"
35
35
  pattern: "<agent>.md with frontmatter (name, description, tools, model)"
36
36
 
37
37
  - path: packages/cli/src/core/experts/
38
38
  purpose: Expert knowledge files
39
- count: 25
39
+ count: "{{SKILL_COUNT}}"
40
40
  pattern: "<domain>/expertise.yaml, question.md, self-improve.md, workflow.md"
41
41
 
42
42
  - path: packages/cli/src/core/skills/
43
43
  purpose: Auto-activating skills
44
- count: 23
44
+ count: "{{SKILL_COUNT}}"
45
45
  pattern: "<skill>/SKILL.md"
46
46
 
47
47
  scripts:
@@ -67,10 +67,10 @@ relationships:
67
67
 
68
68
  - name: content_structure
69
69
  locations:
70
- - "commands/ - 41 .md files"
71
- - "agents/ - 26 .md files"
72
- - "experts/ - 25 directories"
73
- - "skills/ - 23 directories"
70
+ - "commands/ - {{COMMAND_COUNT}} .md files"
71
+ - "agents/ - {{AGENT_COUNT}} .md files"
72
+ - "experts/ - {{SKILL_COUNT}} directories"
73
+ - "skills/ - {{SKILL_COUNT}} directories"
74
74
  observation: "Consistent patterns across all content types"
75
75
 
76
76
  patterns:
@@ -78,9 +78,14 @@ patterns:
78
78
  description: "Placeholders replaced at install time"
79
79
  location: "lib/content-injector.js"
80
80
  placeholders:
81
- - "<!-- {{AGENT_LIST}} -->"
82
- - "<!-- {{COMMAND_LIST}} -->"
83
- benefit: "Zero maintenance for lists"
81
+ - "{{COMMAND_COUNT}} - Number of commands"
82
+ - "{{AGENT_COUNT}} - Number of agents"
83
+ - "{{SKILL_COUNT}} - Number of skills"
84
+ - "{{VERSION}} - AgileFlow version"
85
+ - "{{INSTALL_DATE}} - Installation date"
86
+ - "<!-- {{AGENT_LIST}} --> - Full agent list"
87
+ - "<!-- {{COMMAND_LIST}} --> - Full command list"
88
+ benefit: "Zero maintenance for lists and counts"
84
89
 
85
90
  - name: IDE-Specific Installers
86
91
  description: "Separate installer per IDE"
@@ -116,7 +121,7 @@ learnings:
116
121
 
117
122
  - date: 2025-12-21
118
123
  context: "Analyzed content structure"
119
- insight: "Consistent patterns: 41 commands, 26 agents, 25 experts, 23 skills - all use frontmatter markdown"
124
+ insight: "Consistent patterns: {{COMMAND_COUNT}} commands, {{AGENT_COUNT}} agents, {{SKILL_COUNT}} experts, {{SKILL_COUNT}} skills - all use frontmatter markdown"
120
125
  source: "packages/cli/src/core/"
121
126
 
122
127
  - date: 2025-12-21
@@ -6,7 +6,7 @@
6
6
  "hooks": [
7
7
  {
8
8
  "type": "command",
9
- "command": "echo '🚀 AgileFlow v2.19.0 loaded - Type /agileflow:help for commands'"
9
+ "command": "echo '🚀 AgileFlow v{{VERSION}} loaded - Type /agileflow:help for commands'"
10
10
  },
11
11
  {
12
12
  "type": "command",
@@ -6,7 +6,7 @@
6
6
  "hooks": [
7
7
  {
8
8
  "type": "command",
9
- "command": "echo '🚀 AgileFlow v2.19.0 loaded - Use /agileflow:help to see available commands'"
9
+ "command": "echo '🚀 AgileFlow v{{VERSION}} loaded - Use /agileflow:help to see available commands'"
10
10
  }
11
11
  ]
12
12
  },
@@ -10,6 +10,7 @@ const fs = require('fs-extra');
10
10
  const yaml = require('js-yaml');
11
11
  const { Installer } = require('../installers/core/installer');
12
12
  const { displayLogo, displaySection, success, warning, info } = require('../lib/ui');
13
+ const { parseFrontmatter: parseYamlFrontmatter } = require('../../../scripts/lib/frontmatter-parser');
13
14
 
14
15
  const installer = new Installer();
15
16
 
@@ -255,23 +256,17 @@ async function listExperts(agileflowPath) {
255
256
  }
256
257
 
257
258
  /**
258
- * Parse YAML frontmatter from markdown
259
+ * Parse YAML frontmatter from markdown (wrapper for shared parser)
259
260
  * @param {string} content - File content
260
261
  * @returns {{ frontmatter: Object|null, content: string }}
261
262
  */
262
263
  function parseFrontmatter(content) {
263
- const match = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
264
-
265
- if (!match) {
266
- return { frontmatter: null, content };
267
- }
268
-
269
- try {
270
- const frontmatter = yaml.load(match[1]);
271
- return { frontmatter, content: match[2] };
272
- } catch {
273
- return { frontmatter: null, content };
274
- }
264
+ const frontmatter = parseYamlFrontmatter(content);
265
+ const body = content.replace(/^---\n[\s\S]*?\n---\n?/, '');
266
+ return {
267
+ frontmatter: Object.keys(frontmatter).length > 0 ? frontmatter : null,
268
+ content: body,
269
+ };
275
270
  }
276
271
 
277
272
  /**
@@ -5,26 +5,15 @@
5
5
  */
6
6
 
7
7
  const path = require('node:path');
8
- const crypto = require('node:crypto');
9
8
  const fs = require('fs-extra');
10
9
  const chalk = require('chalk');
11
10
  const ora = require('ora');
12
11
  const yaml = require('js-yaml');
12
+ const { injectContent } = require('../../lib/content-injector');
13
+ const { sha256Hex, toPosixPath, safeTimestampForPath } = require('../../lib/utils');
13
14
 
14
15
  const TEXT_EXTENSIONS = new Set(['.md', '.yaml', '.yml', '.txt', '.json']);
15
16
 
16
- function sha256Hex(data) {
17
- return crypto.createHash('sha256').update(data).digest('hex');
18
- }
19
-
20
- function toPosixPath(filePath) {
21
- return filePath.split(path.sep).join('/');
22
- }
23
-
24
- function safeTimestampForPath(date = new Date()) {
25
- return date.toISOString().replace(/[:.]/g, '-');
26
- }
27
-
28
17
  /**
29
18
  * Get the source path for AgileFlow content
30
19
  * @returns {string} Path to src directory
@@ -48,6 +37,11 @@ class Installer {
48
37
  constructor() {
49
38
  this.sourcePath = getSourcePath();
50
39
  this.packageRoot = getPackageRoot();
40
+ this.coreDir = path.join(this.sourcePath, 'core');
41
+
42
+ // Load version from package.json
43
+ const packageJson = require(path.join(this.packageRoot, 'package.json'));
44
+ this.version = packageJson.version;
51
45
  }
52
46
 
53
47
  /**
@@ -260,7 +254,7 @@ class Installer {
260
254
  }
261
255
 
262
256
  /**
263
- * Copy a file with placeholder replacements
257
+ * Copy a file with placeholder replacements using content injector
264
258
  * @param {string} source - Source file path
265
259
  * @param {string} dest - Destination file path
266
260
  * @param {string} agileflowFolder - AgileFlow folder name
@@ -271,9 +265,12 @@ class Installer {
271
265
  if (TEXT_EXTENSIONS.has(ext)) {
272
266
  let content = await fs.readFile(source, 'utf8');
273
267
 
274
- // Replace placeholders
275
- content = content.replace(/\{agileflow_folder\}/g, agileflowFolder);
276
- content = content.replace(/\{project-root\}/g, '{project-root}'); // Keep as-is for runtime
268
+ // Use content injector for all placeholder replacements
269
+ content = injectContent(content, {
270
+ coreDir: this.coreDir,
271
+ agileflowFolder,
272
+ version: this.version,
273
+ });
277
274
 
278
275
  await fs.writeFile(dest, content, 'utf8');
279
276
  } else {
@@ -304,8 +301,12 @@ class Installer {
304
301
  let newContent;
305
302
  if (isText) {
306
303
  let content = await fs.readFile(source, 'utf8');
307
- content = content.replace(/\{agileflow_folder\}/g, agileflowFolder);
308
- content = content.replace(/\{project-root\}/g, '{project-root}');
304
+ // Use content injector for all placeholder replacements
305
+ content = injectContent(content, {
306
+ coreDir: this.coreDir,
307
+ agileflowFolder,
308
+ version: this.version,
309
+ });
309
310
  newContent = content;
310
311
  } else {
311
312
  newContent = await fs.readFile(source);
@@ -68,11 +68,25 @@ class BaseIdeSetup {
68
68
  injectDynamicContent(content, agileflowDir) {
69
69
  const { injectContent } = require('../../lib/content-injector');
70
70
  // agileflowDir is the user's .agileflow installation directory
71
- // which has agents/ and commands/ at the root level (not src/core/)
72
- const agentsDir = path.join(agileflowDir, 'agents');
73
- const commandsDir = path.join(agileflowDir, 'commands');
71
+ // which has agents/, commands/, skills/ at the root level
72
+ return injectContent(content, {
73
+ coreDir: agileflowDir,
74
+ agileflowFolder: this.agileflowFolder,
75
+ version: this.getVersion(),
76
+ });
77
+ }
74
78
 
75
- return injectContent(content, agentsDir, commandsDir);
79
+ /**
80
+ * Get the current AgileFlow version
81
+ * @returns {string} Version string
82
+ */
83
+ getVersion() {
84
+ try {
85
+ const packageJson = require('../../../../package.json');
86
+ return packageJson.version || 'unknown';
87
+ } catch {
88
+ return 'unknown';
89
+ }
76
90
  }
77
91
 
78
92
  /**
@@ -63,22 +63,11 @@ class ClaudeCodeSetup extends BaseIdeSetup {
63
63
  await this.installCommandsRecursive(agentsSource, spawnableAgentsDir, agileflowDir, false);
64
64
  console.log(chalk.dim(` - Spawnable agents: .claude/agents/agileflow/`));
65
65
 
66
- // Install skills (.claude/skills/)
67
- const skillsSource = path.join(agileflowDir, 'skills');
66
+ // Create skills directory for user-generated skills (.claude/skills/)
67
+ // AgileFlow no longer ships static skills - users generate them via /agileflow:skill:create
68
68
  const skillsTargetDir = path.join(claudeDir, 'skills');
69
- let skillCount = 0;
70
- if (await this.exists(skillsSource)) {
71
- const skillResult = await this.installCommandsRecursive(
72
- skillsSource,
73
- skillsTargetDir,
74
- agileflowDir,
75
- false
76
- );
77
- skillCount = skillResult.commands + skillResult.subdirs;
78
- if (skillCount > 0) {
79
- console.log(chalk.dim(` - Skills: .claude/skills/`));
80
- }
81
- }
69
+ await this.ensureDir(skillsTargetDir);
70
+ console.log(chalk.dim(` - Skills directory: .claude/skills/ (for user-generated skills)`));
82
71
 
83
72
  const totalCommands = commandResult.commands + agentResult.commands;
84
73
  const totalSubdirs =
@@ -16,6 +16,7 @@ const fs = require('fs-extra');
16
16
  const chalk = require('chalk');
17
17
  const yaml = require('js-yaml');
18
18
  const { BaseIdeSetup } = require('./_base-ide');
19
+ const { parseFrontmatter } = require('../../../../scripts/lib/frontmatter-parser');
19
20
 
20
21
  /**
21
22
  * OpenAI Codex CLI setup handler
@@ -59,22 +60,17 @@ class CodexSetup extends BaseIdeSetup {
59
60
  * @returns {string} Codex SKILL.md content
60
61
  */
61
62
  convertAgentToSkill(content, agentName) {
62
- // Extract frontmatter if present
63
+ // Extract frontmatter using shared parser
63
64
  let description = `AgileFlow ${agentName} agent`;
64
65
  let model = 'default';
65
66
 
66
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
67
- if (frontmatterMatch) {
68
- try {
69
- const frontmatter = yaml.load(frontmatterMatch[1]);
70
- if (frontmatter.description) {
71
- description = frontmatter.description;
72
- }
73
- if (frontmatter.model) {
74
- model = frontmatter.model;
75
- }
76
- } catch (e) {
77
- // Ignore YAML parse errors
67
+ const frontmatter = parseFrontmatter(content);
68
+ if (frontmatter && Object.keys(frontmatter).length > 0) {
69
+ if (frontmatter.description) {
70
+ description = frontmatter.description;
71
+ }
72
+ if (frontmatter.model) {
73
+ model = frontmatter.model;
78
74
  }
79
75
  }
80
76