feat: add interactive GitHub issue-to-code wizard#266
feat: add interactive GitHub issue-to-code wizard#266rubenmarcus wants to merge 2 commits intomainfrom
Conversation
New `ralph-starter github` command with 4-step interactive flow: repo selection, issue picking, tech stack auto-detect, model choice. Mirrors the Figma wizard pattern and delegates to runCommand. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Issue Linking ReminderThis PR doesn't appear to have a linked issue. Consider linking to:
Using If this PR doesn't need an issue, you can ignore this message. |
✔️ Bundle Size Analysis
Bundle breakdown |
Greptile SummaryThis PR introduces a Key issues found:
Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
actor User
participant CLI as ralph-starter CLI
participant Wizard as githubCommand()
participant Agents as detectAvailableAgents()
participant GH as gh CLI (execSync)
participant Run as runCommand()
User->>CLI: ralph-starter github [options]
CLI->>Wizard: githubCommand(options)
Wizard->>Agents: detectAvailableAgents()
Agents-->>Wizard: available agents (claude-code, codex, …)
Wizard-->>User: Step 1 — Enter repository (owner/repo or URL)
User->>Wizard: e.g. acme/webapp
Wizard->>GH: gh issue list -R acme/webapp --json …
GH-->>Wizard: GitHubIssue[]
Wizard-->>User: Step 2 — Numbered issue list
User->>Wizard: Pick issue number
Wizard-->>User: Step 3 — Tech stack list (auto-detected default)
User->>Wizard: Pick or type stack
Wizard-->>User: Step 4 — Model list (agent-aware)
User->>Wizard: Pick or type model
Wizard->>Run: runCommand(fullTask, { from: 'github', project, issue, model, … })
Run-->>User: Autonomous coding loop output
Last reviewed commit: e1454e0 |
| interface GitHubWizardOptions { | ||
| commit?: boolean; | ||
| validate?: boolean; | ||
| maxIterations?: number; | ||
| agent?: string; | ||
| } | ||
|
|
||
| interface GitHubIssue { | ||
| number: number; | ||
| title: string; | ||
| labels: Array<{ name: string }>; | ||
| body?: string; | ||
| } |
There was a problem hiding this comment.
Use type instead of interface for data structures
Both GitHubWizardOptions and GitHubIssue are plain data structures with no inheritance or extension, so they should be type aliases per the project's TypeScript conventions.
| interface GitHubWizardOptions { | |
| commit?: boolean; | |
| validate?: boolean; | |
| maxIterations?: number; | |
| agent?: string; | |
| } | |
| interface GitHubIssue { | |
| number: number; | |
| title: string; | |
| labels: Array<{ name: string }>; | |
| body?: string; | |
| } | |
| type GitHubWizardOptions = { | |
| commit?: boolean; | |
| validate?: boolean; | |
| maxIterations?: number; | |
| agent?: string; | |
| }; | |
| type GitHubIssue = { | |
| number: number; | |
| title: string; | |
| labels: Array<{ name: string }>; | |
| body?: string; | |
| }; |
Context Used: Rule from dashboard - Use type by default in TypeScript unless you specifically need interface features like extension... (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/commands/github.ts
Line: 19-31
Comment:
**Use `type` instead of `interface` for data structures**
Both `GitHubWizardOptions` and `GitHubIssue` are plain data structures with no inheritance or extension, so they should be `type` aliases per the project's TypeScript conventions.
```suggestion
type GitHubWizardOptions = {
commit?: boolean;
validate?: boolean;
maxIterations?: number;
agent?: string;
};
type GitHubIssue = {
number: number;
title: string;
labels: Array<{ name: string }>;
body?: string;
};
```
**Context Used:** Rule from `dashboard` - Use `type` by default in TypeScript unless you specifically need `interface` features like extension... ([source](https://app.greptile.com/review/custom-context?memory=c862f053-5655-4b41-be69-c840e3c9f280))
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| { | ||
| "name": "Cli", | ||
| "documentCount": 14, | ||
| "documentCount": 15, |
There was a problem hiding this comment.
documentCount is off by one
This PR adds two new CLI documents — figma and github — to the documents array in this category. The count was 14 before, so it should now be 16, not 15.
| "documentCount": 15, | |
| "documentCount": 16, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/static/ai-index.json
Line: 160
Comment:
**`documentCount` is off by one**
This PR adds **two** new CLI documents — `figma` and `github` — to the `documents` array in this category. The count was `14` before, so it should now be `16`, not `15`.
```suggestion
"documentCount": 16,
```
How can I resolve this? If you propose a fix, please make it concise.| }, | ||
| "stats": { | ||
| "totalDocuments": 40, | ||
| "totalDocuments": 41, |
There was a problem hiding this comment.
totalDocuments is off by one
Two new documents (figma and github) were added in this PR, so the total should increase by 2 from 40 to 42, not 41.
| "totalDocuments": 41, | |
| "totalDocuments": 42, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/static/ai-index.json
Line: 698
Comment:
**`totalDocuments` is off by one**
Two new documents (`figma` and `github`) were added in this PR, so the total should increase by 2 from `40` to `42`, not `41`.
```suggestion
"totalDocuments": 42,
```
How can I resolve this? If you propose a fix, please make it concise.| "url": "https://ralphstarter.ai", | ||
| "version": "1.0.0", | ||
| "generatedAt": "2026-02-13T21:19:43.300Z", | ||
| "version": "0.4.0", |
There was a problem hiding this comment.
Version was downgraded from 1.0.0 to 0.4.0
The version field was "1.0.0" on main and is now being set to "0.4.0". This is a regression in the metadata version. Was this intentional? If this file's version is meant to track a separate versioning scheme, please add a comment clarifying that. Otherwise, this should be restored to "1.0.0" (or bumped to a higher value).
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/static/ai-index.json
Line: 7
Comment:
**Version was downgraded from `1.0.0` to `0.4.0`**
The `version` field was `"1.0.0"` on `main` and is now being set to `"0.4.0"`. This is a regression in the metadata version. Was this intentional? If this file's version is meant to track a separate versioning scheme, please add a comment clarifying that. Otherwise, this should be restored to `"1.0.0"` (or bumped to a higher value).
How can I resolve this? If you propose a fix, please make it concise.| const result = execSync( | ||
| `gh issue list -R ${owner}/${repo} --json number,title,labels --state open --limit ${limit}`, | ||
| { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] } | ||
| ); | ||
| return JSON.parse(result) as GitHubIssue[]; | ||
| } catch { | ||
| return []; | ||
| } |
There was a problem hiding this comment.
Shell command with string interpolation — consider execFileSync instead
Even though owner and repo are validated by the parseRepo regex (only [a-zA-Z0-9_.-] allowed), building a shell command string with interpolated user-controlled values is a fragile pattern. If the regex ever relaxes, it could open a command injection vector. Using execFileSync (or passing args as an array) eliminates this class of issue entirely:
import { execFileSync } from 'node:child_process';
const result = execFileSync(
'gh',
['issue', 'list', '-R', `${owner}/${repo}`, '--json', 'number,title,labels', '--state', 'open', '--limit', String(limit)],
{ encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }
);Prompt To Fix With AI
This is a comment left during a code review.
Path: src/commands/github.ts
Line: 57-64
Comment:
**Shell command with string interpolation — consider `execFileSync` instead**
Even though `owner` and `repo` are validated by the `parseRepo` regex (only `[a-zA-Z0-9_.-]` allowed), building a shell command string with interpolated user-controlled values is a fragile pattern. If the regex ever relaxes, it could open a command injection vector. Using `execFileSync` (or passing `args` as an array) eliminates this class of issue entirely:
```typescript
import { execFileSync } from 'node:child_process';
const result = execFileSync(
'gh',
['issue', 'list', '-R', `${owner}/${repo}`, '--json', 'number,title,labels', '--state', 'open', '--limit', String(limit)],
{ encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }
);
```
How can I resolve this? If you propose a fix, please make it concise.| /** Detect the frontend framework from the current project's package.json */ | ||
| function detectProjectStack(): string | null { | ||
| const pkgPath = join(process.cwd(), 'package.json'); | ||
| if (!existsSync(pkgPath)) return null; | ||
|
|
||
| try { | ||
| const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')); | ||
| const allDeps = { | ||
| ...pkg.dependencies, | ||
| ...pkg.devDependencies, | ||
| }; | ||
|
|
||
| if (allDeps.next) return 'Next.js + TypeScript + Tailwind CSS'; | ||
| if (allDeps.astro) return 'Astro'; | ||
| if (allDeps.nuxt) return 'Nuxt + Vue + TypeScript'; | ||
| if (allDeps.svelte || allDeps['@sveltejs/kit']) return 'SvelteKit'; | ||
| if (allDeps.vue) return 'Vue + TypeScript'; | ||
| if (allDeps.react) { | ||
| const hasTailwind = !!allDeps.tailwindcss; | ||
| return hasTailwind ? 'React + TypeScript + Tailwind CSS' : 'React + TypeScript'; | ||
| } | ||
| return null; | ||
| } catch { | ||
| return null; | ||
| } | ||
| } |
There was a problem hiding this comment.
detectProjectStack is duplicated from figma.ts
This function is byte-for-byte identical to the one in src/commands/figma.ts. Consider extracting it to a shared utility (e.g., src/utils/detect-stack.ts) and importing it in both commands to avoid the two implementations drifting apart over time.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/commands/github.ts
Line: 67-92
Comment:
**`detectProjectStack` is duplicated from `figma.ts`**
This function is byte-for-byte identical to the one in `src/commands/figma.ts`. Consider extracting it to a shared utility (e.g., `src/utils/detect-stack.ts`) and importing it in both commands to avoid the two implementations drifting apart over time.
How can I resolve this? If you propose a fix, please make it concise.| if (model === 'custom') { | ||
| const { customModel } = await inquirer.prompt([ | ||
| { | ||
| type: 'input', | ||
| name: 'customModel', | ||
| message: 'Model ID:', | ||
| suffix: chalk.dim('\n (e.g., claude-opus-4-6, claude-sonnet-4-5-20250929)\n '), | ||
| validate: (input: string) => (input.trim().length > 0 ? true : 'Please enter a model ID'), | ||
| }, | ||
| ]); | ||
| model = customModel.trim(); | ||
|
|
||
| const validModelPattern = /^(claude-|gpt-|o[0-9]|gemini-)/; | ||
| if (!validModelPattern.test(model)) { | ||
| console.log( | ||
| chalk.red(` Invalid model ID: "${model}". Use a full model ID like claude-opus-4-6`) | ||
| ); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Invalid custom model silently exits instead of re-prompting
When the user enters a custom model ID that fails the validModelPattern regex, the wizard prints an error and returns early, forcing the user to re-run the entire 4-step wizard from scratch. Consider looping back to the model prompt (or at least just the custom-ID prompt) instead of bailing out. The same pattern exists in figma.ts.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/commands/github.ts
Line: 289-307
Comment:
**Invalid custom model silently exits instead of re-prompting**
When the user enters a custom model ID that fails the `validModelPattern` regex, the wizard prints an error and returns early, forcing the user to re-run the entire 4-step wizard from scratch. Consider looping back to the model prompt (or at least just the custom-ID prompt) instead of bailing out. The same pattern exists in `figma.ts`.
How can I resolve this? If you propose a fix, please make it concise.The cli/figma doc page does not exist — removed from sidebar and updated all links to point to sources/figma instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🔗 Docs PreviewPreview URL: https://feat-github-wizard.ralph-starter-docs.pages.dev This preview was deployed from the latest commit on this PR. |
Summary
ralph-starter githubcommand — 4-step interactive wizard for building code from GitHub issuesrunCommand()with--from githubflagsTest plan
pnpm build— TypeScript compiles cleanlypnpm test:run— all 213 tests passpnpm buildin docs/ — site builds with 43 docs (was 42)ralph-starter github— walks through 4-step wizard with a real repo/docs/cli/githubgithubafterfigmain CLI Reference🤖 Generated with Claude Code