|
| 1 | +# CLAUDE.md β ralphify |
| 2 | + |
| 3 | +Ralphify is the open-source framework for ralph loop harness engineering, published on [PyPI](https://pypi.org/project/ralphify/). It's a CLI tool (`ralph`) that runs AI coding agents in autonomous loops β piping prompts to agents, running commands to capture dynamic data, and repeating with fresh context each iteration. |
| 4 | + |
| 5 | +For full architecture details, see `docs/contributing/codebase-map.md`. |
| 6 | + |
| 7 | +## Quick commands |
| 8 | + |
| 9 | +```bash |
| 10 | +uv run pytest # Run tests (required before any commit) |
| 11 | +uv run pytest -x # Stop on first failure |
| 12 | +uv run ruff check . # Lint |
| 13 | +uv run ruff format --check . # Check formatting |
| 14 | +uv run ty check # Type check |
| 15 | +uv run mkdocs build --strict # Build docs (must pass with zero warnings) |
| 16 | +uv run mkdocs serve # Preview docs at http://127.0.0.1:8000 |
| 17 | +``` |
| 18 | + |
| 19 | +## Project layout |
| 20 | + |
| 21 | +All source code is in `src/ralphify/`. The main file is `cli.py` β it contains the CLI commands and delegates to the engine for the core loop. |
| 22 | + |
| 23 | +Key modules: |
| 24 | +- `cli.py` β CLI commands (`run`, `new`, `init`); delegates to `_console_emitter.py` for terminal event rendering |
| 25 | +- `engine.py` β Core run loop orchestration with structured event emission |
| 26 | +- `manager.py` β Multi-run orchestration (concurrent runs via threads) |
| 27 | +- `_frontmatter.py` β YAML frontmatter parsing (uses PyYAML) and the `RALPH_MARKER` constant |
| 28 | +- `_run_types.py` β `RunConfig`, `RunState`, `RunStatus`, `Command` dataclasses |
| 29 | +- `_resolver.py` β Template placeholder resolution (`{{ commands.name }}`, `{{ args.name }}`) |
| 30 | +- `_agent.py` β Run agent subprocesses (streaming + blocking modes, log writing) |
| 31 | +- `_runner.py` β Generic command execution with timeout |
| 32 | +- `_events.py` β Event types, emitter protocol (NullEmitter, QueueEmitter, FanoutEmitter), and BoundEmitter convenience wrapper |
| 33 | +- `_console_emitter.py` β Rich terminal rendering of events |
| 34 | +- `_output.py` β `ProcessResult` base class, combine stdout+stderr, format durations |
| 35 | +- `_brand.py` β Brand color constants shared across CLI and console rendering |
| 36 | +- `_source.py` β GitHub source parsing and git-based ralph fetching for `ralph add` |
| 37 | +- `_skills.py` β Skill installation, agent detection, and command building for `ralph new` |
| 38 | +- `skills/new-ralph/SKILL.md` β AI-guided ralph creation skill (bundled, installed into agent skill dir) |
| 39 | + |
| 40 | +Tests are in `tests/` with one file per module. Docs are in `docs/` using MkDocs with Material theme. |
| 41 | + |
| 42 | +## Core concepts |
| 43 | + |
| 44 | +A **ralph** is a directory containing a `RALPH.md` file. That's it. No project-level config, no `.ralphify/` directory, no `ralph init`. |
| 45 | + |
| 46 | +**RALPH.md** has YAML frontmatter + a prompt body: |
| 47 | +- `agent` (required) β the agent command to run |
| 48 | +- `commands` (optional) β list of `{name, run}` commands whose output fills `{{ commands.<name> }}` placeholders |
| 49 | +- `args` (optional) β declared argument names for `{{ args.<name> }}` placeholders |
| 50 | + |
| 51 | +**The loop**: run commands β assemble prompt (resolve placeholders) β pipe to agent β repeat. |
| 52 | + |
| 53 | +## Conventions |
| 54 | + |
| 55 | +- **Commit messages**: `docs: explain X for users who want to Y`, `feat: add X so users can Y`, `fix: resolve X that caused Y` |
| 56 | +- **Dependencies**: Minimal by design. Runtime deps are `typer`, `rich`, and `pyyaml`. Prefer stdlib over new deps. |
| 57 | +- **Tests**: No external services, no API keys. All tests use temporary directories. |
| 58 | +- **Docs**: Every user-facing feature needs a docs page. Run `mkdocs build --strict` before committing doc changes. |
| 59 | +- **Keeping docs surfaces in sync**: When making user-facing changes (new features, changed behavior, new CLI flags), update all relevant surfaces: |
| 60 | + - `docs/` (MkDocs) β user-facing docs: CLI reference, quick reference, writing prompts guide, cookbook. Only include what's relevant for users. |
| 61 | + - `docs/contributing/` β contributor/agent docs: codebase map, architecture. Only include what's relevant for contributors and coding agents. |
| 62 | + - `README.md` β keep short and high-level. Update only when the change affects the quickstart, install, or core concepts. |
| 63 | + - `src/ralphify/skills/new-ralph/SKILL.md` β the skill that powers `ralph new`. Update when new frontmatter fields or features are added. |
| 64 | + - `CHANGELOG.md` β add an entry for every release. |
| 65 | + |
| 66 | +## Boundaries |
| 67 | + |
| 68 | +### Always Do |
| 69 | +- Run `uv run pytest` and `uv run ruff check .` before committing |
| 70 | +- Save all skills in `skills/` directory (not `.claude/skills/` which is gitignored) |
| 71 | + |
| 72 | +## Traps |
| 73 | + |
| 74 | +- The ralph marker filename (`RALPH.md`) is defined as `RALPH_MARKER` in `_frontmatter.py`. All modules import from there. |
| 75 | +- Frontmatter parsing uses PyYAML (`yaml.safe_load`). The `commands` field is a list of dicts, `args` is a list of strings. |
| 76 | +- Commands use `_runner.py:run_command()` with `shlex.split()` β no shell features (pipes, redirections, `&&`). Scripts are the escape hatch. |
| 77 | +- Commands starting with `./` run relative to the ralph directory. Other commands run from the project root. |
| 78 | +- The `agent` field in frontmatter is split with `shlex.split()` to build the command list. |
| 79 | +- Placeholder resolution uses `_resolver.py` β `{{ commands.<name> }}` and `{{ args.<name> }}` are the two supported kinds. |
| 80 | + |
| 81 | +The project has a website called ralphify.co and the docs live a ralphify.co/docs/ |
0 commit comments