rails/rails
Generators and the CLI
How bin/rails works, the Thor-based command system, and the generator framework that powers rails new and rails generate.
The CLI entry point
railties/exe/rails is a one-line bootstrap:
require "rails/cli"railties/lib/rails/cli.rb figures out where it's being invoked from:
- Inside a Rails app — load
config/boot.rband dispatch toRails::Command. - Outside an app — fall back to
Rails::AppLoaderto either find an app in a parent directory or run the meta-command (rails new).
Rails::Command (railties/lib/rails/command.rb) is the dispatcher. It uses Thor's command lookup, with an extra layer that finds commands across:
- The
rails/commands/<name>/<name>_command.rbdirectories. - Engine-shipped commands.
- App-defined commands under
lib/tasks/.
Built-in commands
railties/lib/rails/commands/:
about— versions, env, database (inabout_command.rb).app— manage the app's structure.boot— boot the app and exit (useful for measuring boot time).console— IRB with the app loaded.credentials/encrypted/secret— encrypted credentials.db—db:create,db:migrate,db:rollback,db:seed,db:reset, etc.dbconsole— open the database client.dev— toggle dev caching, profile dev mode.devcontainer— generate / update.devcontainer/.destroy— undo a generator.gem_help,help— built-in help.generate— invoke a generator.initializers— print the resolved initializer order.middleware— print the middleware stack.new—rails new myapp.notes— collect annotations (TODO,FIXME, etc.) from source.plugin—rails plugin new.query— read-only query console (new in 8.2).restart— touchtmp/restart.txt.routes/unused_routes— show or audit the route table.runner— run a Ruby script with the app loaded.secret— generate a random secret.server— boot the web server.stats— code statistics for the app.test/test:system— Minitest runner.
Each command lives in its own directory (commands/<name>/<name>_command.rb) and is a Thor subclass.
Command resolution
graph LR
A["bin/rails X"] --> B[Rails::CommandsTasks]
B --> C{X is a command?}
C -->|yes| D[Rails::Command.invoke]
C -->|no| E[fall through to Rake]
D --> F[Thor: parse args, run command]
E --> G["Rake task X"]If a name isn't a registered command, the dispatcher falls through to Rake. This is why bin/rails routes is a command but bin/rails db:migrate is a Rake task (technically — the db:migrate command is a thin wrapper around the Rake task).
Generator framework
railties/lib/rails/generators/:
base.rb—Rails::Generators::Base, a Thor::Group subclass.app_base.rb— shared bits betweenrails newandrails plugin new.named_base.rb— for resource-named generators (scaffold,model,controller).actions.rb— high-level helpers (gem,route,environment,git,template).database.rb— picks the right database adapter scaffolding.js_package_manager.rb— Yarn/npm/bun/Importmap selection.migration.rb,model_helpers.rb,resource_helpers.rb— shared scaffolding.rails/— the built-in generators.test_unit/— generators for test files (one per resource type).erb/— view scaffolding templates.
Built-in generators
railties/lib/rails/generators/rails/:
app/—rails new(the largest generator; ~50 files).application_record/assets/benchmark/channel/controller/db/system/change/devcontainer/dev_container/generator/helper/integration_test/master_key//credentials/migration/model/plugin/resource/scaffold/scaffold_controller/script/system_test/task/
Each generator is a Thor::Group of named tasks. For example, Rails::Generators::ScaffoldGenerator invokes model, scaffold_controller, helper, assets, system_test, and test_unit:scaffold in sequence.
Application generator
Rails::Generators::AppGenerator (railties/lib/rails/generators/rails/app/app_generator.rb) is the most complex. It creates:
Gemfile,Gemfile.lock(skeleton)config/(application.rb, environments, initializers, routes, database.yml)app/(controllers, models, views, helpers, channels, jobs, mailers)bin/(rails, setup, dev, ci, kamal-style scripts)db/seeds.rbtest/(orspec/if--rspec)Dockerfile,.dockerignore,bin/docker-entrypoint.kamal/secrets,config/deploy.yml(Kamal scaffolding)config/storage.yml(Active Storage)config/cable.yml(Action Cable)app/javascript/(if Importmap is the default)package.jsonif a JS bundler is selected
Many decisions are flag-driven: --api, --minimal, --javascript=esbuild, --css=tailwind, --database=postgresql, etc. Each option is implemented as a method group inside AppGenerator plus lib/rails/generators/rails/app/templates/.
Testing generators
Rails::Generators::TestCase (railties/lib/rails/generators/test_case.rb) is a base class that provides:
run_generator— invoke the generator in a temp directory.assert_file,assert_no_file,assert_directory.- File content assertions via regexes.
Tests live under railties/test/generators/.
Application templates
The --template flag and the standalone bin/rails app:template command apply a template script to an existing app:
rails new myapp --template=https://example.com/template.rbThe DSL exposed by templates is in railties/lib/rails/generators/actions.rb: gem, gem_group, add_source, route, inside, git, generate, rake, rails_command, environment, lib, vendor, initializer, template, after_bundle.
Configuration
config.generators (set in config/application.rb) controls generator defaults:
config.generators do |g|
g.test_framework :minitest
g.fixture_replacement :factory_bot
g.javascript_engine :esbuild
endImplementation in railties/lib/rails/generators.rb. Apps can also override defaults per-environment.
Hooks and discovery
Rails::Generators.hide_namespace hides built-in generators from the help output. Rails::Generators.invoke is the public entry point used by rails generate <name>.
Generators discovered:
- Across all loaded gems, scanning
lib/generators/<name>/<name>_generator.rb. - From the app at
lib/generators/<name>/<name>_generator.rb. - From engines via their
Rails::Engine.generatorsblock.
Entry points for modification
- Adding a sub-command: new
Rails::Command::Basesubclass underrailties/lib/rails/commands/<name>/<name>_command.rb. Tests underrailties/test/commands/. - Adding a generator: new
Rails::Generators::NamedBasesubclass underrailties/lib/rails/generators/rails/<name>/. Templates under the same directory'stemplates/. Tests underrailties/test/generators/. - Modifying
rails new: editRails::Generators::AppGeneratorand templates underrailties/lib/rails/generators/rails/app/templates/. There's a lot of test coverage here —rake test:isolatedexercises real generator runs.
Related pages
- packages/railties
- how-to-contribute/tooling — the test runner that all
bin/testscripts share.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.