Skip to content

feat: add interactive GitHub issue-to-code wizard#266

Open
rubenmarcus wants to merge 2 commits intomainfrom
feat/github-wizard
Open

feat: add interactive GitHub issue-to-code wizard#266
rubenmarcus wants to merge 2 commits intomainfrom
feat/github-wizard

Conversation

@rubenmarcus
Copy link
Member

Summary

  • New ralph-starter github command — 4-step interactive wizard for building code from GitHub issues
  • Step 1: Repository input (owner/repo or URL)
  • Step 2: Issue selection (fetches open issues via gh CLI, numbered menu)
  • Step 3: Tech stack auto-detection from package.json
  • Step 4: Model selection based on installed agents
  • Delegates to runCommand() with --from github flags
  • Includes CLI docs page, sidebar entry, llms.txt and ai-index.json updates

Test plan

  • pnpm build — TypeScript compiles cleanly
  • pnpm test:run — all 213 tests pass
  • pnpm build in docs/ — site builds with 43 docs (was 42)
  • ralph-starter github — walks through 4-step wizard with a real repo
  • Docs page renders at /docs/cli/github
  • Sidebar shows github after figma in CLI Reference

🤖 Generated with Claude Code

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>
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

Issue Linking Reminder

This PR doesn't appear to have a linked issue. Consider linking to:

  • This repo: Closes #123
  • ralph-ideas: Closes multivmlabs/ralph-ideas#123

Using Closes, Fixes, or Resolves will auto-close the issue when this PR is merged.


If this PR doesn't need an issue, you can ignore this message.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

✔️ Bundle Size Analysis

Metric Value
Base 2425.03 KB
PR 2446.03 KB
Diff 21.00 KB (0%)
Bundle breakdown
156K	dist/auth
32K	dist/automation
4.0K	dist/cli.d.ts
4.0K	dist/cli.d.ts.map
20K	dist/cli.js
12K	dist/cli.js.map
600K	dist/commands
28K	dist/config
4.0K	dist/index.d.ts
4.0K	dist/index.d.ts.map
4.0K	dist/index.js
4.0K	dist/index.js.map
896K	dist/integrations
84K	dist/llm
900K	dist/loop
188K	dist/mcp
32K	dist/presets
92K	dist/setup
40K	dist/skills
392K	dist/sources
76K	dist/ui
144K	dist/utils
336K	dist/wizard

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 6, 2026

Greptile Summary

This PR introduces a ralph-starter github command — a 4-step interactive wizard that mirrors the existing figma command but targets GitHub issues. It collects a repository, an open issue, a tech stack, and a model, then delegates to runCommand(). Docs, sidebar, llms.txt, and ai-index.json are all updated accordingly.

Key issues found:

  • documentCount and totalDocuments are both off by 1 in docs/static/ai-index.json: two new CLI documents (figma + github) were added, but the counters only increased by 1 each.
  • version in ai-index.json was downgraded from "1.0.0" to "0.4.0" — this appears to be an unintentional regression.
  • interface used instead of type for GitHubWizardOptions and GitHubIssue in src/commands/github.ts, contrary to the project's TypeScript conventions.
  • detectProjectStack and buildModelChoices are duplicated verbatim from figma.ts; extracting them to a shared utility would prevent drift.
  • fetchIssues uses shell string interpolation via execSync — using execFileSync with an arguments array would be more defensive.
  • Invalid custom model ID causes a hard exit rather than re-prompting the user, forcing a full wizard restart.

Confidence Score: 3/5

  • Mergeable after fixing the two off-by-one count bugs and the version downgrade in ai-index.json.
  • The core wizard logic is sound and consistent with the existing figma command. However, two factual data bugs in ai-index.json (miscounted documents and a version regression) would ship incorrect metadata to consumers, and there are a handful of code-quality issues worth addressing before merge.
  • docs/static/ai-index.json (count/version bugs) and src/commands/github.ts (interface vs type, code duplication).

Important Files Changed

Filename Overview
src/commands/github.ts New 4-step interactive wizard; has interface instead of type for both data types (custom rule violation), detectProjectStack/buildModelChoices duplicated from figma.ts, shell string interpolation in fetchIssues, and invalid-model path exits the wizard rather than re-prompting.
src/cli.ts Clean addition of the github command registration, consistent with the existing figma command pattern.
docs/static/ai-index.json Adds figma and github CLI doc entries, but documentCount for the Cli category is 15 (should be 16) and totalDocuments is 41 (should be 42); also regresses version from 1.0.0 to 0.4.0.
docs/docs/cli/github.md Well-written documentation page covering all 4 wizard steps, options table, example session, and prerequisites.
docs/sidebars.ts Correctly adds cli/figma and cli/github to the CLI Reference sidebar section.
docs/static/llms.txt Correctly adds figma and github CLI doc links in alphabetical order.

Sequence Diagram

sequenceDiagram
    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
Loading

Last reviewed commit: e1454e0

Comment on lines +19 to +31
interface GitHubWizardOptions {
commit?: boolean;
validate?: boolean;
maxIterations?: number;
agent?: string;
}

interface GitHubIssue {
number: number;
title: string;
labels: Array<{ name: string }>;
body?: string;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Suggested change
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,
Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Suggested change
"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,
Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Suggested change
"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",
Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Comment on lines +57 to +64
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 [];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Comment on lines +67 to +92
/** 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;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Comment on lines +289 to +307
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;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

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>
@github-actions
Copy link
Contributor

github-actions bot commented Mar 8, 2026

🔗 Docs Preview

Preview URL: https://feat-github-wizard.ralph-starter-docs.pages.dev

This preview was deployed from the latest commit on this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant