API Reference

This section documents the public API of pyralph.

Core Module

The main entry point and orchestrator for Ralph.

Ralph - Autonomous Software Development Agent.

This package provides the Ralph CLI tool for autonomous software development through a three-phase loop: Architect -> Planner -> Execute.

Public API:
Core:

RalphOrchestrator - Main orchestrator class for running Ralph workflows main - CLI entry point function get_version - Get the version string from pyproject.toml

Configuration:

Config - Configuration dataclass CONF - Global configuration singleton

Logging:

Logger - Static logger class with CLI-controlled flags

Utilities:

Shell - Safe wrapper for subprocess calls PRDManager - PRD file operations with caching JsonUtils - Robust JSON parsing of LLM outputs PromptFormatter - Utility for consistent prompt formatting TemplateManager - Template loading and management

Hooks:

HookManager - Hook discovery, loading, and execution Event - Immutable event payload EventType - Lifecycle event types enum Hook - Abstract base class for hooks

Agents:

BaseAgent - Abstract base class for agents AgentError - Agent execution error get_agent - Factory function to get agent instances list_agents - List available agent names

Example

>>> from ralph import RalphOrchestrator, Logger
>>> Logger.set_verbosity(1)
>>> orchestrator = RalphOrchestrator()
>>> orchestrator.start(phase="all")
class pyralph.RalphOrchestrator(agent_name: str = 'claude', enable_hooks: bool = True, enabled_hook_names: List[str] | None = None, intent: str | None = None, intent_file: str | None = None, prompt_file: str | None = None, enhance_intent: bool = False, enhance_intent_strict: bool = False, tree_depth: int = 2, tree_ignore: List[str] | None = None, test_cmd: str | None = None, skip_verify: bool = False, retries: int | None = None, timeout: int | None = None, only: List[str] | None = None, except_tasks: List[str] | None = None, resume: str | None = None, include: List[str] | None = None, exclude: List[str] | None = None, context_limit: int | None = None, model: str | None = None, temperature: float | None = None, max_tokens: int | None = None, seed: int | None = None, log_file: str | None = None, log_level: str | None = None, json_output: bool = False, ndjson_output: bool = False, print_prd: bool = False, prd_out: str | None = None, archive: bool = True, non_interactive: bool = False, ci: bool = False, status_check: bool = False, pre: List[str] | None = None, post: List[str] | None = None, plugin: List[str] | None = None, schema: str | None = None, min_criteria: int | None = None, label: List[str] | None = None, revise_prd: bool = False)[source]

Bases: object

run_architect(user_intent: str) None[source]

Run the architect phase to generate architecture documentation.

Generates ARCHITECTURE.md and ARCH.md with project structure, tech stack, and test command configuration.

Parameters:

user_intent – Description of what the user wants to build

run_planner(user_intent: str) None[source]

Run the planner phase to create a Product Requirements Document.

Generates a PRD with user stories and acceptance criteria, saved to .ralph/prd.json.

Respects the following flags: - –schema: Validate PRD against a JSON schema file - –min-criteria: Ensure each story has at least N acceptance criteria - –label: Add custom labels to the PRD - –revise-prd: Pass PRD through revision agent before saving

Parameters:

user_intent – Description of what the user wants to build

execute_loop() None[source]

Execute all pending tasks from the PRD.

Iterates through user stories, executing each pending task with verification. Continues to next task on failure instead of terminating. Archives the PRD upon completion.

Respects the following flags: - –test-cmd: Override the test command - –skip-verify: Skip verification step after task execution - –retries: Override max retry count - –only: Execute only specified task IDs - –except: Skip specified task IDs - –resume: Resume execution from a specific task ID - –pre: Run pre-commands before phase execution - –post: Run post-commands after phase completion

start(phase: str = 'all', accept_all: bool = False) None[source]

Start the Ralph orchestrator.

Parameters:
  • phase – Which phase to run (“architect”, “planner”, “execute”, or “all”)

  • accept_all – If True, skip user confirmation prompts

Respects the following flags: - –print-prd: Print PRD contents and exit without executing - –prd-out: Export PRD to specified file and continue - –status-check: Check PRD status and exit with appropriate code

pyralph.main() None[source]

Entry point for the ralph CLI.

pyralph.get_version() str[source]

Get the version string from package metadata.

Returns:

Version string from package metadata, or ‘unknown’ if not found.

class pyralph.Config(BASE_DIR: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs'), ROOT_DIR: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph'), ARCHIVE_DIR: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/archive'), TEMPLATES_DIR: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/templates'), HOOKS_DIR: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/hooks'), PRD_FILE: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/prd.json'), PROGRESS_FILE: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/progress.txt'), LOG_FILE: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/ralph_log.txt'), MAX_RETRIES: int = 3, TIMEOUT_SECONDS: int = 600)[source]

Bases: object

BASE_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs')
ROOT_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph')
ARCHIVE_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/archive')
TEMPLATES_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/templates')
HOOKS_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/hooks')
PRD_FILE: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/prd.json')
PROGRESS_FILE: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/progress.txt')
LOG_FILE: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/ralph_log.txt')
MAX_RETRIES: int = 3
TIMEOUT_SECONDS: int = 600
ensure_directories() None[source]
class pyralph.Logger[source]

Bases: object

COLORS = {'CYAN': '\x1b[96m', 'GREEN': '\x1b[92m', 'MAGENTA': '\x1b[95m', 'RED': '\x1b[91m', 'RESET': '\x1b[0m', 'YELLOW': '\x1b[93m'}
no_color = False
quiet = False
no_emoji = False
LOG_LEVELS = {'debug': 10, 'error': 40, 'info': 20, 'warn': 30}
log_level = 20
json_output = False
ndjson_output = False
custom_log_file: Path | None = None
non_interactive = False
redact_patterns: List[str] = []
no_log_prompts = False
no_log_responses = False
static set_no_color(enabled: bool) None[source]
static set_verbose(enabled: bool) None[source]

Set verbose mode (backwards compatible, sets verbosity to 1 or 0).

This method is provided for backwards compatibility. The verbose and verbosity attributes are automatically synchronized via descriptors.

static set_verbosity(level: int) None[source]

Set verbosity level (0=normal, 1=verbose, 2=very verbose, 3=debug).

When verbosity >= 1, log_level is automatically set to debug to allow debug/trace/ultra messages to appear. This maintains backwards compatibility with existing -v/-vv/-vvv behavior.

The verbose and verbosity attributes are automatically synchronized via descriptors, so setting verbosity will update verbose accordingly.

static set_quiet(enabled: bool) None[source]

Set quiet mode (suppresses all non-error output).

static set_no_emoji(enabled: bool) None[source]

Set no-emoji mode (replaces emojis with text equivalents).

static set_log_level(level: str) None[source]

Set log level (debug, info, warn, error).

static set_json_output(enabled: bool) None[source]

Enable JSON output format.

static set_ndjson_output(enabled: bool) None[source]

Enable newline-delimited JSON output format.

static set_log_file(path: str | None) None[source]

Set custom log file path.

static set_non_interactive(enabled: bool) None[source]

Set non-interactive mode (disables all interactive prompts).

static set_redact_patterns(patterns: List[str]) None[source]

Set patterns to redact from logs.

Parameters:

patterns – List of regex patterns to redact from log output

static add_redact_patterns_from_file(file_path: str) None[source]

Load redaction patterns from a file (one pattern per line).

Parameters:

file_path – Path to file containing patterns (one per line)

static set_no_log_prompts(enabled: bool) None[source]

Disable logging of prompts to log file.

Parameters:

enabled – If True, prompts will not be written to logs

static set_no_log_responses(enabled: bool) None[source]

Disable logging of responses to log file.

Parameters:

enabled – If True, responses will not be written to logs

static get_log_file() Path[source]

Get the effective log file path (custom or default).

static info(msg: str, color: str = 'RESET') None[source]

Print info message (suppressed in quiet mode or if log level > info).

static debug(msg: str, color: str = 'RESET') None[source]

Print debug message (requires verbosity >= 1 and log level <= debug).

static trace(msg: str, color: str = 'RESET') None[source]

Print trace message (requires verbosity >= 2 and log level <= debug).

static ultra(msg: str, color: str = 'RESET') None[source]

Print ultra-verbose message (requires verbosity >= 3 and log level <= debug).

static warning(msg: str) None[source]

Print warning message (shown even in quiet mode, respects log level).

static error(msg: str) None[source]

Print error message (always shown, respects log level).

static file_log(content: str, type: str, tag: str = 'UNKNOWN') None[source]

Append a timestamped entry to the persistent log file.

Respects the following privacy flags: - –no-log-prompts: Skip logging when type is PROMPT - –no-log-responses: Skip logging when type is RESPONSE - –redact / –redact-file: Apply redaction patterns to content

class pyralph.Shell[source]

Bases: object

Safe wrapper for subprocess calls.

static run(command: str, timeout: int = 30) Tuple[str, str, int][source]

Execute a shell command and capture its output.

Parameters:
  • command – The shell command to execute

  • timeout – Maximum seconds to wait for command completion

Returns:

Tuple of (stdout, stderr, return_code)

Security Note:

This method uses shell=True which enables shell features (pipes, wildcards, variable expansion) but introduces command injection risks if command contains unsanitized user input.

Safe usage (internal/trusted sources):
  • Hardcoded commands (e.g., “pytest”, “tree -L 2”)

  • Commands from configuration files controlled by the user

  • Agent-generated commands (trusted AI output)

Unsafe usage (AVOID):
  • Commands built from external/untrusted input

  • Commands containing unvalidated user data

This is acceptable here because:
  1. Commands originate from trusted sources (config, agents)

  2. The tool runs locally with user’s own permissions

  3. Shell features (pipes, globs) are required for functionality

DEFAULT_TREE_IGNORE = ['node_modules', 'venv', '.git', '.ralph', '__pycache__']
static get_file_tree(depth: int = 2, ignore: List[str] | None = None) str[source]

Generate a file tree representation of the project directory.

Parameters:
  • depth – Maximum directory depth to traverse (default: 2)

  • ignore – List of directory/file patterns to exclude (default: node_modules, venv, .git, .ralph, __pycache__)

Returns:

String representation of the directory tree

class pyralph.PRDManager(prd_path: Path)[source]

Bases: object

Consolidated manager for PRD file operations.

Provides caching to avoid repeated disk reads and centralizes all PRD read/write operations in one place.

exists() bool[source]

Check if PRD file exists on disk.

invalidate_cache() None[source]

Clear cached PRD data, forcing next read from disk.

read_raw() str[source]

Read raw PRD content as string.

Returns:

Raw JSON string from PRD file

Raises:

FileNotFoundError – If PRD file does not exist

load() Dict[str, Any][source]

Load and parse PRD from disk with caching.

Returns:

Parsed PRD data as dictionary

Raises:
  • FileNotFoundError – If PRD file does not exist

  • json.JSONDecodeError – If PRD contains invalid JSON

save(data: Dict[str, Any]) None[source]

Save PRD data to disk and update cache.

Parameters:

data – PRD data to write

delete() None[source]

Delete PRD file from disk and clear cache.

class pyralph.JsonUtils[source]

Bases: object

Robust JSON parsing for LLM outputs.

static parse(text: str) Dict[str, Any][source]

Parse JSON from LLM output, handling markdown fences and comments.

Parameters:

text – Raw text potentially containing JSON with markdown fences

Returns:

Parsed JSON as a dictionary

Raises:

json.JSONDecodeError – If the text cannot be parsed as valid JSON

class pyralph.TemplateManager[source]

Bases: object

DEFAULT_TEMPLATES = {'architect.txt': '# ROLE\nSenior Software Architect\n\n# OBJECTIVE\nAnalyze project structure and create architecture documentation.\n\n# CONTEXT\n<USER_INTENT>\n{{user_intent}}\n</USER_INTENT>\n\n<FILE_TREE>\n{{file_tree}}\n</FILE_TREE>\n\n# ANALYSIS REQUIREMENTS\n\nAnalyze and document the following aspects:\n\n1. **SOLID Principles**: Evaluate Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion adherence.\n\n2. **Architectural Patterns**: Identify patterns (MVC, Layered, Microservices, Event-Driven, Repository, Clean Architecture, Hexagonal).\n\n3. **Security**: Document authentication, input validation, secrets management, and potential vulnerabilities.\n\n4. **Error Handling**: Document error strategies, logging framework, and log levels.\n\n5. **API Boundaries**: Identify external/internal APIs, data formats, and protocols.\n\n# FALLBACK BEHAVIOR\n\nWhen information cannot be determined from the file tree:\n- Use file extensions to infer languages\n- Check config files (package.json, pyproject.toml, etc.)\n- For unknown items, use: `[Unable to determine]`\n- For test commands: `[Unable to determine - manual verification required]`\n\n# CONSTRAINTS\n# Create ARCHITECTURE.md in project root\n- Use exact YAML frontmatter format below\n- Include ALL required sections\n- Detect actual test command (pytest, npm test, etc.)\n- Do NOT invent technologies not evident in file tree\n- Keep descriptions concise and factual\n\n# OUTPUT SPECIFICATION\n\n## File 1: ARCHITECTURE.md\n\n```markdown\n---\ntype: wiki\ntitle: Architecture\n---\n\n# Architecture\n\n## Tech Stack\n- **Language**: [detected language and version]\n- **Testing**: [detected test framework]\n- **Build**: [detected build tool]\n- [additional relevant technologies]\n\n## Overview\n[2-3 sentence description of project purpose and architecture]\n\n## Architectural Patterns\n- **Primary Pattern**: [main architectural pattern]\n- **Supporting Patterns**: [additional patterns used]\n\n## Key Components\n| Component | Description |\n|-----------|-------------|\n| [path/file] | [brief description] |\n[list 3-6 key components]\n\n## SOLID Principles Assessment\n| Principle | Status | Notes |\n|-----------|--------|-------|\n| Single Responsibility | [Good/Needs Work] | [brief observation] |\n| Open/Closed | [Good/Needs Work] | [brief observation] |\n| Liskov Substitution | [Good/N/A] | [brief observation] |\n| Interface Segregation | [Good/Needs Work] | [brief observation] |\n| Dependency Inversion | [Good/Needs Work] | [brief observation] |\n\n## API Boundaries & Integration Points\n- **External Integrations**: [list external APIs/services]\n- **Internal Interfaces**: [key module boundaries]\n- **Data Formats**: [JSON, XML, etc.]\n- **Protocols**: [REST, GraphQL, gRPC, etc.]\n\n## Error Handling & Logging\n- **Error Strategy**: [how errors are handled]\n- **Logging Approach**: [logging framework and patterns]\n- **Log Levels**: [how levels are used]\n\n## Security Considerations\n- **Authentication**: [method used or N/A]\n- **Input Validation**: [where/how validated]\n- **Secrets Management**: [how secrets are handled]\n- **Potential Concerns**: [any security gaps identified]\n\n## Test Command\nTest Command: `[actual test command]`\n```\n\n## File 2: ARCH.md (Project Root)\nCreate a copy of the architecture documentation in the project root for git tracking.\n\n# RESPONSE FORMAT\nAfter creating the file, output EXACTLY:\n```\nSTATUS: CREATED ARCHITECTURE.md\n```\n', 'developer.txt': "# ROLE\nDeveloper\n\n# OBJECTIVE\nImplement assigned task per acceptance criteria while following software engineering best practices.\n\n# TASK CONTEXT\n\n<TASK_ID>{{task_id}}</TASK_ID>\n<TASK_DESC>{{task_description}}</TASK_DESC>\n<ACCEPTANCE_CRITERIA>{{acceptance_criteria}}</ACCEPTANCE_CRITERIA>\n\n# MANDATORY INSTRUCTIONS\n<USER_CONTEXT>{{user_context}}</USER_CONTEXT>\n\n# AVAILABLE CONTEXT\n<PREV_ERRORS>{{prev_errors}}</PREV_ERRORS>\n\n# CODE QUALITY PRINCIPLES\n\n## DRY, KISS, YAGNI\n- **DRY**: Extract repeated code into reusable functions; centralize config/constants\n- **KISS**: Prefer straightforward solutions; use standard patterns; break complex logic into well-named functions\n- **YAGNI**: Only implement what's required; remove unused code; no speculative features\n\n## Security (OWASP Top 10)\n- **Injection**: Use parameterized queries; never concatenate user input into SQL/commands\n- **XSS**: Escape user data before rendering; use auto-escaping templates\n- **Auth**: Hash passwords (bcrypt/Argon2); secure session cookies; rate limit\n- **Data**: Never log secrets/PII; use env vars for secrets; encrypt in transit/at rest\n- **Config**: Disable debug in production; remove defaults; keep deps updated\n\n## Error Handling\n- Catch specific exceptions, not generic Exception\n- Log with context (operation, IDs) at appropriate levels (DEBUG/INFO/WARNING/ERROR)\n- Preserve exception chains; provide meaningful user messages\n- Use context managers for resource cleanup\n\n## Project Conventions\nBefore coding, analyze codebase to detect and follow:\n- Naming conventions (snake_case, camelCase, PascalCase)\n- Import organization (stdlib, third-party, local)\n- Existing architectural patterns and utilities\n- Test file naming and assertion patterns\n\n## Self-Documenting Code\n- Use intention-revealing names; verbs for functions, nouns for classes/variables\n- Keep functions short (single responsibility); limit to 3-4 parameters\n- Return early to avoid nesting; extract complex conditionals to named variables\n\n# EXECUTION WORKFLOW\n\n## Phase 1: Planning\n1. Analyze acceptance criteria and scope boundaries\n2. Review existing code for conventions and patterns\n3. Identify files to modify; consider edge cases and security implications\n\n## Phase 2: Implementation\n1. Read all code before modifying; match existing patterns\n2. Make minimal, focused changes (YAGNI)\n3. Write self-documenting code with proper error handling\n\n## Phase 3: Verification\n1. Run: `{{test_cmd}}`\n2. If tests fail, analyze errors, fix, and re-run\n3. Only proceed when all tests pass\n\n# FALLBACK STRATEGIES\n\n## Cannot Find Code\nBroaden search terms; trace imports; check tests for implementation; document attempts\n\n## Unfamiliar Patterns\nLook for similar code elsewhere; examine tests for behavior; match existing pattern for consistency\n\n## Tests Fail\n1. Read FULL error message\n2. Check if regression or new failure\n3. Fix incrementally; verify imports/signatures\n4. If same error twice, try different approach\n\n## Conflicting Requirements\nRe-read carefully; prioritize criteria over existing tests; document conflicts\n\n# ERROR CORRECTION\n\nIf tests fail:\n1. Read error carefully; identify root cause\n2. Fix specific issue only\n3. Re-run verification\n\nSelf-correction rules:\n- Same error twice try different approach\n- 3+ failures re-analyze requirements\n- Do NOT modify test files unless explicitly required\n- Do NOT skip/disable failing tests\n\n# OUTPUT SPECIFICATION\n\n## On Success\n```\nSTATUS: SUCCESS\n```\n\n## On Failure\n```\nSTATUS: FAILURE - <specific reason>\n```\nInclude: what was attempted, what failed, what might resolve it\n\n# CONSTRAINTS\n- MUST run `{{test_cmd}}` before reporting success\n- MUST NOT report SUCCESS if verification fails\n- MUST follow acceptance criteria exactly\n- MUST keep changes minimal and focused\n- MUST NOT modify unrelated files\n- MUST follow DRY, KISS, YAGNI principles\n- MUST prevent OWASP vulnerabilities\n- MUST match existing project conventions", 'enhance_intent.txt': "# ROLE\nIntent Enhancement Specialist\n\n# OBJECTIVE\nRefine and clarify the user's intent into a precise, actionable description.\n\n# INPUT\n<ORIGINAL_INTENT>\n{{original_intent}}\n</ORIGINAL_INTENT>\n\n# ENHANCEMENT TASKS\n1. Clarify ambiguities and resolve vague parts\n2. Add concrete details where too general\n3. Structure into clear, logical components\n4. Surface implicit but essential requirements\n5. Translate user language into technical requirements\n\n# CONSTRAINTS\n- PRESERVE core intent - do not change fundamental goals\n- DO NOT add features not mentioned or implied\n- KEEP concise and focused\n- AVOID over-engineering\n- MAINTAIN user's tone and terminology\n\n# OUTPUT FORMAT\n\n<ENHANCED_INTENT>\n[Enhanced, refined version that can be passed directly to architect phase]\n</ENHANCED_INTENT>\n\nOutput ONLY the enhanced intent within the tags. No explanations outside tags.", 'planner.txt': '# ROLE\nProduct Manager\n\n# OBJECTIVE\nCreate a PRD in JSON format following product management best practices.\n\n# CONTEXT\n<USER_INTENT>\n{{user_intent}}\n</USER_INTENT>\n\n# REQUIREMENTS\n\n## INVEST Criteria (ALL must be satisfied per story)\n- **I**ndependent: Self-contained, minimal dependencies\n- **N**egotiable: Details can evolve during implementation\n- **V**aluable: Delivers clear user/stakeholder value\n- **E**stimable: Clear enough for effort estimation\n- **S**mall: Completable in single iteration\n- **T**estable: Has verifiable completion conditions\n\n## MoSCoW Prioritization\n- **Must Have**: Critical for release viability\n- **Should Have**: Important but has workarounds\n- **Could Have**: Desirable if time permits\n- **Won\'t Have**: Explicitly out of scope for this release\n\n## Acceptance Criteria Requirements\nEach story MUST include criteria for:\n- Happy path (normal behavior)\n- Edge cases (boundaries, empty states, limits)\n- Error scenarios (invalid input, failures, denied access)\n\n## Risks\nDocument per story: technical (complexity, unfamiliar tech), dependency (external systems), scope (unclear requirements)\n\n# FALLBACK STRATEGIES\n\n## Conflicting Requirements\nDocument conflict explicitly in risks array with: "Scope Risk: Requirements conflict detected; stakeholder clarification recommended"\n\n## Large Scope\nBreak into INVEST-compliant stories, use MoSCoW to identify minimal viable subset, defer remainder as "Won\'t Have"\n\n## Required Fields\n| Field | Type | Description |\n|-------|------|-------------|\n| id | string | PRD-XXX format |\n| description | string | 1-2 sentence summary |\n| userStories | array | Min 1 story |\n| userStories[].id | string | TASK-XXX format (sequential) |\n| userStories[].description | string | "As a... I want... so that..." format |\n| userStories[].priority | string | MoSCoW value |\n| userStories[].acceptanceCriteria | array | Min 3, must include edge case + error scenario |\n| userStories[].definitionOfDone | array | Min 3 quality gates |\n| userStories[].dependencies | array | Task IDs or empty |\n| userStories[].status | string | Always "pending" |\n\n# CONSTRAINTS\n- Output ONLY valid JSON (no markdown, no text outside JSON)\n- All stories MUST satisfy INVEST criteria\n- All stories MUST use MoSCoW priority\n- All acceptance criteria MUST be testable\n- Status MUST be "pending"\n\n# OUTPUT\nRaw JSON only:\n{"id":"PRD-001","description":"...","userStories":[{"id":"TASK-001","description":"...","priority":"Must Have","acceptanceCriteria":[...],"definitionOfDone":[...],"dependencies":[],"status":"pending"}]}\n', 'revise_prd.txt': '# ROLE\nPRD Quality Reviewer\n\n# OBJECTIVE\nReview and improve the PRD for clarity, completeness, and quality while preserving original intent.\n\n# INPUT\n<ORIGINAL_PRD>\n{{original_prd}}\n</ORIGINAL_PRD>\n\n# REVIEW TASKS\n1. Ensure clear, unambiguous user story descriptions\n2. Verify acceptance criteria are specific, measurable, testable\n3. Identify missing edge cases or error handling\n4. Ensure consistent terminology and formatting\n5. Verify technical requirements are correct\n6. Fix any JSON structure/formatting issues\n\n# CONSTRAINTS\n- PRESERVE original intent and scope of each story\n- DO NOT add new stories or features not implied\n- DO NOT remove any user stories\n- KEEP same task IDs and structure\n- FIX JSON formatting issues if present\n\n# OUTPUT FORMAT\n\n<REVISED_PRD>\n{\n  "userStories": [...]\n}\n</REVISED_PRD>\n\n<REVISION_SUMMARY>\n[Brief summary. If no changes needed: "No revisions needed - PRD meets quality standards."]\n</REVISION_SUMMARY>\n\nIMPORTANT:\n- Output ONLY valid JSON within <REVISED_PRD> tags\n- If original has invalid JSON, attempt to repair it\n- If already optimal, output unchanged with summary note'}
static ensure_templates()[source]

Ensure template directory exists and default templates are created.

static load(template_name: str) str[source]

Load a template by name.

File-based templates take precedence over defaults. If a template file exists but is empty, the default template content is used. If the custom template directory is missing, falls back to defaults without error.

Parameters:

template_name – Name of the template file to load

Returns:

Template content as string

Raises:

FileNotFoundError – If template not found in files or defaults

static render(template_name: str, **variables) str[source]

Load and render a template with variable substitution.

Parameters:
  • template_name – Name of the template file to load

  • **variables – Key-value pairs to substitute in template

Returns:

Rendered template with variables substituted

class pyralph.HookManager(hooks_dir: Path, logger: Any = None)[source]

Bases: object

Discovers, loads, and executes hooks.

CONFIG_FILENAME = 'hooks.yaml'
enable() None[source]

Enable hook execution.

disable() None[source]

Disable hook execution.

set_enabled_hooks(hook_names: List[str] | None) None[source]

Set which hooks are enabled by name.

Parameters:

hook_names – List of hook names to enable, or None to enable all hooks.

property is_enabled: bool

Check if hooks are enabled.

is_hook_enabled(hook_name: str) bool[source]

Check if a specific hook is enabled.

Parameters:

hook_name – The name of the hook to check.

Returns:

True if the hook is enabled, False otherwise.

register_hook(name: str, handler: Callable[[Event], Event | None], events: List[str], priority: int = 100, timeout: float = 5.0, modifies_data: bool = False) bool[source]

Register a hook programmatically.

This allows plugins and external code to register hooks without creating files in the .ralph/hooks/ directory.

Parameters:
  • name – Unique identifier for this hook.

  • handler – Callable that receives an Event and optionally returns a modified Event.

  • events – List of event names to subscribe to (e.g., [“TASK_START”, “TASK_SUCCESS”]).

  • priority – Execution order (lower = earlier). Default: 100.

  • timeout – Maximum execution time in seconds. Default: 5.0.

  • modifies_data – If True, handler’s return value is used as modified event.

Returns:

True if hook was registered successfully, False otherwise.

Example

>>> def my_handler(event):
...     print(f"Task {event.task_id} started")
>>> manager.register_hook(
...     name="my_plugin",
...     handler=my_handler,
...     events=["TASK_START", "TASK_SUCCESS"]
... )
unregister_hook(name: str) bool[source]

Unregister a hook by name.

Removes a previously registered hook from all event subscriptions.

Parameters:

name – The name of the hook to unregister.

Returns:

True if a hook was unregistered, False if no hook with that name was found.

Example

>>> manager.unregister_hook("my_plugin")
clear_hooks() int[source]

Clear all registered hooks.

This removes all hooks (both programmatically registered and discovered). Useful for resetting state in tests or when reloading plugins.

Returns:

Number of unique hooks that were cleared.

Example

>>> count = manager.clear_hooks()
>>> print(f"Cleared {count} hooks")
discover() int[source]

Scan hooks directory and load all valid hooks.

Hooks are loaded from three sources: 1. Python module hooks (.py files in hooks directory) 2. Executable hooks (executable files with optional .yaml config) 3. Configuration file (hooks.yaml) for registering external scripts

Returns:

Number of hooks loaded.

emit(event: Event) Event[source]

Emit an event to all subscribed hooks.

Hooks are executed in priority order (lower = earlier). Hook errors are caught and logged but never halt execution. Hooks with modifies_data=True can transform the event data, with modifications chained through subsequent hooks.

Parameters:

event – The event to emit.

Returns:

The (potentially modified) event after all hooks have executed.

get_hooks_for_event(event_type: EventType) List[Hook][source]

Get all hooks registered for an event type.

get_all_hooks() List[Hook][source]

Get all registered hooks (deduplicated).

class pyralph.Event(event_type: ~pyralph.hooks.EventType, timestamp: str = <factory>, phase: str | None = None, task_id: str | None = None, task_description: str | None = None, retry_count: int | None = None, max_retries: int | None = None, error: ~typing.Any | None = None, verification_command: str | None = None, verification_exit_code: int | None = None, prd_path: str | None = None, issue_number: int | None = None, issue_title: str | None = None, issue_url: str | None = None, issues_count: int | None = None, metadata: ~typing.Dict[str, ~typing.Any] = <factory>)[source]

Bases: object

Immutable event payload passed to hooks.

event_type: EventType
timestamp: str
phase: str | None = None
task_id: str | None = None
task_description: str | None = None
retry_count: int | None = None
max_retries: int | None = None
error: Any | None = None
verification_command: str | None = None
verification_exit_code: int | None = None
prd_path: str | None = None
issue_number: int | None = None
issue_title: str | None = None
issue_url: str | None = None
issues_count: int | None = None
metadata: Dict[str, Any]
to_dict() Dict[str, Any][source]

Serialize event to dictionary for JSON export.

to_json() str[source]

Serialize event to JSON string.

class pyralph.EventType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

All lifecycle events that can be hooked.

PHASE_START = 1
PHASE_END = 2
ARCHITECT_START = 3
ARCHITECT_SUCCESS = 4
ARCHITECT_FAILURE = 5
PLANNER_START = 6
PLANNER_SUCCESS = 7
PLANNER_FAILURE = 8
EXECUTE_START = 9
EXECUTE_END = 10
TASK_START = 11
TASK_SUCCESS = 12
TASK_FAILURE = 13
TASK_RETRY = 14
VERIFICATION_START = 15
VERIFICATION_SUCCESS = 16
VERIFICATION_FAILURE = 17
INTENT_ENHANCE_START = 18
INTENT_ENHANCE_SUCCESS = 19
INTENT_ENHANCE_FAILURE = 20
PRD_CREATED = 21
PRD_ARCHIVED = 22
PRD_REVISE_START = 23
PRD_REVISE_SUCCESS = 24
PRD_REVISE_FAILURE = 25
PRD_COMPLETE = 26
PRD_INCOMPLETE = 27
ERROR = 28
WATCHER_START = 29
WATCHER_STOP = 30
ISSUE_DETECTED = 31
ISSUE_STORED = 32
ISSUE_QUEUED = 33
ISSUE_PROCESSING_START = 34
ISSUE_PROCESSING_SUCCESS = 35
ISSUE_PROCESSING_FAILURE = 36
POLL_START = 37
POLL_SUCCESS = 38
POLL_ERROR = 39
class pyralph.Hook(name: str, events: Set[EventType], priority: int = 100, timeout: float = 5.0, modifies_data: bool = False)[source]

Bases: ABC

Abstract base class for all hook types.

abstract execute(event: Event) Event | None[source]

Execute the hook with the given event.

Parameters:

event – The event to process.

Returns:

If modifies_data is True, returns a modified Event or None to keep original. If modifies_data is False, return value is ignored.

class pyralph.PythonHook(path: Path, module: Any)[source]

Bases: Hook

Hook loaded from a Python module.

execute(event: Event) Event | None[source]

Execute the Python hook handler.

Returns:

Modified Event if modifies_data is True and handler returns an Event, None otherwise.

class pyralph.ExecutableHook(path: Path, events: Set[EventType], priority: int = 100, timeout: float = 5.0, modifies_data: bool = False)[source]

Bases: Hook

Hook that runs an external executable.

execute(event: Event) Event | None[source]

Execute the external hook, passing event JSON via stdin.

If modifies_data is True, the hook’s stdout is parsed as JSON to create a modified Event.

Returns:

Modified Event if modifies_data is True and valid JSON is returned, None otherwise.

class pyralph.FunctionHook(name: str, handler: Callable[[Event], Event | None], events: Set[EventType], priority: int = 100, timeout: float = 5.0, modifies_data: bool = False)[source]

Bases: Hook

Hook backed by a Python callable for programmatic registration.

execute(event: Event) Event | None[source]

Execute the callable handler.

Returns:

Modified Event if modifies_data is True and handler returns an Event, None otherwise.

class pyralph.BaseAgent(timeout_seconds: int = 600, model: str | None = None, max_tokens: int | None = None, temperature: float | None = None, seed: int | None = None)[source]

Bases: ABC

set_logger(logger: Any) None[source]

Set the logger instance for this agent.

set_config(config: Any) None[source]

Set the config instance for this agent.

abstract check_dependencies() bool[source]
abstract get_name() str[source]
run(prompt: str, tag: str) Tuple[bool, str, AgentError | None][source]
class pyralph.AgentError(exception_type: str, message: str, stack_trace: str, timestamp: str, agent_name: str, task_id: str)[source]

Bases: object

exception_type: str
message: str
stack_trace: str
timestamp: str
agent_name: str
task_id: str
format_log_entry() str[source]
classmethod from_exception(exc: Exception, agent_name: str, task_id: str) AgentError[source]
pyralph.get_agent(agent_name: str, **kwargs) BaseAgent[source]
pyralph.list_agents() List[str][source]

Get a list of available agent names.

Returns:

List of available agent names

Orchestrator

The core execution logic for the Ralph autonomous development agent.

RalphOrchestrator - Core execution logic for Ralph autonomous development agent.

NOTE: This module is the documented exception to the ~500 line target (TASK-015). As the core orchestrator containing the main RalphOrchestrator class with all CLI flag handling and execution logic, it is expected to be the largest module in the codebase.

class pyralph.orchestrator.RalphOrchestrator(agent_name: str = 'claude', enable_hooks: bool = True, enabled_hook_names: List[str] | None = None, intent: str | None = None, intent_file: str | None = None, prompt_file: str | None = None, enhance_intent: bool = False, enhance_intent_strict: bool = False, tree_depth: int = 2, tree_ignore: List[str] | None = None, test_cmd: str | None = None, skip_verify: bool = False, retries: int | None = None, timeout: int | None = None, only: List[str] | None = None, except_tasks: List[str] | None = None, resume: str | None = None, include: List[str] | None = None, exclude: List[str] | None = None, context_limit: int | None = None, model: str | None = None, temperature: float | None = None, max_tokens: int | None = None, seed: int | None = None, log_file: str | None = None, log_level: str | None = None, json_output: bool = False, ndjson_output: bool = False, print_prd: bool = False, prd_out: str | None = None, archive: bool = True, non_interactive: bool = False, ci: bool = False, status_check: bool = False, pre: List[str] | None = None, post: List[str] | None = None, plugin: List[str] | None = None, schema: str | None = None, min_criteria: int | None = None, label: List[str] | None = None, revise_prd: bool = False)[source]

Bases: object

run_architect(user_intent: str) None[source]

Run the architect phase to generate architecture documentation.

Generates ARCHITECTURE.md and ARCH.md with project structure, tech stack, and test command configuration.

Parameters:

user_intent – Description of what the user wants to build

run_planner(user_intent: str) None[source]

Run the planner phase to create a Product Requirements Document.

Generates a PRD with user stories and acceptance criteria, saved to .ralph/prd.json.

Respects the following flags: - –schema: Validate PRD against a JSON schema file - –min-criteria: Ensure each story has at least N acceptance criteria - –label: Add custom labels to the PRD - –revise-prd: Pass PRD through revision agent before saving

Parameters:

user_intent – Description of what the user wants to build

execute_loop() None[source]

Execute all pending tasks from the PRD.

Iterates through user stories, executing each pending task with verification. Continues to next task on failure instead of terminating. Archives the PRD upon completion.

Respects the following flags: - –test-cmd: Override the test command - –skip-verify: Skip verification step after task execution - –retries: Override max retry count - –only: Execute only specified task IDs - –except: Skip specified task IDs - –resume: Resume execution from a specific task ID - –pre: Run pre-commands before phase execution - –post: Run post-commands after phase completion

start(phase: str = 'all', accept_all: bool = False) None[source]

Start the Ralph orchestrator.

Parameters:
  • phase – Which phase to run (“architect”, “planner”, “execute”, or “all”)

  • accept_all – If True, skip user confirmation prompts

Respects the following flags: - –print-prd: Print PRD contents and exit without executing - –prd-out: Export PRD to specified file and continue - –status-check: Check PRD status and exit with appropriate code

Configuration

Configuration management for Ralph.

Configuration module for Ralph.

This module contains the Config dataclass and CONF singleton that define all path and limit configurations for the Ralph CLI tool.

class pyralph.config.Config(BASE_DIR: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs'), ROOT_DIR: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph'), ARCHIVE_DIR: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/archive'), TEMPLATES_DIR: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/templates'), HOOKS_DIR: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/hooks'), PRD_FILE: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/prd.json'), PROGRESS_FILE: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/progress.txt'), LOG_FILE: pathlib.Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/ralph_log.txt'), MAX_RETRIES: int = 3, TIMEOUT_SECONDS: int = 600)[source]

Bases: object

BASE_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs')
ROOT_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph')
ARCHIVE_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/archive')
TEMPLATES_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/templates')
HOOKS_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/hooks')
PRD_FILE: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/prd.json')
PROGRESS_FILE: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/progress.txt')
LOG_FILE: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/pyralph/checkouts/latest/docs/.ralph/ralph_log.txt')
MAX_RETRIES: int = 3
TIMEOUT_SECONDS: int = 600
ensure_directories() None[source]

CLI

Command-line interface for Ralph.

CLI module for Ralph.

This module contains the CLI entry point (main) and version functions that handle command-line argument parsing and application startup.

pyralph.cli.get_version() str[source]

Get the version string from package metadata.

Returns:

Version string from package metadata, or ‘unknown’ if not found.

pyralph.cli.main() None[source]

Entry point for the ralph CLI.

Logger

Logging utilities.

Logger module for Ralph.

This module contains the Logger class and _LoggerMeta metaclass that provide centralized logging infrastructure for the Ralph CLI tool.

class pyralph.logger.Logger[source]

Bases: object

COLORS = {'CYAN': '\x1b[96m', 'GREEN': '\x1b[92m', 'MAGENTA': '\x1b[95m', 'RED': '\x1b[91m', 'RESET': '\x1b[0m', 'YELLOW': '\x1b[93m'}
no_color = False
quiet = False
no_emoji = False
LOG_LEVELS = {'debug': 10, 'error': 40, 'info': 20, 'warn': 30}
log_level = 20
json_output = False
ndjson_output = False
custom_log_file: Path | None = None
non_interactive = False
redact_patterns: List[str] = []
no_log_prompts = False
no_log_responses = False
static set_no_color(enabled: bool) None[source]
static set_verbose(enabled: bool) None[source]

Set verbose mode (backwards compatible, sets verbosity to 1 or 0).

This method is provided for backwards compatibility. The verbose and verbosity attributes are automatically synchronized via descriptors.

static set_verbosity(level: int) None[source]

Set verbosity level (0=normal, 1=verbose, 2=very verbose, 3=debug).

When verbosity >= 1, log_level is automatically set to debug to allow debug/trace/ultra messages to appear. This maintains backwards compatibility with existing -v/-vv/-vvv behavior.

The verbose and verbosity attributes are automatically synchronized via descriptors, so setting verbosity will update verbose accordingly.

static set_quiet(enabled: bool) None[source]

Set quiet mode (suppresses all non-error output).

static set_no_emoji(enabled: bool) None[source]

Set no-emoji mode (replaces emojis with text equivalents).

static set_log_level(level: str) None[source]

Set log level (debug, info, warn, error).

static set_json_output(enabled: bool) None[source]

Enable JSON output format.

static set_ndjson_output(enabled: bool) None[source]

Enable newline-delimited JSON output format.

static set_log_file(path: str | None) None[source]

Set custom log file path.

static set_non_interactive(enabled: bool) None[source]

Set non-interactive mode (disables all interactive prompts).

static set_redact_patterns(patterns: List[str]) None[source]

Set patterns to redact from logs.

Parameters:

patterns – List of regex patterns to redact from log output

static add_redact_patterns_from_file(file_path: str) None[source]

Load redaction patterns from a file (one pattern per line).

Parameters:

file_path – Path to file containing patterns (one per line)

static set_no_log_prompts(enabled: bool) None[source]

Disable logging of prompts to log file.

Parameters:

enabled – If True, prompts will not be written to logs

static set_no_log_responses(enabled: bool) None[source]

Disable logging of responses to log file.

Parameters:

enabled – If True, responses will not be written to logs

static get_log_file() Path[source]

Get the effective log file path (custom or default).

static info(msg: str, color: str = 'RESET') None[source]

Print info message (suppressed in quiet mode or if log level > info).

static debug(msg: str, color: str = 'RESET') None[source]

Print debug message (requires verbosity >= 1 and log level <= debug).

static trace(msg: str, color: str = 'RESET') None[source]

Print trace message (requires verbosity >= 2 and log level <= debug).

static ultra(msg: str, color: str = 'RESET') None[source]

Print ultra-verbose message (requires verbosity >= 3 and log level <= debug).

static warning(msg: str) None[source]

Print warning message (shown even in quiet mode, respects log level).

static error(msg: str) None[source]

Print error message (always shown, respects log level).

static file_log(content: str, type: str, tag: str = 'UNKNOWN') None[source]

Append a timestamped entry to the persistent log file.

Respects the following privacy flags: - –no-log-prompts: Skip logging when type is PROMPT - –no-log-responses: Skip logging when type is RESPONSE - –redact / –redact-file: Apply redaction patterns to content

Shell

Shell command execution utilities.

Shell module for Ralph.

This module contains the Shell class that provides subprocess execution functionality for the Ralph CLI tool.

class pyralph.shell.Shell[source]

Bases: object

Safe wrapper for subprocess calls.

static run(command: str, timeout: int = 30) Tuple[str, str, int][source]

Execute a shell command and capture its output.

Parameters:
  • command – The shell command to execute

  • timeout – Maximum seconds to wait for command completion

Returns:

Tuple of (stdout, stderr, return_code)

Security Note:

This method uses shell=True which enables shell features (pipes, wildcards, variable expansion) but introduces command injection risks if command contains unsanitized user input.

Safe usage (internal/trusted sources):
  • Hardcoded commands (e.g., “pytest”, “tree -L 2”)

  • Commands from configuration files controlled by the user

  • Agent-generated commands (trusted AI output)

Unsafe usage (AVOID):
  • Commands built from external/untrusted input

  • Commands containing unvalidated user data

This is acceptable here because:
  1. Commands originate from trusted sources (config, agents)

  2. The tool runs locally with user’s own permissions

  3. Shell features (pipes, globs) are required for functionality

DEFAULT_TREE_IGNORE = ['node_modules', 'venv', '.git', '.ralph', '__pycache__']
static get_file_tree(depth: int = 2, ignore: List[str] | None = None) str[source]

Generate a file tree representation of the project directory.

Parameters:
  • depth – Maximum directory depth to traverse (default: 2)

  • ignore – List of directory/file patterns to exclude (default: node_modules, venv, .git, .ralph, __pycache__)

Returns:

String representation of the directory tree

PRD Manager

Product Requirements Document management.

PRD module for Ralph.

This module contains the PRDManager class for PRD file operations with caching and CRUD capabilities, and the JsonUtils class for robust JSON parsing of LLM outputs.

class pyralph.prd.PRDManager(prd_path: Path)[source]

Bases: object

Consolidated manager for PRD file operations.

Provides caching to avoid repeated disk reads and centralizes all PRD read/write operations in one place.

exists() bool[source]

Check if PRD file exists on disk.

invalidate_cache() None[source]

Clear cached PRD data, forcing next read from disk.

read_raw() str[source]

Read raw PRD content as string.

Returns:

Raw JSON string from PRD file

Raises:

FileNotFoundError – If PRD file does not exist

load() Dict[str, Any][source]

Load and parse PRD from disk with caching.

Returns:

Parsed PRD data as dictionary

Raises:
  • FileNotFoundError – If PRD file does not exist

  • json.JSONDecodeError – If PRD contains invalid JSON

save(data: Dict[str, Any]) None[source]

Save PRD data to disk and update cache.

Parameters:

data – PRD data to write

delete() None[source]

Delete PRD file from disk and clear cache.

class pyralph.prd.JsonUtils[source]

Bases: object

Robust JSON parsing for LLM outputs.

static parse(text: str) Dict[str, Any][source]

Parse JSON from LLM output, handling markdown fences and comments.

Parameters:

text – Raw text potentially containing JSON with markdown fences

Returns:

Parsed JSON as a dictionary

Raises:

json.JSONDecodeError – If the text cannot be parsed as valid JSON

Templates

Template management for prompts.

Templates module for Ralph.

This module contains the PromptFormatter and TemplateManager classes that provide prompt generation and template loading functionality.

class pyralph.templates.PromptFormatter[source]

Bases: object

Utility class for consistent prompt formatting with delimiters.

DELIMITERS: Dict[str, Tuple[str, str]] = {'acceptance_criteria': ('ACCEPTANCE_CRITERIA', 'Task acceptance criteria'), 'file_tree': ('FILE_TREE', 'Project directory structure'), 'prev_errors': ('PREV_ERRORS', 'Previous error messages'), 'task_description': ('TASK_DESC', 'Task description'), 'task_id': ('TASK_ID', 'Task identifier'), 'test_cmd': ('TEST_CMD', 'Verification command'), 'user_context': ('USER_CONTEXT', 'User preferences and instructions'), 'user_intent': ('USER_INTENT', 'User-provided intent/goal')}
static wrap(content: str, delimiter_key: str) str[source]

Wrap content in XML-style delimiters for clear boundaries.

static format_list(items: list, prefix: str = '- ') str[source]

Format a list with consistent prefix.

static format_code_block(content: str, language: str = '') str[source]

Format content as a fenced code block.

class pyralph.templates.TemplateManager[source]

Bases: object

DEFAULT_TEMPLATES = {'architect.txt': '# ROLE\nSenior Software Architect\n\n# OBJECTIVE\nAnalyze project structure and create architecture documentation.\n\n# CONTEXT\n<USER_INTENT>\n{{user_intent}}\n</USER_INTENT>\n\n<FILE_TREE>\n{{file_tree}}\n</FILE_TREE>\n\n# ANALYSIS REQUIREMENTS\n\nAnalyze and document the following aspects:\n\n1. **SOLID Principles**: Evaluate Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion adherence.\n\n2. **Architectural Patterns**: Identify patterns (MVC, Layered, Microservices, Event-Driven, Repository, Clean Architecture, Hexagonal).\n\n3. **Security**: Document authentication, input validation, secrets management, and potential vulnerabilities.\n\n4. **Error Handling**: Document error strategies, logging framework, and log levels.\n\n5. **API Boundaries**: Identify external/internal APIs, data formats, and protocols.\n\n# FALLBACK BEHAVIOR\n\nWhen information cannot be determined from the file tree:\n- Use file extensions to infer languages\n- Check config files (package.json, pyproject.toml, etc.)\n- For unknown items, use: `[Unable to determine]`\n- For test commands: `[Unable to determine - manual verification required]`\n\n# CONSTRAINTS\n# Create ARCHITECTURE.md in project root\n- Use exact YAML frontmatter format below\n- Include ALL required sections\n- Detect actual test command (pytest, npm test, etc.)\n- Do NOT invent technologies not evident in file tree\n- Keep descriptions concise and factual\n\n# OUTPUT SPECIFICATION\n\n## File 1: ARCHITECTURE.md\n\n```markdown\n---\ntype: wiki\ntitle: Architecture\n---\n\n# Architecture\n\n## Tech Stack\n- **Language**: [detected language and version]\n- **Testing**: [detected test framework]\n- **Build**: [detected build tool]\n- [additional relevant technologies]\n\n## Overview\n[2-3 sentence description of project purpose and architecture]\n\n## Architectural Patterns\n- **Primary Pattern**: [main architectural pattern]\n- **Supporting Patterns**: [additional patterns used]\n\n## Key Components\n| Component | Description |\n|-----------|-------------|\n| [path/file] | [brief description] |\n[list 3-6 key components]\n\n## SOLID Principles Assessment\n| Principle | Status | Notes |\n|-----------|--------|-------|\n| Single Responsibility | [Good/Needs Work] | [brief observation] |\n| Open/Closed | [Good/Needs Work] | [brief observation] |\n| Liskov Substitution | [Good/N/A] | [brief observation] |\n| Interface Segregation | [Good/Needs Work] | [brief observation] |\n| Dependency Inversion | [Good/Needs Work] | [brief observation] |\n\n## API Boundaries & Integration Points\n- **External Integrations**: [list external APIs/services]\n- **Internal Interfaces**: [key module boundaries]\n- **Data Formats**: [JSON, XML, etc.]\n- **Protocols**: [REST, GraphQL, gRPC, etc.]\n\n## Error Handling & Logging\n- **Error Strategy**: [how errors are handled]\n- **Logging Approach**: [logging framework and patterns]\n- **Log Levels**: [how levels are used]\n\n## Security Considerations\n- **Authentication**: [method used or N/A]\n- **Input Validation**: [where/how validated]\n- **Secrets Management**: [how secrets are handled]\n- **Potential Concerns**: [any security gaps identified]\n\n## Test Command\nTest Command: `[actual test command]`\n```\n\n## File 2: ARCH.md (Project Root)\nCreate a copy of the architecture documentation in the project root for git tracking.\n\n# RESPONSE FORMAT\nAfter creating the file, output EXACTLY:\n```\nSTATUS: CREATED ARCHITECTURE.md\n```\n', 'developer.txt': "# ROLE\nDeveloper\n\n# OBJECTIVE\nImplement assigned task per acceptance criteria while following software engineering best practices.\n\n# TASK CONTEXT\n\n<TASK_ID>{{task_id}}</TASK_ID>\n<TASK_DESC>{{task_description}}</TASK_DESC>\n<ACCEPTANCE_CRITERIA>{{acceptance_criteria}}</ACCEPTANCE_CRITERIA>\n\n# MANDATORY INSTRUCTIONS\n<USER_CONTEXT>{{user_context}}</USER_CONTEXT>\n\n# AVAILABLE CONTEXT\n<PREV_ERRORS>{{prev_errors}}</PREV_ERRORS>\n\n# CODE QUALITY PRINCIPLES\n\n## DRY, KISS, YAGNI\n- **DRY**: Extract repeated code into reusable functions; centralize config/constants\n- **KISS**: Prefer straightforward solutions; use standard patterns; break complex logic into well-named functions\n- **YAGNI**: Only implement what's required; remove unused code; no speculative features\n\n## Security (OWASP Top 10)\n- **Injection**: Use parameterized queries; never concatenate user input into SQL/commands\n- **XSS**: Escape user data before rendering; use auto-escaping templates\n- **Auth**: Hash passwords (bcrypt/Argon2); secure session cookies; rate limit\n- **Data**: Never log secrets/PII; use env vars for secrets; encrypt in transit/at rest\n- **Config**: Disable debug in production; remove defaults; keep deps updated\n\n## Error Handling\n- Catch specific exceptions, not generic Exception\n- Log with context (operation, IDs) at appropriate levels (DEBUG/INFO/WARNING/ERROR)\n- Preserve exception chains; provide meaningful user messages\n- Use context managers for resource cleanup\n\n## Project Conventions\nBefore coding, analyze codebase to detect and follow:\n- Naming conventions (snake_case, camelCase, PascalCase)\n- Import organization (stdlib, third-party, local)\n- Existing architectural patterns and utilities\n- Test file naming and assertion patterns\n\n## Self-Documenting Code\n- Use intention-revealing names; verbs for functions, nouns for classes/variables\n- Keep functions short (single responsibility); limit to 3-4 parameters\n- Return early to avoid nesting; extract complex conditionals to named variables\n\n# EXECUTION WORKFLOW\n\n## Phase 1: Planning\n1. Analyze acceptance criteria and scope boundaries\n2. Review existing code for conventions and patterns\n3. Identify files to modify; consider edge cases and security implications\n\n## Phase 2: Implementation\n1. Read all code before modifying; match existing patterns\n2. Make minimal, focused changes (YAGNI)\n3. Write self-documenting code with proper error handling\n\n## Phase 3: Verification\n1. Run: `{{test_cmd}}`\n2. If tests fail, analyze errors, fix, and re-run\n3. Only proceed when all tests pass\n\n# FALLBACK STRATEGIES\n\n## Cannot Find Code\nBroaden search terms; trace imports; check tests for implementation; document attempts\n\n## Unfamiliar Patterns\nLook for similar code elsewhere; examine tests for behavior; match existing pattern for consistency\n\n## Tests Fail\n1. Read FULL error message\n2. Check if regression or new failure\n3. Fix incrementally; verify imports/signatures\n4. If same error twice, try different approach\n\n## Conflicting Requirements\nRe-read carefully; prioritize criteria over existing tests; document conflicts\n\n# ERROR CORRECTION\n\nIf tests fail:\n1. Read error carefully; identify root cause\n2. Fix specific issue only\n3. Re-run verification\n\nSelf-correction rules:\n- Same error twice try different approach\n- 3+ failures re-analyze requirements\n- Do NOT modify test files unless explicitly required\n- Do NOT skip/disable failing tests\n\n# OUTPUT SPECIFICATION\n\n## On Success\n```\nSTATUS: SUCCESS\n```\n\n## On Failure\n```\nSTATUS: FAILURE - <specific reason>\n```\nInclude: what was attempted, what failed, what might resolve it\n\n# CONSTRAINTS\n- MUST run `{{test_cmd}}` before reporting success\n- MUST NOT report SUCCESS if verification fails\n- MUST follow acceptance criteria exactly\n- MUST keep changes minimal and focused\n- MUST NOT modify unrelated files\n- MUST follow DRY, KISS, YAGNI principles\n- MUST prevent OWASP vulnerabilities\n- MUST match existing project conventions", 'enhance_intent.txt': "# ROLE\nIntent Enhancement Specialist\n\n# OBJECTIVE\nRefine and clarify the user's intent into a precise, actionable description.\n\n# INPUT\n<ORIGINAL_INTENT>\n{{original_intent}}\n</ORIGINAL_INTENT>\n\n# ENHANCEMENT TASKS\n1. Clarify ambiguities and resolve vague parts\n2. Add concrete details where too general\n3. Structure into clear, logical components\n4. Surface implicit but essential requirements\n5. Translate user language into technical requirements\n\n# CONSTRAINTS\n- PRESERVE core intent - do not change fundamental goals\n- DO NOT add features not mentioned or implied\n- KEEP concise and focused\n- AVOID over-engineering\n- MAINTAIN user's tone and terminology\n\n# OUTPUT FORMAT\n\n<ENHANCED_INTENT>\n[Enhanced, refined version that can be passed directly to architect phase]\n</ENHANCED_INTENT>\n\nOutput ONLY the enhanced intent within the tags. No explanations outside tags.", 'planner.txt': '# ROLE\nProduct Manager\n\n# OBJECTIVE\nCreate a PRD in JSON format following product management best practices.\n\n# CONTEXT\n<USER_INTENT>\n{{user_intent}}\n</USER_INTENT>\n\n# REQUIREMENTS\n\n## INVEST Criteria (ALL must be satisfied per story)\n- **I**ndependent: Self-contained, minimal dependencies\n- **N**egotiable: Details can evolve during implementation\n- **V**aluable: Delivers clear user/stakeholder value\n- **E**stimable: Clear enough for effort estimation\n- **S**mall: Completable in single iteration\n- **T**estable: Has verifiable completion conditions\n\n## MoSCoW Prioritization\n- **Must Have**: Critical for release viability\n- **Should Have**: Important but has workarounds\n- **Could Have**: Desirable if time permits\n- **Won\'t Have**: Explicitly out of scope for this release\n\n## Acceptance Criteria Requirements\nEach story MUST include criteria for:\n- Happy path (normal behavior)\n- Edge cases (boundaries, empty states, limits)\n- Error scenarios (invalid input, failures, denied access)\n\n## Risks\nDocument per story: technical (complexity, unfamiliar tech), dependency (external systems), scope (unclear requirements)\n\n# FALLBACK STRATEGIES\n\n## Conflicting Requirements\nDocument conflict explicitly in risks array with: "Scope Risk: Requirements conflict detected; stakeholder clarification recommended"\n\n## Large Scope\nBreak into INVEST-compliant stories, use MoSCoW to identify minimal viable subset, defer remainder as "Won\'t Have"\n\n## Required Fields\n| Field | Type | Description |\n|-------|------|-------------|\n| id | string | PRD-XXX format |\n| description | string | 1-2 sentence summary |\n| userStories | array | Min 1 story |\n| userStories[].id | string | TASK-XXX format (sequential) |\n| userStories[].description | string | "As a... I want... so that..." format |\n| userStories[].priority | string | MoSCoW value |\n| userStories[].acceptanceCriteria | array | Min 3, must include edge case + error scenario |\n| userStories[].definitionOfDone | array | Min 3 quality gates |\n| userStories[].dependencies | array | Task IDs or empty |\n| userStories[].status | string | Always "pending" |\n\n# CONSTRAINTS\n- Output ONLY valid JSON (no markdown, no text outside JSON)\n- All stories MUST satisfy INVEST criteria\n- All stories MUST use MoSCoW priority\n- All acceptance criteria MUST be testable\n- Status MUST be "pending"\n\n# OUTPUT\nRaw JSON only:\n{"id":"PRD-001","description":"...","userStories":[{"id":"TASK-001","description":"...","priority":"Must Have","acceptanceCriteria":[...],"definitionOfDone":[...],"dependencies":[],"status":"pending"}]}\n', 'revise_prd.txt': '# ROLE\nPRD Quality Reviewer\n\n# OBJECTIVE\nReview and improve the PRD for clarity, completeness, and quality while preserving original intent.\n\n# INPUT\n<ORIGINAL_PRD>\n{{original_prd}}\n</ORIGINAL_PRD>\n\n# REVIEW TASKS\n1. Ensure clear, unambiguous user story descriptions\n2. Verify acceptance criteria are specific, measurable, testable\n3. Identify missing edge cases or error handling\n4. Ensure consistent terminology and formatting\n5. Verify technical requirements are correct\n6. Fix any JSON structure/formatting issues\n\n# CONSTRAINTS\n- PRESERVE original intent and scope of each story\n- DO NOT add new stories or features not implied\n- DO NOT remove any user stories\n- KEEP same task IDs and structure\n- FIX JSON formatting issues if present\n\n# OUTPUT FORMAT\n\n<REVISED_PRD>\n{\n  "userStories": [...]\n}\n</REVISED_PRD>\n\n<REVISION_SUMMARY>\n[Brief summary. If no changes needed: "No revisions needed - PRD meets quality standards."]\n</REVISION_SUMMARY>\n\nIMPORTANT:\n- Output ONLY valid JSON within <REVISED_PRD> tags\n- If original has invalid JSON, attempt to repair it\n- If already optimal, output unchanged with summary note'}
static ensure_templates()[source]

Ensure template directory exists and default templates are created.

static load(template_name: str) str[source]

Load a template by name.

File-based templates take precedence over defaults. If a template file exists but is empty, the default template content is used. If the custom template directory is missing, falls back to defaults without error.

Parameters:

template_name – Name of the template file to load

Returns:

Template content as string

Raises:

FileNotFoundError – If template not found in files or defaults

static render(template_name: str, **variables) str[source]

Load and render a template with variable substitution.

Parameters:
  • template_name – Name of the template file to load

  • **variables – Key-value pairs to substitute in template

Returns:

Rendered template with variables substituted

Hooks

Event hooks for extensibility.

Hook/Event system for Ralph lifecycle events.

This module provides a mechanism for external programs to subscribe to Ralph’s lifecycle events (phase start/end, task execution, verification, etc.).

TECHNICAL DEBT (TASK-015): This module exceeds the ~500 line target at ~2100 lines. Consider future decomposition into separate modules for: - Hook registration and discovery - Event execution and dispatch - Built-in hook implementations

Usage:
  1. Create Python hooks in .ralph/hooks/*.py with: - EVENTS = [“TASK_SUCCESS”, “TASK_FAILURE”] # Required - PRIORITY = 100 # Optional, lower = earlier - def on_event(event): … # Required handler

  2. Or create executable hooks that receive JSON via stdin

Example hook (.ralph/hooks/notify.py):

EVENTS = [“TASK_SUCCESS”, “TASK_FAILURE”]

def on_event(event):

print(f”Task {event.task_id}: {event.event_type.name}”)

class pyralph.hooks.EventType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

All lifecycle events that can be hooked.

PHASE_START = 1
PHASE_END = 2
ARCHITECT_START = 3
ARCHITECT_SUCCESS = 4
ARCHITECT_FAILURE = 5
PLANNER_START = 6
PLANNER_SUCCESS = 7
PLANNER_FAILURE = 8
EXECUTE_START = 9
EXECUTE_END = 10
TASK_START = 11
TASK_SUCCESS = 12
TASK_FAILURE = 13
TASK_RETRY = 14
VERIFICATION_START = 15
VERIFICATION_SUCCESS = 16
VERIFICATION_FAILURE = 17
INTENT_ENHANCE_START = 18
INTENT_ENHANCE_SUCCESS = 19
INTENT_ENHANCE_FAILURE = 20
PRD_CREATED = 21
PRD_ARCHIVED = 22
PRD_REVISE_START = 23
PRD_REVISE_SUCCESS = 24
PRD_REVISE_FAILURE = 25
PRD_COMPLETE = 26
PRD_INCOMPLETE = 27
ERROR = 28
WATCHER_START = 29
WATCHER_STOP = 30
ISSUE_DETECTED = 31
ISSUE_STORED = 32
ISSUE_QUEUED = 33
ISSUE_PROCESSING_START = 34
ISSUE_PROCESSING_SUCCESS = 35
ISSUE_PROCESSING_FAILURE = 36
POLL_START = 37
POLL_SUCCESS = 38
POLL_ERROR = 39
class pyralph.hooks.Event(event_type: ~pyralph.hooks.EventType, timestamp: str = <factory>, phase: str | None = None, task_id: str | None = None, task_description: str | None = None, retry_count: int | None = None, max_retries: int | None = None, error: ~typing.Any | None = None, verification_command: str | None = None, verification_exit_code: int | None = None, prd_path: str | None = None, issue_number: int | None = None, issue_title: str | None = None, issue_url: str | None = None, issues_count: int | None = None, metadata: ~typing.Dict[str, ~typing.Any] = <factory>)[source]

Bases: object

Immutable event payload passed to hooks.

event_type: EventType
timestamp: str
phase: str | None = None
task_id: str | None = None
task_description: str | None = None
retry_count: int | None = None
max_retries: int | None = None
error: Any | None = None
verification_command: str | None = None
verification_exit_code: int | None = None
prd_path: str | None = None
issue_number: int | None = None
issue_title: str | None = None
issue_url: str | None = None
issues_count: int | None = None
metadata: Dict[str, Any]
to_dict() Dict[str, Any][source]

Serialize event to dictionary for JSON export.

to_json() str[source]

Serialize event to JSON string.

class pyralph.hooks.Hook(name: str, events: Set[EventType], priority: int = 100, timeout: float = 5.0, modifies_data: bool = False)[source]

Bases: ABC

Abstract base class for all hook types.

abstract execute(event: Event) Event | None[source]

Execute the hook with the given event.

Parameters:

event – The event to process.

Returns:

If modifies_data is True, returns a modified Event or None to keep original. If modifies_data is False, return value is ignored.

class pyralph.hooks.PythonHook(path: Path, module: Any)[source]

Bases: Hook

Hook loaded from a Python module.

execute(event: Event) Event | None[source]

Execute the Python hook handler.

Returns:

Modified Event if modifies_data is True and handler returns an Event, None otherwise.

class pyralph.hooks.ExecutableHook(path: Path, events: Set[EventType], priority: int = 100, timeout: float = 5.0, modifies_data: bool = False)[source]

Bases: Hook

Hook that runs an external executable.

execute(event: Event) Event | None[source]

Execute the external hook, passing event JSON via stdin.

If modifies_data is True, the hook’s stdout is parsed as JSON to create a modified Event.

Returns:

Modified Event if modifies_data is True and valid JSON is returned, None otherwise.

class pyralph.hooks.FunctionHook(name: str, handler: Callable[[Event], Event | None], events: Set[EventType], priority: int = 100, timeout: float = 5.0, modifies_data: bool = False)[source]

Bases: Hook

Hook backed by a Python callable for programmatic registration.

execute(event: Event) Event | None[source]

Execute the callable handler.

Returns:

Modified Event if modifies_data is True and handler returns an Event, None otherwise.

class pyralph.hooks.HookManager(hooks_dir: Path, logger: Any = None)[source]

Bases: object

Discovers, loads, and executes hooks.

CONFIG_FILENAME = 'hooks.yaml'
enable() None[source]

Enable hook execution.

disable() None[source]

Disable hook execution.

set_enabled_hooks(hook_names: List[str] | None) None[source]

Set which hooks are enabled by name.

Parameters:

hook_names – List of hook names to enable, or None to enable all hooks.

property is_enabled: bool

Check if hooks are enabled.

is_hook_enabled(hook_name: str) bool[source]

Check if a specific hook is enabled.

Parameters:

hook_name – The name of the hook to check.

Returns:

True if the hook is enabled, False otherwise.

register_hook(name: str, handler: Callable[[Event], Event | None], events: List[str], priority: int = 100, timeout: float = 5.0, modifies_data: bool = False) bool[source]

Register a hook programmatically.

This allows plugins and external code to register hooks without creating files in the .ralph/hooks/ directory.

Parameters:
  • name – Unique identifier for this hook.

  • handler – Callable that receives an Event and optionally returns a modified Event.

  • events – List of event names to subscribe to (e.g., [“TASK_START”, “TASK_SUCCESS”]).

  • priority – Execution order (lower = earlier). Default: 100.

  • timeout – Maximum execution time in seconds. Default: 5.0.

  • modifies_data – If True, handler’s return value is used as modified event.

Returns:

True if hook was registered successfully, False otherwise.

Example

>>> def my_handler(event):
...     print(f"Task {event.task_id} started")
>>> manager.register_hook(
...     name="my_plugin",
...     handler=my_handler,
...     events=["TASK_START", "TASK_SUCCESS"]
... )
unregister_hook(name: str) bool[source]

Unregister a hook by name.

Removes a previously registered hook from all event subscriptions.

Parameters:

name – The name of the hook to unregister.

Returns:

True if a hook was unregistered, False if no hook with that name was found.

Example

>>> manager.unregister_hook("my_plugin")
clear_hooks() int[source]

Clear all registered hooks.

This removes all hooks (both programmatically registered and discovered). Useful for resetting state in tests or when reloading plugins.

Returns:

Number of unique hooks that were cleared.

Example

>>> count = manager.clear_hooks()
>>> print(f"Cleared {count} hooks")
discover() int[source]

Scan hooks directory and load all valid hooks.

Hooks are loaded from three sources: 1. Python module hooks (.py files in hooks directory) 2. Executable hooks (executable files with optional .yaml config) 3. Configuration file (hooks.yaml) for registering external scripts

Returns:

Number of hooks loaded.

emit(event: Event) Event[source]

Emit an event to all subscribed hooks.

Hooks are executed in priority order (lower = earlier). Hook errors are caught and logged but never halt execution. Hooks with modifies_data=True can transform the event data, with modifications chained through subsequent hooks.

Parameters:

event – The event to emit.

Returns:

The (potentially modified) event after all hooks have executed.

get_hooks_for_event(event_type: EventType) List[Hook][source]

Get all hooks registered for an event type.

get_all_hooks() List[Hook][source]

Get all registered hooks (deduplicated).

Agents

Agent implementations for different AI backends.

Agent implementations for Ralph orchestrator.

class pyralph.agents.BaseAgent(timeout_seconds: int = 600, model: str | None = None, max_tokens: int | None = None, temperature: float | None = None, seed: int | None = None)[source]

Bases: ABC

set_logger(logger: Any) None[source]

Set the logger instance for this agent.

set_config(config: Any) None[source]

Set the config instance for this agent.

abstract check_dependencies() bool[source]
abstract get_name() str[source]
run(prompt: str, tag: str) Tuple[bool, str, AgentError | None][source]
class pyralph.agents.AgentError(exception_type: str, message: str, stack_trace: str, timestamp: str, agent_name: str, task_id: str)[source]

Bases: object

exception_type: str
message: str
stack_trace: str
timestamp: str
agent_name: str
task_id: str
format_log_entry() str[source]
classmethod from_exception(exc: Exception, agent_name: str, task_id: str) AgentError[source]
class pyralph.agents.ClaudeAgent(timeout_seconds: int = 600, model: str | None = None, max_tokens: int | None = None, temperature: float | None = None, seed: int | None = None)[source]

Bases: BaseAgent

Interface to the Claude CLI agent.

get_name() str[source]

Get the display name of this agent.

check_dependencies() bool[source]

Check if Claude CLI is available.

pyralph.agents.get_agent(agent_name: str, **kwargs) BaseAgent[source]
pyralph.agents.list_agents() List[str][source]

Get a list of available agent names.

Returns:

List of available agent names

Base Agent

Abstract base class for agents.

Base Agent interface for Ralph orchestrator.

class pyralph.agents.base.AgentError(exception_type: str, message: str, stack_trace: str, timestamp: str, agent_name: str, task_id: str)[source]

Bases: object

exception_type: str
message: str
stack_trace: str
timestamp: str
agent_name: str
task_id: str
format_log_entry() str[source]
classmethod from_exception(exc: Exception, agent_name: str, task_id: str) AgentError[source]
class pyralph.agents.base.BaseAgent(timeout_seconds: int = 600, model: str | None = None, max_tokens: int | None = None, temperature: float | None = None, seed: int | None = None)[source]

Bases: ABC

set_logger(logger: Any) None[source]

Set the logger instance for this agent.

set_config(config: Any) None[source]

Set the config instance for this agent.

abstract check_dependencies() bool[source]
abstract get_name() str[source]
run(prompt: str, tag: str) Tuple[bool, str, AgentError | None][source]

Claude Agent

Claude AI agent implementation.

Claude CLI Agent implementation.

class pyralph.agents.claude.ClaudeAgent(timeout_seconds: int = 600, model: str | None = None, max_tokens: int | None = None, temperature: float | None = None, seed: int | None = None)[source]

Bases: BaseAgent

Interface to the Claude CLI agent.

get_name() str[source]

Get the display name of this agent.

check_dependencies() bool[source]

Check if Claude CLI is available.

GitHub Copilot Agent

GitHub Copilot agent implementation.

Interface to the Copilot CLI agent.

class pyralph.agents.copilot.GithubAgent(timeout_seconds: int = 600, model: str | None = None, max_tokens: int | None = None, temperature: float | None = None, seed: int | None = None)[source]

Bases: BaseAgent

Interface to the Copilot CLI agent.

get_name() str[source]

Get the display name of this agent.

check_dependencies() bool[source]

Check if Copilot CLI is available.

run(prompt: str, tag: str) Tuple[bool, str, AgentError | None][source]