claude-autopm 2.1.0 → 2.2.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.
- package/README.md +57 -5
- package/bin/autopm.js +91 -179
- package/lib/cli/commands/prd.js +389 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ Transform your development workflow with intelligent automation, parallel AI age
|
|
|
15
15
|
|
|
16
16
|
ClaudeAutoPM is a comprehensive project management and development automation framework designed specifically for [Claude Code](https://claude.ai/code). It combines:
|
|
17
17
|
|
|
18
|
-
- **
|
|
18
|
+
- **112+ CLI commands** for deterministic operations (scaffolding, templates, automation)
|
|
19
19
|
- **39 specialized AI agents** for intelligent tasks (analysis, design, development)
|
|
20
20
|
- **Dynamic team management** with automatic agent switching
|
|
21
21
|
- **Hybrid execution modes** - choose between templates or AI assistance
|
|
@@ -44,7 +44,58 @@ PRD → Epic Decomposition → Parallel Development → Testing → Production
|
|
|
44
44
|
|
|
45
45
|
## ✨ Key Features
|
|
46
46
|
|
|
47
|
-
### 🆕 **NEW in
|
|
47
|
+
### 🆕 **NEW in v2.1.0: STANDALONE CLI Commands - Direct Service Access!**
|
|
48
|
+
|
|
49
|
+
**Three New CLI Commands** - Direct access to service layer without AI overhead
|
|
50
|
+
- 🎯 **Deterministic Operations** - Fast, predictable, no AI required
|
|
51
|
+
- 🎨 **Modern UX** - Progress spinners, color-coded output, streaming support
|
|
52
|
+
- ⚡ **High Performance** - Direct service layer access for instant results
|
|
53
|
+
- 🧪 **100% Test Coverage** - 65 CLI tests passing, full TDD methodology
|
|
54
|
+
|
|
55
|
+
**New Commands:**
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# PRD Management
|
|
59
|
+
autopm prd parse my-prd --ai # AI-powered PRD parsing
|
|
60
|
+
autopm prd parse my-prd --stream # Real-time streaming output
|
|
61
|
+
autopm prd extract-epics my-prd # Extract epics from PRD
|
|
62
|
+
autopm prd summarize my-prd # Generate comprehensive summary
|
|
63
|
+
autopm prd validate my-prd # Validate structure & quality
|
|
64
|
+
|
|
65
|
+
# Task Management
|
|
66
|
+
autopm task list epic-001 # Display all tasks from epic
|
|
67
|
+
autopm task prioritize epic-001 # AI-powered prioritization
|
|
68
|
+
|
|
69
|
+
# Agent Invocation
|
|
70
|
+
autopm agent list # Display available agents
|
|
71
|
+
autopm agent search "kubernetes" # Search agents by keyword
|
|
72
|
+
autopm agent invoke aws-architect "Design VPC" # Invoke agent with task
|
|
73
|
+
autopm agent invoke --stream agent-name "task" # Streaming invocation
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**User Experience Features:**
|
|
77
|
+
- 🔄 Progress indicators with ora spinners
|
|
78
|
+
- 🎨 Color-coded output (green=success, red=error, yellow=warning)
|
|
79
|
+
- 📡 Streaming support for real-time AI responses
|
|
80
|
+
- ❌ Comprehensive error handling with user-friendly messages
|
|
81
|
+
- 📋 Consistent patterns across all commands
|
|
82
|
+
|
|
83
|
+
**Technical Implementation:**
|
|
84
|
+
- Extended PRDService with 4 non-streaming methods
|
|
85
|
+
- All services support both streaming and non-streaming modes
|
|
86
|
+
- Proper separation of concerns (CLI → Service → Provider)
|
|
87
|
+
- Zero breaking changes to existing functionality
|
|
88
|
+
- CommonJS compatibility maintained
|
|
89
|
+
|
|
90
|
+
**Test Coverage:**
|
|
91
|
+
- 28 new tests across 3 CLI command suites
|
|
92
|
+
- 65 total CLI tests passing (100% pass rate)
|
|
93
|
+
- Full TDD methodology with Jest
|
|
94
|
+
- Comprehensive coverage of success, error, and streaming scenarios
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### 🎉 **v1.30.0: Advanced Conflict Resolution - Complete Sync Safety!**
|
|
48
99
|
|
|
49
100
|
**Three-Way Merge Conflict Resolution** - Safe GitHub synchronization
|
|
50
101
|
- 🔒 **Intelligent Merge** - Three-way diff (local/remote/base) with conflict detection
|
|
@@ -341,7 +392,7 @@ claude --dangerously-skip-permissions .
|
|
|
341
392
|
│ │
|
|
342
393
|
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
343
394
|
│ │ CLI Layer │ │ Agent Teams │ │ MCP Servers │ │
|
|
344
|
-
│ │ (
|
|
395
|
+
│ │ (112 cmds) │ │ (39 agents) │ │ (Context7) │ │
|
|
345
396
|
│ └──────┬──────┘ └──────┬───────┘ └──────┬───────┘ │
|
|
346
397
|
│ │ │ │ │
|
|
347
398
|
│ └─────────────────┼──────────────────┘ │
|
|
@@ -351,6 +402,7 @@ claude --dangerously-skip-permissions .
|
|
|
351
402
|
│ │ - Sequential / Adaptive / Hybrid │ │
|
|
352
403
|
│ │ - Parallel agent coordination │ │
|
|
353
404
|
│ │ - Context optimization │ │
|
|
405
|
+
│ │ - STANDALONE mode (direct service access) │ │
|
|
354
406
|
│ └────────────────────────┬─────────────────────────┘ │
|
|
355
407
|
│ │ │
|
|
356
408
|
│ ┌────────────────────────┴─────────────────────────┐ │
|
|
@@ -405,8 +457,8 @@ claude --dangerously-skip-permissions .
|
|
|
405
457
|
|
|
406
458
|
## 📦 What's Included
|
|
407
459
|
|
|
408
|
-
### CLI Commands (
|
|
409
|
-
- **Project Management**: PRD, Epic, Issue, Task management
|
|
460
|
+
### CLI Commands (112 total)
|
|
461
|
+
- **Project Management**: PRD, Epic, Issue, Task management (3 new STANDALONE commands in v2.1.0)
|
|
410
462
|
- **Development**: Scaffolding, testing, deployment
|
|
411
463
|
- **Configuration**: Provider setup, team management, MCP servers
|
|
412
464
|
- **DevOps**: Docker, Kubernetes, CI/CD automation
|
package/bin/autopm.js
CHANGED
|
@@ -232,12 +232,35 @@ function main() {
|
|
|
232
232
|
.wrap(cli.terminalWidth())
|
|
233
233
|
// Enhanced help epilogue
|
|
234
234
|
.epilogue(`
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
235
|
+
╔════════════════════════════════════════════════════════════════════════════╗
|
|
236
|
+
║ ClaudeAutoPM v${VERSION} - Quick Reference ║
|
|
237
|
+
║ AI-Powered Project Management for Claude Code ║
|
|
238
|
+
╚════════════════════════════════════════════════════════════════════════════╝
|
|
239
|
+
|
|
240
|
+
🚀 Quick Start (3 Steps):
|
|
241
|
+
1. autopm install # Install framework in project
|
|
242
|
+
2. autopm config set provider github # Configure your provider
|
|
243
|
+
3. claude --dangerously-skip-permissions . # Open Claude Code
|
|
244
|
+
|
|
245
|
+
🆕 NEW in v2.1.0 - STANDALONE Commands:
|
|
246
|
+
autopm prd parse <name> # Parse PRD without AI overhead
|
|
247
|
+
autopm prd extract-epics <name> # Extract epics from PRD
|
|
248
|
+
autopm prd summarize <name> # Generate PRD summary
|
|
249
|
+
autopm prd validate <name> # Validate PRD structure
|
|
250
|
+
|
|
251
|
+
autopm task list <epic> # List tasks from epic
|
|
252
|
+
autopm task prioritize <epic> # AI-powered prioritization
|
|
253
|
+
|
|
254
|
+
autopm agent list # List available agents
|
|
255
|
+
autopm agent search <keyword> # Search agents
|
|
256
|
+
autopm agent invoke <name> <task> # Invoke agent directly
|
|
257
|
+
|
|
258
|
+
📋 Common Commands:
|
|
259
|
+
autopm validate # Check configuration status
|
|
260
|
+
autopm update # Update to latest version
|
|
261
|
+
autopm team load fullstack # Load development agents
|
|
262
|
+
autopm mcp enable context7 # Enable documentation access
|
|
263
|
+
autopm config show # View current configuration
|
|
241
264
|
|
|
242
265
|
🔧 Configuration Setup:
|
|
243
266
|
# View current configuration
|
|
@@ -289,187 +312,76 @@ function main() {
|
|
|
289
312
|
|
|
290
313
|
🤖 Team Management:
|
|
291
314
|
autopm team list # See all available agent teams
|
|
292
|
-
autopm team load
|
|
293
|
-
autopm team load backend # Load Python/Node.js agents
|
|
294
|
-
autopm team load fullstack # Load complete development stack
|
|
295
|
-
autopm team load devops # Load Docker/K8s/CI-CD agents
|
|
315
|
+
autopm team load <name> # Load specific team (frontend/backend/fullstack/devops)
|
|
296
316
|
autopm team current # Check currently active team
|
|
297
|
-
autopm team reset # Reset to default team
|
|
298
317
|
|
|
299
|
-
💡 Claude Code
|
|
300
|
-
/pm:what-next # ⭐ Smart suggestions for
|
|
318
|
+
💡 Claude Code Workflows (In-Editor Commands):
|
|
319
|
+
/pm:what-next # ⭐ Smart suggestions for next steps
|
|
301
320
|
/pm:status # Project overview and health
|
|
302
|
-
/pm:
|
|
303
|
-
/pm:
|
|
304
|
-
/pm:
|
|
305
|
-
/pm:
|
|
306
|
-
/pm:
|
|
307
|
-
/pm:
|
|
308
|
-
/pm:
|
|
309
|
-
/pm:issue-start TASK-123 # Start working on specific task
|
|
310
|
-
/pm:issue-show TASK-123 # View task details
|
|
311
|
-
/pm:issue-close TASK-123 # Close completed task
|
|
312
|
-
/pm:standup # Generate daily standup summary
|
|
313
|
-
/pm:search keyword # Search across PRDs and epics
|
|
314
|
-
/pm:help # Show all PM commands
|
|
315
|
-
|
|
316
|
-
📋 PM Workflow Decision Guide:
|
|
317
|
-
|
|
318
|
-
WHEN TO USE ONE EPIC (/pm:epic-decompose):
|
|
319
|
-
✅ Simple feature (1-2 weeks)
|
|
320
|
-
✅ Single component (frontend OR backend)
|
|
321
|
-
✅ One developer
|
|
322
|
-
Examples: "User profile page", "REST API endpoint"
|
|
323
|
-
|
|
324
|
-
WHEN TO USE MULTIPLE EPICS (/pm:epic-split):
|
|
325
|
-
✅ Complex project (2+ months)
|
|
326
|
-
✅ Multiple components (frontend + backend + infra)
|
|
327
|
-
✅ Multiple teams working in parallel
|
|
328
|
-
Examples: "E-commerce platform", "Social dashboard"
|
|
329
|
-
|
|
330
|
-
SIMPLE FEATURE FLOW:
|
|
331
|
-
/pm:prd-new feature → /pm:prd-parse feature → /pm:epic-decompose feature
|
|
332
|
-
|
|
333
|
-
COMPLEX PROJECT FLOW:
|
|
334
|
-
/pm:prd-new project → /pm:prd-parse project → /pm:epic-split project
|
|
335
|
-
→ /pm:epic-decompose project/01-epic1 → /pm:epic-decompose project/02-epic2 ...
|
|
336
|
-
|
|
337
|
-
📖 Full Guide: See PM-WORKFLOW-GUIDE.md
|
|
338
|
-
|
|
339
|
-
🚀 Complete Workflows:
|
|
340
|
-
|
|
341
|
-
=== GITHUB WORKFLOW (PRD → Epic → Issues) ===
|
|
342
|
-
1. autopm install # Setup project framework
|
|
343
|
-
2. autopm config set provider github # Set provider
|
|
344
|
-
autopm config set github.owner <username>
|
|
345
|
-
autopm config set github.repo <repository>
|
|
346
|
-
export GITHUB_TOKEN=<your-token>
|
|
347
|
-
3. autopm team load fullstack # Load appropriate agents
|
|
348
|
-
4. claude --dangerously-skip-permissions . # Open Claude Code
|
|
349
|
-
5. /pm:validate # Verify GitHub integration
|
|
350
|
-
|
|
351
|
-
6. /pm:prd-new user-auth # Create Product Requirements Document
|
|
352
|
-
7. /pm:prd-parse user-auth # Parse PRD into structured format
|
|
353
|
-
8. /pm:epic-split user-auth # [OPTIONAL] Split complex PRD into multiple epics
|
|
354
|
-
9. /pm:epic-decompose user-auth # Break PRD/Epic into Issues
|
|
355
|
-
10. /pm:epic-sync user-auth # Create GitHub Epic + Issues
|
|
356
|
-
11. /pm:next # Get next priority issue
|
|
357
|
-
12. /pm:issue-start ISSUE-123 # Start working on specific issue
|
|
358
|
-
13. # ... development work ...
|
|
359
|
-
14. /pm:issue-close ISSUE-123 # Close completed issue
|
|
360
|
-
15. /pm:standup # Generate progress summary
|
|
361
|
-
|
|
362
|
-
=== AZURE DEVOPS WORKFLOW (PRD → User Stories → Tasks) ===
|
|
363
|
-
1. autopm install # Setup project framework
|
|
364
|
-
2. autopm config set provider azure # Set provider
|
|
365
|
-
autopm config set azure.organization <org>
|
|
366
|
-
autopm config set azure.project <project>
|
|
367
|
-
export AZURE_DEVOPS_PAT=<your-pat>
|
|
368
|
-
3. autopm team load fullstack # Load appropriate agents
|
|
369
|
-
4. claude --dangerously-skip-permissions . # Open Claude Code
|
|
370
|
-
5. /pm:validate # Verify Azure DevOps integration
|
|
371
|
-
|
|
372
|
-
6. /pm:prd-new user-auth # Create Product Requirements Document
|
|
373
|
-
7. /pm:prd-parse user-auth # Parse PRD into structured format
|
|
374
|
-
8. /pm:epic-split user-auth # [OPTIONAL] Split complex PRD into multiple epics
|
|
375
|
-
9. /pm:epic-decompose user-auth # Break PRD/Epic into User Stories + Tasks
|
|
376
|
-
10. /pm:epic-sync user-auth # Create Azure Epic + User Stories + Tasks
|
|
377
|
-
11. /pm:next # Get next priority task
|
|
378
|
-
12. /pm:issue-start TASK-123 # Start working on specific task
|
|
379
|
-
13. # ... development work ...
|
|
380
|
-
14. /pm:issue-close TASK-123 # Close completed task
|
|
381
|
-
15. /pm:standup # Generate sprint summary
|
|
382
|
-
|
|
383
|
-
=== COMPLEX PROJECT WORKFLOW (Multi-Epic Split) ===
|
|
384
|
-
Example: Full-stack e-commerce platform
|
|
385
|
-
|
|
386
|
-
6. /pm:prd-new ecommerce-platform
|
|
387
|
-
7. /pm:prd-parse ecommerce-platform
|
|
388
|
-
8. /pm:epic-split ecommerce-platform # → Creates 6 epics automatically
|
|
389
|
-
→ Epic 1: Infrastructure Foundation (Docker, DB, monitoring)
|
|
390
|
-
→ Epic 2: Authentication Backend (JWT, users, RBAC)
|
|
391
|
-
→ Epic 3: Product API Services (catalog, inventory, orders)
|
|
392
|
-
→ Epic 4: Frontend Foundation (React setup, state management)
|
|
393
|
-
→ Epic 5: E-commerce UI (product pages, cart, checkout)
|
|
394
|
-
→ Epic 6: Testing & Deployment (CI/CD, quality gates)
|
|
395
|
-
9. /pm:epic-decompose ecommerce-platform/01-infrastructure # Decompose each epic
|
|
396
|
-
10. /pm:epic-decompose ecommerce-platform/02-auth-backend
|
|
397
|
-
11. ... (repeat for each epic)
|
|
398
|
-
12. /pm:epic-sync ecommerce-platform # Sync all epics to provider
|
|
399
|
-
13. /pm:next # Start with P0 infrastructure epic
|
|
400
|
-
|
|
401
|
-
📋 Detailed Step-by-Step Examples:
|
|
402
|
-
|
|
403
|
-
STEP 6 - Creating PRD:
|
|
404
|
-
/pm:prd-new user-authentication
|
|
405
|
-
→ Creates: .claude/prds/user-authentication.md
|
|
406
|
-
→ Contains: Problem statement, user stories, acceptance criteria
|
|
407
|
-
|
|
408
|
-
STEP 7 - Parsing PRD:
|
|
409
|
-
/pm:prd-parse user-authentication
|
|
410
|
-
→ Analyzes PRD content and structure
|
|
411
|
-
→ Prepares for epic decomposition
|
|
412
|
-
|
|
413
|
-
STEP 8 - Epic Split (Optional for Complex Projects):
|
|
414
|
-
/pm:epic-split user-authentication
|
|
415
|
-
→ Analyzes PRD complexity and identifies logical divisions
|
|
416
|
-
→ Splits into multiple epics: Infrastructure, Backend, Frontend, UI, etc.
|
|
417
|
-
→ Creates structured epic hierarchy with dependencies
|
|
418
|
-
→ Example: 6 epics identified (Infrastructure, Auth Backend, Frontend, etc.)
|
|
419
|
-
→ Use when: Multi-component projects, large teams, parallel work needed
|
|
420
|
-
|
|
421
|
-
STEP 9 - Epic Decomposition:
|
|
422
|
-
/pm:epic-decompose user-authentication
|
|
423
|
-
→ GitHub: Creates Epic with linked Issues
|
|
424
|
-
→ Azure: Creates Epic with User Stories and child Tasks
|
|
425
|
-
→ File: .claude/epics/user-authentication.md (or multiple epic folders if split)
|
|
426
|
-
|
|
427
|
-
STEP 10 - Sync with Provider:
|
|
428
|
-
/pm:epic-sync user-authentication
|
|
429
|
-
→ GitHub: Creates Epic + Issues in repository
|
|
430
|
-
→ Azure: Creates Epic + User Stories + Tasks in project
|
|
431
|
-
→ Links local files with remote work items
|
|
432
|
-
|
|
433
|
-
STEP 11 - Get Next Work:
|
|
434
|
-
/pm:next
|
|
435
|
-
→ Returns highest priority unassigned item
|
|
436
|
-
→ GitHub: Next issue to work on
|
|
437
|
-
→ Azure: Next task to work on
|
|
438
|
-
|
|
439
|
-
STEP 12 - Start Development:
|
|
440
|
-
/pm:issue-start USER-AUTH-001
|
|
441
|
-
→ Assigns work item to you
|
|
442
|
-
→ Updates status to "In Progress"
|
|
443
|
-
→ Creates development branch (if configured)
|
|
444
|
-
|
|
445
|
-
STEP 13 - Complete Work:
|
|
446
|
-
/pm:issue-close USER-AUTH-001
|
|
447
|
-
→ Updates status to "Done/Closed"
|
|
448
|
-
→ Links commits and PR (if available)
|
|
449
|
-
→ Updates epic progress tracking
|
|
321
|
+
/pm:prd-new <name> # Create new PRD
|
|
322
|
+
/pm:epic-decompose <name> # Break PRD into tasks
|
|
323
|
+
/pm:epic-sync <name> # Sync to GitHub/Azure
|
|
324
|
+
/pm:next # Get next priority task
|
|
325
|
+
/pm:issue-start <id> # Start working on task
|
|
326
|
+
/pm:issue-close <id> # Complete task
|
|
327
|
+
/pm:standup # Generate daily summary
|
|
450
328
|
|
|
451
|
-
|
|
452
|
-
# Check installation and configuration
|
|
453
|
-
autopm validate # Comprehensive status check
|
|
454
|
-
ls -la .claude/ # Should show: agents/, commands/, config.json
|
|
329
|
+
📋 Quick Workflow Examples:
|
|
455
330
|
|
|
456
|
-
|
|
457
|
-
/pm:
|
|
458
|
-
|
|
331
|
+
SIMPLE FEATURE (Use this for most tasks):
|
|
332
|
+
1. /pm:prd-new user-login # Create PRD
|
|
333
|
+
2. /pm:epic-decompose user-login # Break into tasks
|
|
334
|
+
3. /pm:epic-sync user-login # Push to GitHub/Azure
|
|
335
|
+
4. /pm:next # Start working
|
|
459
336
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
337
|
+
COMPLEX PROJECT (Multiple epics):
|
|
338
|
+
1. /pm:prd-new ecommerce # Create PRD
|
|
339
|
+
2. /pm:epic-split ecommerce # Split into multiple epics
|
|
340
|
+
3. /pm:epic-decompose ecommerce/01-backend # Decompose each epic
|
|
341
|
+
4. /pm:epic-sync ecommerce # Sync all epics
|
|
342
|
+
|
|
343
|
+
🔍 Using STANDALONE Commands:
|
|
344
|
+
|
|
345
|
+
# Parse PRD without AI (fast, deterministic)
|
|
346
|
+
autopm prd parse my-feature
|
|
347
|
+
|
|
348
|
+
# AI-powered parsing with streaming output
|
|
349
|
+
autopm prd parse my-feature --ai --stream
|
|
463
350
|
|
|
464
|
-
|
|
465
|
-
autopm
|
|
466
|
-
autopm
|
|
467
|
-
|
|
351
|
+
# Extract and validate
|
|
352
|
+
autopm prd extract-epics my-feature
|
|
353
|
+
autopm prd validate my-feature --fix
|
|
354
|
+
|
|
355
|
+
# Task management
|
|
356
|
+
autopm task list epic-001
|
|
357
|
+
autopm task prioritize epic-001
|
|
358
|
+
|
|
359
|
+
# Agent invocation
|
|
360
|
+
autopm agent search kubernetes
|
|
361
|
+
autopm agent invoke aws-architect "Design VPC" --stream
|
|
362
|
+
|
|
363
|
+
🛠️ Troubleshooting:
|
|
364
|
+
autopm validate # Check installation & config
|
|
365
|
+
autopm validate --fix # Auto-fix common issues
|
|
366
|
+
autopm mcp diagnose # Check MCP server health
|
|
367
|
+
autopm install --force # Reinstall framework
|
|
468
368
|
|
|
469
|
-
📚 Resources:
|
|
470
|
-
Documentation:
|
|
471
|
-
Report Issues:
|
|
472
|
-
|
|
369
|
+
📚 Resources & Help:
|
|
370
|
+
📖 Documentation: https://github.com/rafeekpro/ClaudeAutoPM
|
|
371
|
+
🐛 Report Issues: https://github.com/rafeekpro/ClaudeAutoPM/issues
|
|
372
|
+
💬 Discussions: https://github.com/rafeekpro/ClaudeAutoPM/discussions
|
|
373
|
+
📦 npm Package: https://www.npmjs.com/package/claude-autopm
|
|
374
|
+
|
|
375
|
+
💡 Pro Tips:
|
|
376
|
+
• Use \`autopm --help\` to see this guide anytime
|
|
377
|
+
• Run \`autopm validate\` after configuration changes
|
|
378
|
+
• Use \`--stream\` flag for real-time AI responses
|
|
379
|
+
• Check \`autopm mcp status\` to verify documentation access
|
|
380
|
+
• Load appropriate team before starting work (frontend/backend/fullstack)
|
|
381
|
+
|
|
382
|
+
╔════════════════════════════════════════════════════════════════════════════╗
|
|
383
|
+
║ Need more help? Run: autopm <command> --help for detailed command docs ║
|
|
384
|
+
╚════════════════════════════════════════════════════════════════════════════╝
|
|
473
385
|
`)
|
|
474
386
|
.fail((msg, err, yargs) => {
|
|
475
387
|
if (err) {
|
package/lib/cli/commands/prd.js
CHANGED
|
@@ -17,6 +17,7 @@ const fs = require('fs-extra');
|
|
|
17
17
|
const ora = require('ora');
|
|
18
18
|
const chalk = require('chalk');
|
|
19
19
|
const path = require('path');
|
|
20
|
+
const { spawn } = require('child_process');
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Get PRD file path
|
|
@@ -46,6 +47,310 @@ async function readPrdFile(name) {
|
|
|
46
47
|
return await fs.readFile(prdPath, 'utf8');
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
/**
|
|
51
|
+
* List all PRDs
|
|
52
|
+
*/
|
|
53
|
+
async function prdList(argv) {
|
|
54
|
+
const spinner = ora('Loading PRDs...').start();
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const prdsDir = path.join(process.cwd(), '.claude', 'prds');
|
|
58
|
+
|
|
59
|
+
// Check if directory exists
|
|
60
|
+
const dirExists = await fs.pathExists(prdsDir);
|
|
61
|
+
if (!dirExists) {
|
|
62
|
+
spinner.info(chalk.yellow('No PRDs directory found'));
|
|
63
|
+
console.log(chalk.yellow('\nCreate your first PRD with: autopm prd new <name>'));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Read all PRD files
|
|
68
|
+
const files = await fs.readdir(prdsDir);
|
|
69
|
+
const prdFiles = files.filter(f => f.endsWith('.md'));
|
|
70
|
+
|
|
71
|
+
if (prdFiles.length === 0) {
|
|
72
|
+
spinner.info(chalk.yellow('No PRDs found'));
|
|
73
|
+
console.log(chalk.yellow('\nCreate your first PRD with: autopm prd new <name>'));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
spinner.succeed(chalk.green(`Found ${prdFiles.length} PRD(s)`));
|
|
78
|
+
|
|
79
|
+
// Read and parse each PRD
|
|
80
|
+
const prds = [];
|
|
81
|
+
for (const file of prdFiles) {
|
|
82
|
+
const filePath = path.join(prdsDir, file);
|
|
83
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
84
|
+
|
|
85
|
+
// Extract frontmatter
|
|
86
|
+
const titleMatch = content.match(/^title:\s*(.+)$/m);
|
|
87
|
+
const statusMatch = content.match(/^status:\s*(\w+)$/m);
|
|
88
|
+
const priorityMatch = content.match(/^priority:\s*(P\d|Critical|High|Medium|Low)$/m);
|
|
89
|
+
const createdMatch = content.match(/^created:\s*(.+)$/m);
|
|
90
|
+
|
|
91
|
+
prds.push({
|
|
92
|
+
name: file.replace('.md', ''),
|
|
93
|
+
title: titleMatch ? titleMatch[1] : file.replace('.md', ''),
|
|
94
|
+
status: statusMatch ? statusMatch[1] : 'unknown',
|
|
95
|
+
priority: priorityMatch ? priorityMatch[1] : 'P2',
|
|
96
|
+
created: createdMatch ? createdMatch[1] : 'unknown'
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Sort by priority (P0 > P1 > P2 > P3)
|
|
101
|
+
prds.sort((a, b) => {
|
|
102
|
+
const priorities = { 'P0': 0, 'Critical': 0, 'P1': 1, 'High': 1, 'P2': 2, 'Medium': 2, 'P3': 3, 'Low': 3 };
|
|
103
|
+
return (priorities[a.priority] || 2) - (priorities[b.priority] || 2);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Display PRDs
|
|
107
|
+
console.log(chalk.green('\n📋 PRDs:\n'));
|
|
108
|
+
|
|
109
|
+
prds.forEach((prd, index) => {
|
|
110
|
+
const priorityColor = prd.priority.startsWith('P0') || prd.priority === 'Critical' ? chalk.red :
|
|
111
|
+
prd.priority.startsWith('P1') || prd.priority === 'High' ? chalk.yellow :
|
|
112
|
+
chalk.blue;
|
|
113
|
+
|
|
114
|
+
const statusColor = prd.status === 'completed' ? chalk.green :
|
|
115
|
+
prd.status === 'in-progress' ? chalk.yellow :
|
|
116
|
+
prd.status === 'draft' ? chalk.gray :
|
|
117
|
+
chalk.white;
|
|
118
|
+
|
|
119
|
+
console.log(`${index + 1}. ${chalk.bold(prd.name)}`);
|
|
120
|
+
console.log(` ${priorityColor(prd.priority.padEnd(10))} ${statusColor(prd.status.padEnd(12))} ${chalk.gray(prd.created)}`);
|
|
121
|
+
if (prd.title !== prd.name) {
|
|
122
|
+
console.log(` ${chalk.dim(prd.title)}`);
|
|
123
|
+
}
|
|
124
|
+
console.log('');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
console.log(chalk.dim(`\nTotal: ${prds.length} PRD(s)`));
|
|
128
|
+
console.log(chalk.dim('Use: autopm prd show <name> to view details\n'));
|
|
129
|
+
|
|
130
|
+
} catch (error) {
|
|
131
|
+
spinner.fail(chalk.red('Failed to list PRDs'));
|
|
132
|
+
console.error(chalk.red(`\nError: ${error.message}`));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Show PRD content
|
|
138
|
+
* @param {Object} argv - Command arguments
|
|
139
|
+
*/
|
|
140
|
+
async function prdShow(argv) {
|
|
141
|
+
const spinner = ora(`Loading PRD: ${argv.name}`).start();
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
const content = await readPrdFile(argv.name);
|
|
145
|
+
spinner.succeed(chalk.green('PRD loaded'));
|
|
146
|
+
|
|
147
|
+
console.log('\n' + chalk.gray('─'.repeat(80)) + '\n');
|
|
148
|
+
console.log(content);
|
|
149
|
+
console.log('\n' + chalk.gray('─'.repeat(80)) + '\n');
|
|
150
|
+
|
|
151
|
+
const prdPath = getPrdPath(argv.name);
|
|
152
|
+
console.log(chalk.dim(`File: ${prdPath}\n`));
|
|
153
|
+
|
|
154
|
+
} catch (error) {
|
|
155
|
+
spinner.fail(chalk.red('Failed to show PRD'));
|
|
156
|
+
|
|
157
|
+
if (error.message.includes('not found')) {
|
|
158
|
+
console.error(chalk.red(`\nError: ${error.message}`));
|
|
159
|
+
console.error(chalk.yellow('Use: autopm prd list to see available PRDs'));
|
|
160
|
+
} else {
|
|
161
|
+
console.error(chalk.red(`\nError: ${error.message}`));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Edit PRD in editor
|
|
168
|
+
* @param {Object} argv - Command arguments
|
|
169
|
+
*/
|
|
170
|
+
async function prdEdit(argv) {
|
|
171
|
+
const spinner = ora(`Opening PRD: ${argv.name}`).start();
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
const prdPath = getPrdPath(argv.name);
|
|
175
|
+
|
|
176
|
+
// Check if file exists
|
|
177
|
+
const exists = await fs.pathExists(prdPath);
|
|
178
|
+
if (!exists) {
|
|
179
|
+
spinner.fail(chalk.red('PRD not found'));
|
|
180
|
+
console.error(chalk.red(`\nError: PRD file not found: ${prdPath}`));
|
|
181
|
+
console.error(chalk.yellow('Use: autopm prd list to see available PRDs'));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
spinner.succeed(chalk.green('Opening editor...'));
|
|
186
|
+
|
|
187
|
+
// Determine editor
|
|
188
|
+
const editor = process.env.EDITOR || process.env.VISUAL || 'nano';
|
|
189
|
+
|
|
190
|
+
// Spawn editor
|
|
191
|
+
const { spawn } = require('child_process');
|
|
192
|
+
const child = spawn(editor, [prdPath], {
|
|
193
|
+
stdio: 'inherit',
|
|
194
|
+
cwd: process.cwd()
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Wait for editor to close
|
|
198
|
+
await new Promise((resolve, reject) => {
|
|
199
|
+
child.on('close', (code) => {
|
|
200
|
+
if (code === 0) {
|
|
201
|
+
console.log(chalk.green('\n✓ PRD saved'));
|
|
202
|
+
resolve();
|
|
203
|
+
} else {
|
|
204
|
+
reject(new Error(`Editor exited with code ${code}`));
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
child.on('error', reject);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
} catch (error) {
|
|
211
|
+
spinner.fail(chalk.red('Failed to edit PRD'));
|
|
212
|
+
console.error(chalk.red(`\nError: ${error.message}`));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Show PRD status
|
|
218
|
+
* @param {Object} argv - Command arguments
|
|
219
|
+
*/
|
|
220
|
+
async function prdStatus(argv) {
|
|
221
|
+
const spinner = ora(`Analyzing PRD: ${argv.name}`).start();
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
const content = await readPrdFile(argv.name);
|
|
225
|
+
|
|
226
|
+
// Extract metadata
|
|
227
|
+
const titleMatch = content.match(/^title:\s*(.+)$/m);
|
|
228
|
+
const statusMatch = content.match(/^status:\s*(\w+)$/m);
|
|
229
|
+
const priorityMatch = content.match(/^priority:\s*(P\d|Critical|High|Medium|Low)$/m);
|
|
230
|
+
const createdMatch = content.match(/^created:\s*(.+)$/m);
|
|
231
|
+
const authorMatch = content.match(/^author:\s*(.+)$/m);
|
|
232
|
+
const timelineMatch = content.match(/^timeline:\s*(.+)$/m);
|
|
233
|
+
|
|
234
|
+
// Count sections
|
|
235
|
+
const sections = {
|
|
236
|
+
'Problem Statement': content.includes('## Problem Statement'),
|
|
237
|
+
'User Stories': content.includes('## User Stories'),
|
|
238
|
+
'Technical Requirements': content.includes('## Technical Requirements'),
|
|
239
|
+
'Success Metrics': content.includes('## Success Metrics'),
|
|
240
|
+
'Implementation Plan': content.includes('## Implementation Plan'),
|
|
241
|
+
'Risks': content.includes('## Risks')
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const completedSections = Object.values(sections).filter(Boolean).length;
|
|
245
|
+
const totalSections = Object.keys(sections).length;
|
|
246
|
+
const completeness = Math.round((completedSections / totalSections) * 100);
|
|
247
|
+
|
|
248
|
+
spinner.succeed(chalk.green('Status analyzed'));
|
|
249
|
+
|
|
250
|
+
// Display status
|
|
251
|
+
console.log('\n' + chalk.bold('📊 PRD Status Report') + '\n');
|
|
252
|
+
console.log(chalk.gray('─'.repeat(50)) + '\n');
|
|
253
|
+
|
|
254
|
+
console.log(chalk.bold('Metadata:'));
|
|
255
|
+
console.log(` Title: ${titleMatch ? titleMatch[1] : 'N/A'}`);
|
|
256
|
+
console.log(` Status: ${statusMatch ? chalk.yellow(statusMatch[1]) : 'N/A'}`);
|
|
257
|
+
console.log(` Priority: ${priorityMatch ? chalk.red(priorityMatch[1]) : 'N/A'}`);
|
|
258
|
+
console.log(` Created: ${createdMatch ? createdMatch[1] : 'N/A'}`);
|
|
259
|
+
console.log(` Author: ${authorMatch ? authorMatch[1] : 'N/A'}`);
|
|
260
|
+
console.log(` Timeline: ${timelineMatch ? timelineMatch[1] : 'N/A'}`);
|
|
261
|
+
|
|
262
|
+
console.log('\n' + chalk.bold('Completeness:') + ` ${completeness}%`);
|
|
263
|
+
|
|
264
|
+
const progressBar = '█'.repeat(Math.floor(completeness / 5)) +
|
|
265
|
+
'░'.repeat(20 - Math.floor(completeness / 5));
|
|
266
|
+
console.log(` [${completeness >= 80 ? chalk.green(progressBar) :
|
|
267
|
+
completeness >= 50 ? chalk.yellow(progressBar) :
|
|
268
|
+
chalk.red(progressBar)}]`);
|
|
269
|
+
|
|
270
|
+
console.log('\n' + chalk.bold('Sections:'));
|
|
271
|
+
Object.entries(sections).forEach(([name, exists]) => {
|
|
272
|
+
const icon = exists ? chalk.green('✓') : chalk.red('✗');
|
|
273
|
+
console.log(` ${icon} ${name}`);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// Statistics
|
|
277
|
+
const lines = content.split('\n').length;
|
|
278
|
+
const words = content.split(/\s+/).length;
|
|
279
|
+
const chars = content.length;
|
|
280
|
+
|
|
281
|
+
console.log('\n' + chalk.bold('Statistics:'));
|
|
282
|
+
console.log(` Lines: ${lines}`);
|
|
283
|
+
console.log(` Words: ${words}`);
|
|
284
|
+
console.log(` Chars: ${chars}`);
|
|
285
|
+
|
|
286
|
+
console.log('\n' + chalk.gray('─'.repeat(50)) + '\n');
|
|
287
|
+
|
|
288
|
+
const prdPath = getPrdPath(argv.name);
|
|
289
|
+
console.log(chalk.dim(`File: ${prdPath}\n`));
|
|
290
|
+
|
|
291
|
+
} catch (error) {
|
|
292
|
+
spinner.fail(chalk.red('Failed to analyze status'));
|
|
293
|
+
|
|
294
|
+
if (error.message.includes('not found')) {
|
|
295
|
+
console.error(chalk.red(`\nError: ${error.message}`));
|
|
296
|
+
} else {
|
|
297
|
+
console.error(chalk.red(`\nError: ${error.message}`));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Create new PRD
|
|
304
|
+
* @param {Object} argv - Command arguments
|
|
305
|
+
*/
|
|
306
|
+
async function prdNew(argv) {
|
|
307
|
+
const spinner = ora(`Creating PRD: ${argv.name}`).start();
|
|
308
|
+
|
|
309
|
+
try {
|
|
310
|
+
// Build script path
|
|
311
|
+
const scriptPath = path.join(process.cwd(), '.claude', 'scripts', 'pm', 'prd-new.js');
|
|
312
|
+
|
|
313
|
+
// Check if script exists
|
|
314
|
+
const scriptExists = await fs.pathExists(scriptPath);
|
|
315
|
+
if (!scriptExists) {
|
|
316
|
+
spinner.fail(chalk.red('PRD creation script not found'));
|
|
317
|
+
console.error(chalk.red('\nError: .claude/scripts/pm/prd-new.js not found'));
|
|
318
|
+
console.error(chalk.yellow('Run: autopm install'));
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Build arguments
|
|
323
|
+
const args = [scriptPath, argv.name];
|
|
324
|
+
if (argv.template) {
|
|
325
|
+
args.push('--template', argv.template);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
spinner.stop();
|
|
329
|
+
|
|
330
|
+
// Spawn interactive process
|
|
331
|
+
const child = spawn('node', args, {
|
|
332
|
+
stdio: 'inherit',
|
|
333
|
+
cwd: process.cwd()
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// Wait for completion
|
|
337
|
+
await new Promise((resolve, reject) => {
|
|
338
|
+
child.on('close', (code) => {
|
|
339
|
+
if (code === 0) {
|
|
340
|
+
resolve();
|
|
341
|
+
} else {
|
|
342
|
+
reject(new Error(`PRD creation failed with code ${code}`));
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
child.on('error', reject);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
} catch (error) {
|
|
349
|
+
spinner.fail(chalk.red('Failed to create PRD'));
|
|
350
|
+
console.error(chalk.red(`\nError: ${error.message}`));
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
49
354
|
/**
|
|
50
355
|
* Parse PRD with AI
|
|
51
356
|
* @param {Object} argv - Command arguments
|
|
@@ -222,7 +527,7 @@ async function prdValidate(argv) {
|
|
|
222
527
|
*/
|
|
223
528
|
async function handler(argv) {
|
|
224
529
|
// Validate action
|
|
225
|
-
const validActions = ['parse', 'extract-epics', 'summarize', 'validate'];
|
|
530
|
+
const validActions = ['list', 'new', 'show', 'edit', 'status', 'parse', 'extract-epics', 'summarize', 'validate'];
|
|
226
531
|
|
|
227
532
|
if (!validActions.includes(argv.action)) {
|
|
228
533
|
console.error(chalk.red(`\nError: Unknown action: ${argv.action}`));
|
|
@@ -233,6 +538,21 @@ async function handler(argv) {
|
|
|
233
538
|
// Route to appropriate handler
|
|
234
539
|
try {
|
|
235
540
|
switch (argv.action) {
|
|
541
|
+
case 'list':
|
|
542
|
+
await prdList(argv);
|
|
543
|
+
break;
|
|
544
|
+
case 'new':
|
|
545
|
+
await prdNew(argv);
|
|
546
|
+
break;
|
|
547
|
+
case 'show':
|
|
548
|
+
await prdShow(argv);
|
|
549
|
+
break;
|
|
550
|
+
case 'edit':
|
|
551
|
+
await prdEdit(argv);
|
|
552
|
+
break;
|
|
553
|
+
case 'status':
|
|
554
|
+
await prdStatus(argv);
|
|
555
|
+
break;
|
|
236
556
|
case 'parse':
|
|
237
557
|
await prdParse(argv);
|
|
238
558
|
break;
|
|
@@ -259,6 +579,69 @@ async function handler(argv) {
|
|
|
259
579
|
*/
|
|
260
580
|
function builder(yargs) {
|
|
261
581
|
return yargs
|
|
582
|
+
.command(
|
|
583
|
+
'list',
|
|
584
|
+
'List all PRDs',
|
|
585
|
+
(yargs) => {
|
|
586
|
+
return yargs
|
|
587
|
+
.example('autopm prd list', 'Show all PRDs');
|
|
588
|
+
}
|
|
589
|
+
)
|
|
590
|
+
.command(
|
|
591
|
+
'new <name>',
|
|
592
|
+
'Create new PRD interactively',
|
|
593
|
+
(yargs) => {
|
|
594
|
+
return yargs
|
|
595
|
+
.positional('name', {
|
|
596
|
+
describe: 'PRD name (use-kebab-case)',
|
|
597
|
+
type: 'string'
|
|
598
|
+
})
|
|
599
|
+
.option('template', {
|
|
600
|
+
describe: 'Template to use (api-feature, ui-feature, bug-fix, data-migration, documentation)',
|
|
601
|
+
type: 'string',
|
|
602
|
+
alias: 't'
|
|
603
|
+
})
|
|
604
|
+
.example('autopm prd new my-feature', 'Create PRD with wizard')
|
|
605
|
+
.example('autopm prd new payment-api --template api-feature', 'Create PRD from template');
|
|
606
|
+
}
|
|
607
|
+
)
|
|
608
|
+
.command(
|
|
609
|
+
'show <name>',
|
|
610
|
+
'Display PRD content',
|
|
611
|
+
(yargs) => {
|
|
612
|
+
return yargs
|
|
613
|
+
.positional('name', {
|
|
614
|
+
describe: 'PRD name (without .md extension)',
|
|
615
|
+
type: 'string'
|
|
616
|
+
})
|
|
617
|
+
.example('autopm prd show my-feature', 'Display PRD content');
|
|
618
|
+
}
|
|
619
|
+
)
|
|
620
|
+
.command(
|
|
621
|
+
'edit <name>',
|
|
622
|
+
'Edit PRD in your editor',
|
|
623
|
+
(yargs) => {
|
|
624
|
+
return yargs
|
|
625
|
+
.positional('name', {
|
|
626
|
+
describe: 'PRD name (without .md extension)',
|
|
627
|
+
type: 'string'
|
|
628
|
+
})
|
|
629
|
+
.example('autopm prd edit my-feature', 'Open PRD in editor')
|
|
630
|
+
.example('EDITOR=code autopm prd edit my-feature', 'Open PRD in VS Code');
|
|
631
|
+
}
|
|
632
|
+
)
|
|
633
|
+
.command(
|
|
634
|
+
'status <name>',
|
|
635
|
+
'Show PRD status and completeness',
|
|
636
|
+
(yargs) => {
|
|
637
|
+
return yargs
|
|
638
|
+
.positional('name', {
|
|
639
|
+
describe: 'PRD name (without .md extension)',
|
|
640
|
+
type: 'string'
|
|
641
|
+
})
|
|
642
|
+
.example('autopm prd status my-feature', 'Show PRD status report');
|
|
643
|
+
}
|
|
644
|
+
)
|
|
262
645
|
.command(
|
|
263
646
|
'parse <name>',
|
|
264
647
|
'Parse PRD with AI analysis',
|
|
@@ -337,6 +720,11 @@ module.exports = {
|
|
|
337
720
|
builder,
|
|
338
721
|
handler,
|
|
339
722
|
handlers: {
|
|
723
|
+
list: prdList,
|
|
724
|
+
new: prdNew,
|
|
725
|
+
show: prdShow,
|
|
726
|
+
edit: prdEdit,
|
|
727
|
+
status: prdStatus,
|
|
340
728
|
parse: prdParse,
|
|
341
729
|
extractEpics: prdExtractEpics,
|
|
342
730
|
summarize: prdSummarize,
|