Get started

From zero to a running app.

One install line, one line describing your app, a short interview. The agent writes every line of code and stops only when the tests are green. Most of the wait is the first compile.

Railboard: a live Kanban built by AI in 7 prompts 3:06 · Watch on YouTube

Install

One line, on macOS or Linux:

curl -fsSL https://rustoffrails.org/install.sh | sh
  • Rust, if cargo is missing: it asks first, then runs the official rustup installer. It never uses sudo.
  • The cargo tools the framework uses: sea-orm-cli, cargo-nextest, cargo-watch, only the missing ones.
  • The framework, from the GitHub release, SHA-256 verified, in ~/.offrails/, plus the offrails command.
  • The Claude Code plugin, if claude is on your PATH. For other agents, it prints the one-line prompt.
  • Docker, Node and pnpm are only detected, never installed. No telemetry.

Read before you pipe? Read the install script and INSTALL.md, or print the plan without changing anything:

curl -fsSL https://rustoffrails.org/install.sh | sh -s -- --dry-run

Already in Claude Code?

Install just the plugin, once per machine:

/plugin marketplace add rust-off-rails/rustoffrails
/plugin install offrails@offrails

That adds nine skills, from /offrails:new to /offrails:upgrade, and the guardrail hooks. Both do nothing outside a Rust off Rails app. Using Codex or Cursor? See without Claude Code.

What you need

The installer takes care of the first two and tells you about the rest. To set up by hand, or to see what you're getting:

  • Rust, stable required

    Installed with rustup, from rustup.rs:

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  • Three cargo tools required

    Migrations, the test runner, and rebuild-on-save. bin/setup installs any that are missing, but doing it now saves a wait later.

    cargo install --locked sea-orm-cli cargo-nextest cargo-watch
  • Docker optional

    For running the tests on Postgres locally, running the whole app with docker compose, and deploying. Without it, everything still runs on SQLite, and CI runs the Postgres tests for you.

  • Node 24 LTS and pnpm only for a JS UI

    Only for the inertia or spa modes, or htmx with islands. The default, htmx, needs no Node at all. pnpm comes with Node through corepack:

    corepack enable pnpm
  • A coding agent required

    Claude Code (recommended: the plugin adds the skills and guardrails below). Or Codex, Cursor, or any agent that reads AGENTS.md: see without Claude Code.

Your first app

Start Claude Code in an empty directory:

mkdir bookshelf && cd bookshelf
claude

Then describe the app in one line:

/offrails:new bookshelf: people track books they've read

Or from any terminal, with the offrails command the installer added (it starts Claude Code, or Codex, or prints the prompt for your agent):

offrails new bookshelf "people track the books they've read"
  1. The interview

    Product questions only, at most three rounds, each with a recommended default listed first. It never asks which ORM or where files go: the framework already decided. Answer with a letter, in your own words, or with "you decide" to take the defaults.

  2. The plan

    A compact plan: resources, pages, jobs, and everything it assumed. Nothing is generated until you say yes. Change anything by saying so.

  3. Generation

    Your answers go into product/ specs and the app's AGENTS.md. Then the app: migrations, models, controllers, templates, tests, a Dockerfile, compose.yaml and CI, one vertical slice at a time.

  4. Green on both databases

    It isn't done until the Definition of Done passes: fmt, clippy, and the whole test suite on SQLite and Postgres.

~/bookshelf, claude
An abridged, illustrative session: the command, three interview questions with their recommended defaults, the plan, the generated files, and the tests passing on SQLite and Postgres.
  1. > /offrails:new bookshelf: people track books they've read
  2. ● Reading the framework: interview · doctrine · structure · stack · workflow
  3. ? Accounts? a) Magic link (Recommended) b) Email + password c) Invite-only d) None
  4. › a
  5. ? Who owns data? a) Each user owns their records (Recommended) b) Teams c) Shared
  6. › you decide
  7. ? Frontend? a) htmx (Recommended) b) inertia c) spa d) api
  8. › you decide
  9. ◆ Plan: frontend htmx · Postgres in prod (SQLite locally) · deploy later
  10. Accounts magic link; each user owns their books
  11. Book title, author, finished_on (date), rating (1–5), belongs to User
  12. Pages books index/show/new/edit
  13. › yes
  14. + product/README.md · product/features/books.md · AGENTS.md
  15. + src/models/book.rs · src/controllers/books.rs · templates/books/
  16. + Dockerfile · compose.yaml · .github/workflows/ci.yml (+ many more)
  17. ✓ cargo clippy --all-targets -- -D warnings
  18. ✓ cargo nextest run · SQLite · all passed
  19. ✓ cargo nextest run · Postgres · all passed
  20. Definition of Done: green. Run bin/setup && bin/dev

Run it

bin/setup && bin/dev

bin/setup creates .env, builds the CSS, compiles, and migrates and seeds the development database. bin/dev prints the URL to open: https://localhost:3000 (HTTP/2) when mkcert is installed, otherwise http://localhost:3000 with a note saying why (framework 0.6.1+; never a self-signed certificate, because browsers drop login cookies on it). It rebuilds, migrates and reloads open tabs whenever the agent changes something.

What you get on day one

  • /dev

    Dev tools: live tiles for the mailbox and jobs, routes, system info, pending migrations, and buttons to send a test email or enqueue a test job.

  • /dev/mailbox

    The dev mailbox. Every email the app sends in development lands here, rendered, plus mailer previews. Nothing leaves your machine.

  • /admin/jobs

    The jobs dashboard: states, retries, cron, queues. It runs in production too, behind admin access.

  • Docker

    docker compose up --build runs the production image against Postgres, on your laptop.

  • CI

    .github/workflows/ci.yml: the tests on SQLite and Postgres, and the Docker build, on every push.

  • /up

    A health check for load balancers and deploys: 200 when the app is up, 503 while migrations are pending.

Your first feature

Two ways in. Both end in the same place: a spec in product/features/, then code, then green.

A Say it

/offrails:feature let people review books; email the owner

The agent asks only what changes the build (who can review? can a review be edited? can owners opt out of the email?), then writes the spec for you to read.

B Write it

Plain English in product/features/reviews.md. Any part is fine; the agent fills the gaps and marks what it assumed.

# Feature: Reviews

## Why
Readers want to know what others thought of a book.

## Behavior
- A logged-in user can review a book once: 1–5 stars and a few lines.
- The book's owner gets an email for each new review.

Then:

/offrails:feature

With no argument it builds whatever changed in product/.

For anything bigger than one slice, it shows the plan and waits for a yes. Then it builds migration → model → failing tests → code, ticks each acceptance criterion once its test passes on both databases, and tells you what changed in product terms. What a full spec looks like.

Ship it

/offrails:deploy kamal

Pick a target: Kamal (your own server), Fly.io, Render or Railway. With no target it uses the one from the interview, or asks.

It writes the Dockerfile and the target's config, runs the Definition of Done, builds the image and checks /up locally. Then it stops and confirms before anything outward-facing: the exact commands, what each one costs or changes, and which secrets you supply. Nothing runs without your yes. Migrations run on every boot.

Upgrading your app

Each app keeps its own pinned copy of the framework in .offrails/, so nothing changes until you upgrade. Commit first. Then get the latest release:

offrails update

See whether your app is behind (it compares content, not just version numbers): framework 0.4.0+

cd my-app && offrails upgrade --check

And upgrade: framework 0.4.0+

offrails upgrade

It starts your agent with the upgrade recipe: Claude Code runs /offrails:upgrade, opencode and Codex get the recipe automatically, and for any other agent it prints a prompt to paste. The agent shows you a plan before changing anything.

On a release before 0.4.0, run offrails update, then ask your agent, in the app:

Upgrade this Rust off Rails app to the framework in ~/.offrails/current, following https://github.com/rust-off-rails/rustoffrails/blob/main/generators/upgrade.md step by step. Reconcile, don't re-create; never edit applied migrations. Start from a clean git tree, show me the plan before changing anything, and finish with the Definition of Done on SQLite and Postgres.

Several releases behind? Upgrade one release at a time. What the agent does during an upgrade.

Without Claude Code

The framework is Markdown, so any agent that reads AGENTS.md can use it: Codex, Cursor, and others. Clone the framework repository, then tell your agent:

Read /path/to/rustoffrails/AGENTS.md and make me a new app called "bookshelf".

Every generated app carries its own AGENTS.md and a pinned copy of the framework in .offrails/, so later sessions need no setup. Without the plugin you don't get the slash commands or the hooks: ask in plain words ("add reviews to books", "run the Definition of Done").

Only want your agent to read the docs, with nothing installed? Connect it to the hosted MCP server: Claude Code, Claude, Cursor, ChatGPT and Codex all work.

Troubleshooting

Is my machine set up right?

The installer's command prints a table of every prerequisite and its version:

offrails doctor

Re-run the installer, or offrails update, to fill any gaps.

The first build is taking forever

Expected: a cold build of this stack takes about 10 minutes, and bin/setup says so. After that, rebuilds are incremental and take seconds.

The agent says the Postgres tests were skipped

It never claims Postgres passed when it couldn't run it. Start the app's Postgres container, then run the suite against it:

docker compose up -d db
TEST_DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres cargo nextest run

No Docker? CI runs the Postgres tests on every push.

Where are the logs?
  • Requests and errors print to the terminal running bin/dev, one span per request with its request id. Turn the detail up or down with RUST_LOG in .env.
  • Failed jobs: /admin/jobs, or in a terminal:
cargo run -- jobs list --state discarded
  • Emails: /dev/mailbox. Environment, database and migrations: /dev/system.
A page says migrations are pending

Press its Run migrations button, or run:

cargo run -- db migrate
Port 3000 is already taken
PORT=3001 bin/dev
Something's red

Ask the agent to run the Definition of Done and fix what fails:

/offrails:check

If the app has drifted from the conventions (say, after someone edited code by hand), /offrails:doctor audits it and /offrails:doctor --fix repairs it.