Ralph
An autonomous coding agent loop. Ralph takes a feature description, breaks it into right-sized user stories, and implements them one by one — running quality checks and committing after each step — until the feature is done.
You work from your terminal. Ralph works in an isolated workspace.
This repository also contains AutoRalph — an autonomous daemon that watches Linear for assigned issues and drives them through a complete development lifecycle (refine, plan, build, open PR, address review feedback) using Ralph under the hood.
Quick Links
- Getting Started — Prerequisites, installation, and a quick-start workflow
- Workflow — The Ralph development loop: init, new, run, done
- Commands — CLI command reference
- Configuration — ralph.yaml reference and prompt customization
- Setup — Setting up Ralph in an existing codebase
- Architecture — Execution loop and workspace isolation
AutoRalph
- Overview — What AutoRalph is and its capabilities
- Lifecycle — Issue lifecycle and state transitions
- Abilities — Refine, build, rebase, feedback, fix checks, complete
- Configuration — Credentials, project configs, and options
- Security — Trusted users, GitHub App auth, credential isolation
- Dashboard — Web dashboard, REST API, and WebSocket protocol
Getting Started
Prerequisites
- Go 1.25+ (build from source)
- Claude Code (
claudeCLI) installed and authenticated - git (for worktree operations)
- bash or zsh (for shell integration)
To build from source, you also need just (task runner). For full development (web, docs, E2E), use mise — the project includes a mise.toml with all tool versions; run mise install in the repo root.
Installation
From install script
curl -fsSL https://raw.githubusercontent.com/uesteibar/ralph/main/install-ralph.sh | sh
From source (go install)
go install github.com/uesteibar/ralph/cmd/ralph@latest
From source (clone and build)
git clone https://github.com/uesteibar/ralph.git
cd ralph
mise install # Install Go, just, etc. (recommended)
just install # Install ralph to $GOPATH/bin
Quick Start
# 1. Navigate to your project
cd ~/code/my-project
# 2. Initialize Ralph (creates .ralph/ directory and config)
ralph init
# 3. Set up shell integration (add to ~/.bashrc or ~/.zshrc)
eval "$(ralph shell-init)"
# 4. Review and edit the generated config
$EDITOR .ralph/ralph.yaml
# 5. Create a workspace and start building
ralph new login-page
# └─ Creates workspace, cd's into it, starts PRD session with Claude
# 6. Discuss the feature with Claude, then type /finish
# 7. Run the autonomous loop
ralph run
# 8. When done, squash-merge and clean up
ralph done
What happens in each step
-
ralph initscaffolds the.ralph/directory with a config file, progress log, and prompt templates. It optionally uses Claude to auto-detect your project's quality check commands. -
ralph new login-pagecreates an isolated workspace (git worktree + branch), switches you into it, and launches an interactive PRD creation session with Claude. -
During the PRD session, you discuss the feature with Claude. When the plan is solid, type
/finishand Claude writes a structured PRD with user stories and integration tests. -
ralph runstarts the autonomous execution loop. Ralph picks up stories one by one, implements them, runs quality checks, and commits. After all stories pass, a QA phase verifies integration tests. -
ralph donesquash-merges the workspace branch into your base branch, archives the PRD, and cleans up the workspace.
Advanced: If you want to create a workspace without the interactive PRD session (e.g., to write the PRD manually or import one), use
ralph workspaces new <name>instead ofralph new. This creates the workspace only, without launching PRD creation.
Workflow
Ralph follows a linear workflow from project setup to feature completion. The four main commands — ralph init, ralph new, ralph run, and ralph done — map to the phases of the development cycle.
Overview
flowchart TD
A["ralph init"] -->|one-time setup| B["ralph new feature-name"]
B -->|creates workspace, launches PRD session| C["Chat with Claude + /finish"]
C -->|PRD generated| D["ralph run"]
D -->|autonomous loop| E{All stories pass?}
E -->|no| D
E -->|yes| F{QA tests pass?}
F -->|no| D
F -->|yes| G["ralph done"]
G -->|squash-merge + cleanup| H[Feature on main]
D -.->|need manual fix?| I["ralph chat"]
I -.->|back to loop| D
D -.->|main branch updated?| J["ralph rebase"]
J -.->|back to loop| D
Phase 1: Initialize (ralph init)
One-time project setup. Creates the .ralph/ directory with configuration, progress log, and prompt templates. Safe to run multiple times (idempotent).
During init, you choose whether to track Ralph files in git (recommended for teams) or keep them local. Optionally, Claude analyzes your project to auto-detect quality check commands (test runners, linters, type checkers).
Phase 2: Plan (ralph new)
Creates a new workspace — an isolated git worktree on a dedicated branch — and launches an interactive PRD creation session with Claude.
During the session:
- You describe the feature you want to build
- Claude asks clarifying questions about scope, requirements, and edge cases
- You discuss and refine until the plan is solid
- Type
/finish— Claude writes a structured PRD JSON file with:- User stories (ordered by dependency, right-sized for one iteration each)
- Integration tests (end-to-end verification specs)
If the branch already exists from a previous attempt, Ralph asks whether to start fresh or resume.
Tip: If you want to create a workspace without launching PRD creation (e.g., to import an existing PRD or skip the AI session), use
ralph workspaces new <name>instead.
Phase 3: Build (ralph run)
The core of Ralph. Runs the autonomous execution loop that implements your feature story by story.
The story loop
For each iteration, Ralph:
- Reads the PRD and finds the next unfinished story
- Invokes Claude with the story context, acceptance criteria, and project patterns
- Claude implements the story, writes tests, and runs quality checks
- On success, Claude commits and marks the story as passing in the PRD
- Appends a progress entry to the shared progress log
The QA phase
When all stories pass, Ralph enters QA:
- A QA agent reads the integration test specs from the PRD
- It builds and runs automated tests for each spec
- If tests fail, a QA fix agent resolves the issues
- The cycle continues until all integration tests pass
Interrupting the loop
You can interact with the loop at any time:
ralph chat— open a free-form Claude session to debug or make manual adjustmentsralph rebase— rebase onto the latest base branch (Claude resolves conflicts using PRD context)ralph stop— gracefully stop the current runralph attach— re-attach to a running loop from another terminal
Phase 4: Complete (ralph done)
Finalizes the feature:
- Verifies the base branch is an ancestor (prompts to rebase if not)
- Generates a commit message from the PRD
- Lets you edit the message before committing
- Squash-merges into the base branch
- Archives the PRD and removes the workspace
- Returns you to the base repo directory
Working on Multiple Features
Ralph supports multiple workspaces simultaneously. Each workspace is fully isolated with its own branch, PRD, and working directory:
ralph new login-page # Start feature A (PRD created interactively)
# ... /finish, then:
ralph run # Run the loop
ralph new dark-mode # Start feature B (parallel)
# ... /finish, then:
ralph run # Run the loop
ralph switch login-page # Jump back to feature A
ralph overview # See progress across all workspaces
Commands
CLI command reference for Ralph. This page is auto-generated from ralph --help output.
To regenerate:
just docs-gen-cli
init
Scaffold .ralph/ directory and config
ralph init
validate
Validate project configuration
ralph validate [--project-config path]
Flags:
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
run
Run the agent loop
ralph run [--project-config path] [--max-iterations n] [--workspace name] [--no-tui]
Flags:
-max-iterations int
Maximum loop iterations (default 20)
-no-tui
Disable TUI and use plain-text output
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
-verbose
Enable verbose debug logging
-workspace string
Workspace name
chat
Ad-hoc Claude session
ralph chat [--project-config path] [--continue] [--workspace name]
Flags:
-continue
Resume the most recent conversation
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
-workspace string
Workspace name
switch
Switch workspace (interactive picker if no name)
ralph switch [name] [--project-config path]
Flags:
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
rebase
Rebase onto base branch
ralph rebase [branch] [--project-config path] [--workspace name]
Flags:
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
-workspace string
Workspace name
new
Create a new workspace (alias for ralph workspaces new)
ralph new <name> [--project-config path]
Flags:
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
eject
Export prompt templates to .ralph/prompts/ for customization
ralph eject [--project-config path]
Flags:
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
tui
Multi-workspace overview TUI
ralph tui [--project-config path]
Flags:
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
attach
Attach to a running daemon's viewer
ralph attach [--project-config path] [--workspace name] [--no-tui]
Flags:
-no-tui
Disable TUI and use plain-text output
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
-workspace string
Workspace name
stop
Stop a running daemon
ralph stop [<name>] [--project-config path] [--workspace name]
Flags:
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
-workspace string
Workspace name
done
Squash-merge and clean up
ralph done [--project-config path] [--workspace name]
Flags:
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
-workspace string
Workspace name
status
Show workspace and story progress
ralph status [--project-config path] [--short]
Flags:
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
-short
Short output for shell prompt embedding
overview
Show progress across all workspaces
ralph overview [--project-config path]
Flags:
-project-config string
Path to project config YAML (default: discover .ralph/ralph.yaml)
workspaces
Manage workspaces (new, list, switch, remove, prune)
ralph workspaces <subcommand> [args...]
Subcommands:
| Subcommand | Description |
|---|---|
new <name> | Create a new workspace |
list | List all workspaces |
switch <name> | Switch to a workspace |
remove <name> | Remove a workspace |
prune | Remove all done workspaces |
check
Run command with compact output, log full output
ralph check [--tail N] <command> [args...]
shell-init
Print shell integration (eval in .bashrc/.zshrc)
ralph shell-init
Configuration
Ralph is configured per-project via .ralph/ralph.yaml. It is created by ralph init and can be edited at any time.
Config Discovery
When --project-config is not provided, Ralph walks up from the current working directory looking for .ralph/ralph.yaml. This means you can run commands from any subdirectory (or from inside a workspace tree).
ralph.yaml Reference
# Human-readable project name (required)
project: MyProject
repo:
# Base branch for merges (required)
default_base: main
# Prefix prepended to workspace names to form branch names
# e.g., "ralph/" + "login-page" = "ralph/login-page"
branch_prefix: "ralph/" # default: "ralph/"
# Regex that generated branch names must match (optional)
branch_pattern: "^ralph/[a-zA-Z0-9._-]+$"
# Directory paths relative to repo root
paths:
tasks_dir: ".ralph/tasks"
skills_dir: ".ralph/skills"
# Commands that must pass before the agent commits
# Each runs via sh -c in the workspace working directory
quality_checks:
- "npm test"
- "npm run lint"
- "npm run typecheck"
# Lifecycle hooks (optional)
# Commands that run at specific points during the build process
hooks:
pre_commit:
- "npm run format"
post_commit: []
pre_pr:
- "npm run build"
# Files/patterns to copy from repo root into workspace worktrees (optional)
# Supports literal paths, wildcards (*), and recursive globs (**)
copy_to_worktree:
- ".env"
- "scripts/**"
- "fixtures/*.json"
Required Fields
| Field | Description |
|---|---|
project | Project name |
repo.default_base | Base branch (e.g., main, develop) |
All other fields are optional with sensible defaults.
quality_checks
Commands that must pass before the agent commits. Each command runs via sh -c in the workspace working directory. The agent will not commit if any check fails.
Examples:
quality_checks:
- "npm test"
- "npm run lint"
- "go test ./..."
- "cargo clippy"
hooks
Lifecycle hooks that run at specific points during the build process. Each hook runs via sh -c in the workspace working directory. If a hook produces file changes, they are auto-committed.
hooks:
# Run before committing changes (e.g., formatters, code generators)
pre_commit:
- "npm run format"
- "go generate ./..."
# Run after a successful commit
post_commit:
- "npm run post-build"
# Run before creating a pull request
pre_pr:
- "npm run build"
| Hook | When it runs | Use case |
|---|---|---|
pre_commit | Before each commit | Formatters, linters with auto-fix, code generators |
post_commit | After each successful commit | Notifications, cache invalidation |
pre_pr | Before opening a pull request | Full builds, release preparation |
Hooks run sequentially in the order listed. If a hook fails, the failure is logged as a warning and the next hook runs -- hook failures do not block the build. If a hook modifies files in the working tree, those changes are automatically committed with the hook command as the commit message.
copy_to_worktree
When creating a workspace, Ralph already copies .ralph/ and .claude/ automatically. Use copy_to_worktree for additional files the agent might need that aren't committed to git (e.g., .env files) or that live outside those directories.
Supports:
- Literal paths:
scripts/setup.sh - Single-level wildcards:
configs/*.json - Recursive globs:
fixtures/**/*.txt - Directories:
data/(copied recursively)
PRD Format
The PRD (Product Requirements Document) is a JSON file that drives the execution loop. It is generated by typing /finish during the PRD creation session (launched by ralph new) and updated by the agent during ralph run.
{
"project": "MyProject",
"branchName": "ralph/login-page",
"description": "Add user login with email and password",
"userStories": [
{
"id": "US-001",
"title": "Add user schema and migration",
"description": "Create the users table with email, password_hash, created_at",
"acceptanceCriteria": [
"Migration creates users table with correct columns",
"Model validates email format",
"All quality checks pass"
],
"priority": 1,
"passes": false,
"notes": ""
}
],
"integrationTests": [
{
"id": "IT-001",
"description": "Full login flow works end-to-end",
"steps": [
"Create a user via the API",
"POST /api/login with valid credentials",
"Verify response contains a valid session token"
],
"passes": false,
"failure": "",
"notes": ""
}
]
}
User Stories
Each story represents one iteration of the loop — it should be completable in a single Claude context window. Stories are executed in priority order (lowest first).
Right-sized stories:
- Add a database table and migration
- Add an API endpoint with tests
- Add a UI component to an existing page
- Update validation logic
Too large (split into multiple):
- Build the entire authentication system
- Redesign the settings page
Stories are ordered by dependency: schema first, then backend, then UI.
Integration Tests
Integration tests are end-to-end verification specs agreed upon during PRD creation. After all stories pass, the QA agent builds automated tests matching these specs and verifies the feature works as a whole.
Fields Reference
| Field | Type | Description |
|---|---|---|
userStories[].id | string | Story identifier (e.g., US-001) |
userStories[].passes | bool | Set to true by the agent when complete |
userStories[].notes | string | Agent notes (patterns learned, decisions made) |
integrationTests[].id | string | Test identifier (e.g., IT-001) |
integrationTests[].passes | bool | Set to true by QA agent when verified |
integrationTests[].failure | string | Failure details if test didn't pass |
integrationTests[].notes | string | QA agent notes |
Prompt Customization
Ralph's agent behavior is driven by prompt templates compiled into the binary. You can customize them by ejecting:
ralph eject
This creates .ralph/prompts/ with all templates:
| Template | Used by | Purpose |
|---|---|---|
loop_iteration.md | ralph run | Main prompt for implementing a single story |
qa_verification.md | ralph run | QA agent prompt for integration test verification |
qa_fix.md | ralph run | QA fix agent prompt for resolving test failures |
prd_new.md | ralph new | Interactive PRD creation conversation |
chat_system.md | ralph chat | System prompt for free-form chat sessions |
rebase_conflict.md | ralph rebase | Conflict resolution prompt |
When .ralph/prompts/ exists, Ralph loads templates from there instead of the built-in versions. You can override individual templates — any missing files fall back to the embedded defaults.
Templates use Go's text/template syntax with {{ .FieldName }} placeholders.
To re-eject (e.g., after upgrading Ralph), delete .ralph/prompts/ and run ralph eject again.
Setup
How to set up Ralph in an existing codebase.
Initialize Your Project
Run ralph init from your project root:
cd ~/code/my-project
ralph init
This scaffolds the .ralph/ directory with configuration and prompt templates.
Interactive Prompts
During init, Ralph asks two questions:
-
Git tracking choice:
- Track in git (recommended for teams) — gitignores only ephemeral directories
- Keep local — gitignores the entire
.ralph/directory
-
LLM analysis: optionally uses Claude to auto-detect quality check commands for your project (test runners, linters, type checkers, etc.)
What It Creates
| Path | Purpose |
|---|---|
.ralph/ralph.yaml | Project configuration (edit this!) |
.ralph/tasks/ | Task markdown files |
.ralph/skills/ | Project-specific skills for the agent |
.ralph/workspaces/ | Workspace directories (gitignored) |
.ralph/state/workspaces.json | Workspace registry (gitignored) |
.ralph/state/archive/ | Completed PRDs (gitignored) |
.claude/commands/finish.md | The /finish skill for PRD generation |
.claude/CLAUDE.md | Project rules for the agent |
Shell Integration
Ralph requires a thin shell wrapper for workspace switching. It lets commands like ralph new, ralph switch, and ralph done change your working directory and track the current workspace via the RALPH_WORKSPACE environment variable.
Add this to your ~/.bashrc or ~/.zshrc:
eval "$(ralph shell-init)"
What It Does
- Wraps the
ralphbinary in a shell function - Intercepts workspace commands (
new,switch,done,workspaces *) to automaticallycdinto the correct directory - Sets/unsets
RALPH_WORKSPACEto track the active workspace - After
ralph new, automatically starts an interactive PRD creation session if no PRD exists yet - All other commands pass through to the binary unchanged
Currently supports bash and zsh.
Shell Prompt Integration
You can embed workspace status in your shell prompt:
PS1='$(ralph status --short 2>/dev/null) $ '
# Shows: "login-page 3/5 $ " or "base $ "
Edit Your Configuration
After init, review and customize .ralph/ralph.yaml:
$EDITOR .ralph/ralph.yaml
At minimum, verify:
projectis set to your project namerepo.default_basepoints to your main branch (e.g.,main,develop)quality_checkslists the commands the agent should run before committing
See the Configuration chapter for the full reference.
Verify Setup
Run the config validator to check for issues:
ralph validate
This checks required fields, validates regex patterns, and warns about missing quality checks.
Start Building
With setup complete, create your first workspace:
ralph new my-first-feature
This creates an isolated workspace and launches the PRD creation session. See the Workflow chapter for the full development cycle.
Architecture
Execution Loop
The execution loop is the core of ralph run. It picks up user stories one by one, implements them, and then runs a QA phase to verify integration tests.
flowchart TD
Start["ralph run"] --> ReadPRD["Read PRD"]
ReadPRD --> FindStory["Find next unfinished story"]
FindStory --> HasStory{Story found?}
HasStory -->|yes| Invoke["Invoke Claude with story context"]
Invoke --> Implement["Claude implements + tests"]
Implement --> QualityChecks["Run quality checks"]
QualityChecks --> CheckPass{Checks pass?}
CheckPass -->|yes| Commit["Commit + mark story passing"]
Commit --> ReadPRD
CheckPass -->|no| Fix["Claude fixes issues"]
Fix --> QualityChecks
HasStory -->|no| QA["QA Phase"]
QA --> QAAgent["QA agent runs integration tests"]
QAAgent --> QAPass{Tests pass?}
QAPass -->|yes| Done["Exit — suggest ralph done"]
QAPass -->|no| QAFix["QA fix agent resolves failures"]
QAFix --> QAAgent
Each iteration, the agent receives:
- The full PRD with story context and acceptance criteria
- The project's progress log (patterns discovered in earlier iterations)
- Recent git history for consistency
- Quality check commands to run
The agent writes code, runs tests via the configured quality_checks, commits on success, and appends a progress entry. The progress log carries context between iterations so later stories can build on patterns established by earlier ones.
Event-Driven Output
The loop emits events (ToolUse, StoryStarted, IterationStart, etc.) consumed by either the TUI or a plain-text handler. This decouples the execution logic from the output rendering.
Workspace Isolation
Each feature runs in a separate git worktree, keeping the main branch clean and enabling parallel agents.
flowchart LR
Repo["your-project/"] --> Main["main branch"]
Repo --> WA[".ralph/workspaces/login-page/tree/"]
Repo --> WB[".ralph/workspaces/dark-mode/tree/"]
WA --> BrA["ralph/login-page branch"]
WB --> BrB["ralph/dark-mode branch"]
A workspace consists of:
| Component | Location | Purpose |
|---|---|---|
| Git worktree | .ralph/workspaces/<name>/tree/ | Isolated checkout on a dedicated branch |
| PRD | .ralph/workspaces/<name>/prd.json | Requirements driving the loop |
| Metadata | .ralph/workspaces/<name>/workspace.json | Name, branch, timestamps |
| Config copy | tree/.ralph/ | Agent has full project context |
| Claude config | tree/.claude/ | Agent rules and skills |
Why Worktrees?
Git worktrees let multiple branches be checked out simultaneously in different directories. This means:
- No stashing or switching branches — each feature has its own directory
- Multiple
ralph runinstances can execute in parallel - The main branch stays clean while features are in progress
ralph donesquash-merges everything into a single commit
Base Mode
You can also run commands without a workspace (in base mode). This uses the main repo directory and stores the PRD at .ralph/state/prd.json. Workspaces are recommended for any non-trivial work, but base mode is useful for quick experiments or when you just want ralph chat.
Project Structure
cmd/ralph/main.go Entry point + CLI dispatch
internal/
config/ YAML config types + loading + discovery
shell/ Subprocess runner (exec.Command wrapper)
prd/ PRD JSON types + read/write/query helpers
gitops/ Git operations (worktrees, branches, rebase)
workspace/ Workspace lifecycle (create, remove, registry)
claude/ Claude CLI invocation + streaming output parsing
prompts/ Embedded prompt templates (go:embed)
loop/ The execution loop (stories -> QA -> done)
events/ Event system (EventHandler interface)
tui/ BubbleTea-based terminal UI
commands/ One file per CLI command
Design Decisions
- Minimal dependencies:
yaml.v3for config,lipgloss/bubbletea/huhfor terminal UI,doublestarfor glob patterns. Everything else is stdlib. - Shell out to CLIs:
gitandclaudeare invoked as subprocesses. No API client libraries. - Prompts compiled into binary: Markdown templates are embedded via
go:embed. No external files needed at runtime (unless ejected). - Workspace isolation: Each feature runs in a separate git worktree, keeping the main branch clean and enabling parallel agents.
- Event-driven output: The loop emits events consumed by either the TUI or a plain-text handler.
Overview
AutoRalph is an autonomous agent that watches Linear for assigned issues and drives them through a complete development lifecycle — from refinement and planning to building, opening pull requests, fixing CI failures, and addressing review feedback — without human intervention.
AutoRalph wraps Ralph's execution loop in a long-running daemon. It polls Linear for new issues, uses AI to refine requirements, creates workspaces, invokes Ralph to build features, opens GitHub pull requests, automatically fixes failing CI checks, responds to code review feedback, and marks issues as done when PRs are merged.
How It Works
Linear AutoRalph GitHub
------ --------- ------
Assign issue ------> Poll & ingest (QUEUED)
AI refinement (REFINING)
Post questions to Linear
User approves ------> Detect approval (APPROVED)
Create workspace + PRD (BUILDING)
Run Ralph loop (stories, QA)
Push branch ------> Create PR
Monitor checks <------ Check results
Fix failing checks (FIXING_CHECKS)
Push fixes ------> Checks re-run
Wait for review <------ Review comments
Address feedback (ADDRESSING_FEEDBACK)
Push fixes ------> Updated PR
Detect merge <------ PR merged
Cleanup workspace (COMPLETED)
Move to Done <------ Update Linear state
AutoRalph bridges three systems — Linear (issue tracking), your local codebase (via Ralph), and GitHub (code review and merging) — into a continuous autonomous workflow.
Prerequisites
- Go 1.25+ (build from source)
- Claude Code (
claudeCLI) installed and authenticated - git (workspace operations use worktrees)
- Node.js 18+ (building the web dashboard)
- A Linear account with an API key
- A GitHub account with a personal access token or a GitHub App
To build from source, use mise to install Go, Node, and just: run mise install in the repo root (see mise.toml).
Installation
One-liner
curl -fsSL https://raw.githubusercontent.com/uesteibar/ralph/main/install-autoralph.sh | sh
This detects your OS and architecture, downloads the latest release from
GitHub, verifies the SHA256 checksum, and installs to /usr/local/bin/.
From source
git clone https://github.com/uesteibar/ralph.git
cd ralph
mise install # Install Go, Node, just
just web-build # Build the React dashboard
just autoralph # Build the Go binary
Verify
autoralph --version
What's Next
- Lifecycle — the full issue state machine
- Abilities — what AutoRalph can do at each stage
- Configuration — setting up credentials and projects
- GitHub App Setup — creating and installing a GitHub App
- Security — authentication and access controls
- Dashboard — the web UI and API
Lifecycle
AutoRalph manages each issue through a deterministic state machine. Every issue progresses through a series of states, with transitions triggered by external events (user actions, PR reviews, merges) or internal completions (build success, feedback addressed).
State Diagram
stateDiagram-v2
[*] --> QUEUED : Issue assigned in Linear
QUEUED --> REFINING : Orchestrator picks up issue
REFINING --> REFINING : User replies with feedback
REFINING --> APPROVED : User comments approval
APPROVED --> BUILDING : Workspace created, PRD generated
BUILDING --> IN_REVIEW : Build succeeds, PR opened
BUILDING --> FAILED : Build error
IN_REVIEW --> ADDRESSING_FEEDBACK : Review requests changes
IN_REVIEW --> FIXING_CHECKS : CI checks fail
IN_REVIEW --> COMPLETED : PR merged
ADDRESSING_FEEDBACK --> IN_REVIEW : Feedback addressed, pushed
FIXING_CHECKS --> IN_REVIEW : Checks fixed, pushed
FIXING_CHECKS --> PAUSED : Max fix attempts exhausted
COMPLETED --> [*]
PAUSED --> QUEUED : Resume
PAUSED --> REFINING : Resume
PAUSED --> APPROVED : Resume
PAUSED --> BUILDING : Resume
PAUSED --> IN_REVIEW : Resume
PAUSED --> ADDRESSING_FEEDBACK : Resume
FAILED --> QUEUED : Retry
FAILED --> REFINING : Retry
FAILED --> APPROVED : Retry
FAILED --> BUILDING : Retry
FAILED --> IN_REVIEW : Retry
FAILED --> ADDRESSING_FEEDBACK : Retry
States
| State | Description |
|---|---|
QUEUED | Issue discovered and ingested from Linear, waiting to be processed |
REFINING | AI is reading the issue, asking clarifying questions via Linear comments |
APPROVED | User approved the refined plan, ready for building |
BUILDING | Workspace created, PRD generated, Ralph execution loop running |
IN_REVIEW | Branch pushed, PR opened on GitHub, awaiting review |
ADDRESSING_FEEDBACK | Reviewer requested changes, AI is addressing review comments |
FIXING_CHECKS | CI checks failed on the PR, AI is analyzing logs and pushing fixes |
COMPLETED | PR merged, workspace cleaned up, Linear issue moved to Done |
FAILED | An error occurred; can be retried via the API or dashboard |
PAUSED | Issue paused by user or due to merge conflict; can be resumed |
Transitions
| From | To | Trigger |
|---|---|---|
QUEUED | REFINING | Orchestrator picks up new issue |
REFINING | REFINING | User replies with feedback (iteration) |
REFINING | APPROVED | User comments @autoralph approved |
APPROVED | BUILDING | Workspace created, PRD generated |
BUILDING | IN_REVIEW | Build succeeds, PR opened |
BUILDING | FAILED | Build fails (error stored in DB) |
IN_REVIEW | ADDRESSING_FEEDBACK | GitHub review with changes requested |
IN_REVIEW | FIXING_CHECKS | CI check runs fail on the PR head SHA |
IN_REVIEW | COMPLETED | PR merged |
ADDRESSING_FEEDBACK | IN_REVIEW | Feedback addressed, changes pushed |
FIXING_CHECKS | IN_REVIEW | Checks fixed, changes pushed |
FIXING_CHECKS | PAUSED | Max fix attempts exhausted (default: 3) |
| any active | PAUSED | User pauses via API or merge conflict |
PAUSED | (previous state) | User resumes via API |
FAILED | (previous state) | User retries via API |
The Lifecycle in Detail
-
Ingest: The Linear poller discovers new issues assigned to a configured user and creates them in the local database as
QUEUED. -
Refine: AI reads the issue title and description, asks clarifying questions, and posts them as a Linear comment. The issue moves to
REFINING. -
Iterate: When the user replies on Linear, AI incorporates the feedback and posts an updated plan. This loop continues until the user is satisfied.
-
Approve: The user comments
@autoralph approvedon the Linear issue. AutoRalph extracts the approved plan and moves the issue toAPPROVED. -
Build: AutoRalph creates a git workspace (worktree + branch), generates a PRD from the approved plan, and invokes Ralph's execution loop. The issue moves to
BUILDING. -
Open PR: When the build succeeds, AutoRalph pushes the branch and opens a GitHub pull request with an AI-generated description. The issue moves to
IN_REVIEW. -
Address Feedback: If reviewers request changes, AutoRalph detects the
CHANGES_REQUESTEDreview, feeds the comments to AI, commits fixes, pushes, and replies to each review comment. The issue moves toADDRESSING_FEEDBACKand back toIN_REVIEW. -
Fix Checks: If CI checks fail on the PR, AutoRalph fetches the check run logs from GitHub, feeds them to AI, and commits fixes. The issue moves to
FIXING_CHECKSand back toIN_REVIEW. If the checks cannot be fixed after 3 attempts, the issue is paused with a comment on the PR asking for human help. -
Complete: When the PR is merged, AutoRalph cleans up the workspace, updates the Linear issue state to "Done", and marks the issue as
COMPLETED.
Error Handling
- Build failures transition to
FAILEDwith the error stored in the database. Users can retry via the dashboard or API. - Merge conflicts during rebase automatically pause the issue. Users resolve the conflict and resume.
- API failures (Linear, GitHub) are retried with exponential backoff (3 attempts: 1s, 5s, 15s). HTTP 5xx errors retry; 4xx errors fail immediately.
Abilities
AutoRalph performs different actions at each stage of the issue lifecycle. Each
ability is implemented as a self-contained package under
internal/autoralph/ with its own interfaces, tests, and error handling.
Refine
Transition: QUEUED → REFINING
The refine ability reads an issue's title and description, uses AI to analyze the requirements, and posts clarifying questions as a Linear comment. This enables a back-and-forth refinement loop before any code is written.
- Loads the project and pulls the latest code for context
- Renders an AI prompt from a template with the issue details
- Invokes Claude to generate questions and a proposed plan
- Posts the AI response as a Linear comment
- Appends an approval hint so the user knows how to proceed
The refinement loop continues each time the user replies on Linear. AI
incorporates the new feedback and posts an updated plan until the user
comments @autoralph approved.
Build
Transition: APPROVED → BUILDING
The build ability creates an isolated workspace and drives the Ralph execution loop to implement the approved plan.
- Creates a git worktree with a dedicated branch (e.g.,
autoralph/uni-42) - Generates a PRD (Product Requirements Document) from the approved plan using AI
- Invokes Ralph's execution loop inside the worktree
- Ralph iterates through user stories, running quality checks after each
- On success, the branch is ready for a pull request
The workspace name and branch name are stored on the issue record so subsequent actions know where to find the worktree.
Build Configuration
| Option | Default | Description |
|---|---|---|
max_iterations | 20 | Maximum Ralph loop iterations per build |
ralph_config_path | .ralph/ralph.yaml | Path to Ralph config relative to project |
branch_prefix | autoralph/ | Branch name prefix for worktrees |
Rebase
When the target branch (usually main) has advanced since the feature branch
was created, AutoRalph rebases the workspace branch to incorporate upstream
changes.
- Fetches the latest target branch
- Performs a git rebase
- If conflicts are detected, pauses the issue for manual resolution
- On success, force-pushes the updated branch
The rebase ability handles push failures gracefully — if a push fails due to upstream changes, it retries with a fresh rebase.
Feedback
Transition: IN_REVIEW → ADDRESSING_FEEDBACK
When a GitHub reviewer requests changes, AutoRalph feeds the review comments to AI and commits fixes.
- Detects
CHANGES_REQUESTEDorCOMMENTEDreviews via the GitHub poller - Loads the review comments and diff context
- Renders an AI prompt with the feedback details
- Invokes Claude in the workspace worktree to make fixes
- Runs pre-commit and post-commit hooks if configured
- Commits changes, pushes, and replies to each review comment on GitHub
- Updates the PR description to reflect the changes
- Transitions back to
IN_REVIEW
The feedback loop repeats each time new changes are requested, until the
reviewer approves. Only reviews from trusted users
are acted upon when github_user_id is configured.
Fix Checks
Transition: IN_REVIEW → FIXING_CHECKS
When CI checks fail on a pull request, AutoRalph automatically analyzes the failures and pushes fixes.
- The GitHub poller monitors check runs on the PR head SHA
- When all checks complete and at least one has failed, the issue transitions
to
FIXING_CHECKS - Fetches check run results and logs from the GitHub API (logs truncated to 200 lines: 30 head + 170 tail)
- Renders a prompt with the failure details and the project's
quality_checksfor AI analysis - Invokes Claude in the workspace worktree to apply fixes
- Runs pre-commit and post-commit hooks if configured
- Commits and pushes the changes
- Updates the PR description to reflect the fixes
- Transitions back to
IN_REVIEWwhere checks re-run automatically
Loop Protection
To prevent infinite fix loops, AutoRalph tracks the number of fix attempts per issue. After 3 attempts (configurable), it:
- Posts a comment on the PR asking for human help
- Pauses the issue
The attempt counter resets when the head SHA changes externally (e.g., someone pushes a manual fix or feedback is addressed).
Complete
Transition: IN_REVIEW → COMPLETED
When a PR is merged on GitHub, the complete ability cleans up and closes out the issue.
- Detects the merge event via the GitHub poller
- Cleans up the git worktree and local branch
- Updates the Linear issue state to "Done"
- Marks the issue as
COMPLETEDin the database - Logs the completion in the activity timeline
Configuration
All AutoRalph configuration lives under ~/.autoralph/.
~/.autoralph/
credentials.yaml # API keys (Linear + GitHub)
autoralph.db # SQLite database (auto-created)
projects/
my-project.yaml # One file per project
another-project.yaml
Credentials
Create ~/.autoralph/credentials.yaml:
default_profile: personal
profiles:
# Option A: Personal access token (simpler)
personal:
linear_api_key: lin_api_xxxxxxxxxxxxx
github_token: ghp_xxxxxxxxxxxxx
github_user_id: 12345678 # optional: restrict to your reviews
git_author_name: autoralph-personal
git_author_email: autoralph-personal@example.com
# Option B: GitHub App (recommended for organizations)
work:
linear_api_key: lin_api_yyyyyyyyyyyyy
github_app_client_id: "Iv23liXXXXXX"
github_app_installation_id: 12345678
github_app_private_key_path: ~/.autoralph/my-app.pem
github_user_id: 87654321 # optional: restrict to your reviews
git_author_name: autoralph-work
git_author_email: autoralph@myorg.com
Resolution Order
Credentials are resolved in this order (highest precedence first):
- Environment variables
LINEAR_API_KEY/GITHUB_TOKEN - Named profile (from project config's
credentials_profile) default_profilefrom credentials file
If no credentials file exists and both environment variables are set, they are used directly.
Note: When the
GITHUB_TOKENenvironment variable is set, it takes precedence over GitHub App credentials. This is useful for temporarily overriding app auth during development.
Trusted Reviewer
Set github_user_id to restrict which reviewer's feedback AutoRalph acts on.
When set, only reviews from that GitHub user (or reviewers they explicitly
requested) trigger the feedback cycle. See Security
for details.
Find your GitHub user ID with:
gh api /user --jq .id
Git Identity
AutoRalph can use a dedicated git identity for commits, making it easy to distinguish AutoRalph-authored changes from human ones.
| Field | Default | Description |
|---|---|---|
git_author_name | autoralph | Name used for git author and committer |
git_author_email | autoralph@noreply | Email used for git author and committer |
Each profile can specify its own git identity so different projects can commit under different names.
Environment variable overrides:
| Variable | Overrides |
|---|---|
AUTORALPH_GIT_AUTHOR_NAME | git_author_name from the active profile |
AUTORALPH_GIT_AUTHOR_EMAIL | git_author_email from the active profile |
Projects
Create one YAML file per project in ~/.autoralph/projects/:
# ~/.autoralph/projects/my-project.yaml
name: my-project
local_path: ~/code/my-project
credentials_profile: personal
github:
owner: myorg
repo: my-project
linear:
team_id: "abc-123-def"
assignee_id: "user-456-ghi"
# project_id: "proj-789-jkl" # Optional: omit to poll all projects
# label: "autoralph" # Optional: only pick up issues with this label
# Optional (shown with defaults)
ralph_config_path: .ralph/ralph.yaml
max_iterations: 20
branch_prefix: "autoralph/"
Project Fields
| Field | Required | Default | Description |
|---|---|---|---|
name | yes | Human-readable project name (must be unique) | |
local_path | yes | Absolute path to the local git clone | |
credentials_profile | no | default_profile | Which credentials profile to use |
github.owner | yes | GitHub org or user | |
github.repo | yes | GitHub repository name | |
linear.team_id | yes | Linear team UUID | |
linear.assignee_id | yes | Linear user UUID to watch for assigned issues | |
linear.project_id | no | (all projects) | Linear project UUID |
linear.label | no | (none) | Label name to filter issue ingestion (case-insensitive) |
ralph_config_path | no | .ralph/ralph.yaml | Path to Ralph config (relative to local_path) |
max_iterations | no | 20 | Max Ralph loop iterations per build |
branch_prefix | no | autoralph/ | Branch name prefix |
Finding your Linear IDs: In Linear, go to Settings > Account > API to find your API key. Team and user UUIDs can be found via the Linear GraphQL API explorer or by inspecting URLs.
Running
Start the Server
autoralph serve
This starts the HTTP server on 127.0.0.1:7749 with the web dashboard, REST
API, and all background workers (Linear poller, GitHub poller, orchestrator,
build workers).
Flags
| Flag | Env Var | Default | Description |
|---|---|---|---|
--addr | 127.0.0.1:7749 | Address to listen on | |
--dev | Proxy non-API requests to Vite dev server | ||
--linear-url | AUTORALPH_LINEAR_URL | Override Linear API (for testing) | |
--github-url | AUTORALPH_GITHUB_URL | Override GitHub API (for testing) |
Subcommands
autoralph serve [flags] # Start the server
autoralph version # Print version
autoralph help # Show usage
What Happens on Startup
- Opens (or creates) the SQLite database at
~/.autoralph/autoralph.db - Loads and validates all project configs from
~/.autoralph/projects/*.yaml - Syncs project configs to the database
- Resolves credentials for each project
- Starts the Linear poller (polls every 30s for new assigned issues)
- Starts the GitHub poller (polls every 30s for PR reviews, check runs, and merges)
- Starts the orchestrator loop (evaluates state transitions)
- Starts the build worker pool
- Recovers any BUILDING issues from a previous run
- Serves the web dashboard and API on the configured address
GitHub App Setup
AutoRalph can authenticate with GitHub using either a personal access token (PAT) or a GitHub App. This guide walks through creating and installing a GitHub App, which is the recommended approach for organizations.
Why Use a GitHub App?
| Personal Access Token | GitHub App | |
|---|---|---|
| Token lifetime | Long-lived (until revoked) | 1-hour auto-rotating tokens |
| Permission scope | Broad (tied to your account) | Scoped to specific repos |
| Rate limits | Shared with your personal usage | Separate pool (5,000/hr per installation) |
| Audit trail | Actions attributed to you | Actions attributed to the app |
| Org installation | Requires your PAT to have org access | Installed per-org with owner approval |
For personal repos, a PAT works fine. For organizations, a GitHub App is strongly recommended.
Step 1: Create the App
-
Go to GitHub Developer Settings → New GitHub App
-
Fill in the basics:
Field Value GitHub App name Something unique, e.g., AutoRalph - YourNameHomepage URL Any valid URL (e.g., your repo URL) -
Under Webhook:
- Uncheck "Active" — AutoRalph uses polling, no webhooks needed
-
Under Permissions → Repository permissions, grant:
Permission Access Contents Read and write Pull requests Read and write Issues Read and write Leave all other permissions at "No access".
-
Under Where can this GitHub App be installed?:
- Choose Only on this account if you only need it for your personal repos
- Choose Any account if you need to install it on an organization (see Installing on an Organization below)
-
Click Create GitHub App
Step 2: Get the Client ID
After creation, you'll land on the app's settings page. Copy the Client ID
— it starts with Iv (e.g., Iv23liXXXXXX).
This goes into your credentials as github_app_client_id.
Step 3: Generate a Private Key
-
On the app settings page, scroll to Private keys
-
Click Generate a private key
-
A
.pemfile will download — save it somewhere safe:mv ~/Downloads/your-app-name.*.pem ~/.autoralph/github-app.pem chmod 600 ~/.autoralph/github-app.pem
This goes into your credentials as github_app_private_key_path.
Keep this file safe. Anyone with the private key can authenticate as your app. Never commit it to version control.
Step 4: Install the App
Installing on Your Personal Account
- From the app settings page, click Install App in the sidebar
- Select your personal account
- Choose repository access:
- All repositories — grants access to everything
- Only select repositories — pick specific repos (recommended)
- Click Install
Installing on an Organization
To install on an org, the app must be public (set to "Any account" in Step 1). If you created it as private, change it:
- Go to your app settings → Advanced (bottom of sidebar)
- Under "Danger zone", click Make public
- Confirm
"Public" does not mean anyone can use your app. It means anyone can install it, but they cannot authenticate as it without your private key. Since AutoRalph uses polling (no webhooks), an unauthorized installation would have zero effect.
Then install it:
- Go to
https://github.com/apps/<your-app-name>/installations/new - Select the organization
- Choose repository access (only select repositories is recommended)
- If you're an org owner: the installation happens immediately
- If you're not an org owner: GitHub sends an installation request to the org owners for approval — you'll need to coordinate with them
Tip for org procurement: The app introduces no new vendor, no webhooks, no external servers. It's a self-hosted tool using GitHub's built-in App platform. The only change is granting API access to specific repos.
Step 5: Get the Installation ID
After the app is installed:
- Go to
https://github.com/settings/installations(for personal) or the org's Settings → Integrations → GitHub Apps page - Click Configure next to your app
- The URL will look like:
https://github.com/settings/installations/12345678 - That number (
12345678) is your installation ID
This goes into your credentials as github_app_installation_id.
Different orgs = different installation IDs. If you install the same app on your personal account and your work org, each gets its own installation ID. Use separate credential profiles for each.
Step 6: Configure AutoRalph
Add a credentials profile in ~/.autoralph/credentials.yaml:
profiles:
work:
linear_api_key: lin_api_yyyyyyyyyyyyy
github_app_client_id: "Iv23liXXXXXX"
github_app_installation_id: 12345678
github_app_private_key_path: ~/.autoralph/github-app.pem
github_user_id: 87654321
git_author_name: autoralph
git_author_email: autoralph@myorg.com
Then reference it in your project config:
# ~/.autoralph/projects/my-project.yaml
name: my-project
local_path: ~/code/my-project
credentials_profile: work
# ...
All three github_app_* fields are required — partial configuration is an
error. See Configuration for the full reference.
Verifying the Setup
Start AutoRalph and check the logs for successful GitHub API calls:
autoralph serve
You can also verify the app can access your repos by checking the dashboard at
http://127.0.0.1:7749 — project status should show as healthy.
If you run into authentication errors, verify:
- The private key file path is correct and the file is readable
- The installation ID matches the org/account you're targeting
- The client ID matches your app (not the App ID — look for the one starting
with
Iv) - The app has the required permissions (Contents, Pull requests, Issues — all read/write)
- The app is installed on the repositories your project config references
Managing Installations
Changing Repository Access
After installation, you can adjust which repos the app can access:
- Go to the installation's configure page (org settings or personal settings)
- Under Repository access, add or remove repos
- Changes take effect immediately
Revoking Access
To uninstall the app from an org or account:
- Go to the installation's configure page
- Click Uninstall at the bottom
- The app loses all access immediately
Rotating the Private Key
If you need to rotate the private key:
- Go to your app settings → Private keys
- Click Generate a private key (creates a new one)
- Update
github_app_private_key_pathin your credentials to point to the new.pemfile - Restart AutoRalph
- Delete the old key from the app settings page
Security
AutoRalph interacts with external services (Linear, GitHub) and runs AI-driven code generation. This chapter covers the security measures in place to protect your repositories and credentials.
Trusted Reviewer
On public repositories, anyone can submit a PR review. By default, AutoRalph
treats all non-bot reviews as actionable feedback. The github_user_id
setting restricts AutoRalph to only act on reviews from a specific GitHub
user.
What it does: When github_user_id is set, AutoRalph compares each
reviewer's numeric ID against the configured value. Reviews from other users
are skipped (logged as untrusted_feedback_skipped in the activity log) and
never trigger the addressing_feedback transition. When github_user_id is
not set (or 0), all non-bot reviews are trusted — the existing default
behavior.
How to find your GitHub user ID:
gh api /user --jq .id
Example configuration:
profiles:
personal:
linear_api_key: lin_api_xxxxxxxxxxxxx
github_token: ghp_xxxxxxxxxxxxx
github_user_id: 12345678
This prevents untrusted third parties from injecting malicious review comments that AutoRalph would otherwise act on.
Delegated Trust via Review Requests
When github_user_id is set, AutoRalph also trusts reviewers whose review
was explicitly requested by the trusted user through GitHub's review request
mechanism. This allows the trusted user to delegate review authority without
changing the AutoRalph configuration.
The trust evaluation works as follows:
- Each poll cycle, AutoRalph fetches the PR timeline from the GitHub API
review_requestedevents where the requester matchesgithub_user_idadd the requested reviewer to the trusted setreview_request_removedevents where the requester matchesgithub_user_idremove that reviewer from the trusted set- A reviewer is trusted if they are the configured
github_user_idor are in the current trusted set
Removing a review request immediately revokes trust for that reviewer. The next poll cycle will recompute the trusted set and skip any subsequent reviews from the revoked reviewer.
Implementation detail: Trust is verified via the immutable PR timeline API (
/repos/{owner}/{repo}/issues/{number}/timeline), not the currentrequested_reviewerslist on the PR. The timeline provides a complete audit trail of request and removal events, ensuring trust decisions are based on the full history rather than a point-in-time snapshot.
When github_user_id is not set (or 0), the timeline is not fetched and
all non-bot reviews remain trusted — no behavior changes for unconfigured
setups.
GitHub App Authentication
GitHub Apps provide better security than personal access tokens for organization use:
- Short-lived tokens: GitHub App installation tokens expire after 1 hour, limiting the window of exposure if compromised
- Scoped permissions: Apps are granted only the specific permissions they need (Contents, Pull requests, Issues — all read/write)
- No personal rate limits: API calls don't count against a personal user's rate limit
- Audit trail: All actions are attributed to the app, not a personal account
Required Fields
| Field | Description |
|---|---|
github_app_client_id | GitHub App Client ID (starts with Iv) |
github_app_installation_id | Numeric ID from the installation URL |
github_app_private_key_path | Path to the .pem private key file |
Important: If you set any
github_app_*field, you must set all three. Partial configuration is an error.
Setting Up a GitHub App
See the GitHub App Setup guide for a complete walkthrough covering app creation, permissions, private key management, and installing on organizations.
Credential Isolation
AutoRalph uses a profile-based credential system that isolates credentials per project:
- Separate profiles: Each project can reference a different credentials profile, preventing cross-project credential leakage
- File-based storage: Credentials live in
~/.autoralph/credentials.yaml, separate from project configs - Environment overrides:
LINEAR_API_KEYandGITHUB_TOKENenvironment variables override file-based credentials, useful for CI/CD environments where secrets are injected - Private key files: GitHub App private keys are stored as separate
.pemfiles referenced by path, not embedded in YAML
Git Identity Isolation
Each credentials profile can specify its own git identity
(git_author_name, git_author_email). This ensures:
- AutoRalph commits are clearly distinguished from human commits
- Different projects can use different identities
- Environment variables (
AUTORALPH_GIT_AUTHOR_NAME,AUTORALPH_GIT_AUTHOR_EMAIL) can override profile values without modifying the credentials file
Workspace Isolation
Each issue gets its own git worktree, preventing concurrent builds from interfering with each other. Worktrees are cleaned up when issues complete, and the build worker pool uses a semaphore to limit concurrent builds.
Dashboard
AutoRalph includes a built-in web dashboard for monitoring issues, viewing
build progress, and managing the autonomous workflow. The React-based SPA is
compiled into the Go binary via go:embed, so no separate static file
serving is needed.
Open http://127.0.0.1:7749 in your browser after starting AutoRalph.
Web Interface
Dashboard (/)
- Project cards: Each configured project with active issue count, GitHub link, and state breakdown (how many issues in each state)
- Active issues table: All non-completed issues with identifier, title, state badge, progress indicator (when building), and PR link (when in review)
- Activity feed: Recent activity across all projects (state changes, build events, comments posted)
Issue Detail (/issues/:id)
- Header: Issue identifier, state badge, project name, title
- PR link: When a PR exists
- Error display: When the issue has failed
- Action buttons:
- Pause: Pauses any active issue
- Resume: Resumes a paused issue to its previous state
- Retry: Retries a failed issue from its pre-failure state
- Live build log: When the issue is in BUILDING state, shows a real-time terminal-style log of the Ralph execution loop
- Story progress: Sidebar showing which stories have passed/failed during the build
- Timeline: Chronological activity log with event icons, state transitions, and timestamps
Live Updates
The dashboard connects via WebSocket and automatically refreshes when state changes, build events, new issues, or activity entries occur. If the connection drops, it reconnects automatically after 3 seconds.
REST API
All endpoints return JSON. Errors use the format {"error": "message"}.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/status | Health check with uptime and active build count |
GET | /api/projects | List all projects with active issue counts and state breakdown |
GET | /api/issues | List issues (filterable) |
GET | /api/issues/{id} | Issue detail with activity timeline |
POST | /api/issues/{id}/pause | Pause an active issue |
POST | /api/issues/{id}/resume | Resume a paused issue |
POST | /api/issues/{id}/retry | Retry a failed issue |
GET | /api/activity | Recent activity across all projects |
Query Parameters
GET /api/issues:
project_id— Filter by projectstate— Filter by state (e.g.,building,in_review)
GET /api/issues/{id}:
limit— Activity entries per page (default: 20)offset— Activity pagination offset
GET /api/activity:
limit— Max entries to return (default: 20)
Examples
# Health check
curl http://127.0.0.1:7749/api/status
# List all projects
curl http://127.0.0.1:7749/api/projects
# List building issues
curl http://127.0.0.1:7749/api/issues?state=building
# Get issue detail
curl http://127.0.0.1:7749/api/issues/<issue-id>
# Pause an issue
curl -X POST http://127.0.0.1:7749/api/issues/<issue-id>/pause
# Resume a paused issue
curl -X POST http://127.0.0.1:7749/api/issues/<issue-id>/resume
# Retry a failed issue
curl -X POST http://127.0.0.1:7749/api/issues/<issue-id>/retry
# Recent activity
curl http://127.0.0.1:7749/api/activity?limit=10
WebSocket
Connect to ws://127.0.0.1:7749/api/ws for real-time updates.
Message Format
{
"type": "issue_state_changed",
"payload": { ... },
"timestamp": "2026-02-11T16:42:19Z"
}
Message Types
| Type | Description |
|---|---|
issue_state_changed | An issue transitioned to a new state |
build_event | A build event occurred (story started, passed, failed, etc.) |
new_issue | A new issue was ingested from Linear |
activity | A new activity log entry was created |
The dashboard uses these events to refresh data in real time. You can build custom integrations by connecting to the same WebSocket endpoint.