From rails
This skill should be used when upgrading a Rails application from one minor version to the next. Guides the full upgrade process: updating gems, running app:update, booting the app, fixing deprecation warnings, running tests, and progressively enabling new framework defaults. Enforces one minor version per invocation following Rails' official recommendation. Activates on: "upgrade rails", "upgrade to Rails", "rails upgrade", "update rails version", "bump rails", "next rails version", "rails version upgrade", "upgrade my rails app", "move to Rails", "rails upgrade path", "aggiornare rails", "aggiornamento rails".
npx claudepluginhub fabn/claude-plugins --plugin railsThis skill uses the workspace's default tool permissions.
Upgrade a Rails application one minor version at a time, following the official
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Upgrade a Rails application one minor version at a time, following the official Rails upgrade guide. Each invocation handles a single version bump (e.g., 7.1→7.2, not 7.1→8.0). For multi-version jumps, run this skill repeatedly.
Reference files: Consult reference/version-changes.md for breaking changes
and common gotchas per Rails version.
Establish the starting state before making any changes.
Detect current Rails version:
bundle exec rails runner "puts Rails.version"
Determine target version: Ask the user which version to upgrade to, or default to the next minor version. Validate it's exactly one minor version ahead. If the user wants to skip versions, explain they should upgrade incrementally and offer to start with the next minor.
Verify clean git state:
git status --porcelain
If there are uncommitted changes, ask the user to commit or stash first.
Run the test suite to establish baseline health:
bundle exec rspec --format progress
Record the result. If tests are already failing, warn the user — it's best to start an upgrade from a green test suite. Ask if they want to proceed.
Verify the app boots:
bin/rails runner "puts 'Boot OK: Rails ' + Rails.version"
Capture existing deprecation warnings (for comparison later):
RUBYOPT="-W:deprecated" bin/rails runner "puts 'done'" 2>&1 | grep -i deprec
Note these — some may already exist and should not be confused with upgrade-introduced warnings.
Change the Rails gem version in Gemfile:
gem 'rails', '~> X.Y.0'
Where X.Y is the target version.
Run bundle update:
bundle update rails
Handle dependency conflicts: If bundle update fails, read the error and resolve iteratively:
bundle update rails gem_a gem_bVerify the bundle resolves:
bundle check
Commit the gem update:
git add Gemfile Gemfile.lock
git commit -m "Update Rails to X.Y"
app:update TaskThe app:update task updates config files, binstubs, and generates new
framework defaults.
bin/rails app:update
This produces file-by-file conflicts. Handle them as follows:
Auto-revert config/application.rb: This file almost never needs
changes from the update task. Before reverting, check if app:update
changed the load_defaults line — if so, keep the old load_defaults
value (Step 9 handles that transition). Then revert:
git checkout config/application.rb
For each changed config file, examine the diff:
git diff config/
For each file, use AskUserQuestion to present the diff and ask the user whether to:
Guidelines for common files:
config/environments/*.rb: Review carefully. New settings are usually
safe to accept. Removed settings may indicate deprecated config.config/initializers/: Accept new initializers. Be cautious with changes
to existing ones.bin/*: Usually safe to accept (binstub updates).config/boot.rb, config/environment.rb: Rarely change. Accept if
they do.Accept whitespace-only or comment-only changes unless they break linting. Don't bother the user with these.
Commit accepted changes:
git add config/ bin/
git commit -m "Update config files for Rails X.Y"
Verify the application boots after the config changes:
bin/rails runner "puts 'Boot OK: Rails ' + Rails.version"
If it fails:
git add -A && git commit -m "Fix boot after Rails X.Y upgrade"
Check if the update task installed any new migrations:
bin/rails db:migrate:status | grep down
If there are pending migrations, invoke the rails:migrate skill workflow
to run them with a clean schema diff. Do not duplicate that workflow here —
reference it by name.
If no migrations are pending, skip this step.
Capture deprecation warnings introduced by the upgrade:
RUBYOPT="-W:deprecated" bin/rails runner "puts 'done'" 2>&1 | grep -i deprec
Also run a quick test pass to surface runtime deprecations:
bundle exec rspec --format progress 2>&1 | grep -i deprec
Compare against the pre-upgrade warnings from Step 1. For each new warning:
Commit deprecation fixes as a group:
git add -A && git commit -m "Remove deprecation warnings for Rails X.Y"
Consult reference/version-changes.md for breaking changes specific to the
target version. Cross-reference with the project:
Search for affected APIs:
# Example: if the upgrade guide says `before_filter` is removed
grep -r "before_filter" app/
Apply necessary changes based on the reference file's guidance for this version pair
Commit version-specific fixes:
git add -A && git commit -m "Apply version-specific changes for Rails X.Y"
If no version-specific changes affect the project, skip this step.
Run the full test suite, excluding slow JavaScript/system tests:
bundle exec rspec --format progress --tag ~js --tag ~system
If the project uses a different exclusion method (e.g., --exclude-pattern),
adapt accordingly:
bundle exec rspec --format progress --exclude-pattern "**/system/**"
For failures:
git add -A && git commit -m "Fix test failures after Rails X.Y upgrade"
If the system/JS tests were skipped, mention this to the user and suggest running them separately after the upgrade is stable.
The app:update task in Step 3 generated a file like
config/initializers/new_framework_defaults_X_Y.rb. This file contains all
new defaults commented out.
The goal is to enable each default, verify nothing breaks, and eventually
update config.load_defaults to the new version.
Read the defaults file:
cat config/initializers/new_framework_defaults_X_Y.rb
For each default setting:
a. Uncomment it (enable it)
b. Check if the app boots: bin/rails runner "puts 'OK'"
c. Run the test suite (or relevant subset)
d. If tests pass → keep it enabled
e. If tests fail → assess whether the failure is a real bug or expected
behavior change. Use AskUserQuestion to ask the user about risky ones
(e.g., encryption changes, cookie format changes, cache format changes)
f. If the user defers a default, re-comment it with a # TODO: note
Batching tip: Low-risk defaults (naming conventions, log formatting, whitespace behavior) can be enabled in batches. High-risk defaults (serialization formats, encryption, cache format versions) should be enabled one at a time with full test runs.
After all safe defaults are enabled, check if all settings are uncommented. If yes:
new_framework_defaults_X_Y.rb fileconfig/application.rb:
config.load_defaults X.Y
config.load_defaults at the old version. Add a
comment explaining why.Commit:
git add config/
git commit -m "Enable Rails X.Y framework defaults"
| Situation | Action |
|---|---|
| Bundle update fails with conflicts | Identify conflicting gems, update them alongside rails, ask user about substitutions |
| App doesn't boot after gem update | Check error, fix missing/renamed gems or config, iterate |
app:update overwrites custom config | Revert the file, apply only specific needed changes manually |
| Tests fail with unclear errors | Consult reference/version-changes.md for known breaking changes in the target version |
| Framework default breaks tests | Re-comment it, add TODO note, ask user about the expected behavior change |
| User wants to skip multiple versions | Explain incremental upgrade is safer, offer to start with the next minor |
rails:migrate skill not available | Run migrations manually: RAILS_ENV=test bin/rails db:migrate and verify schema diff |
| Pre-existing test failures | Warn user, record baseline failures, distinguish them from upgrade-caused failures |
After completing all steps, summarize for the user:
reference/version-changes.md — Breaking changes and common gotchas per Rails version (7.0→7.1, 7.1→7.2, 7.2→8.0, 8.0→8.1)