# Developing Ralphy

> Read this BEFORE you start a dev task on Ralphy itself (writing code, editing docs, changing a playbook, adding a skill or template, bumping a model). Skip it when the user is in "use Ralphy to make a video" mode — `AGENTS.md` already handles that.

This file does **not** describe the architecture — read `CLAUDE.md`, `cli/index.ts`, and `docs/playbooks/README.md` for that, or grep the codebase. This file lists the **non-obvious** things you'd miss without being told.

## English-only output (hard rule, applies to EVERY dev edit)

**Every file you write or edit lands on disk in English. EXCLUSIVELY.** Cyrillic (or any other non-Latin script in prose / identifiers / examples) is banned repo-wide. This includes:

- TypeScript code: identifiers, string literals, JSDoc, inline comments.
- Markdown: prose, headings, callouts, example utterances, table cells.
- JSON fixtures: every `description`, `name`, `example`, `prompt`, `reason`, `note`.
- Playbooks, skills, templates, prompts (`docs/prompts/`), `notes/` (including `notes/issues/*.md`), `MODELS.md`.
- Commit messages, PR titles + bodies, release notes, CHANGELOG entries.
- Tests + fixtures — including "fixture for the Russian-utterance case." Pick an off-domain English string that produces the same low-keyword-score path instead (see `tests/unit/template-suggest.test.ts` for the worked pattern).

**The user talking to you in Russian is fine — match their language in chat.** What lands in a file is English. If the user pastes a Russian quote and asks you to file it, translate / paraphrase before committing. If the file is by nature a verbatim transcript of a Russian user, you still translate — the on-disk artifact is English.

Before every commit, run `rg '\p{Cyrillic}' --hidden -g '!.git' -g '!node_modules' -g '!*.lock'` (PCRE2 / `--pcre2`-enabled rg). **Empty output is the gate.** A `lint:no-cyrillic` script should be wired into CI; if it's not yet, file a `notes/issues/` entry rather than skip the check.



## Where things live (non-obvious only)

- **`notes/`** — the only dev tracker. Ideas, issues, and informal decisions all live here; there is no separate roadmap board. See `notes/README.md` for the shape. **Filing a note is the right first move** when the user surfaces an idea that isn't immediately actionable.
- **`notes/issues/`** — the live backlog. Status is by folder: the flat top level holds active work (open issues), `notes/issues/done/` holds resolved or landed issues, `notes/issues/deprecated/` holds superseded / won't-do issues. Numbering is monotonic across all three (`NNN-slug.md`). To see open work, read the top-level files only. Full layout: `notes/README.md` (`#issues-folder-layout`).
- **`MEMORY.md`** at `~/.claude/projects/-Users-maximovchinnikov-github-ugc-cli/memory/MEMORY.md` — the user's auto-memory. Battle-tested rules live here: anti-AI-slop, photoreal-still-register, Kling-no-RU-audio, ElevenLabs-no-artist-names, broadcast-realism=square, deliberate-prop-VFX, frame-break-hook, etc. **Read the relevant memory before recommending a prompt, model, or composition pattern.**
- **`docs-mintlify/.archive/`** — old docs structure pre-2026-05-20 rewrite. If you're tempted to copy something from there, ask why it was archived first (the new IA is in `docs-mintlify/docs.json`).
- **`docs-mintlify/.styleguide.md`** — tone, length, components, banned phrases, angle-bracket rules. **Read before editing any `docs-mintlify/*.mdx`** — and especially before dispatching a sub-agent to write docs.

## The append-only contract

`AGENTS.md` invariant #13 is wider than it looks. **You don't delete or overwrite user/agent-produced artifacts without explicit consent.** That applies to:

- `.ralphy/workspaces/<ws>/projects/<id>/` — every file. Regen writes `.v2`, never overwrites.
- `cli/lib/errors/catalog.ts` — codes are **append-only post-v1.0** (decision `01-D-07`). Don't rename, don't remove, don't repurpose a code. Cap is `< 40` (raised from `< 30` when category 02 landed). The test in `tests/unit/errors-catalog.test.ts` enforces this.
- `MODELS.md` "Tried-and-dropped" section — once a model is in there, leave it. The next person trying the same swap reads that section first.
- `generations.jsonl`, `user-prompts.jsonl`, `user-assets.jsonl` — never truncate, never rewrite in-place.

## Auto-generated files (don't hand-edit)

These are regenerated from source. Hand-edits get clobbered the next time the script runs.

| File / dir | Generated by | When |
|---|---|---|
| `docs-mintlify/reference/cli/*.mdx` | `bun run docs:cli` (`scripts/build-cli-docs.ts`) | After any change to `cli/commands/<verb>.ts` |
| `docs/cli-surface.generated.md` | `bun run cli:surface` (`scripts/extract-cli-surface.ts`) | After any new verb |
| `docs/assets-catalog.md` | `ralphy assets catalog --write` | After any change to the ralphy-assets companion |
| `MEMORY.md` | The agent itself, via memory tools | When you save a fact |

If you change the *generator*, run the generator after; if the diff is non-empty, commit the regenerated output in the same commit.

## Lint scripts (run before commit)

CI runs all of them. Run locally first:

```bash
bun run lint:errors           # error catalog shape
bun run lint:help-examples    # every verb's --help block has a working example
bun run lint:skills           # skill frontmatter (name regex, ≤1536 char desc, namespace)
bun run lint:agents-md        # AGENTS.md routing table + claude-isms
bun run lint:confirmation-shape  # English/Russian confirmation phrases in prompts.json
bun run lint:motion-graphics  # motion-graphics misroutes in prompts.json
bun run lint:docs-links:fast  # internal links resolve (use lint:docs-links for external probe)
bun run cli:surface:check     # cli-surface.generated.md is fresh
bun run docs:cli:check        # docs-mintlify/reference/cli/*.mdx are fresh
```

If you add a new lint, wire it into `package.json` AND into the CI workflow (`.github/workflows/ci.yml`).

## Skill discipline

- `name`: kebab-case, `/^[a-z][a-z0-9-]*$/`.
- `description`: ≤ **1536 chars**. If you exceed, move ALSO FIRE / DO NOT FIRE / HARD INVARIANTS blocks from the description into body sections (`## ALSO FIRE`, `## DO NOT FIRE`, `## HARD INVARIANTS`).
- `namespace`: `user` (user-facing, default) or `maintainer` (maintainer-only workflows). Slugs carry no `ralphy-` prefix. Never invent a new namespace value.
- The installer (`cli/lib/skill/installer.ts`) writes via **sentinel-bounded merge**: `<!-- ralphy:start v=1 --> ... <!-- ralphy:end -->`. Never delete those markers. Content above and below them belongs to the user.

## Template discipline

- The repo-public `templates/<category>/<slug>/` folder was retired in #084. Public templates now live in the content library — a static `library.json` (committed at `landing/lib/library-v2/library.json`, served on Bunny CDN), read by the CLI via `cli/lib/library/client.ts`. The Supabase Postgres backend was retired (June 2026): `library.json` is the single source of truth. Author user-local templates into `.ralphy/workspaces/<ws>/templates/<slug>/`; publish onward via the `templater` / `dev-publish-template` path.
- Category ∈ `{b2b-saas, dtc-commerce, creator-lifestyle, entertainment-viral, cinematic-narrative}`.
- Workspace overrides the public tier on id collision (`.ralphy/workspaces/<ws>/templates/<slug>/` wins).
- `template.yaml` schema is in `cli/lib/schemas/template.ts` (Zod). The version gate is `E_TEMPLATE_VERSION_UNSUPPORTED`.

## Model discipline

- **Read `MODELS.md` before naming any model id.** Training memory is stale.
- Default image model as of 2026-05-20: `google/gemini-3-pro-image-preview` (nano-banana-pro). Premium typography alternative: `openai/gpt-5.4-image-2`.
- Adding a new model: update `MODELS.md` first, then add a prompt adapter under `cli/lib/providers/prompt-adapter/`, then add tests. See [Cookbook → Add a new model](https://github.com/alecs5am/ralphy/blob/main/docs-mintlify/cookbook/new-model.mdx).
- The model registry verb `ralphy models list` is OR-catalog-backed (24h cached) — when the OR catalog changes shape, the catalog ages out automatically.

## Test discipline

- `bun test` runs everything (`tests/unit/`, `tests/integration/`). No jest/vitest/mocha.
- TDD-leaning: new CLI verb → smoke via `bun run cli/index.ts <cmd>` (NOT `bunx tsx` — breaks on `bun:sqlite`) + JSON assertion in `tests/unit/`. New UI → Playwright. New HyperFrames composition → `bunx hyperframes lint .ralphy/workspaces/<ws>/projects/<id>` + `bunx hyperframes snapshot` for keyframe PNGs.
- Errors-catalog test is the gatekeeper for the append-only contract — never bypass it.

## Tools

- **Bun only.** Never `npm` / `npx` / `yarn`. Always `bun` / `bunx`.
- The user's machine has `fd`, `rg`, `bat`, `jq`, `yq`, `sd`, `ast-grep`, `xh`, `gh`, `hyperfine`, `dust`, `procs`, `mlr`, `scc`, `tokei` installed (see `~/.claude/CLAUDE.md`). **Prefer these over their legacy equivalents** — `fd` over `find`, `rg` over `grep -r`, `sd` over simple `sed`, `ast-grep` for structural code refactors.

## Where to file work (it all goes in `notes/`)

There is no separate board — `notes/` is the only tracker.

- **File in `notes/issues/`** (flat top level) when: the work is scoped enough for a downstream agent to pick up — a concrete bug, gap, or actionable change. This is the live backlog `/dev-loop` executes.
- **File in `notes/ideas/`** when: the user surfaces an idea mid-conversation, the work isn't immediately scoped, the design has open questions, or the change would need a decision (`D-NN`) we haven't made yet.
- When an idea matures into something actionable, **promote it into a tracked issue** under `notes/issues/` and drop the idea note (git history preserves the rationale). Don't let both exist for the same thing.

## What this file does NOT cover

If you need any of these, read the actual source — they're discoverable:

- The CLI verb surface — read `cli/index.ts` and `cli/commands/<verb>.ts`, or use `ralphy --help`.
- The provider layer — read `cli/lib/providers/media.ts` and `cli/lib/providers/llm.ts`.
- The HyperFrames composition layer — read `.ralphy/workspaces/<ws>/projects/<id>/index.html` examples and the `.agents/skills/hyperframes/` skill body.
- The role playbooks — read `docs/playbooks/<role>.md` per-task; routing is in `AGENTS.md`.
- Architecture diagram — `docs-mintlify/concepts/architecture.mdx`.

The point of this file is to make the **non-obvious** things visible. Everything else, you can find by reading.
