Interactive CLI wizard for generating Rails 8 applications with customizable configuration and smart defaults.
Think of it as rails new with an opinion and a friendly interactive experience.
Requires Ruby 3.2 or newer. Development and release tooling use Ruby 4.0.5.
gem install railstart# Generate config files (optional, for customization)
railstart init
# Generate a new Rails app
railstart new my_app
# Or run without arguments for help
railstartThis launches an interactive wizard that guides you through Rails app setup:
Which database?
1) SQLite (default)
2) PostgreSQL
3) MySQL
> 2
Which CSS framework?
1) Tailwind (default)
2) Bootstrap
3) Bulma
4) PostCSS
5) None
> 1
Which JavaScript bundler?
1) Importmap (default)
2) esbuild
3) Webpack
4) Rollup
> 1
Skip any features?
(space to select, enter when done)
‣ ⓞ Action Mailer
ⓞ Action Mailbox
ⓞ Action Text
...
Generate API-only app?
> No
... (more questions) ...
Summary
════════════════════════════════════════
App name: my_app
Database: postgresql
CSS: tailwind
JavaScript: importmap
Skipped: (none)
API: No
════════════════════════════════════════
Proceed with app generation? Yes
Running: rails new my_app --database=postgresql --css=tailwind ...
Creating Rails app...
✨ Rails app created successfully at ./my_app
Presets are configuration overlays that let you define different defaults and even different questions/post-actions for specific use cases.
Important: When you use --default without --preset, Railstart automatically applies the default preset (from ~/.config/railstart/presets/default.yaml or the gem's built-in version). This means defaults may differ from the base rails8_defaults.yaml config.
Modes:
- Interactive (default): prompts for each question from the config schema
- With --default: skips questions, loads "default" preset, shows summary and confirms
- With --yes / -y: fully headless, implies
--default, requiresAPP_NAME, skips all confirmations (post-action prompts follow each action'sdefault) - With --preset: loads specified preset as config overlay (can be interactive or with --default/--yes)
# Interactive mode (builtin defaults)
railstart new my_app
# Non-interactive with "default" preset (asks no questions, shows summary + confirms)
# Note: --default automatically loads the "default" preset (user or gem)
railstart new my_app --default
# Fully headless mode (implies --default, no prompts at all)
railstart new my_app --yes
# Interactive with custom preset
railstart new my_app --preset api-only
# Fully headless with custom preset
railstart new my_app --preset api-only --yesCreate custom presets at ~/.config/railstart/presets/my-preset.yaml:
Presets use the same YAML schema as config files - they can override question defaults, change choices, add new questions, or modify post-actions:
# ~/.config/railstart/presets/api-only.yaml
# Presets merge on top of user config (and built-in config)
questions:
- id: database
choices:
- name: PostgreSQL
value: postgresql
default: true # Different default for this preset
- id: api_only
default: true # Override default to true for API preset
post_actions:
- id: init_git
enabled: false # Disable git init for this presetThen use it:
# Interactive with api-only config
railstart new my_app --preset api-only
# Non-interactive with api-only config
railstart new my_app --preset api-only --defaultPresets are powerful tools for defining opinionated Rails configurations for specific stacks or team standards.
Create a new preset file in ~/.config/railstart/presets/{name}.yaml:
---
# My Team Preset - PostgreSQL + Tailwind + Importmap
questions:
- id: database
choices:
- name: PostgreSQL
value: postgresql
default: true
- id: css
choices:
- name: Tailwind
value: tailwind
default: true
- id: javascript
choices:
- name: Importmap
value: importmap
default: true
rails_flag: "--javascript=importmap"
post_actions:
- id: init_git
enabled: trueThen use it:
# Interactive mode - prompts for each question
railstart new myapp --preset my-team
# Non-interactive mode - uses all preset defaults
railstart new myapp --preset my-team --defaultRailstart includes several ready-to-use presets:
default- PostgreSQL + Tailwind + Importmap (sensible defaults)api-only- Minimal Rails for JSON APIs (no views, no frontend)vite-bun- Modern SPA with Vite + Bundlebun
This repository also includes copyable YAML examples in examples/:
examples/config.yml- global defaults for~/.config/railstart/config.yamlexamples/presets/api-postgresql.yml- JSON API service with PostgreSQLexamples/presets/standard-postgresql.yml- full-stack PostgreSQL appexamples/presets/minimal-sqlite.yml- lightweight local prototype appexamples/presets/vite-bun.yml- Vite, Bun, Tailwind, and PostgreSQLexamples/presets/template-action.yml- template post-action reference
Use a preset example directly by passing its path:
railstart new my_app --preset ./examples/presets/standard-postgresql.yml --defaultOr copy one into your user presets directory:
cp examples/presets/standard-postgresql.yml ~/.config/railstart/presets/standard-postgresql.yml
railstart new my_app --preset standard-postgresql --defaultThe easiest way to get started with custom configuration is to generate template files:
railstart initThis creates:
~/.config/railstart/config.yaml- Minimal example containing only a few global overrides~/.config/railstart/presets/- Directory for your presets~/.config/railstart/presets/example.yaml- Example preset to get started
Keep config.yaml minimal so future built-in choices and flags continue to reach your installation. The full shipped schema remains available in config/rails8_defaults.yaml, while examples/config.yml provides a larger copyable example.
Railstart ships with sensible Rails 8 defaults defined in config/rails8_defaults.yaml. These drive the interactive questions and their defaults.
You can create ~/.config/railstart/config.yaml manually or use railstart init to generate a minimal starting point. Add only the defaults you want to change:
# After running `railstart init`, config.yaml contains a few example overrides.
# Keep only the overrides you want to apply to every run:
questions:
- id: database
default: postgresql
post_actions:
- id: bundle_install
enabled: false # Disabled - your team manages gems differently
- id: setup_auth
name: "Setup authentication"
enabled: true
command: "bundle exec rails generate devise:install" # New custom actionMerge behavior:
- User config (at
~/.config/railstart/config.yaml) overrides built-in config - By
id: questions and post-actions are merged by their uniqueid - If you override a question's
choices, the entire choice list is replaced - New questions/actions are appended in order
questions:
- id: database # unique identifier
type: select|multi_select|yes_no|input
prompt: "User-facing question"
help: "Optional inline help text"
default: value_or_true_or_false
# For select/multi_select
choices:
- name: "Display name"
value: "internal_value"
default: true # at most one per select
rails_flag: "--flag=%{value}"
# For yes_no/input
rails_flag: "--flag" # or --flag=%{value}
# Optional: only ask if condition is met
depends_on:
question: other_question_id
value: expected_valueQuestion types:
select- Single choice; returns scalar valuemulti_select- Multiple choices; returns arrayyes_no- Boolean; returns true/falseinput- Free text; returns string
post_actions:
- id: my_action # unique identifier
name: "Human readable name"
enabled: true # can be disabled
command: "shell command to run"
# Optional: prompt user before running
prompt: "Run this action?"
default: true
# Optional: only run if condition is met
if:
question: question_id
equals: value # or includes: [array, values]Post-actions can now execute full Rails application templates (including RailsBytes scripts) instead of plain shell commands.
post_actions:
- id: apply_tailwind_dash
name: "Apply Tailwind dashboard template"
type: template
enabled: false # keep disabled unless you trust the source
prompt: "Run the sample template?"
source: "https://railsbytes.com/script/zAasQK"
variables:
app_label: "internal-tools" # optional instance variables available inside templateKey differences from command actions:
- Set
type: templateand provide asource(local path or URL). Railstart streams that template into Rails' ownapplyhelper, so all standard DSL commands (gem,route,after_bundle, etc.) are available. variablesis optional; when present, its keys become instance variables accessible from the template (e.g.,@app_label). Railstart always exposes@app_nameand@answersfor convenience.- Template actions still honor
prompt,default, andifjust like command actions. Keep remote templates disabled by default unless you explicitly trust them.
For lightweight files (AGENTS.md, scripts, dotfiles) you can skip Rails templates entirely and write a file directly into the generated app. File actions never load Rails in-process.
post_actions:
- id: write_agents_md
name: "Create AGENTS.md for coding agents"
type: file
enabled: true
prompt: "Create AGENTS.md for coding agents?"
default: true
path: AGENTS.md # required, relative to the app root
source: AGENTS.md # template file (or use `content:` for an inline string)
overwrite: false # optional; skip instead of overwriting existing filesKey differences from template actions:
pathis required and must stay inside the app (absolute,~-prefixed, and..paths are rejected).- Provide exactly one of
content(inline string) orsource(file path). Relativesourcepaths resolve against the gem'sconfig/templates/directory; absolute or~/paths are used as-is. - Content supports
%{app_name}interpolation, like%{value}inrails_flag. Other%sequences pass through unchanged. overwritedefaults tofalse: existing files are skipped with a warning. Source-based writes keep the source file's executable bit.prompt,default, andifbehave exactly like command actions.
The built-in config ships two file actions: write_agents_md (enabled by default, writes an opinionated AGENTS.md for coding agents) and setup_bin_ci (opt-in; Rails 8.1+ already generates bin/ci).
# Install the required Ruby version
mise install ruby@4.0.5
# Install dependencies
bundle install
# Or use the setup script
bin/setup# Test the executable during development
bundle exec exe/railstart new my_app
bundle exec exe/railstart new my_app --default
# Interactive console for experimenting
bin/console
# Then in IRB:
# Railstart::CLI.start(["new", "my_app"])
# Install locally to test as a real gem
gem build railstart.gemspec
gem install railstart-[version].gem
railstart new my_app# Run tests
bundle exec rake test
# Lint code
bundle exec rubocop
# Lint and auto-fix
bundle exec rubocop -a
# Full check
bundle exec rake test && bundle exec rubocop && bundle exec rake yard && gem build railstart.gemspecRailstart merges configuration from three sources (in order):
- Built-in config:
config/rails8_defaults.yaml(shipped with gem) - User config:
~/.config/railstart/config.yaml(optional global overrides) - Preset (optional):
~/.config/railstart/presets/NAME.yaml(per-run overlay)
Each layer can:
- Override question defaults
- Replace choice lists entirely (by question ID)
- Add new questions
- Add/modify post-actions
- Enable/disable post-actions
Merging is by id for both questions and post_actions, allowing surgical overrides without duplicating entire configs.
- Generator (
lib/railstart/generator.rb) - Orchestrates interactive flow - Command Builder (
lib/railstart/command_builder.rb) - Translates answers torails newflags - CLI (
lib/railstart/cli.rb) - Thor command interface with--presetoption
Railstart ships with an agent skill at skills/railstart-coder/ for Codex- and Claude-style coding agents, installable with npx skills. The skill is structured as a lean SKILL.md plus focused reference files covering CLI usage, config layering, preset authoring, template post-actions, and gem development.
Bug reports and pull requests are welcome on GitHub at https://github.com/dpaluy/railstart.
The gem is available as open source under the terms of the MIT License.
Supported by Majestic Labs.