ralphy is a single binary built with Commander. Every subcommand inherits five global flags, an auto-detection scheme for the project workspace, and a uniform cancellation contract. Read this page once and you’ll know how to wire ralphy into a shell pipeline, a CI job, or an agent harness without surprises.
Global flags
Every verb honors these. They’re parsed before the subcommand and apply uniformly.Force rich UI output (colors, tables, icons, spinners). Overrides TTY auto-detection. Useful when piping into
tee or a script that retains color codes.Force JSON output on stdout. Overrides both
--pretty and TTY auto-detection. Use for shell scripts and agent harnesses. Errors still print a structured payload on stderr.Suppress progress chatter, spinners, and
ok/info/warn lines. The final result (JSON object or pretty table) still prints. Errors still print on stderr.Disable ANSI color codes even on TTY. Pairs well with
--pretty when you want layout but no colors (e.g. piping into less).Print the ralphy version and exit. The CLI uses the lowercase
-v (npm / docker / kubectl convention) instead of Commander’s default -V.Working directory. Overrides project auto-detection. Use when running
ralphy from outside your checkout or when you want to point at a specific workspace.Output mode resolution
The CLI runs in one of three modes — pretty, JSON, or auto — resolved on every invocation by thepreAction hook in cli/index.ts:
--jsonwins outright. Sets mode tojson, silences pretty primitives.--prettyis next. Sets mode toprettyregardless of TTY.- Otherwise
auto: pretty when stdout is a TTY, JSON when piped.
TTY auto-detection
When neither--json nor --pretty is set, the CLI checks process.stdout.isTTY. Interactive shells get the pretty rendering; pipes (ralphy ... | jq) and redirects (ralphy ... > out.json) get JSON. This is the right default for both humans and agents — the agent reads stdout as a stream and never needs to set --json explicitly.
Project auto-detection
The samepreAction hook resolves the project root. Order:
--cwd <path>if set — wins outright,loadProjectEnv()runs against it.- Walk up from
process.cwd()looking forpackage.jsonwithname: "ugc-cli". RALPHY_PROJECT_DIRenv var if set.~/.config/ralphy/config.json#default_project_dir(set byralphy setup --link <path>).
setup verb is exempt — it has its own first-run logic that handles the unlinked case. Every other verb sees a resolved root or reports E_PROJECT_NOT_LINKED when one is needed.
Whenever a root resolves, loadProjectEnv() reads <root>/.env and merges keys into process.env. Real shell-exported variables always win — the .env only fills the gaps.
The bare dashboard
Runralphy with no subcommand and you get a status dashboard. The agent calls this on session start to load user context.
version, user.skill.{score,band}, user.is_developer, user.signals, capabilities.{openrouter,elevenlabs}, project_root. Use it to decide intake verbosity (see intake.md).
Cancellation
SIGINT (Ctrl-C) is handled cooperatively. The handler flips a global token; verbs read it between API calls and exit cleanly when they next check. The command boundary catches the resultingCancelledError and emits the structured E_CANCELLED payload with exit code 130.
A second Ctrl-C exits hard with 130, no matter what the verb is doing. Append-only state (logs, manifests) is preserved either way — see Error catalog.
Exit codes
| Code | Class | Source |
|---|---|---|
| 0 | success | normal termination |
| 1 | runtime / internal | E_INTERNAL, uncaught exception |
| 2 | user error | bad flag, missing arg, not found |
| 3 | provider | OpenRouter / ElevenLabs / yt-dlp failures |
| 4 | env | missing key, missing dep, fs permission |
| 5 | quality gate | scenario / image / video / ref refused |
| 130 | cancelled | SIGINT |
classifyExitCode() in cli/lib/errors/catalog.ts. The append-only contract that protects them is documented on Error catalog.
Help drill-down
The built-in help walks the subcommand tree.ralphy help generate shows the generate group; ralphy help generate image drills into the leaf and prints every flag plus a per-model whitelist when the OR catalog is cached.
Versioning
ralphy --version reads cli/lib/version.ts. The /release skill bumps that file in lockstep with package.json, the Homebrew formula, and the npm package. If your binary lags the version in AGENTS.md, upgrade:
Related
- Output modes — what each mode actually prints
- Error catalog — every
E_code + exit class - Env + config — required keys,
.envprecedence - cli/index.ts — source of truth for global flags