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.

  • 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 (claude CLI) 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

  1. ralph init scaffolds 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.

  2. ralph new login-page creates an isolated workspace (git worktree + branch), switches you into it, and launches an interactive PRD creation session with Claude.

  3. During the PRD session, you discuss the feature with Claude. When the plan is solid, type /finish and Claude writes a structured PRD with user stories and integration tests.

  4. ralph run starts 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.

  5. ralph done squash-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 of ralph 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:

  1. You describe the feature you want to build
  2. Claude asks clarifying questions about scope, requirements, and edge cases
  3. You discuss and refine until the plan is solid
  4. 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:

  1. Reads the PRD and finds the next unfinished story
  2. Invokes Claude with the story context, acceptance criteria, and project patterns
  3. Claude implements the story, writes tests, and runs quality checks
  4. On success, Claude commits and marks the story as passing in the PRD
  5. Appends a progress entry to the shared progress log

The QA phase

When all stories pass, Ralph enters QA:

  1. A QA agent reads the integration test specs from the PRD
  2. It builds and runs automated tests for each spec
  3. If tests fail, a QA fix agent resolves the issues
  4. 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 adjustments
  • ralph rebase — rebase onto the latest base branch (Claude resolves conflicts using PRD context)
  • ralph stop — gracefully stop the current run
  • ralph attach — re-attach to a running loop from another terminal

Phase 4: Complete (ralph done)

Finalizes the feature:

  1. Verifies the base branch is an ancestor (prompts to rebase if not)
  2. Generates a commit message from the PRD
  3. Lets you edit the message before committing
  4. Squash-merges into the base branch
  5. Archives the PRD and removes the workspace
  6. 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:

SubcommandDescription
new <name>Create a new workspace
listList all workspaces
switch <name>Switch to a workspace
remove <name>Remove a workspace
pruneRemove 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

FieldDescription
projectProject name
repo.default_baseBase 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"
HookWhen it runsUse case
pre_commitBefore each commitFormatters, linters with auto-fix, code generators
post_commitAfter each successful commitNotifications, cache invalidation
pre_prBefore opening a pull requestFull 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

FieldTypeDescription
userStories[].idstringStory identifier (e.g., US-001)
userStories[].passesboolSet to true by the agent when complete
userStories[].notesstringAgent notes (patterns learned, decisions made)
integrationTests[].idstringTest identifier (e.g., IT-001)
integrationTests[].passesboolSet to true by QA agent when verified
integrationTests[].failurestringFailure details if test didn't pass
integrationTests[].notesstringQA 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:

TemplateUsed byPurpose
loop_iteration.mdralph runMain prompt for implementing a single story
qa_verification.mdralph runQA agent prompt for integration test verification
qa_fix.mdralph runQA fix agent prompt for resolving test failures
prd_new.mdralph newInteractive PRD creation conversation
chat_system.mdralph chatSystem prompt for free-form chat sessions
rebase_conflict.mdralph rebaseConflict 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:

  1. Git tracking choice:

    • Track in git (recommended for teams) — gitignores only ephemeral directories
    • Keep local — gitignores the entire .ralph/ directory
  2. LLM analysis: optionally uses Claude to auto-detect quality check commands for your project (test runners, linters, type checkers, etc.)

What It Creates

PathPurpose
.ralph/ralph.yamlProject configuration (edit this!)
.ralph/tasks/Task markdown files
.ralph/skills/Project-specific skills for the agent
.ralph/workspaces/Workspace directories (gitignored)
.ralph/state/workspaces.jsonWorkspace registry (gitignored)
.ralph/state/archive/Completed PRDs (gitignored)
.claude/commands/finish.mdThe /finish skill for PRD generation
.claude/CLAUDE.mdProject 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 ralph binary in a shell function
  • Intercepts workspace commands (new, switch, done, workspaces *) to automatically cd into the correct directory
  • Sets/unsets RALPH_WORKSPACE to 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:

  • project is set to your project name
  • repo.default_base points to your main branch (e.g., main, develop)
  • quality_checks lists 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:

ComponentLocationPurpose
Git worktree.ralph/workspaces/<name>/tree/Isolated checkout on a dedicated branch
PRD.ralph/workspaces/<name>/prd.jsonRequirements driving the loop
Metadata.ralph/workspaces/<name>/workspace.jsonName, branch, timestamps
Config copytree/.ralph/Agent has full project context
Claude configtree/.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 run instances can execute in parallel
  • The main branch stays clean while features are in progress
  • ralph done squash-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.v3 for config, lipgloss/bubbletea/huh for terminal UI, doublestar for glob patterns. Everything else is stdlib.
  • Shell out to CLIs: git and claude are 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 (claude CLI) 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

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

StateDescription
QUEUEDIssue discovered and ingested from Linear, waiting to be processed
REFININGAI is reading the issue, asking clarifying questions via Linear comments
APPROVEDUser approved the refined plan, ready for building
BUILDINGWorkspace created, PRD generated, Ralph execution loop running
IN_REVIEWBranch pushed, PR opened on GitHub, awaiting review
ADDRESSING_FEEDBACKReviewer requested changes, AI is addressing review comments
FIXING_CHECKSCI checks failed on the PR, AI is analyzing logs and pushing fixes
COMPLETEDPR merged, workspace cleaned up, Linear issue moved to Done
FAILEDAn error occurred; can be retried via the API or dashboard
PAUSEDIssue paused by user or due to merge conflict; can be resumed

Transitions

FromToTrigger
QUEUEDREFININGOrchestrator picks up new issue
REFININGREFININGUser replies with feedback (iteration)
REFININGAPPROVEDUser comments @autoralph approved
APPROVEDBUILDINGWorkspace created, PRD generated
BUILDINGIN_REVIEWBuild succeeds, PR opened
BUILDINGFAILEDBuild fails (error stored in DB)
IN_REVIEWADDRESSING_FEEDBACKGitHub review with changes requested
IN_REVIEWFIXING_CHECKSCI check runs fail on the PR head SHA
IN_REVIEWCOMPLETEDPR merged
ADDRESSING_FEEDBACKIN_REVIEWFeedback addressed, changes pushed
FIXING_CHECKSIN_REVIEWChecks fixed, changes pushed
FIXING_CHECKSPAUSEDMax fix attempts exhausted (default: 3)
any activePAUSEDUser pauses via API or merge conflict
PAUSED(previous state)User resumes via API
FAILED(previous state)User retries via API

The Lifecycle in Detail

  1. Ingest: The Linear poller discovers new issues assigned to a configured user and creates them in the local database as QUEUED.

  2. Refine: AI reads the issue title and description, asks clarifying questions, and posts them as a Linear comment. The issue moves to REFINING.

  3. Iterate: When the user replies on Linear, AI incorporates the feedback and posts an updated plan. This loop continues until the user is satisfied.

  4. Approve: The user comments @autoralph approved on the Linear issue. AutoRalph extracts the approved plan and moves the issue to APPROVED.

  5. 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.

  6. 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.

  7. Address Feedback: If reviewers request changes, AutoRalph detects the CHANGES_REQUESTED review, feeds the comments to AI, commits fixes, pushes, and replies to each review comment. The issue moves to ADDRESSING_FEEDBACK and back to IN_REVIEW.

  8. 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_CHECKS and back to IN_REVIEW. If the checks cannot be fixed after 3 attempts, the issue is paused with a comment on the PR asking for human help.

  9. 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 FAILED with 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: QUEUEDREFINING

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: APPROVEDBUILDING

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

OptionDefaultDescription
max_iterations20Maximum Ralph loop iterations per build
ralph_config_path.ralph/ralph.yamlPath to Ralph config relative to project
branch_prefixautoralph/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_REVIEWADDRESSING_FEEDBACK

When a GitHub reviewer requests changes, AutoRalph feeds the review comments to AI and commits fixes.

  • Detects CHANGES_REQUESTED or COMMENTED reviews 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_REVIEWFIXING_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_checks for 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_REVIEW where 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:

  1. Posts a comment on the PR asking for human help
  2. 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_REVIEWCOMPLETED

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 COMPLETED in 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):

  1. Environment variables LINEAR_API_KEY / GITHUB_TOKEN
  2. Named profile (from project config's credentials_profile)
  3. default_profile from credentials file

If no credentials file exists and both environment variables are set, they are used directly.

Note: When the GITHUB_TOKEN environment 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.

FieldDefaultDescription
git_author_nameautoralphName used for git author and committer
git_author_emailautoralph@noreplyEmail 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:

VariableOverrides
AUTORALPH_GIT_AUTHOR_NAMEgit_author_name from the active profile
AUTORALPH_GIT_AUTHOR_EMAILgit_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

FieldRequiredDefaultDescription
nameyesHuman-readable project name (must be unique)
local_pathyesAbsolute path to the local git clone
credentials_profilenodefault_profileWhich credentials profile to use
github.owneryesGitHub org or user
github.repoyesGitHub repository name
linear.team_idyesLinear team UUID
linear.assignee_idyesLinear user UUID to watch for assigned issues
linear.project_idno(all projects)Linear project UUID
linear.labelno(none)Label name to filter issue ingestion (case-insensitive)
ralph_config_pathno.ralph/ralph.yamlPath to Ralph config (relative to local_path)
max_iterationsno20Max Ralph loop iterations per build
branch_prefixnoautoralph/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

FlagEnv VarDefaultDescription
--addr127.0.0.1:7749Address to listen on
--devProxy non-API requests to Vite dev server
--linear-urlAUTORALPH_LINEAR_URLOverride Linear API (for testing)
--github-urlAUTORALPH_GITHUB_URLOverride GitHub API (for testing)

Subcommands

autoralph serve [flags]   # Start the server
autoralph version         # Print version
autoralph help            # Show usage

What Happens on Startup

  1. Opens (or creates) the SQLite database at ~/.autoralph/autoralph.db
  2. Loads and validates all project configs from ~/.autoralph/projects/*.yaml
  3. Syncs project configs to the database
  4. Resolves credentials for each project
  5. Starts the Linear poller (polls every 30s for new assigned issues)
  6. Starts the GitHub poller (polls every 30s for PR reviews, check runs, and merges)
  7. Starts the orchestrator loop (evaluates state transitions)
  8. Starts the build worker pool
  9. Recovers any BUILDING issues from a previous run
  10. 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 TokenGitHub App
Token lifetimeLong-lived (until revoked)1-hour auto-rotating tokens
Permission scopeBroad (tied to your account)Scoped to specific repos
Rate limitsShared with your personal usageSeparate pool (5,000/hr per installation)
Audit trailActions attributed to youActions attributed to the app
Org installationRequires your PAT to have org accessInstalled 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

  1. Go to GitHub Developer SettingsNew GitHub App

  2. Fill in the basics:

    FieldValue
    GitHub App nameSomething unique, e.g., AutoRalph - YourName
    Homepage URLAny valid URL (e.g., your repo URL)
  3. Under Webhook:

    • Uncheck "Active" — AutoRalph uses polling, no webhooks needed
  4. Under Permissions → Repository permissions, grant:

    PermissionAccess
    ContentsRead and write
    Pull requestsRead and write
    IssuesRead and write

    Leave all other permissions at "No access".

  5. 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)
  6. 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

  1. On the app settings page, scroll to Private keys

  2. Click Generate a private key

  3. A .pem file 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

  1. From the app settings page, click Install App in the sidebar
  2. Select your personal account
  3. Choose repository access:
    • All repositories — grants access to everything
    • Only select repositories — pick specific repos (recommended)
  4. 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:

  1. Go to your app settings → Advanced (bottom of sidebar)
  2. Under "Danger zone", click Make public
  3. 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:

  1. Go to https://github.com/apps/<your-app-name>/installations/new
  2. Select the organization
  3. Choose repository access (only select repositories is recommended)
  4. If you're an org owner: the installation happens immediately
  5. 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:

  1. Go to https://github.com/settings/installations (for personal) or the org's Settings → Integrations → GitHub Apps page
  2. Click Configure next to your app
  3. The URL will look like: https://github.com/settings/installations/12345678
  4. 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:

  1. The private key file path is correct and the file is readable
  2. The installation ID matches the org/account you're targeting
  3. The client ID matches your app (not the App ID — look for the one starting with Iv)
  4. The app has the required permissions (Contents, Pull requests, Issues — all read/write)
  5. 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:

  1. Go to the installation's configure page (org settings or personal settings)
  2. Under Repository access, add or remove repos
  3. Changes take effect immediately

Revoking Access

To uninstall the app from an org or account:

  1. Go to the installation's configure page
  2. Click Uninstall at the bottom
  3. The app loses all access immediately

Rotating the Private Key

If you need to rotate the private key:

  1. Go to your app settings → Private keys
  2. Click Generate a private key (creates a new one)
  3. Update github_app_private_key_path in your credentials to point to the new .pem file
  4. Restart AutoRalph
  5. 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:

  1. Each poll cycle, AutoRalph fetches the PR timeline from the GitHub API
  2. review_requested events where the requester matches github_user_id add the requested reviewer to the trusted set
  3. review_request_removed events where the requester matches github_user_id remove that reviewer from the trusted set
  4. A reviewer is trusted if they are the configured github_user_id or 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 current requested_reviewers list 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

FieldDescription
github_app_client_idGitHub App Client ID (starts with Iv)
github_app_installation_idNumeric ID from the installation URL
github_app_private_key_pathPath 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_KEY and GITHUB_TOKEN environment 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 .pem files 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

MethodPathDescription
GET/api/statusHealth check with uptime and active build count
GET/api/projectsList all projects with active issue counts and state breakdown
GET/api/issuesList issues (filterable)
GET/api/issues/{id}Issue detail with activity timeline
POST/api/issues/{id}/pausePause an active issue
POST/api/issues/{id}/resumeResume a paused issue
POST/api/issues/{id}/retryRetry a failed issue
GET/api/activityRecent activity across all projects

Query Parameters

GET /api/issues:

  • project_id — Filter by project
  • state — 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

TypeDescription
issue_state_changedAn issue transitioned to a new state
build_eventA build event occurred (story started, passed, failed, etc.)
new_issueA new issue was ingested from Linear
activityA 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.