| title | Ralphify Changelog |
|---|---|
| description | Ralphify release history — new features, bug fixes, and breaking changes across all versions. |
| keywords | ralphify changelog, release history, new features, version updates, breaking changes |
All notable changes to ralphify are documented here.
- Placeholder cross-contamination between args and commands — when an arg value contained text like
{{ commands.tests }}, the sequential resolution would re-process it as a command placeholder, injecting unrelated output. Placeholders are now resolved in a single pass so inserted values are never re-scanned. - Helpful error when command binary is not found — when a
commandsentry references a binary that isn't installed (e.g.run: mypy src/), the error now identifies which command failed and points to thecommandsfield. Previously this surfaced as a generic crash with no context. - Timed-out agent output not echoed when logging enabled — when using
--log-dirand the agent timed out, partial output was written to the log file but silently swallowed from the terminal. Both completion and timeout paths now echo consistently. --separator not ending flag parsing in user args —ralph run my-ralph -- --verbose ./srcnow correctly treats--verboseas a positional value instead of parsing it as a flag.- Command output garbled when stdout lacked trailing newline — when a command's stdout didn't end with a newline and stderr was non-empty, the two streams were concatenated directly (e.g.
"test passedwarning: dep"), producing garbled output in log files and{{ commands.* }}placeholder values. - Indented
---in YAML block scalars mistaken for closing frontmatter delimiter — the frontmatter parser usedline.strip()to detect the closing---, which caused indented---inside YAML block scalars (e.g.notes: |with---content) to be treated as the end of the frontmatter. Now only---at column 0 is recognized as the closing delimiter. - Indented opening
---delimiter accepted inconsistently — the opening frontmatter delimiter check usedstrip()which accepted leading whitespace (e.g.---), while the closing delimiter required column 0. Both delimiters now require---at column 0 per the YAML frontmatter spec. - Arg values with spaces breaking command execution — when
{{ args.name }}placeholders were substituted into commandrunstrings, values containing spaces (e.g."hello world") were split into separate tokens byshlex.split, causing the wrong command to execute. Arg values are now shell-quoted before substitution so they are always treated as single tokens. - Helpful error when command has invalid syntax — when a command's
runstring has malformed shell syntax (e.g. unmatched quotes), the error now identifies which command failed and points to thecommandsfield. Previously this surfaced as a bareValueErrorlike "No closing quotation" with no context. - Empty arg values breaking
./working directory detection — when an{{ args.name }}placeholder resolved to an empty string, the substitution could introduce leading whitespace that prevented the./prefix from being detected, causing the command to run from the project root instead of the ralph directory. - Windows
.cmd/.exeextension breaking streaming mode detection — on Windows,claudeis installed asclaude.cmdorclaude.exe. The streaming mode check compared the full filename (including extension) against"claude", so it never matched. Ralphify now compares the stem only, enabling real-time activity tracking on Windows.
ralph dashboardcommand (POC) — launches a local web server serving a real-time dashboard UI. Connects to running ralphs via SSE for live event streaming. Uses stdlibhttp.server— no new dependencies. Start withralph dashboard(default port 8420).
BoundEmitterconvenience methods —log_info(message)andlog_error(message, traceback=...)let Python API users emit log events without constructingEventobjects manually.- Extracted
ProcessResultbase class —RunResultandAgentResultnow share a common base with consistentsuccess/timed_outsemantics, reducing duplication in_runner.pyand_agent.py. - Code quality — extracted CLI validation helpers, renamed
resolver.pyto_resolver.pyto match private module convention, deduplicated output echoing and timeout/blocking paths in_agent.py, extractedensure_strhelper for consistent bytes-to-string decoding.
- Co-authored-by credit trailer — every prompt now includes an instruction telling the agent to add
Co-authored-by: Ralphify <noreply@ralphify.co>to commit messages. On by default; opt out withcredit: falsein RALPH.md frontmatter.
- Typed event payloads — replaced
dict[str, Any]event data with TypedDict classes throughout the engine and console emitter for stronger type safety. - Code quality — standardized imports, extracted constants, simplified TypedDicts with
NotRequired.
ralph initcommand — scaffold a new ralph with a ready-to-customize template, no AI agent required. Runralph init my-taskto create a directory with aRALPH.mdthat includes example commands, args, and placeholders. A faster alternative to the AI-guidedralph new.ralphify-coworkskill — a Claude Cowork skill that lets non-technical users set up and run autonomous loops from plain English. Handles installation, ralph creation, running, and tweaking — no coding knowledge needed. Install it in Cowork fromskills/ralphify-cowork/.
{{ args.* }}placeholders now resolved in commandrunstrings — previously, arg placeholders were only resolved in the prompt body. Commands likerun: gh issue view {{ args.issue }}would fail becauseshlex.splittokenized the raw placeholder into multiple arguments. Args are now resolved before command execution.
The v2 rewrite. Ralphify is now simpler: a ralph is a directory with a RALPH.md file. No more ralph.toml, no more .ralphify/ directory, no more ralph init. Everything lives in one file.
- Removed
ralph.toml— the agent command is now in theagentfield of RALPH.md frontmatter. No separate configuration file. - Removed
ralph init— create a ralph directory with aRALPH.mdfile manually, or useralph new. - Removed
.ralphify/directory — no more checks, contexts, or named ralphs as separate primitives. Everything is defined in RALPH.md. - Removed checks and contexts — replaced by
commandsin RALPH.md frontmatter. Commands run each iteration and their output is available via{{ commands.<name> }}placeholders. ralph runrequires a path —ralph run my-ralphinstead ofralph runwith optional name. The argument is a path to a directory containing RALPH.md.- Placeholder syntax changed —
{{ contexts.<name> }}is now{{ commands.<name> }}. The{{ args.<name> }}syntax is unchanged. - User arguments — pass named flags to your ralph:
ralph run my-ralph --dir ./src.
commandsfrontmatter field — define commands that run each iteration directly in RALPH.md. Each command has anameandrunfield.- Single-file configuration — the
agentfield, commands, args, and prompt all live in one RALPH.md file.
- Guard against double-starting a run —
RunManagernow prevents the same run from being started twice. - Eliminate TOCTOU race in RunManager —
start_runis now atomic to prevent race conditions in concurrent runs. - UTF-8 encoding for all subprocess calls — prevents encoding errors on systems with non-UTF-8 defaults.
- Stricter input validation — reject whitespace-only agent fields, command names, command
runvalues, and command strings. Validate negative delay, non-positivemax_iterations, and timeout values. Validatecommandsfield type and reject duplicate command names. Validate commandtimeoutfield in frontmatter. - Clear command placeholders when no commands exist — matches the existing behavior for args placeholders.
- Error handling for
os.execvpinralph new— graceful error instead of unhandled exception when the agent binary is not found.
- Extensive test coverage — added unit tests for
_agent.py,_events.py,ConsoleEmitter, engine internals, streaming agent execution, command cwd logic, and frontmatter edge cases. - Code quality — extracted magic strings into named constants, consolidated duplicate test helpers, replaced lambda closures with
functools.partial, and compiled module-level regexes in the resolver.
-
Move agent config into RALPH.md — take the
commandandargsfromralph.tomland combine them into theagentfield in RALPH.md frontmatter. -
Convert checks and contexts to commands — each check/context becomes a command entry:
# Before (separate files): # .ralphify/checks/tests/CHECK.md with command: uv run pytest -x # .ralphify/contexts/git-log/CONTEXT.md with command: git log --oneline -10 # After (in RALPH.md frontmatter): commands: - name: tests run: uv run pytest -x - name: git-log run: git log --oneline -10
-
Update placeholders — change
{{ contexts.<name> }}to{{ commands.<name> }}. -
Move RALPH.md into a directory — create a directory for your ralph and put RALPH.md inside it.
-
Delete old files — remove
ralph.tomland the.ralphify/directory. -
Update CLI usage —
ralph runbecomesralph run <path>.
- New tagline — updated project tagline to "Stop stressing over not having an agent running. Ralph is always running" across CLI, PyPI, and docs.
ralph newruns without permission prompts — Claude Code is now launched with--dangerously-skip-permissionsso the AI-guided setup flow is uninterrupted.- Simpler
ralph newexperience — the skill no longer asks users about checks, contexts, or frontmatter. Just describe what you want to automate in plain English and the agent builds the ralph for you. ralph newknows about user arguments — the skill can now suggest{{ args.name }}placeholders when a ralph would benefit from being reusable across projects.
- User arguments for ralphs — pass
--name valueflags or positional args toralph runand reference them in prompts with{{ args.name }}placeholders. Declare positional arg names in frontmatter withargs: [dir, focus]. Context and check scripts receive user arguments asRALPH_ARG_<KEY>environment variables. - Quick reference page — single-page cheat sheet covering CLI commands, directory structure, frontmatter fields, placeholders, and common patterns.
- Prompt writing guide — best practices for writing effective RALPH.md prompts, including tips on scoping, context usage, and user arguments.
- "How it works" page — explains the iteration lifecycle so users understand the system model.
- "When to use" guide — helps users evaluate whether ralph loops fit their task.
- Agent comparison table — side-by-side comparison of supported agents with output behavior notes.
- Expanded cookbook — new recipes for Python, TypeScript, Rust, Go, bug fixing, codebase migration, and multi-ralph project setup.
- Malformed
ralph.tomlnow shows a helpful error message instead of a rawKeyError.
Tightened the primitive system: global primitives are now opt-in, context placeholders must be named, and primitives are re-discovered every iteration.
- Explicit primitive dependencies required — global checks and contexts are no longer auto-applied to all ralphs. Each ralph must declare which global primitives it uses in its frontmatter (
checks: [lint, tests],contexts: [git-log]). Unknown names produce a clear error. Ralph-local primitives still auto-apply. - Named placeholders only — the bulk
{{ contexts }}placeholder and implicit append behavior have been removed. Each context must be referenced by name ({{ contexts.git-log }}). Contexts not referenced by a placeholder are excluded from the prompt. - Removed
ralph statuscommand — setup validation has been moved intoralph runstartup, so a separate status command is no longer needed.
- Live re-discovery — primitives are re-discovered every iteration, so adding or editing a check, context, or ralph on disk takes effect on the next cycle without restarting the loop.
Redesigned ralph new with AI-guided setup, and added environment variables for scripts.
- AI-guided
ralph new—ralph newnow installs a skill into your agent (Claude Code or Codex) and launches an interactive session where the agent guides you through creating a complete ralph — prompt, checks, and contexts — via conversation. Replaces the oldralph new check/ralph new context/ralph new ralphscaffolding subcommands. RALPH_NAMEenvironment variable — context and check scripts now receive the name of the current ralph inRALPH_NAME, so scripts can adapt their behavior based on which ralph is running.
Simplified the CLI, added a spinner during iterations, and removed the experimental web dashboard to focus on the CLI experience.
- Removed
ralph uisubcommand and web dashboard — the experimental web dashboard introduced in 0.1.6 has been removed. - Removed
ralph ralphssubcommand —ralph new <name>is now shorthand forralph new ralph <name>. - Removed instructions primitive — the
instructionsprimitive type introduced in 0.1.3 has been removed. Use contexts for injecting reusable rules into prompts instead. - Removed ad-hoc prompts (
-pflag) — the--prompt/-pflag onralph runhas been removed.
- Spinner with elapsed time — iterations now show a live spinner with elapsed seconds.
- Agent result message is now displayed in CLI output after each iteration.
- Raw Claude Code
stream-jsonoutput no longer leaks to the terminal during iterations.
Named ralphs, ralph-scoped primitives, and live agent activity streaming.
- Named ralphs — save reusable, task-focused ralphs in
.ralphify/ralphs/<name>/RALPH.mdand switch between them withralph run <name>. - Live agent activity streaming — when the agent command is Claude Code, the engine auto-detects it and uses
--output-format stream-jsonwithsubprocess.Popenfor line-by-line streaming. - Contributor docs — new
docs/contributing/section with a codebase map.
RUN_STOPPEDevent now emits exactly once with the correct stop reason.- Windows compatibility fix for Unicode characters in terminal output.
Dashboard UI polish (experimental — dashboard removed in 0.1.7).
Ad-hoc prompts, better discoverability, and expanded cookbook recipes.
- Ad-hoc prompts —
ralph run -p "Fix the login bug"passes a prompt directly on the command line. - Rust and Go cookbook recipes — complete copy-pasteable setups.
The primitives release. Checks, contexts, and instructions turn the basic loop into a self-healing feedback system.
- Checks — post-iteration validation scripts in
.ralphify/checks/. - Contexts — dynamic data injection in
.ralphify/contexts/. - Instructions — reusable prompt rules in
.ralphify/instructions/.
Quality-of-life improvements for the core loop.
ralph statuscommand--timeout/-toption--log-dir/-loption--version/-Vflag- ASCII art startup banner
Initial release.
ralph init— createralph.tomlandRALPH.mdin your projectralph run— the core autonomous loop: read prompt, pipe to agent, repeat- Iteration tracking with exit codes and duration
--stop-on-error/-s,-n,--delay/-d- Auto-detection of project type during
ralph init