Ralph Documentation

repository·main·Indexed 21 days ago

https://github.com/iannuttall/ralph

A minimal, file-based agent loop for autonomous coding that uses files and Git as primary memory. Ralph executes tasks based on JSON-defined Product Requirements Documents (PRDs) and supports multiple agent runners including codex, claude, droid, and opencode. The CLI provides tools for generating PRDs, running build iterations, managing templates and skills, and tracking project progress via state files.

Tokens
15.1K
Snippets
52
Records
63
Agent score
75%

What's inside Ralph

  1. Avoid TypeScript in page.evaluate()

    main

    The page.evaluate() method executes code directly in the browser context. The browser engine does not support TypeScript syntax. You must use plain JavaScript inside the callback.

    Incorrect (will fail):

    await page.evaluate(() => {
      const el: HTMLElement = document.body; // Type annotation is invalid in browser
      return el.innerText;
    });

    Correct:

    await page.evaluate(() => {
      return document.body.innerText;
    });
  2. How the PRD Generator skill works

    main

    The prd skill is a specialized agent capability designed to generate a structured Product Requirements Document (PRD) in JSON format. This JSON file serves as the single source of truth for Ralph to execute tasks, manage stories, gates, and status.

    When triggered (e.g., by commands like create a prd, write prd for, or plan this feature), the skill follows a two-step process:

    1. Clarifying Questions: The agent asks 5–10 questions in batches of up to 5 to capture details about goals, scope, stack, UI/routes, data models, and quality gates (required commands like npm test that must pass). It explicitly asks if the project is new or existing.
    2. JSON Generation: Once details are gathered, it generates a detailed JSON file and saves it to a specified path (e.g., .agents/tasks/prd-<slug>.json).

    Important: The skill only generates JSON; it does not implement the feature itself.

    ralph build
  3. Understand Ralph state files and directory structure

    main

    Ralph uses two main directories for persistence and state:

    .agents/ralph/ (Portable Configuration)

    Contains templates, custom prompts, loop behavior, and config.sh. This directory is portable and can be copied between repositories.

    .ralph/ (Per-project State)

    Contains project-specific execution data:

    • progress.md: Append-only progress log.
    • guardrails.md: "Signs" or lessons learned.
    • activity.log: Activity and timing logs.
    • errors.log: Repeated failures and notes.
    • runs/: Raw run logs and summaries.
  4. Discover and interact with elements using ARIA Snapshots

    main

    When page layouts are unknown, use the ARIA snapshotting workflow to discover elements and interact with them using stable references.

    1. Get the Snapshot: Use client.getAISnapshot("page_name") to get a YAML-formatted accessibility tree.
    2. Identify the Reference: Look for [ref=eN] tags in the YAML. These represent visible, clickable elements.
    3. Interact: Use client.selectSnapshotRef("page_name", "eN") to get the element, then call Playwright methods like .click().

    Example Snapshot Format:

    - banner:
      - link "Hacker News" [ref=e1]
    - main:
      - list:
        - listitem:
          - link "Article Title" [ref=e8]
    const snapshot = await client.getAISnapshot("hackernews");
    console.log(snapshot); // Find the ref you need
    
    const element = await client.selectSnapshotRef("hackernews", "e2");
    await element.click();
  5. Prefer API replay over DOM scrolling for data scraping

    main
    When scraping large datasets (such as followers, posts, or search results), avoid scrolling and parsing the DOM. Instead, intercept and replay network requests. This approach is faster, more reliable, and handles pagination automatically because APIs return structured data with built-in pagination mechanisms.
  6. Install Ralph templates and skills

    main

    To customize prompts and loop behavior, run ralph install to create a .agents/ralph/ directory in your current repository.

    To also install required skills (such as commit, dev-browser, and prd), use the --skills flag. During this process, you will be prompted to choose an agent runner (e.g., codex, claude, droid, or opencode) and whether to perform a local or global installation.

    # Install templates for customization
    ralph install
    
    # Install templates and required skills
    ralph install --skills
  7. Replay API requests with pagination using `page.evaluate`

    main

    Once the schema and headers are known, replay requests directly within the browser context using page.evaluate. This ensures the requests inherit the existing authentication (cookies/headers) of the session.

    Workflow:

    1. Load captured headers from a file.
    2. Use a while loop to iterate through pages.
    3. Construct the URL with pagination parameters (e.g., cursor).
    4. Use page.evaluate to perform a fetch inside the browser.
    5. Extract data and the next cursor from the response.
    6. Use a Map to deduplicate items that might overlap between pages.
    7. Implement a delay (e.g., 500ms) to respect rate limits.
    import { connect } from "@/client.js";
    import * as fs from "node:fs";
    
    const client = await connect();
    const page = await client.page("site");
    
    const results = new Map(); // Use Map for deduplication
    const headers = JSON.parse(fs.readFileSync("tmp/request-details.json", "utf8")).headers;
    const baseUrl = "https://example.com/api/data";
    
    let cursor = null;
    let hasMore = true;
    
    while (hasMore) {
      // Build URL with pagination cursor
      const params = { count: 20 };
      if (cursor) params.cursor = cursor;
      const url = `${baseUrl}?params=${encodeURIComponent(JSON.stringify(params))}`;
    
      // Execute fetch in browser context (has auth cookies/headers)
      const response = await page.evaluate(
        async ({ url, headers }) => {
          const res = await fetch(url, { headers });
          return res.json();
        },
        { url, headers }
      );
    
      // Extract data and cursor (adjust paths for your API)
      const entries = response?.data?.entries || [];
      for (const entry of entries) {
        if (entry.type === "cursor-bottom") {
          cursor = entry.value;
        } else if (entry.id && !results.has(entry.id)) {
          results.set(entry.id, {
            id: entry.id,
            text: entry.content,
            timestamp: entry.created_at,
          });
        }
      }
    
      console.log(`Fetched page, total: ${results.size}`);
    
      // Check stop conditions
      if (!cursor || entries.length === 0) hasMore = false;
    
      // Rate limiting - be respectful
      await new Promise((r) => setTimeout(r, 500));
    }
    
    // Export results
    const data = Array.from(results.values());
    fs.writeFileSync("tmp/results.json", JSON.stringify(data, null, 2));
    console.log(`Saved ${data.length} items`);
    
    await client.disconnect();
  8. Override the agent runner

    main

    You can specify which agent to use for commands using the --agent flag. This is useful for testing different models or ensuring a specific agent is responsive.

    • ralph ping --agent=<agent_name>: Checks if the specified agent is installed and responsive.
    • ralph build <run_number> --agent=<agent_name>: Executes a run using a specific agent (e.g., codex, claude, or droid).
    ralph ping --agent=codex
    ralph build 1 --agent=codex
    ralph build 1 --agent=claude
    ralph build 1 --agent=droid
  9. Override PRD paths

    main

    Instead of generating a new PRD from a string, you can point Ralph to an existing PRD JSON file using the --prd flag or the --out flag during generation.

    • ralph prd "..." --out <path>: Generates a PRD and saves it to the specified path.
    • ralph build <run_number> --prd <path>: Executes a run using a specific PRD file.
    • ralph overview --prd <path>: Shows an overview based on a specific PRD file.
    ralph prd "..." --out .agents/tasks/prd-api.json
    ralph build 1 --prd .agents/tasks/prd-api.json
    ralph overview --prd .agents/tasks/prd-api.json
  10. Naming and saving PRD JSON files

    main

    When the PRD generator saves the output, it follows these rules:

    1. Path: Save to the exact path provided in the prompt. If a directory is provided instead of a filename, the agent creates a file named prd-<short-slug>.json.
    2. Slug: The <short-slug> should be 1–3 meaningful words (e.g., prd-workout-tracker.json). Avoid filler words.
    3. Format: The file must contain only the JSON content. No Markdown wrappers or extra commentary.
    4. Post-generation: After saving, the agent will instruct you to: PRD JSON saved to <path>. Close this chat and run alph build.`
  11. Use the 'commit' skill for Conventional Commits

    main

    The commit skill is designed to help you write git commit messages following the Conventional Commits format. It enforces the use of a type(scope): subject structure, ensuring messages are descriptive, standardized, and machine-readable for tools like semantic-release.

    Quick Start Workflow

    1. Stage changes: Use git add <files> or git add -A.
    2. Create commit: Use the git commit -m command following the required format.

    Commit Structure

    • Type: A short identifier of the change (e.g., feat, fix).
    • Scope: A required, kebab-case identifier for the specific module or area (e.g., auth, api).
    • Subject: A concise description (max 50 chars) in the present tense imperative (e.g., add, fix, improve). Do not end with a period.

    Complex Commits

    For changes requiring more detail, include a body after a blank line to explain the HOW and WHY. You can use heredocs in your shell to pass multi-line bodies to git commit -m.

    # 1. Stage changes
    git add <files>  # or: git add -A
    
    # 2. Create commit (branch commit format)
    git commit -m "type(scope): subject
    
    Body explaining HOW and WHY.
    Reference: Task X.Y, Req N"
  12. Install and run Ralph via Global CLI

    main

    Install the Ralph CLI globally to run it from any directory. You can use ralph prd to launch an interactive prompt for generating a Product Requirements Document (PRD) and ralph build <n> to execute a specific number of build iterations.

    Note: Ralph uses a template hierarchy. It first looks for templates in .agents/ralph/ within your current project; if not found, it uses the bundled defaults.

    npm i -g @iannuttall/ralph
    
    # Launch interactive PRD prompt
    ralph prd
    
    # Run one build iteration
    ralph build 1