Feature Dev
Converts one or more user stories into a fully implemented feature by orchestrating the complete development pipeline: issue creation, branch setup, PRD generation, Ralph conversion, and autonomous execution.
Variables
STORY: $ARGUMENTS.story (optional if url is provided)
URL: $ARGUMENTS.url (optional if story is provided)
ORCHESTRA_PROJECT_ROOT: The orchestra project root — the git repository root where .claude/, .worktrees/, and Makefile live. Resolve via git rev-parse --show-toplevel. All paths in this skill are anchored to this variable. Always cd $ORCHESTRA_PROJECT_ROOT before running commands to ensure worktrees are created in the correct location.
PLAN_TEMPLATE_PATH: .github/ISSUE_TEMPLATE/feature_request.md
WORKSPACE_DOCS: orchestra/wiki
Exactly one of story or url must be provided.
Input Formats
Option A: Pass user stories directly via story
Single story:
story="As a user, I want to export chat history as PDF so that I can share conversations offline."
Multiple stories (newline-separated or numbered):
story="1. As a developer, I want tool inputs collapsed by default so that chat is less noisy.
2. As a user, I want to expand tool inputs on click so that I can inspect them.
3. As a user, I want a toggle to show/hide all tool inputs at once."
All input stories are grouped into a single feature — one GitHub issue, one PRD, one Ralph run.
Option B: Pass a GitHub issue URL via url
url="https://github.com/ruska-ai/orchestra/issues/810"
When url is provided the skill extracts all context from the existing issue:
- RUN
gh issue view <URL> --json number,title,body,labels - PARSE user stories from the issue body (look for "User Stories" section or "As a..." patterns)
- EXTRACT issue number and title for branch naming
- Skips Phase 1 (duplication check) — the issue already exists
- Skips Phase 2 (issue creation) — the issue already exists
- Proceeds directly to Phase 3 with the extracted data
Commit Strategy: Early & Often
Commit after every phase that produces artifacts. Each phase's output should be committed and pushed immediately so that:
- Work is never lost if a later phase fails
- The PR on GitHub shows incremental progress
- Reviewers can follow the pipeline's history via commit log
The pattern at the end of each artifact-producing phase:
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>
git add <phase artifacts>
git commit -s -m "<phase commit message>"
git push
Pre-Phase: Read Issue Template
MANDATORY first step. Read the issue template to extract conventions before any other work.
- READ the issue template at
$ORCHESTRA_PROJECT_ROOT/.github/ISSUE_TEMPLATE/feature_request.md - EXTRACT conventions from the template:
- Branch naming pattern (e.g.,
feat/[issue#]-[shortdesc]) - PR title format (e.g.,
FROM feat/[issue#]-[shortdesc] TO development) - Worktree path pattern (e.g.,
$WORKSPACE/.worktrees/feat-[issue#]) - Required issue sections (User Stories, Summary, Key Integration Points, etc.)
- Validation tools (
agent-browserfor E2E) - Design principles (simplicity, least changes, TDD-first)
- Branch naming pattern (e.g.,
- STORE these conventions for use in all subsequent phases
- NOTE wiki workspace at
$ORCHESTRA_PROJECT_ROOT/wikifor feature context and documentation
Phase 0: Validate Input & Confirm Feature Scope
If url was provided:
- VALIDATE URL format (expected:
https://github.com/<owner>/<repo>/issues/<number>) - FETCH issue details:
- RUN
gh issue view <URL> --json number,title,body,labels
- RUN
- PARSE user stories from the issue body (look for "User Stories" section or "As a..." patterns)
- The issue must contain at least one user story. If none are found, HALT and report the error.
- SET issue number and feature name from the issue metadata (slugify title to kebab-case)
- PRESENT extracted data to the user for confirmation:
## Feature Scope (from Issue #<number>) **Issue**: #<number> - <title> **Feature name**: <feature-name> **Stories** (<N> total): - US-001: <story 1> - US-002: <story 2> ... Does this look correct? (y/n) - WAIT for user confirmation, then skip to Phase 3
If story was provided:
- PARSE the STORY variable into individual user stories
- EXTRACT a short feature name from the stories (kebab-case, e.g.,
export-chat-pdf) - PRESENT parsed stories and feature name to the user for confirmation:
## Feature Scope **Feature name**: <feature-name> **Stories** (<N> total): - US-001: <story 1> - US-002: <story 2> ... Does this look correct? (y/n) - WAIT for user confirmation, then proceed to Phase 1
Phase 1: Duplication Check
Skipped when
urlis provided — the issue already exists on GitHub.
Check for existing work that overlaps with this feature:
- SEARCH GitHub issues for duplicates:
- RUN
gh issue list --search "<feature keywords>" --state open --json number,title,url - RUN
gh issue list --search "<feature keywords>" --state closed --json number,title,url
- RUN
- CHECK existing branches:
- RUN
git branch -a | grep -i "<feature keywords>"(case-insensitive search)
- RUN
- CHECK existing worktrees:
- RUN
git worktree list
- RUN
- IF duplicates found:
- REPORT findings to user with issue numbers, branch names, and worktree paths
- ASK user whether to proceed, merge with existing, or abort
- WAIT for user decision
- IF no duplicates: proceed to Phase 2
Phase 2: Create GitHub Issue
Skipped when
urlis provided — the issue already exists on GitHub.
- COMPOSE issue body using the stories:
## User Stories - As a **[role]**, I want **[capability]** so that **[benefit]**. - ... ## Summary <Brief description synthesized from the stories> ## Acceptance Criteria - [ ] All user stories implemented and verified - [ ] Typecheck passes - [ ] Tests pass (if applicable) - CREATE the issue:
- RUN
gh issue create --title "feat: <feature-name>" --body "<body>" --label "enhancement"
- RUN
- CAPTURE the issue number from output
- REPORT "Created issue #: feat: "
Phase 3: Create Branch & Worktree
- DETERMINE naming:
- Branch:
feat/<issue#>-<feature-name> - Worktree path:
$ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>
- Branch:
- FETCH latest development:
- RUN
git fetch origin development
- RUN
- CREATE worktree:
- RUN
git worktree add $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> -b feat/<issue#>-<feature-name> origin/development
- RUN
- INITIALIZE worktree:
- RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && bash $ORCHESTRA_PROJECT_ROOT/backend/scripts/changelog.sh - RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git add Changelog.md && git commit -s -m "init feat/<issue#>-<feature-name>" - RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git push -u origin feat/<issue#>-<feature-name>
- RUN
- UPDATE the GitHub issue with implementation metadata:
- RUN:
gh issue comment <issue#> --body "$(cat <<'EOF' ## Implementation Started **Branch**: `feat/<issue#>-<feature-name>` **Worktree**: `$ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>` **PR title**: `FROM feat/<issue#>-<feature-name> TO development` EOF )"
- RUN:
- CREATE draft PR so all subsequent pushes are visible:
- RUN:
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && gh pr create \ --draft \ --base development \ --title "FROM feat/<issue#>-<feature-name> TO development" \ --body "$(cat <<'EOF' ## Summary Resolves #<issue#> ## Status Pipeline in progress — this PR will be marked ready for review when Ralph completes. Generated by `/feature-dev` skill. EOF )" - CAPTURE the PR URL from output
- RUN:
- REPORT "Previous run archived. Worktree created at $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> on branch feat/<issue#>-. Draft PR opened."
Phase 4: Research & Plan (Plan Mode)
MANDATORY before PRD generation. Enter plan mode to research the codebase and triage the best implementation approach. This prevents the PRD from being generated blindly.
- CHANGE to worktree directory:
- RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>
- RUN
- ENTER plan mode and research:
- Explore the codebase to understand existing patterns, files, and architecture relevant to the user stories
- Consult documentation at
$ORCHESTRA_PROJECT_ROOT/wikifor feature context - Identify which files will need changes
- Determine dependency order (schema, backend, frontend, integration)
- Flag any risks, blockers, or open questions
- Decide whether stories need to be split, merged, or reordered
- Reference wiki content in the plan when relevant
- WRITE plan to
.claude/plans/feat-<issue#>/plan-0.md:- CREATE directory:
mkdir -p $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>/.claude/plans/feat-<issue#> - STORE the plan at
.claude/plans/feat-<issue#>/plan-0.md— this file becomes the input for PRD generation in Phase 5
- CREATE directory:
- PRESENT the plan to the user for approval:
## Implementation Plan for #<issue#>: <feature-name> ### Affected Areas - <file/module 1>: <what changes> - <file/module 2>: <what changes> ... ### Proposed Story Breakdown 1. <story 1> (schema/backend/frontend) 2. <story 2> ... ### Risks & Open Questions - <any blockers or decisions needed> ### Approach <brief summary of implementation strategy> Plan stored at: `.claude/plans/feat-<issue#>/plan-0.md` - WAIT for user approval before proceeding to Phase 5
- EXIT plan mode
Phase 5: Generate PRD → Convert to Ralph JSON
This phase produces two artifacts in sequence: the PRD markdown file (via /prd), then the Ralph JSON config (via /ralph). The output of /prd is the direct input to /ralph.
Step 1: Generate PRD
- INVOKE the
/prdskill with the approved plan and stories:Load the prd skill and create a PRD for: Feature: <feature-name> (Issue #<issue#>) ## Approved Implementation Plan <plan from Phase 4> ## User Stories <all stories from STORY variable or extracted from issue> IMPORTANT sizing rules for Ralph compatibility: - Each user story must be completable in ONE iteration (one context window) - One story should touch 1-3 files max - Backend and frontend changes are SEPARATE stories - Schema/migration changes are SEPARATE from logic that uses them - If a task spans >3 files, SPLIT into multiple stories - Dependency order: Schema -> Backend -> Frontend -> Integration - Add "Typecheck passes" to every story - Add "Verify in browser using agent-browser skill" to UI stories - VERIFY PRD was created at
tasks/prd-<feature-name>.md - VALIDATE agent-browser verification criteria:
- SCAN all user stories in the PRD
- For UI-changing stories, ENSURE acceptance criteria include:
- "Verify in browser using agent-browser skill"
- "Take screenshot with agent-browser for visual walkthrough"
- AUTO-ADD these criteria if missing from any UI-facing story
- COMMIT PRD artifact:
- RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git add tasks/prd-<feature-name>.md - RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git commit -s -m "docs: add PRD for #<issue#>" - RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git push
- RUN
Step 2: Convert PRD to Ralph JSON
Feed tasks/prd-<feature-name>.md from Step 1 directly into the /ralph skill.
- INVOKE the
/ralphskill with the PRD file as input (archiving already handled in Phase 4):Load the ralph skill and convert tasks/prd-<feature-name>.md to .ralph/prd.json CRITICAL: Set branchName to "feat/<issue#>-<feature-name>" (must match the worktree branch exactly). Do NOT use the "ralph/" prefix. - VERIFY
.ralph/prd.jsonexists and contains valid JSON - VALIDATE branchName matches
feat/<issue#>-<feature-name>:- RUN
jq -r '.branchName' .ralph/prd.json - IF mismatch: manually fix branchName in prd.json
- RUN
- VALIDATE final story includes git status check:
- READ the last user story in prd.json
- ENSURE its acceptance criteria include: "Verify if there are any remaining changes by running git status. If remaining changes exist, commit and push to branch."
- IF missing: add this criterion to the last story
- COMMIT Ralph artifacts:
- RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git add .ralph/prd.json .ralph/progress.txt - RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git commit -s -m "chore: add Ralph config for #<issue#>" - RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git push
- RUN
- REPORT "PRD generated and Ralph config committed with user stories"
Phase 5.5: Agent-Browser Verification Dry Run
Only applies to features with UI changes. Skip if the feature is backend-only.
For features that modify UI:
- CHECK dev server availability:
- IF dev server is not running: REPORT with startup instructions and skip this phase
- TAKE "before" screenshots using
agent-browser screenshot:- Capture the current state of affected UI areas
- Store at
tasks/screenshots/feat-<issue#>-before.png
- COMMIT screenshots as planning artifacts:
- RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git add tasks/screenshots/ - RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git commit -s -m "docs: add before screenshots for #<issue#>" - RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git push
- RUN
- REPORT "Before screenshots captured for visual diff after implementation"
Phase 6: Archive, Final Push & Mark PR Ready
All artifacts have been committed and pushed incrementally in previous phases. This phase archives Ralph artifacts, catches any stragglers, generates a reviewer report, and marks the draft PR as ready for review.
- ARCHIVE Ralph artifacts into
archive/feat-<issue#>/:- RUN
mkdir -p $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>/.ralph/archive/feat-<issue#> - RUN
cp $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>/.ralph/prd.json $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>/.ralph/archive/feat-<issue#>/prd.json - RUN
cp $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>/.ralph/progress.txt $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>/.ralph/archive/feat-<issue#>/progress.txt - RUN
rm $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>/.ralph/prd.json $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>/.ralph/progress.txt
- RUN
- COMMIT archive:
- RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git add .ralph/archive/feat-<issue#>/ && git add -A && git commit -s -m "chore: archive Ralph artifacts for #<issue#>"
- RUN
- PUSH final changes:
- RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git push
- RUN
- GENERATE reviewer report on PR description:
- READ
.ralph/archive/feat-<issue#>/progress.txtandtasks/prd-<feature-name>.mdto summarize what was implemented - COMPOSE a reviewer-friendly PR body:
## Summary Resolves #<issue#> ## What Changed - <bullet summary of implemented stories and key changes> ## Stories Completed - [x] US-001: <title> - [x] US-002: <title> ... ## Testing - <how to verify the changes> - <any agent-browser screenshots or evidence> ## Notes - <any caveats, follow-ups, or reviewer callouts> Generated by `/feature-dev` skill. - UPDATE PR description:
- RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && gh pr edit --body "<reviewer report>"
- RUN
- READ
- MARK PR ready for review:
- RUN
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && gh pr ready
- RUN
- REPORT "Ralph artifacts archived. Reviewer report generated. PR marked ready for review."
Phase 7: Launch Ralph in Tmux
- START Ralph in a tmux session:
- RUN
tmux new-session -d -s feat-<issue#> -c $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> "make -C $ORCHESTRA_PROJECT_ROOT ralph"
- RUN
- REPORT "Ralph launched in tmux session feat-<issue#>"
- PROVIDE monitoring commands:
# Attach to Ralph session tmux attach -t feat-<issue#> # Check progress cat $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>/.ralph/progress.txt
Completion Report
## Feature Dev Complete
**Issue**: #<issue#> - feat: <feature-name>
**Branch**: feat/<issue#>-<feature-name>
**Worktree**: $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>
**PR**: <PR URL> (draft → ready for review)
**PRD**: tasks/prd-<feature-name>.md
**Ralph config**: .ralph/prd.json (<N> user stories)
**Tmux session**: feat-<issue#>
### Stories
- US-001: <title>
- US-002: <title>
...
### Next Steps
- Monitor: `tmux attach -t feat-<issue#>`
- Progress: `cat $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>/.ralph/progress.txt`
Embed Build Awareness
When the feature involves an embeddable widget, iframe component, or any asset served outside the main SPA:
- The embed has its own build command:
npm run build:embed(runsvite.embed.config.ts) - The embed output must land in the backend:
outDirmust be../backend/src/public/embed/— NOTfrontend/dist/embed/ - PRD stories for embed features must include:
- A story to verify
vite.embed.config.tsoutDir is set to../backend/src/public/embed/ - A story to verify the backend mounts
/embedviaStaticFilespointing atsrc/public/embed/ - A story to confirm the SPA catch-all has
os.path.isfile()guard before servingindex.html
- A story to verify
- Widget API origin: The embed widget must derive its
apiBasefromnew URL(document.currentScript.src).origin, NOTwindow.location.origin. Include this as an acceptance criterion for any embed widget story. - Post-Ralph gate: After Ralph completes, invoke
integration-qaagent to validate build ↔ serve alignment before marking the PR ready.
Known build targets:
| Command | Config | Output | Served at |
|---|---|---|---|
npm run build |
vite.config.ts |
frontend/dist/ |
SPA root / |
npm run build:embed |
vite.embed.config.ts |
backend/src/public/embed/ |
/embed/ |
Warnings
- Always read the issue template first (Pre-Phase) — conventions drive all downstream phases
- Always check for duplicates before creating issues or branches (Phase 1)
- Never skip user confirmation in Phase 0 — the user must agree on the feature scope
- ALL changes verified via agent-browser — UI stories must include agent-browser verification criteria
- ALL user story workflows use plan mode — plan before generating PRDs
- Plan files stored at
.claude/plans/feat-<issue#>/plan-0.md— these become PRD input - Wiki workspace at
orchestra/wiki— consult for feature context and documentation - branchName in prd.json must use
feat/prefix, NOTralph/— it must match the worktree branch exactly - Final story must include git status check to catch uncommitted artifacts
- Do NOT implement — Ralph handles implementation. This skill only sets up the pipeline.
- Commit messages must be signed (
-sflag) per repository guidelines - Embed features require
npm run build:embed— the standardnpm run builddoes NOT produce embed assets - Integration QA is mandatory for cross-boundary features — invoke the
integration-qaagent after Ralph completes any feature touching build configs, API routes, or static file serving
Error Handling
- Neither
storynorurlprovided: REPORT "You must provide eitherstoryorurl. See examples below." - Invalid URL format: REPORT "Invalid GitHub issue URL. Expected format: https://github.com/owner/repo/issues/NUMBER"
- Issue not found: REPORT "Could not fetch issue. Check URL and GitHub authentication with
gh auth status" - No stories found in issue body: REPORT "Could not parse user stories from issue body. Add stories manually via
storyargument." - Invalid story format: REPORT "Could not parse user stories. Expected format: As a [role], I want [capability] so that [benefit]."
- Duplicate issue found: REPORT duplicates and ask user how to proceed
- Worktree already exists: REPORT "Worktree already exists at $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>. Remove with
git worktree remove $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#>first." - PRD generation failure: REPORT "Failed to generate PRD. Retry with
/prdmanually." - prd.json conversion failure: REPORT "Failed to convert PRD. Retry with
/ralphmanually." - branchName mismatch: Auto-fix the branchName in prd.json to match
feat/<issue#>-<feature-name> - Push failure: REPORT "Failed to push. Try:
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && git push -u origin feat/<issue#>-<feature-name>" - Tmux failure: REPORT "Failed to launch tmux. Run manually:
cd $ORCHESTRA_PROJECT_ROOT/.worktrees/feat-<issue#> && make -C $ORCHESTRA_PROJECT_ROOT ralph"
Examples
From GitHub Issue URL
/feature-dev url="https://github.com/ruska-ai/orchestra/issues/810"
Extracts stories from issue #810, skips duplication check and issue creation, then:
- Branch:
feat/810-<slugified-title> - Worktree:
$ORCHESTRA_PROJECT_ROOT/.worktrees/feat-810 - PRD, Ralph config, and tmux launch as normal
Single Story
/feature-dev story="As a user, I want to export chat history as PDF so that I can share conversations offline."
Creates:
- Issue:
feat: export-chat-pdf - Branch:
feat/801-export-chat-pdf - Worktree:
./.worktrees/feat-801 - PRD with stories sized for single Ralph iterations
- Ralph launched in tmux session
feat-801
Multiple Stories
/feature-dev story="1. As a developer, I want tool inputs collapsed by default so that chat is less noisy.
2. As a user, I want to expand tool inputs on click so that I can inspect them.
3. As a user, I want a toggle to show/hide all tool inputs at once."
Creates:
- Issue:
feat: collapsible-tool-inputs - Branch:
feat/802-collapsible-tool-inputs - Worktree:
./.worktrees/feat-802 - PRD with 3+ stories (may be further split for Ralph compatibility)
- Ralph launched in tmux session
feat-802
Converted and distributed by TomeVault — claim your Tome and manage your conversions.