claude-autopm 2.1.1 → 2.2.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.
@@ -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,16 +47,366 @@ 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
+ // Debug: Show what we're looking for
314
+ if (process.env.DEBUG) {
315
+ console.log(chalk.gray(`\nDebug: Looking for script at: ${scriptPath}`));
316
+ console.log(chalk.gray(`Debug: Current directory: ${process.cwd()}`));
317
+ }
318
+
319
+ // Check if script exists
320
+ const scriptExists = await fs.pathExists(scriptPath);
321
+ if (!scriptExists) {
322
+ spinner.fail(chalk.red('PRD creation script not found'));
323
+ console.error(chalk.red('\nError: .claude/scripts/pm/prd-new.js not found'));
324
+ console.error(chalk.red(`Expected location: ${scriptPath}`));
325
+ console.error(chalk.yellow('\nSolution: Run "autopm install" to install the framework'));
326
+
327
+ // Show what directories DO exist
328
+ const claudeDir = path.join(process.cwd(), '.claude');
329
+ const scriptsDir = path.join(claudeDir, 'scripts');
330
+ const pmDir = path.join(scriptsDir, 'pm');
331
+
332
+ console.error(chalk.gray('\nDirectory status:'));
333
+ console.error(chalk.gray(` .claude/ exists: ${await fs.pathExists(claudeDir)}`));
334
+ console.error(chalk.gray(` .claude/scripts/ exists: ${await fs.pathExists(scriptsDir)}`));
335
+ console.error(chalk.gray(` .claude/scripts/pm/ exists: ${await fs.pathExists(pmDir)}`));
336
+
337
+ process.exit(1);
338
+ }
339
+
340
+ // Build arguments
341
+ const args = [scriptPath, argv.name];
342
+ if (argv.template) {
343
+ args.push('--template', argv.template);
344
+ }
345
+
346
+ if (process.env.DEBUG) {
347
+ console.log(chalk.gray(`Debug: Running: node ${args.join(' ')}`));
348
+ }
349
+
350
+ spinner.stop();
351
+
352
+ console.log(chalk.cyan(`\nšŸš€ Starting PRD wizard for: ${argv.name}`));
353
+ if (argv.template) {
354
+ console.log(chalk.cyan(`šŸ“ Using template: ${argv.template}`));
355
+ }
356
+ console.log(chalk.gray('Press Ctrl+C to cancel\n'));
357
+
358
+ // Spawn interactive process
359
+ const child = spawn('node', args, {
360
+ stdio: 'inherit',
361
+ cwd: process.cwd(),
362
+ env: { ...process.env }
363
+ });
364
+
365
+ // Wait for completion
366
+ await new Promise((resolve, reject) => {
367
+ child.on('close', (code) => {
368
+ if (code === 0) {
369
+ console.log(chalk.green('\nāœ“ PRD created successfully'));
370
+ resolve();
371
+ } else if (code === null) {
372
+ console.error(chalk.yellow('\n⚠ Process was terminated'));
373
+ reject(new Error('Process terminated'));
374
+ } else {
375
+ console.error(chalk.red(`\nāœ— PRD creation failed with exit code ${code}`));
376
+ reject(new Error(`PRD creation failed with code ${code}`));
377
+ }
378
+ });
379
+
380
+ child.on('error', (err) => {
381
+ console.error(chalk.red(`\nāœ— Failed to start process: ${err.message}`));
382
+ reject(err);
383
+ });
384
+ });
385
+
386
+ } catch (error) {
387
+ console.error(chalk.red(`\nāœ— Error: ${error.message}`));
388
+
389
+ if (error.message.includes('terminated')) {
390
+ console.error(chalk.yellow('Operation cancelled by user'));
391
+ } else if (error.code === 'ENOENT') {
392
+ console.error(chalk.red('Node.js executable not found'));
393
+ console.error(chalk.yellow('Ensure Node.js is installed and in PATH'));
394
+ }
395
+
396
+ process.exit(1);
397
+ }
398
+ }
399
+
49
400
  /**
50
401
  * Parse PRD with AI
51
402
  * @param {Object} argv - Command arguments
52
403
  */
53
404
  async function prdParse(argv) {
54
405
  const spinner = ora(`Parsing PRD: ${argv.name}`).start();
55
- const prdService = new PRDService();
56
406
 
57
407
  try {
58
408
  const content = await readPrdFile(argv.name);
409
+ const prdService = new PRDService();
59
410
 
60
411
  if (argv.stream) {
61
412
  // Streaming mode
@@ -83,12 +434,24 @@ async function prdParse(argv) {
83
434
  spinner.fail(chalk.red('Failed to parse PRD'));
84
435
 
85
436
  if (error.message.includes('not found')) {
86
- console.error(chalk.red(`\nError: ${error.message}`));
437
+ console.error(chalk.red(`\nāœ— Error: PRD file not found`));
438
+ console.error(chalk.red(` File: ${getPrdPath(argv.name)}`));
439
+ console.error(chalk.yellow('\nšŸ’” Use: autopm prd list to see available PRDs'));
440
+ } else if (error.message.includes('ANTHROPIC_API_KEY') || error.message.includes('API key')) {
441
+ console.error(chalk.red(`\nāœ— Error: API key not configured`));
442
+ console.error(chalk.yellow('\nšŸ’” Set your API key in .env file:'));
443
+ console.error(chalk.cyan(' ANTHROPIC_API_KEY=sk-ant-api03-...'));
87
444
  } else if (error.message.includes('Failed to read')) {
88
- console.error(chalk.red(`\nError: ${error.message}`));
445
+ console.error(chalk.red(`\nāœ— Error: Cannot read PRD file`));
446
+ console.error(chalk.red(` ${error.message}`));
89
447
  } else {
90
- console.error(chalk.red(`\nError: Failed to parse PRD: ${error.message}`));
448
+ console.error(chalk.red(`\nāœ— Error: ${error.message}`));
449
+ if (process.env.DEBUG) {
450
+ console.error(chalk.gray('\nStack trace:'));
451
+ console.error(chalk.gray(error.stack));
452
+ }
91
453
  }
454
+ process.exit(1);
92
455
  }
93
456
  }
94
457
 
@@ -98,10 +461,10 @@ async function prdParse(argv) {
98
461
  */
99
462
  async function prdExtractEpics(argv) {
100
463
  const spinner = ora(`Extracting epics from: ${argv.name}`).start();
101
- const prdService = new PRDService();
102
464
 
103
465
  try {
104
466
  const content = await readPrdFile(argv.name);
467
+ const prdService = new PRDService();
105
468
 
106
469
  if (argv.stream) {
107
470
  // Streaming mode
@@ -130,12 +493,24 @@ async function prdExtractEpics(argv) {
130
493
  spinner.fail(chalk.red('Failed to extract epics'));
131
494
 
132
495
  if (error.message.includes('not found')) {
133
- console.error(chalk.red(`\nError: ${error.message}`));
496
+ console.error(chalk.red(`\nāœ— Error: PRD file not found`));
497
+ console.error(chalk.red(` File: ${getPrdPath(argv.name)}`));
498
+ console.error(chalk.yellow('\nšŸ’” Use: autopm prd list to see available PRDs'));
499
+ } else if (error.message.includes('ANTHROPIC_API_KEY') || error.message.includes('API key')) {
500
+ console.error(chalk.red(`\nāœ— Error: API key not configured`));
501
+ console.error(chalk.yellow('\nšŸ’” Set your API key in .env file:'));
502
+ console.error(chalk.cyan(' ANTHROPIC_API_KEY=sk-ant-api03-...'));
134
503
  } else if (error.message.includes('Failed to read')) {
135
- console.error(chalk.red(`\nError: ${error.message}`));
504
+ console.error(chalk.red(`\nāœ— Error: Cannot read PRD file`));
505
+ console.error(chalk.red(` ${error.message}`));
136
506
  } else {
137
- console.error(chalk.red(`\nError: Failed to extract epics: ${error.message}`));
507
+ console.error(chalk.red(`\nāœ— Error: ${error.message}`));
508
+ if (process.env.DEBUG) {
509
+ console.error(chalk.gray('\nStack trace:'));
510
+ console.error(chalk.gray(error.stack));
511
+ }
138
512
  }
513
+ process.exit(1);
139
514
  }
140
515
  }
141
516
 
@@ -145,10 +520,10 @@ async function prdExtractEpics(argv) {
145
520
  */
146
521
  async function prdSummarize(argv) {
147
522
  const spinner = ora(`Generating summary for: ${argv.name}`).start();
148
- const prdService = new PRDService();
149
523
 
150
524
  try {
151
525
  const content = await readPrdFile(argv.name);
526
+ const prdService = new PRDService();
152
527
 
153
528
  if (argv.stream) {
154
529
  // Streaming mode
@@ -172,12 +547,24 @@ async function prdSummarize(argv) {
172
547
  spinner.fail(chalk.red('Failed to generate summary'));
173
548
 
174
549
  if (error.message.includes('not found')) {
175
- console.error(chalk.red(`\nError: ${error.message}`));
550
+ console.error(chalk.red(`\nāœ— Error: PRD file not found`));
551
+ console.error(chalk.red(` File: ${getPrdPath(argv.name)}`));
552
+ console.error(chalk.yellow('\nšŸ’” Use: autopm prd list to see available PRDs'));
553
+ } else if (error.message.includes('ANTHROPIC_API_KEY') || error.message.includes('API key')) {
554
+ console.error(chalk.red(`\nāœ— Error: API key not configured`));
555
+ console.error(chalk.yellow('\nšŸ’” Set your API key in .env file:'));
556
+ console.error(chalk.cyan(' ANTHROPIC_API_KEY=sk-ant-api03-...'));
176
557
  } else if (error.message.includes('Failed to read')) {
177
- console.error(chalk.red(`\nError: ${error.message}`));
558
+ console.error(chalk.red(`\nāœ— Error: Cannot read PRD file`));
559
+ console.error(chalk.red(` ${error.message}`));
178
560
  } else {
179
- console.error(chalk.red(`\nError: Failed to generate summary: ${error.message}`));
561
+ console.error(chalk.red(`\nāœ— Error: ${error.message}`));
562
+ if (process.env.DEBUG) {
563
+ console.error(chalk.gray('\nStack trace:'));
564
+ console.error(chalk.gray(error.stack));
565
+ }
180
566
  }
567
+ process.exit(1);
181
568
  }
182
569
  }
183
570
 
@@ -187,32 +574,41 @@ async function prdSummarize(argv) {
187
574
  */
188
575
  async function prdValidate(argv) {
189
576
  const spinner = ora(`Validating PRD: ${argv.name}`).start();
190
- const prdService = new PRDService();
191
577
 
192
578
  try {
193
579
  const content = await readPrdFile(argv.name);
580
+ const prdService = new PRDService();
194
581
  const result = await prdService.validate(content);
195
582
 
196
583
  if (result.valid) {
197
584
  spinner.succeed(chalk.green('PRD is valid'));
198
- console.log(chalk.green('\nValidation passed - PRD structure is correct'));
585
+ console.log(chalk.green('\nāœ“ Validation passed - PRD structure is correct'));
199
586
  } else {
200
587
  spinner.fail(chalk.red(`PRD validation failed - ${result.issues.length} issues found`));
201
- console.error(chalk.red(`\nValidation failed - ${result.issues.length} issue(s):`));
588
+ console.error(chalk.red(`\nāœ— Validation failed - ${result.issues.length} issue(s):`));
202
589
  result.issues.forEach((issue, index) => {
203
590
  console.error(chalk.red(` ${index + 1}. ${issue}`));
204
591
  });
592
+ process.exit(1);
205
593
  }
206
594
  } catch (error) {
207
595
  spinner.fail(chalk.red('Failed to validate PRD'));
208
596
 
209
597
  if (error.message.includes('not found')) {
210
- console.error(chalk.red(`\nError: ${error.message}`));
598
+ console.error(chalk.red(`\nāœ— Error: PRD file not found`));
599
+ console.error(chalk.red(` File: ${getPrdPath(argv.name)}`));
600
+ console.error(chalk.yellow('\nšŸ’” Use: autopm prd list to see available PRDs'));
211
601
  } else if (error.message.includes('Failed to read')) {
212
- console.error(chalk.red(`\nError: ${error.message}`));
602
+ console.error(chalk.red(`\nāœ— Error: Cannot read PRD file`));
603
+ console.error(chalk.red(` ${error.message}`));
213
604
  } else {
214
- console.error(chalk.red(`\nError: Failed to validate PRD: ${error.message}`));
605
+ console.error(chalk.red(`\nāœ— Error: ${error.message}`));
606
+ if (process.env.DEBUG) {
607
+ console.error(chalk.gray('\nStack trace:'));
608
+ console.error(chalk.gray(error.stack));
609
+ }
215
610
  }
611
+ process.exit(1);
216
612
  }
217
613
  }
218
614
 
@@ -222,7 +618,7 @@ async function prdValidate(argv) {
222
618
  */
223
619
  async function handler(argv) {
224
620
  // Validate action
225
- const validActions = ['parse', 'extract-epics', 'summarize', 'validate'];
621
+ const validActions = ['list', 'new', 'show', 'edit', 'status', 'parse', 'extract-epics', 'summarize', 'validate'];
226
622
 
227
623
  if (!validActions.includes(argv.action)) {
228
624
  console.error(chalk.red(`\nError: Unknown action: ${argv.action}`));
@@ -233,6 +629,21 @@ async function handler(argv) {
233
629
  // Route to appropriate handler
234
630
  try {
235
631
  switch (argv.action) {
632
+ case 'list':
633
+ await prdList(argv);
634
+ break;
635
+ case 'new':
636
+ await prdNew(argv);
637
+ break;
638
+ case 'show':
639
+ await prdShow(argv);
640
+ break;
641
+ case 'edit':
642
+ await prdEdit(argv);
643
+ break;
644
+ case 'status':
645
+ await prdStatus(argv);
646
+ break;
236
647
  case 'parse':
237
648
  await prdParse(argv);
238
649
  break;
@@ -259,6 +670,69 @@ async function handler(argv) {
259
670
  */
260
671
  function builder(yargs) {
261
672
  return yargs
673
+ .command(
674
+ 'list',
675
+ 'List all PRDs',
676
+ (yargs) => {
677
+ return yargs
678
+ .example('autopm prd list', 'Show all PRDs');
679
+ }
680
+ )
681
+ .command(
682
+ 'new <name>',
683
+ 'Create new PRD interactively',
684
+ (yargs) => {
685
+ return yargs
686
+ .positional('name', {
687
+ describe: 'PRD name (use-kebab-case)',
688
+ type: 'string'
689
+ })
690
+ .option('template', {
691
+ describe: 'Template to use (api-feature, ui-feature, bug-fix, data-migration, documentation)',
692
+ type: 'string',
693
+ alias: 't'
694
+ })
695
+ .example('autopm prd new my-feature', 'Create PRD with wizard')
696
+ .example('autopm prd new payment-api --template api-feature', 'Create PRD from template');
697
+ }
698
+ )
699
+ .command(
700
+ 'show <name>',
701
+ 'Display PRD content',
702
+ (yargs) => {
703
+ return yargs
704
+ .positional('name', {
705
+ describe: 'PRD name (without .md extension)',
706
+ type: 'string'
707
+ })
708
+ .example('autopm prd show my-feature', 'Display PRD content');
709
+ }
710
+ )
711
+ .command(
712
+ 'edit <name>',
713
+ 'Edit PRD in your editor',
714
+ (yargs) => {
715
+ return yargs
716
+ .positional('name', {
717
+ describe: 'PRD name (without .md extension)',
718
+ type: 'string'
719
+ })
720
+ .example('autopm prd edit my-feature', 'Open PRD in editor')
721
+ .example('EDITOR=code autopm prd edit my-feature', 'Open PRD in VS Code');
722
+ }
723
+ )
724
+ .command(
725
+ 'status <name>',
726
+ 'Show PRD status and completeness',
727
+ (yargs) => {
728
+ return yargs
729
+ .positional('name', {
730
+ describe: 'PRD name (without .md extension)',
731
+ type: 'string'
732
+ })
733
+ .example('autopm prd status my-feature', 'Show PRD status report');
734
+ }
735
+ )
262
736
  .command(
263
737
  'parse <name>',
264
738
  'Parse PRD with AI analysis',
@@ -337,6 +811,11 @@ module.exports = {
337
811
  builder,
338
812
  handler,
339
813
  handlers: {
814
+ list: prdList,
815
+ new: prdNew,
816
+ show: prdShow,
817
+ edit: prdEdit,
818
+ status: prdStatus,
340
819
  parse: prdParse,
341
820
  extractEpics: prdExtractEpics,
342
821
  summarize: prdSummarize,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-autopm",
3
- "version": "2.1.1",
3
+ "version": "2.2.1",
4
4
  "description": "Autonomous Project Management Framework for Claude Code - Advanced AI-powered development automation",
5
5
  "main": "bin/autopm.js",
6
6
  "bin": {