name: ralph-tui-create-beads-rust description: "Convert PRDs to beads for ralph-tui execution using beads-rust (cn CLI). Creates an epic with child beads for each user story. Use when you have a PRD and want to use ralph-tui with beads-rust as the task source. Triggers on: create beads, convert prd to beads, beads for ralph, ralph beads, br beads, cn beads."
Ralph TUI - Create Beads (chronis)
Converts PRDs to beads (epic + child tasks) for ralph-tui autonomous execution using chronis (cn CLI).
Note: This skill uses the
cncommand from chronis (formerly beads-rust/br). If you have the original beads (bd) installed instead, use theralph-tui-create-beadsskill.
The Job
Take a PRD (markdown file or text) and create beads using cn commands:
- Detect project tooling (build runner, package manager)
- Classify Quality Gates into story-specific vs. epic-level
- Create an epic bead (with epic-level quality gates)
- Create child beads for each user story (with story-specific acceptance criteria only)
- Set up dependencies between beads (schema → backend → UI)
- Output ready for
ralph-tui run --tracker chronis
Step 0: Detect Project Tooling
Before creating beads, detect the project's build runner and package manager. This determines which commands appear in quality gates.
Build runner detection
Check in order:
Taskfile.ymlorTaskfile.yamlexists → usetask(go-task)Makefileexists → usemake- Neither → use raw commands
# Detect build runner
if [ -f Taskfile.yml ] || [ -f Taskfile.yaml ]; then
RUNNER="task" # e.g., task ci, task lint
elif [ -f Makefile ]; then
RUNNER="make" # e.g., make ci, make lint
else
RUNNER="none" # use raw commands directly
fi
When detected, scan the file for available targets to use in quality gates:
task: readTaskfile.ymlfor task names (e.g.,task ci,task lint,task test)make: readMakefilefor target names (e.g.,make ci,make lint,make test)
Package manager
Always use bun as the JS/TS package manager:
bun install(not npm/pnpm install)bun run <script>(not npm/pnpm run)bun test(not npm/pnpm test)bunx <package>(not npx)bun typecheckorbun run typecheckfor type checking
E2E testing with Playwright
If the project has Playwright configured (check for playwright.config.ts or @playwright/test in package.json), use it for:
- E2E tests:
bunx playwright test— runs all end-to-end tests - Visual regression:
bunx playwright test --update-snapshotsto update baselines,bunx playwright testto compare - Single test file:
bunx playwright test tests/my-feature.spec.ts - Show report:
bunx playwright show-report
Playwright gates classify as:
- Story-level:
bunx playwright test tests/<this-story>.spec.ts— when a story adds/modifies a specific e2e test - Epic-level:
bunx playwright test(full suite) — run on epic completion to catch regressions across stories
For UI stories that need visual diff verification, the acceptance criteria should include:
- [ ] Playwright e2e test passes: bunx playwright test tests/<feature>.spec.ts- [ ] Visual snapshot updated and matches expected (bunx playwright test --update-snapshots)
Quality gate command mapping
| What | Command |
|---|---|
| Type checking | bun typecheck or bun run typecheck |
| Linting | bun lint or bun run lint |
| Unit tests | bun test |
| E2E tests | bunx playwright test |
| E2E single file | bunx playwright test tests/<file>.spec.ts |
| Visual snapshots | bunx playwright test --update-snapshots |
| Full CI | task ci / make ci / bun run ci |
| Format check | bun run format:check |
| Exec a package | bunx <pkg> |
Quality Gates: Two Tiers
Quality gates split into two tiers based on scope:
Story-Level Gates (checked per bead)
Criteria that verify THIS story's specific deliverable. The agent MUST check each item individually and mark - [x] before closing the bead.
Examples:
- [ ] Add investorType column with default 'cold'- [ ] Toggle shows confirmation dialog- [ ] Filter persists in URL params- [ ] Verify in browser using dev-browser skill(UI stories only)- [ ] Playwright e2e test passes: bunx playwright test tests/toggle.spec.ts(when story has a specific test)- [ ] Visual snapshot updated and matches expected(when story changes visible UI)
Epic-Level Gates (checked on epic completion only)
General/universal commands that validate the whole codebase. These go in the epic description, NOT in individual stories. They run once when all stories are done.
Examples:
bun typecheckbun linttask ci/make cibun testbunx playwright test(full e2e suite)cargo testmix test
Why? Running bun typecheck after every single story wastes agent context and time. Intermediate stories may legitimately have temporary type errors that the next story fixes. The full Playwright suite also catches cross-story regressions better when run once at the end.
Extracting Gates from a PRD
Look for the "Quality Gates" section in the PRD. Translate any pnpm/npm/npx references to bun/bunx:
## Quality Gates
- `bun typecheck` - Type checking
- `bun lint` - Linting
For UI stories:
- Verify in browser using dev-browser skill
Classify each gate:
bun typecheck→ epic-level (general codebase check)bun lint→ epic-level (general codebase check)Verify in browser→ story-level (specific to UI stories, add to those stories)
If the project has a task ci or make ci target, prefer that as the single epic-level gate since it typically runs all checks.
If no Quality Gates section exists: Ask the user what commands should pass and how to classify them.
Acceptance Criteria: Check Each Item
CRITICAL: The agent working on a bead MUST individually verify and mark each acceptance criteria item as done. This is not optional.
How it works
Each bead's description contains - [ ] checkboxes. The agent must:
- Work through each criterion
- Verify it is satisfied (run a command, check output, inspect code)
- Mark it
- [x]in the bead description (viacn editor comment) - Only close the bead when ALL items are
- [x]
Writing verifiable criteria
Every criterion must be something the agent can concretely verify:
Good (agent can check these):
- [ ] File apps/core/src/new_module.rs exists and compiles- [ ] GET /api/v1/events returns 200 with JSON body- [ ] Column investorType added with default 'cold' (check migration file)- [ ] Component renders without errors (verify in browser)
Bad (agent cannot verify these):
- [ ] Works correctly- [ ] Good UX- [ ] Handles edge cases- [ ] Performant
Output Format
Beads use cn create command with HEREDOC syntax to safely handle special characters:
# Create epic with epic-level quality gates
cn create --type=epic \
--title="[Feature Name]" \
--description="$(cat <<'EOF'
[Feature description from PRD]
## Epic Quality Gates (run on completion)
- [ ] `task ci` passes (or `make ci`, or individual commands)
- [ ] `bun typecheck` passes
- [ ] `bun lint` passes
EOF
)" \
--external-ref="prd:./tasks/feature-name-prd.md"
# Create child bead with story-specific criteria only
cn create \
--parent=EPIC_ID \
--title="[Story Title]" \
--description="$(cat <<'EOF'
[Story description]
## Acceptance Criteria
- [ ] Specific verifiable criterion 1
- [ ] Specific verifiable criterion 2
- [ ] Specific verifiable criterion 3
Mark each item [x] as you complete it. Only close when all are checked.
EOF
)" \
--priority=[1-4]
CRITICAL: Always use
<<'EOF'(single-quoted) for the HEREDOC delimiter. This prevents shell interpretation of backticks,$variables, and()in descriptions.
Story Size: The #1 Rule
Each story must be completable in ONE ralph-tui iteration (~one agent context window).
ralph-tui spawns a fresh agent instance per iteration with no memory of previous work. If a story is too big, the agent runs out of context before finishing.
Right-sized stories:
- Add a database column + migration
- Add a UI component to an existing page
- Update a server action with new logic
- Add a filter dropdown to a list
Too big (split these):
- "Build the entire dashboard" → Split into: schema, queries, UI components, filters
- "Add authentication" → Split into: schema, middleware, login UI, session handling
- "Refactor the API" → Split into one story per endpoint or pattern
Rule of thumb: If you can't describe the change in 2-3 sentences, it's too big.
Story Ordering: Dependencies First
Stories execute in dependency order. Earlier stories must not depend on later ones.
Correct order:
- Schema/database changes (migrations)
- Server actions / backend logic
- UI components that use the backend
- Dashboard/summary views that aggregate data
Dependencies with cn dep add
cn dep add ralph-tui-002 ralph-tui-001 # US-002 depends on US-001
cn dep add ralph-tui-003 ralph-tui-002 # US-003 depends on US-002
Syntax: cn dep add <issue> <depends-on> — the issue depends on (is blocked by) depends-on.
Conversion Rules
- Detect tooling: check for Taskfile.yml/Makefile, always use bun/bunx
- Classify Quality Gates from PRD into story-level vs. epic-level
- Epic-level gates go in the epic description (
task ci/make ci,bun typecheck,bun lint) - Story-level gates go in individual bead descriptions (browser verification for UI stories)
- Each user story → one bead with only story-specific acceptance criteria
- Every criterion must be a
- [ ]checkbox the agent can verify and mark- [x] - First story: No dependencies (creates foundation)
- Subsequent stories: Depend on their predecessors
- Priority: Based on dependency order, then document order (1=high, 2=medium, 3=low)
- All stories: Include the instruction to mark items
[x]and only close when all checked
Example
Input PRD:
# PRD: Friends Outreach
Add ability to mark investors as "friends" for warm outreach.
## Quality Gates
- `bun typecheck` - Type checking
- `bun lint` - Linting
For UI stories:
- Verify in browser using dev-browser skill
## User Stories
### US-001: Add investorType field to investor table
- [ ] Add investorType column: 'cold' | 'friend' (default 'cold')
- [ ] Generate and run migration successfully
### US-002: Add type toggle to investor list rows
- [ ] Each row has Cold | Friend toggle
- [ ] Switching shows confirmation dialog
- [ ] On confirm: updates type in database
### US-003: Filter investors by type
- [ ] Filter dropdown: All | Cold | Friend
- [ ] Filter persists in URL params
Tooling detected: Taskfile.yml exists → use task. Has task ci target.
Gate classification:
bun typecheck→ epic-level (covered bytask ci)bun lint→ epic-level (covered bytask ci)Verify in browser→ story-level (UI stories only)
Output beads:
# Create epic with epic-level quality gates
cn create --type=epic \
--title="Friends Outreach Track" \
--description="$(cat <<'EOF'
Warm outreach for deck feedback.
## Epic Quality Gates (run on completion)
- [ ] `task ci` passes (includes typecheck + lint)
EOF
)" \
--external-ref="prd:./tasks/friends-outreach-prd.md"
# US-001: Schema story (no browser gate, no deps)
cn create --parent=ralph-tui-abc \
--title="US-001: Add investorType field to investor table" \
--description="$(cat <<'EOF'
As a developer, I need to categorize investors as 'cold' or 'friend'.
## Acceptance Criteria
- [ ] Add investorType column: 'cold' | 'friend' (default 'cold')
- [ ] Generate and run migration successfully
- [ ] Verify column exists: check schema file or run migration dry-run
Mark each item [x] as you complete it. Only close when all are checked.
EOF
)" \
--priority=1
# US-002: UI story (includes browser verification gate)
cn create --parent=ralph-tui-abc \
--title="US-002: Add type toggle to investor list rows" \
--description="$(cat <<'EOF'
As Ryan, I want to toggle investor type directly from the list.
## Acceptance Criteria
- [ ] Each row has Cold | Friend toggle
- [ ] Switching shows confirmation dialog
- [ ] On confirm: updates type in database
- [ ] Verify in browser using dev-browser skill
Mark each item [x] as you complete it. Only close when all are checked.
EOF
)" \
--priority=2
cn dep add ralph-tui-002 ralph-tui-001
# US-003: UI story (includes browser verification gate)
cn create --parent=ralph-tui-abc \
--title="US-003: Filter investors by type" \
--description="$(cat <<'EOF'
As Ryan, I want to filter the list to see just friends or cold.
## Acceptance Criteria
- [ ] Filter dropdown: All | Cold | Friend
- [ ] Filter persists in URL params
- [ ] Verify in browser using dev-browser skill
Mark each item [x] as you complete it. Only close when all are checked.
EOF
)" \
--priority=3
cn dep add ralph-tui-003 ralph-tui-002
Syncing Changes
After creating beads, sync to export to JSONL (for git tracking):
cn sync --flush-only
Output Location
Beads are stored in: .beads/ directory (SQLite DB + JSONL export)
After creation, run ralph-tui:
ralph-tui run --tracker chronis --epic ralph-tui-abc
ralph-tui will:
- Pick an unblocked bead, spawn an agent
- Agent works through each
- [ ]item, marking- [x]as verified - Agent closes the bead only when all criteria are
- [x] - When all child beads are closed, ralph-tui runs epic-level quality gates
- If epic gates pass, closes the epic and outputs
<promise>COMPLETE</promise> - If epic gates fail, creates a fix-up bead to address the failures
Checklist Before Creating Beads
- Detected build runner (Taskfile.yml →
task, Makefile →make, or raw commands) - Using
bun/bunxfor all JS/TS commands (not pnpm/npm/npx) - Quality gates classified: story-level vs. epic-level
- Epic description includes epic-level gates as
- [ ]checkboxes - Each story has ONLY story-specific criteria (no typecheck/lint)
- Every criterion is a verifiable
- [ ]checkbox - UI stories include browser verification (if in PRD quality gates)
- Each story includes "Mark each item [x]..." instruction
- Stories are right-sized (one agent context window)
- Dependencies set with
cn dep add - Ran
cn sync --flush-only
Differences from beads (Go version)
| Command | beads (bd) |
chronis (cn) |
|---|---|---|
| Create | bd create |
cn create |
| Dependencies | bd dep add |
cn dep add |
| Sync | bd sync |
cn sync --flush-only |
| Close | bd close |
cn close |
| Storage | .beads/beads.jsonl |
.beads/*.db + JSONL export |