For AI Agents
RailsFast is built to be driven by AI agents end to end — not as a marketing line, but as a set of testable guarantees. An agent has taken a fresh clone to a branded, deployed production app with the human only touching secrets. This page is the contract that makes that repeatable.
Why it works so well: convention over configuration is the best agent
interface ever shipped. Every Rails app looks the same, so your agent has
effectively already seen your codebase. No build step, no node_modules
maze, boring omakase technology — fewer places for an agent to get lost.
Point your agent at these
- Docs, LLM-shaped: railsfast.com/docs/llms.txt — the entire documentation as one plaintext file.
- In-repo context: every clone ships
AGENTS.md/CLAUDE.mdplus.cursor/rules/describing the stack and quality bar. Claude Code additionally auto-discovers the bundledrailsfastskill (.claude/skills/railsfast/) — the workflow verbs and the gotchas that aren't guessable from the file tree. - MCP: the project serves its own state over the Model Context Protocol. One line in any MCP-capable host:
{ "mcpServers": { "railsfast": { "command": "bin/railsfast", "args": ["mcp"] } } }
Tools: doctor (production readiness), status (template sync state), project_info (app identity + docs pointers). Read-only, stdlib-only, zero config.
The guarantees
- Non-interactive everything:
bin/railsfast init --yes --name "My App"takes a fresh clone to a configured, committed, database-ready project with zero prompts. The name is kept exactly as typed. - One deterministic gate:
bin/ciruns RuboCop, dependency audits, Brakeman, the full test suite, system tests, and seed verification. It keeps going past failures and reports everything at the end — one command, one exit code, no judgment calls. - Machine-readable state:
.railsfast/config.jsonrecords what the project is and which template commit it's based on;bin/railsfast statusand the MCPstatustool read it back. - Self-diagnosing setup:
bin/railsfast doctor(or--json) lists everything still unconfigured — placeholder credentials per service, deploy config, backups, branding — and every finding carries its own fix. Exit0means production-ready; branch on it. - Deploys are reproducible:
bin/kamal deploybuilds from git HEAD via a clean clone. If it's not committed, it doesn't ship — an agent can reason about exactly what's live. - Verifiable health: after a deploy,
https://yourdomain.com/healthcheck(allgood) is the agent's post-deploy assertion.
Day zero: from one sentence to a live site
The entire quickstart is agent-executable. The human's job is one
sentence — "I want to build MyProject on myproject.com" — plus answering a
few questions and creating exactly two API tokens. Everything else, the agent
does: it even installs its own tools (brew install hcloud) if they're missing.
What the agent should ask before touching anything
An agent driving the quickstart should qualify the run first (one batch of questions, not twenty interruptions), and always recommend a good default:
- Name + domain — if not already given in the starting sentence. Deploying to a subdomain of a domain the human already has on Cloudflare is the fastest path; a fresh domain is a human purchase (agents can't buy domains).
- New server, or reuse one? — new costs real money: quote the actual price (
hcloud server-type describe ...) and get an explicit yes beforehcloud server create. Reuse means: which IP, and skip server creation. - Which location? — physically close to the app's users. Check live stock first: cheap models come and go per location (
hcloud server-type list). - SSH key: generate fresh, or reuse? — recommend a fresh per-project
ed25519key (ssh-keygen -t ed25519 -f ~/.ssh/myproject_hetzner -N ""): revocable independently, no passphrase prompts to block automation. Reusing an existing key is fine if the human prefers it. - Remote builder? — on Apple Silicon the answer is almost always yes (why): that's a second, small server (same cloud-config), so include it in the spend quote.
- Where does the private GitHub repo live? —
gh repo createunder which account/org.
The two human steps
Both are "create an API token while logged in" — genuinely human (password + 2FA), one minute each:
- Hetzner: Console → your project → Security → API tokens → Generate (Read & Write).
- Cloudflare: profile → API tokens → Create Token → "Edit zone DNS" template → scope it to the one zone, and add Zone → Zone Settings → Read (plus Edit only if the agent may need to set the SSL mode).
Where a step truly needs a human, the agent should say exactly what to click and what scopes to grant — like above — and nothing more.
The secret handoff pattern
Tokens should never be pasted into a chat: transcripts get logged, summarized, and sometimes shared. The pattern that keeps secrets out of band — the human copies the token to the clipboard, then runs:
mkdir -p ~/.config/railsfast && pbpaste > ~/.config/railsfast/hcloud_token && chmod 600 ~/.config/railsfast/hcloud_token
(macOS pbpaste; Linux: xclip -o or wl-paste.) Same for
cloudflare_token. The agent then reads it inline where needed —
HCLOUD_TOKEN="$(cat ~/.config/railsfast/hcloud_token)" hcloud ... — and never
echoes it. The token exists in exactly two places: the provider dashboard and a
chmod 600 file.
The provisioning sequence
The quickstart, as an agent runs it (every step links to its agent-lane block there):
clone template → gh repo create + push → bin/railsfast init --yes --name "My Project"
→ ssh-keygen → hcloud server create (cloud-config, deploy + builder) → firewall
→ Cloudflare A record + SSL-mode check → poll /etc/railsfast-setup.version readiness
→ fill deploy.yml (IPs, host, key) → commit → kamal accessory boot all
→ kamal registry setup → kamal deploy → assert /healthcheck
Server initialization (~5 min) overlaps with DNS and deploy.yml work, so
wall-clock from sentence to live site is dominated by the first Docker build.
Day one: configuring every service
After the site is live, bin/railsfast doctor --json is the agent's
worklist: every remaining finding, machine-readable, each carrying its own
fix. The configuration page carries a
terminal/agent lane for each service. The orchestration layer:
Ask first, in one batch (like day zero — again with recommended defaults):
which AWS profile and SES region (aws sts get-caller-identity tells you
what's already authenticated); the mailbox addresses; which services to skip
for now (Stripe needs KYC on fresh accounts — a fine skip for a first pass);
and the one extra token (Cloudflare account-scoped, R2 Edit + Turnstile
Edit — distinct from day zero's zone-scoped DNS token).
Then verify everything empirically — configured ≠working. The agent's post-configuration assertions, all validated lanes:
- Email: identity status via
aws sesv2 get-email-identity, then a real message from production (the smoke test) — the human confirms SPF/DKIM/DMARC allPASSin the received headers. - Storage: an Active Storage round trip from production
(
upload → exist? → deleteviabin/kamal app exec --reuse 'bin/rails runner ...'). - Turnstile: the widget script and sitekey render on
/users/sign_up. - Backups: trigger one manually and list the bucket (verify-your-backups lane).
- The gate:
bin/railsfast doctorexits clean apart from deliberate skips, and/healthcheckstays green after the redeploy.
Day two: something to sell
Credentials make payments possible — an actual sellable product needs three more things, in order:
- Plans in code: define them in
config/initializers/pricing_plans.rb(pricing, limits, features, marketing bullets) — pure Ruby, fully agent-editable. - Products and Prices in Stripe: one Product per plan plus its recurring
Price(s) — fully agent-executable under the
permission list (sandbox first with the
CLI, live with the org key — commands in that guide). Wire the returned
price_…IDs intoconfig/railsfast/railsfast.ymlunderstripe.plans, and switch each plan from the hardcodedpriceto thestripe_priceline the initializer already stubs out. - The human gates: finishing Stripe account activation (identity
verification — only a human can attest to that), and the branding pass
(logo, OG image, favicon —
doctor's "optional" list).
A good agent flow treats this as its own conversation: propose plan names, prices and limits from what it knows about the product, get the human's yes, then create everything and wire it up.
Day three: operations on (mostly) autopilot
Once the app is live, configured, and selling, the operational loop is:
allgood (/healthcheck — the sensor) → UptimeRobot (the trigger — it
has an API, so monitor creation is agent work) → Telegram (the channel —
the template's admin notifications, one credential block) → you or your
agent (the responder). Wire those once and incidents find you; nothing
polls a dashboard.
The standing cadence an agent can run on your behalf:
- Weekly fleet sweep:
bin/railsfast doctor --json+ a/healthcheckprobe + a skim ofbin/kamal logsacross every app — report anything actionable, touch nothing without a human yes. - Restore drill, once per app (and after any backup-pipeline change): the runbook against a scratch database. A backup that's never been restored is hope, not disaster recovery.
- Template updates: check
bin/railsfast statusfor drift; when a release ships, run the updating protocol on a branch and hand the human a green-CI PR. - Server maintenance: security patches auto-apply, but kernel updates
need a reboot — when
sshgreets you with*** System restart required ***, schedule one (containers come back on their own). Re-run the verify script quarterly. - Know the escape hatch before you need it:
bin/kamal rollbackexists and Kamal retains the last releases for exactly this — practice it once.
What stays human on day three: acknowledging a real incident, anything account-destructive, and spend changes. Everything else above is safe, reversible agent work.
The complete handoff manifest
Everything a human hands over, in total, for a fully hands-off clone-to-configured-production run — each one a "create while logged in" step delivered via the secret handoff pattern above:
| # | Handoff | Where | Scope |
|---|---|---|---|
| 1 | Hetzner API token | Console → project → Security → API tokens | Read & Write |
| 2 | Cloudflare zone token | profile → API tokens | Zone: DNS Edit, Zone Read, Zone Settings Read (+ Edit only if the SSL mode may need changing) |
| 3 | Cloudflare account token | profile → API tokens | Account: Workers R2 Storage Edit + Turnstile Edit |
| 4 | AWS CLI auth | aws configure (usually already done) |
a profile able to create IAM users/policies — the agent then mints per-project scoped users itself |
| 5 | GitHub CLI auth | gh auth login (usually already done) |
repo scope |
| 6 | Stripe login | stripe login (browser, once per account) |
yields all dev credentials |
| 7 | Stripe restricted key | Dashboard → API keys → restricted key | the [[guides/stripe-organizations |
That's the whole surface. Items 4–5 are usually already true on a dev machine; on a fresh project under an existing setup, the marginal human cost is three tokens, one login, and one restricted key — a few minutes, total. Deliberately not on the list: anything account-destructive (deleting repos, closing accounts). Keep those human.
The loop your agent should run
small change → bin/ci → commit → bin/kamal deploy → check /healthcheck
That's the whole workflow. The develop guide has the human version of the same story.
Console steps in these docs (Hetzner, Cloudflare, AWS) increasingly carry CLI equivalents in collapsible blocks — those are the agent lane. Where a step truly needs a human (buying a domain, an OTP), the docs say so explicitly.