Skip to content

feat(create-prd): add --from flag to convert existing PRD documents#147

Closed
KilimcininKorOglu wants to merge 3 commits intosubsy:mainfrom
KilimcininKorOglu:feature/create-prd-from-file
Closed

feat(create-prd): add --from flag to convert existing PRD documents#147
KilimcininKorOglu wants to merge 3 commits intosubsy:mainfrom
KilimcininKorOglu:feature/create-prd-from-file

Conversation

@KilimcininKorOglu
Copy link

@KilimcininKorOglu KilimcininKorOglu commented Jan 18, 2026

Summary

Adds the ability to convert existing PRD documents to ralph-tui format using the --from flag.

Why

I have pre-made PRD.md files for different ideas. Instead of recreating them, it's more practical to convert them to ralph-tui format. And there might be other people like me too (:

Changes

New Skill

  • skills/ralph-tui-convert-prd/SKILL.md - AI skill for analyzing and converting external PRD documents to ralph-tui format with structured user stories

Command Updates

  • Added --from <file> / -i <file> flag to create-prd command
  • Auto-loads convert skill when --from is specified
  • Updated help text with new option and examples

UI Updates

  • PrdChatApp now accepts fromFileContent prop
  • Auto-triggers conversion when in --from mode
  • Shows conversion-specific welcome message

Usage

# Convert an existing PRD to ralph-tui format
ralph-tui create-prd --from ./docs/my-prd.md

# With custom output directory
ralph-tui create-prd --from ./docs/my-prd.md --output ./specs

How It Works

  1. Reads the input PRD file
  2. Sends content to AI agent with the convert skill
  3. AI analyzes document structure and extracts:
    • User stories in US-XXX format
    • Acceptance criteria as checklists
    • Dependencies based on logical order
  4. Outputs converted PRD wrapped in [PRD]...[/PRD] markers
  5. Saves to tasks/prd-<feature-name>.md
  6. Offers tracker conversion (JSON/Beads)

Summary by CodeRabbit

Release Notes

New Features

  • Added PRD conversion feature enabling users to transform existing product requirement documents into well-structured user stories with detailed acceptance criteria
  • Introduced --from command-line option to import and automatically convert PRD files
  • Implemented intelligent automatic conversion workflow with real-time processing updates and comprehensive error handling

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Jan 18, 2026

@KilimcininKorOglu is attempting to deploy a commit to the plgeek Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 18, 2026

Walkthrough

This PR introduces PRD conversion functionality via a new --from flag in the create-prd command. It adds comprehensive skill documentation defining conversion rules, extends the command to read existing PRD files and load a dedicated convert-prd skill, and implements an auto-conversion flow in PrdChatApp that triggers AI-driven conversion when file content is provided.

Changes

Cohort / File(s) Summary
Skill Documentation
skills/ralph-tui-convert-prd/SKILL.md
New file defining PRD-to-user-stories conversion framework, including input analysis rules, conversion rules (sizing, splitting, acceptance criteria, dependencies, priority), explicit output format with [PRD] markers, step-by-step conversion process, example conversion (US-001 through US-007), and pre-output checklist.
Command Enhancement
src/commands/create-prd.tsx
Adds --from/-i flag support with fromFile and fromFileContent fields in CreatePrdArgs. Implements file reading, content storage, and conditional skill loading via new loadConvertPrdSkill helper. Includes error handling for missing/unreadable files and failed skill loading. Propagates file content to PrdChatApp.
Chat Component Auto-Conversion
src/tui/components/PrdChatApp.tsx
Adds fromFileContent prop to PrdChatAppProps. Introduces CONVERSION_WELCOME_MESSAGE for conversion mode. Implements useEffect that auto-triggers conversion prompt when fromFileContent is present, streams AI response, updates loading state, and appends result to chat. Includes autoConversionTriggeredRef guard to prevent repeated triggers and unmount cleanup guards.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as create-prd Command
    participant PrdChatApp
    participant AIEngine as AI Engine
    
    User->>CLI: Run with --from flag
    CLI->>CLI: Read PRD file content
    CLI->>CLI: Load convert-prd skill
    CLI->>PrdChatApp: Pass fromFileContent prop
    
    PrdChatApp->>PrdChatApp: Mount component
    PrdChatApp->>PrdChatApp: Display CONVERSION_WELCOME_MESSAGE
    
    Note over PrdChatApp: useEffect triggered (fromFileContent present)
    PrdChatApp->>AIEngine: Send conversion prompt with PRD content
    AIEngine-->>PrdChatApp: Stream converted user stories
    
    PrdChatApp->>PrdChatApp: Collect streamed segments
    PrdChatApp->>PrdChatApp: Update loading state
    PrdChatApp->>PrdChatApp: Append result to chat
    PrdChatApp-->>User: Display converted PRD in chat UI
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly Related PRs

Poem

🐰 A PRD arrives at the warren's door,
We hop through rules and convert with cheer,
User stories bloom, acceptance criteria soar,
Auto-triggered magic, the conversion is clear!
From files to structured tales we create,
Ralph-tui's power makes projects first-rate! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main feature addition: implementing a --from flag for converting existing PRD documents, which directly aligns with the primary changes across the skill documentation, CLI command, and UI components.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 markdownlint-cli2 (0.18.1)
skills/ralph-tui-convert-prd/SKILL.md

markdownlint-cli2 v0.18.1 (markdownlint v0.38.0)
Finding: skills/ralph-tui-convert-prd/SKILL.md
Linting: 1 file(s)
Summary: 6 error(s)
Error: EACCES: permission denied, open '/markdownlint-cli2-results.json'
at async open (node:internal/fs/promises:640:25)
at async Object.writeFile (node:internal/fs/promises:1214:14)
at async Promise.all (index 0)
at async outputSummary (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:877:5)
at async main (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:1053:25)
at async file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2-bin.mjs:12:22 {
errno: -13,
code: 'EACCES',
syscall: 'open',
path: '/markdownlint-cli2-results.json'
}


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@skills/ralph-tui-convert-prd/SKILL.md`:
- Around line 155-197: The SKILL.md interactive Steps 1–3 conflict with the
auto-conversion prompt in PrdChatApp.tsx that demands a single [PRD]...[/PRD]
output; update either the skill or the app: either (A) modify SKILL.md (steps or
top-level instructions) to include a non-interactive "auto-conversion" mode that
skips Step 1/2 when the incoming prompt equals the explicit string used in
PrdChatApp.tsx (match the prompt text "Output the converted PRD wrapped in
[PRD]...[/PRD]") and produce the full converted PRD directly, or (B) change the
PrdChatApp.tsx prompt to allow the multi-step interactive flow (e.g., request
clarifying questions first) so the skill can ask Steps 1–2; adjust the control
logic that dispatches the prompt so it signals either interactive or auto mode
accordingly (refer to SKILL.md steps and the prompt text in PrdChatApp.tsx to
locate the code to change).

In `@src/commands/create-prd.tsx`:
- Around line 368-400: Detected conflicting flags: when parsedArgs.fromFile is
used we set parsedArgs.prdSkillSource via loadConvertPrdSkill(), but a later
block that reads parsedArgs.prdSkill can overwrite it. Add mutual-exclusivity
validation early (before loading the convert skill) that checks if
parsedArgs.fromFile && parsedArgs.prdSkill and if so prints an error and exits;
reference parsedArgs.fromFile, parsedArgs.prdSkill, parsedArgs.prdSkillSource
and loadConvertPrdSkill to locate the relevant logic to change.
🧹 Nitpick comments (1)
src/tui/components/PrdChatApp.tsx (1)

330-397: Consider adding error recovery for the auto-conversion flow.

The auto-conversion implementation is solid with proper guards and cleanup. However, if conversion fails, users are left with an error state and no clear recovery path since the guard prevents re-triggering.

A few observations:

  1. Line 356: The non-null assertion engineRef.current! is safe here due to the guard at line 332, but could be cleaner with an early return pattern.

  2. No retry mechanism: If the AI agent fails transiently, users must restart the entire command.

  3. Dependency array: The effect depends only on fromFileContent, but internally uses engineRef. Since engineRef is stable (created once), this is fine, but worth noting.

Minor improvement for null safety
     const triggerConversion = async () => {
+      const engine = engineRef.current;
+      if (!engine) return;
+
       setIsLoading(true);
       setLoadingStatus('Analysing PRD document...');
       // ...
       try {
-        const result = await engineRef.current!.sendMessage(conversionPrompt, {
+        const result = await engine.sendMessage(conversionPrompt, {

Comment on lines +155 to +197
## Conversion Process

### Step 1: Document Analysis

First, scan the document and identify:
- Document title/name
- Main sections and structure
- Number of potential user stories
- Technology stack mentioned

Report to user:
```
I've analyzed your PRD. Here's what I found:

- **Title:** [extracted title]
- **Sections:** [count] main feature areas
- **Estimated Stories:** [count] user stories
- **Tech Stack:** [if mentioned]

I'll now convert this to ralph-tui format. Do you want me to:
A. Proceed with conversion (recommended)
B. Ask clarifying questions first
C. Focus on specific sections only
```

### Step 2: Quality Gates Question

Ask about quality gates:
```
What quality commands should pass for each story?
A. bun run typecheck && bun run build
B. npm run typecheck && npm run lint
C. pnpm typecheck && pnpm lint
D. Other: [specify]
```

### Step 3: Conversion

- Extract features → user stories
- Generate acceptance criteria
- Assign priorities and dependencies
- Output wrapped in `[PRD]...[/PRD]`

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Interactive steps may conflict with auto-conversion flow.

The skill defines a multi-step interactive process (Steps 1-3) where the AI asks for user input before proceeding. However, the auto-conversion flow in PrdChatApp.tsx sends a single prompt and expects the converted PRD in the response.

The prompt at lines 342-353 in PrdChatApp.tsx instructs:

"Output the converted PRD wrapped in [PRD]...[/PRD] markers."

This may conflict with Step 1 and Step 2 here which expect the AI to ask clarifying questions first. Consider either:

  1. Adding guidance to skip interactive steps when the prompt explicitly requests direct conversion
  2. Updating the auto-conversion prompt to align with the interactive flow
🤖 Prompt for AI Agents
In `@skills/ralph-tui-convert-prd/SKILL.md` around lines 155 - 197, The SKILL.md
interactive Steps 1–3 conflict with the auto-conversion prompt in PrdChatApp.tsx
that demands a single [PRD]...[/PRD] output; update either the skill or the app:
either (A) modify SKILL.md (steps or top-level instructions) to include a
non-interactive "auto-conversion" mode that skips Step 1/2 when the incoming
prompt equals the explicit string used in PrdChatApp.tsx (match the prompt text
"Output the converted PRD wrapped in [PRD]...[/PRD]") and produce the full
converted PRD directly, or (B) change the PrdChatApp.tsx prompt to allow the
multi-step interactive flow (e.g., request clarifying questions first) so the
skill can ask Steps 1–2; adjust the control logic that dispatches the prompt so
it signals either interactive or auto mode accordingly (refer to SKILL.md steps
and the prompt text in PrdChatApp.tsx to locate the code to change).

Comment on lines +368 to +400
// Handle --from flag: load file content and use convert skill
if (parsedArgs.fromFile) {
const fromPath = resolve(cwd, parsedArgs.fromFile);

try {
await access(fromPath, constants.R_OK);
} catch {
console.error(`Error: Input file not found: ${fromPath}`);
process.exit(1);
}

try {
parsedArgs.fromFileContent = await readFile(fromPath, 'utf-8');
console.log(`Converting PRD from: ${fromPath}`);
console.log(`File size: ${parsedArgs.fromFileContent.length} characters`);
console.log('');
} catch (error) {
console.error(
`Error: Failed to read input file: ${error instanceof Error ? error.message : String(error)}`
);
process.exit(1);
}

// Use the convert skill instead of the regular prd skill
try {
parsedArgs.prdSkillSource = await loadConvertPrdSkill();
} catch (error) {
console.error(
`Error: ${error instanceof Error ? error.message : String(error)}`
);
process.exit(1);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential overwrite of prdSkillSource when both --from and --prd-skill are specified.

If a user specifies both --from ./file.md and --prd-skill custom-skill, the code at lines 391-399 sets prdSkillSource from the convert skill, but the subsequent block at lines 402-414 will overwrite it with the custom skill. This may be intentional (custom skill takes precedence), but could lead to unexpected behaviour where the conversion skill is ignored.

Consider either:

  1. Adding mutual exclusivity validation between --from and --prd-skill
  2. Documenting the precedence behaviour in the help text
Suggested validation
+  // Validate mutually exclusive options
+  if (parsedArgs.fromFile && parsedArgs.prdSkill) {
+    console.error('Error: --from and --prd-skill cannot be used together.');
+    process.exit(1);
+  }
+
   // Handle --from flag: load file content and use convert skill
   if (parsedArgs.fromFile) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Handle --from flag: load file content and use convert skill
if (parsedArgs.fromFile) {
const fromPath = resolve(cwd, parsedArgs.fromFile);
try {
await access(fromPath, constants.R_OK);
} catch {
console.error(`Error: Input file not found: ${fromPath}`);
process.exit(1);
}
try {
parsedArgs.fromFileContent = await readFile(fromPath, 'utf-8');
console.log(`Converting PRD from: ${fromPath}`);
console.log(`File size: ${parsedArgs.fromFileContent.length} characters`);
console.log('');
} catch (error) {
console.error(
`Error: Failed to read input file: ${error instanceof Error ? error.message : String(error)}`
);
process.exit(1);
}
// Use the convert skill instead of the regular prd skill
try {
parsedArgs.prdSkillSource = await loadConvertPrdSkill();
} catch (error) {
console.error(
`Error: ${error instanceof Error ? error.message : String(error)}`
);
process.exit(1);
}
}
// Validate mutually exclusive options
if (parsedArgs.fromFile && parsedArgs.prdSkill) {
console.error('Error: --from and --prd-skill cannot be used together.');
process.exit(1);
}
// Handle --from flag: load file content and use convert skill
if (parsedArgs.fromFile) {
const fromPath = resolve(cwd, parsedArgs.fromFile);
try {
await access(fromPath, constants.R_OK);
} catch {
console.error(`Error: Input file not found: ${fromPath}`);
process.exit(1);
}
try {
parsedArgs.fromFileContent = await readFile(fromPath, 'utf-8');
console.log(`Converting PRD from: ${fromPath}`);
console.log(`File size: ${parsedArgs.fromFileContent.length} characters`);
console.log('');
} catch (error) {
console.error(
`Error: Failed to read input file: ${error instanceof Error ? error.message : String(error)}`
);
process.exit(1);
}
// Use the convert skill instead of the regular prd skill
try {
parsedArgs.prdSkillSource = await loadConvertPrdSkill();
} catch (error) {
console.error(
`Error: ${error instanceof Error ? error.message : String(error)}`
);
process.exit(1);
}
}
🤖 Prompt for AI Agents
In `@src/commands/create-prd.tsx` around lines 368 - 400, Detected conflicting
flags: when parsedArgs.fromFile is used we set parsedArgs.prdSkillSource via
loadConvertPrdSkill(), but a later block that reads parsedArgs.prdSkill can
overwrite it. Add mutual-exclusivity validation early (before loading the
convert skill) that checks if parsedArgs.fromFile && parsedArgs.prdSkill and if
so prints an error and exits; reference parsedArgs.fromFile,
parsedArgs.prdSkill, parsedArgs.prdSkillSource and loadConvertPrdSkill to locate
the relevant logic to change.

@KilimcininKorOglu KilimcininKorOglu closed this by deleting the head repository Feb 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant