From superpowers-ruby
Upgrades Ruby interpreter version (3.x → 4.0.x) with breaking-change audit, mechanical toolchain edits, and verification for Bundler/Rails apps.
How this skill is triggered — by the user, by Claude, or both
Slash command
/superpowers-ruby:ruby-upgradeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill upgrades a Ruby application from one major/minor Ruby version to
This skill upgrades a Ruby application from one major/minor Ruby version to
another — currently targeting the Ruby 3.x → 4.0.x jump. It runs a
breaking-change risk audit against the codebase, writes a stakeholder-ready
analysis, applies the mechanical toolchain edits (.ruby-version, Dockerfile,
CI, RuboCop TargetRubyVersion, Gemfile pins), and verifies via bundle,
RuboCop, type checks, and the test suite.
This is the Ruby-interpreter upgrade. For Rails framework version bumps
(6.x → 7.x → 8.x, config.load_defaults, railsdiff), use the
superpowers-ruby:rails-upgrade skill instead. They are often done together —
run the Rails upgrade's Ruby-compatibility table first to confirm the target
Ruby is supported by the current Rails version.
Announce at start: "I'm using the ruby-upgrade skill to plan this Ruby upgrade."
Breaking-change inventory: references/ruby-4-0-changes.md (bundled with
this skill). It is the source of truth for detection patterns and remediations.
The user may ask for one of:
If the target patch isn't specified, default to the latest stable in the target line and say which you picked.
Confirm this is a Ruby/Rails repo before doing anything:
git rev-parse --show-toplevel
test -f Gemfile && test -f Gemfile.lock
Bail if Gemfile/Gemfile.lock are missing — this skill operates on a Bundler
project. Read references/ruby-4-0-changes.md now and keep it open as you audit.
Read in one parallel batch, recording each into a "Current state" table:
.ruby-version (current pin)Gemfile (note any ruby "..." / ruby file: directive)Gemfile.lock (RUBY VERSION, BUNDLED WITH, and key versions: rails,
sorbet/tapioca if present, openssl, logger, ostruct, benchmark, irb, reline,
pry, debug, nokogiri, pg, grpc, ffi, bcrypt, msgpack)Dockerfile / *.Dockerfile (the Ruby base-image line).github/workflows/*.yml, .gitlab-ci.yml,
.gitlab/ci/**/*.yml, .circleci/config.yml mentioning a Ruby version.rubocop.yml (AllCops: TargetRubyVersion)sorbet/config (only if the project uses Sorbet)Dispatch ONE Agent subagent (subagent_type: Explore) to sweep the codebase
for every change in references/ruby-4-0-changes.md. Hand it that file and ask
for counts + up to 5 file:line examples per change-NN entry. Cover all
entries (change-01 … change-14), and additionally list any HTTP-client gems
from the lockfile that wrap Net::HTTP.
Wait for the structured findings report before proceeding.
Write to a project-relative folder so it works in any repo:
docs/ruby-upgrade/<YYYY-MM-DD>/analysis.md
and if docs folder is not present write to:
tmp/ruby-upgrade/<YYYY-MM-DD>/analysis.md
(Use date +%Y-%m-%d. If the project already has a conventional analysis/report
location, prefer that and say so.)
Sections:
references/ruby-4-0-changes.md entry:
# | change | exposure (counts + file:line) | risk | action, each linking
back to the inventory anchor (e.g. (./../../skills/ruby-upgrade/references/ruby-4-0-changes.md#change-01) or by change number).config/initializers/, lock already on a newer Bundler, etc.).If the user asked for audit-only, STOP HERE and print the report path.
Branch hygiene first: if the current branch doesn't already encode this work,
suggest a name like upgrade-ruby-4-0-5 (prefix with the user's ticket id if
they gave one).
Make each edit only if the file actually pinned the old version — never invent files:
.ruby-version: write the target (e.g. 4.0.5\n).FROM ...ruby:3.X.X → ruby:<target>. Preserve any
private-registry prefix on the image (don't rewrite the registry host)..rubocop.yml: set AllCops: TargetRubyVersion: <major.minor>.Gemfile: add gem "cgi" if any removed CGI API is used (change-02).
Add gem "ostruct" / other demoted gems ONLY if app code requires them
directly and they aren't already resolved (change-03).Then re-resolve:
bundle update --ruby
Capture the resolution diff. If it fails on a specific gem (commonly grpc, a Sorbet package, or a hard pre-Ruby-4 pin), STOP applying and record the failing gem under a "Blockers" section in the report.
Run the relevant checks (in parallel where possible):
bundle exec rubocop # changed files or full repo
If the project uses RSpec execute:
bundle exec rspec --fail-fast
else execute:
bundle exec rails test
bundle exec srb tc # only if sorbet/config exists
bundle exec tapioca gem # only if the project uses Tapioca — regenerate RBIs
On failure: append a "Verification failures" section with the output, then
either fix-forward the obvious cases (RBI staleness, safe RuboCop autocorrects)
or stop and surface to the user. Do not claim success without showing passing
output — see superpowers-ruby:verification-before-completion.
Native-extension hint: if bundle install succeeded but tests crash on
require of a C-extension gem, a cached vendor/bundle was built against the
old ABI — rm -rf vendor/bundle && bundle install (change-09).
Suggest 24-hour monitoring on whatever error tracker the project uses for:
ArgumentError/backtrace fingerprints (change-10),Net::HTTP 400/415 responses from internal clients (change-01),.ruby-version without bumping every Dockerfile/CI image in the
same commit. Drift between them is the most common deploy-time failure for a
Ruby-major upgrade.gem "ostruct" (or other demoted gems) unless app code
directly requires them. Rails 7.1+ pins several transitively; a duplicate
fights the lock.--zjit in production on 4.0.x — experimental. Keep YJIT.CGI.parse, openssl pins, and monitoring fingerprint drift — none of
which the test suite catches.| Mistake | Fix |
|---|---|
| Editing files that never pinned the old version | Only edit files Phase 1 found pinning it |
| Rewriting a private registry host on the Docker image | Keep the prefix; change only the tag |
Adding gem "cgi"/"ostruct" blindly | Add only when the removed/demoted API is actually used |
| Declaring "tests pass" without output | Show the passing run (verification-before-completion) |
| Confusing this with a Rails upgrade | Rails framework bump → superpowers-ruby:rails-upgrade |
2plugins reuse this skill
First indexed Jun 21, 2026
npx claudepluginhub lucianghinda/superpowers-ruby --plugin superpowers-rubyAudits Ruby (and optional Rails) projects before upgrades: detects current/target versions, checks gem compatibility, breakage risks, computes paths, runs test baseline. Read-only.
Upgrades Rails applications between versions 5.2 and latest, assessing readiness, planning multi-hop paths, and handling breaking changes, deprecations, and config.load_defaults transitions.
Analyzes Rails applications and generates upgrade reports with breaking changes, deprecations, and migration guides for Rails 2.3 through 8.1. Useful when upgrading Rails apps or planning multi-hop upgrades.