Rails Hyperdrive: supercharged agentic development for Rails Evil Martians built Rails Hyperdrive, a development-only Rails engine that lets any gem in a bundle ship agent knowledge and exposes eight MCP (Model Context Protocol) tools that answer live from a booted app. The tool follows the Agents on Rails benchmark Evil Martians built for the Rails Foundation, in which Claude Opus 5 and Claude Fable 5.1 each passed 58 of 63 runs but the best models reached for the Rails API the task turned on in only 41% of runs. Rails Hyperdrive ships no knowledge of its own; the bundle decides what the agent learns, with companion gems such as layered-rails-skills@3.1.0 installing a skill, two agents, and eight commands into a project's .claude/ directory. Rails Hyperdrive: supercharged agentic development for Rails Every session, a coding agent meets your Rails app like a stranger. It reads the Gemfile, greps routes.rb , trusts a db/schema.rb that may lag behind the migrations, and guesses the rest from training data. This burns tokens before the first line of work, and these guesses cause bugs. We’ve measured this. In Agents on Rails https://evilmartians.com/clients/rails-foundation , the benchmark Evil Martians built for the Rails Foundation https://rubyonrails.org/foundation , the leading models pass most atomic Rails tasks Claude Opus 5 and Claude Fable 5.1 both pass 58 of 63 runs https://rubyonrails.org/2026/9/2/agents-on-rails-claude-fable-5-1-and-glm-5-3-flash , yet even the best reach for the Rails API the task turns on https://github.com/rails/ai-evals/blob/main/methodology.md in only 41% of runs; the rest of the time, it writes its own version. Frontier models are good at Rails. They’d be much better if someone handed them what the framework and your gems already document. That’s why Evil Martians built Rails Hyperdrive. In this article, we’ll cover all you need to know. Rails Hyperdrive https://github.com/rails-hyperdrive/rails-hyperdrive is a development-only engine that lets any gem in your bundle ship agent knowledge, installed only when your Gemfile calls for it, with eight MCP https://modelcontextprotocol.io Model Context Protocol tools on the side that answer live from your booted app. The engine ships no knowledge of its own. Instead, your bundle decides what your agent learns. In this post, we’ll install Rails Hyperdrive, edit what it installs, watch an upgrade collide with those edits, hand the collision to an agent, and show gem authors how to plug in with nothing but markdown files and one gemspec line. We’ll start from a fresh rails new app Rails 8.1, SQLite, the default Gemfile and nothing else and add two gems to the development group: the engine itself and one companion gem , that is, an ordinary gem whose payload is agent knowledge. Then comes the init: bash $ bundle add rails-hyperdrive layered-rails-skills --group=development $ bin/rails hyperdrive:init create .mcp.json append .gitignore append Gemfile insert config/routes.rb create .hyperdrive/config.yml create .claude/skills/layered-rails/SKILL.md ... 47 more skill files ... create .claude/agents/layered-rails-planner.md create .claude/agents/layered-rails-reviewer.md create .claude/commands/layered-rails-analyze-callbacks.md ... 7 more command files ... create .hyperdrive/lock.yml done hyperdrive initialized Mount: / hyperdrive in config/routes.rb Server: 8 MCP tools at http://localhost:3000/ hyperdrive/mcp Installed 1 skill, 0 guidelines, 2 agents, 8 commands layered-rails-skills@3.1.0 skill layered-rails +47 files agent layered-rails-planner agent layered-rails-reviewer command layered-rails-analyze ... 7 more commands ... The engine has mounted an MCP server inside your dev server and it wrote .mcp.json so Claude Code https://claude.com/claude-code picks it up automatically. The companion gem handled the other half: layered-rails-skills https://github.com/palkan/layered-rails-skills installed an architecture skill SKILL.md plus 47 supporting files into .claude/skills/ , where your agent loads it on demand. The skill is Vladimir Dementyev’s Layered Rails skill https://github.com/palkan/skills , the coding-agent distillation of Layered Design for Ruby on Rails Applications https://www.packtpub.com/en-us/product/layered-design-for-ruby-on-rails-applications-9781806114221 which has been shipped as a companion by the skill’s author. But that skill didn’t come alone. Here’s the whole .claude/ tree after init: bash $ tree -L 3 .claude .claude ├── agents │ ├── layered-rails-planner.md │ └── layered-rails-reviewer.md ├── commands │ ├── layered-rails-analyze-callbacks.md │ ├── layered-rails-analyze-gods.md │ ├── layered-rails-analyze-services.md │ ├── layered-rails-analyze.md │ ├── layered-rails-archspec.md │ ├── layered-rails-plan.md │ ├── layered-rails-review.md │ └── layered-rails-spec-test.md └── skills └── layered-rails ├── examples ├── references ├── SKILL.md └── workflows 8 directories, 11 files The same init installed two sub-agents into .claude/agents/ : layered-rails-reviewer , which checks code for layer violations, and layered-rails-planner , which drafts a phased adoption roadmap. It also dropped eight slash commands into .claude/commands/ . Open one and you’ll find a few lines that route into a workflow file inside the installed skill: bash $ cat .claude/commands/layered-rails-review.md /layered-rails-review Standalone code review from a layered architecture perspective. ... usage block omitted ... Read and follow skills/layered-rails/workflows/review.md ../skills/layered-rails/workflows/review.md , applied to the diff or file path s given as arguments. The knowledge lives in one place and the agents and commands are its entry points. To see what an entry point buys you, let’s give the demo app a deliberately fat OrdersController create that sums line items, applies a promo code, sets the initial status, and logs large orders, all inline. And we’ll run the review command on it: bash $ claude -p "/layered-rails-review app/controllers/orders controller.rb" Layered Rails Review Files Reviewed - app/controllers/orders controller.rb Presentation - Context read: app/models/order.rb , app/models/line item.rb Domain , app/mailers/order mailer.rb , app/views/orders/ , db/schema.rb , test/models/ Layer Analysis - Layers touched: Presentation → Domain direct , Presentation → Infrastructure mailer - Data flow: Violation detected — pricing/discount/status rules live in the Presentation layer ... 2 more lines omitted ... Findings 🔴 Critical: Business logic in controller domain calculation Location: app/controllers/orders controller.rb:13-15 ... the three quoted controller lines omitted ... Problem: Three domain rules — how a total is computed, what "SPRING10" means 10% off, minimum $100 , and what state a new order starts in — are encoded in an HTTP handler. Order knows none of them. Any second creation path admin console, API controller, Rails console, import job, a future Order.create in a test produces an order with total cents = nil and status = nil . The schema permits exactly that: both columns are nullable with no default and no validation. Fix: Move the rules to Order ; the controller keeps params extraction and response. ... fix code, 2 warnings, and 3 suggestions omitted ... Summary ... "Good" list omitted ... Needs Attention: 1. 🔴 Total, discount, and initial status are domain rules stranded in create — move to Order 2. ⚠️ Order is anemic and untested as a result 3. ⚠️ Nil price cents / quantity raises NoMethodError before validation runs 4. 💡 Promo catalog → value object; large? → model predicate One fat action in, a prioritized findings list out, produced by the workflow the command points at. That’s what the artifacts are for; the skill holds the knowledge, and the commands and agents put it to work. That’s three of the four artifact kinds a companion can install. The fourth, guidelines, showed up in the init summary as a zero; we’ll meet a real one later. These kinds differ in exactly one dimension, namely, who activates the content, and when: | Kind | Who activates it and when | Install destination | |---|---|---| | Skill | Lazy: the agent loads it when the task matches its description—costs nothing until then | .claude/skills/ | | Agent | Delegated: a specialist takes a bounded job off the main session’s hands | .claude/agents/ | | Command | Invoked: you type /layered-rails-analyze , that workflow runs now | .claude/commands/ | | Guideline | Eager: short declarative rules in the agent’s context at all times | CLAUDE.md , via @ -import | Everything a companion installs shows up in git status and nothing ends up gitignored except the engine’s own cache for the discover command we’ll meet later. The .hyperdrive/ directory holds the engine’s two bookkeeping files, a settings file that’s yours and a lock that’s the engine’s; we’ll open both when an upgrade forces the question. Let’s look at what we got: bash $ git status --short M .gitignore M Gemfile M config/routes.rb ?? .claude/ ?? .hyperdrive/ ?? .mcp.json The MCP server is live the moment you boot bin/rails server . The agent’s tools answer from the running process; they ask the router instead of grepping routes.rb and read the live database schema instead of trusting db/schema.rb . Here’s the tool list straight from the endpoint: bash $ curl -s http://localhost:3000/ hyperdrive/mcp \ -H 'Content-Type: application/json' -H 'Accept: application/json' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq -r '.result.tools .name' describe app run ruby run sql tail logs list models locate source lookup doc list routes Either half is skippable: hyperdrive:init --skip-content sets up the MCP server without any content, and --skip-mcp does the reverse. But live introspection is table stakes. The other half is the reason this project exists. Package managers for agent knowledge already exist. npx skills https://github.com/vercel-labs/skills installs any GitHub repo with a SKILL.md in it into your agent’s skills directory and Claude Code plugin marketplaces https://code.claude.com/docs/en/plugin-marketplaces distribute versioned catalogs of skills and commands. Both leave you as the resolver: you find the knowledge, judge whether it fits your stack, and install it, whether or not you run the library the advice is about. Laravel Boost https://github.com/laravel/boost goes further it reads your composer.json and installs matching guidelines and skills but the knowledge for the ecosystem’s major packages lives inside Boost itself, one curated repo maintained by the Laravel team, with per-version variants for the stack Laravel blesses: Livewire https://livewire.laravel.com , Inertia https://inertiajs.com , Pest https://pestphp.com . That works because Laravel apps overwhelmingly run those defaults. Rails blesses defaults too omakase https://dhh.dk/2012/rails-is-omakase.html , famously does this . But the same essay grants that “substitutions are allowed, within reason”, and the community exercises that right constantly. RSpec https://rspec.info or Minitest https://github.com/minitest/minitest . Sidekiq https://sidekiq.org or Solid Queue https://github.com/rails/solid queue or GoodJob https://github.com/bensheldon/good job . Hotwire https://hotwired.dev or Inertia https://inertiajs.com . Every mature Rails app is a different intersection of choices, which means a single guideline pack would be wrong for most apps most of the time. An agent told about Minitest conventions in an RSpec codebase is actively worse than one given no guidance at all. So Rails Hyperdrive ships zero content : no skills or guidelines go in your agent’s context window by default. What it ships is a contract. This means any gem can carry agent knowledge, declare what stack it targets, and the engine installs the intersection. Your bundle decides what your agent learns. This division of labor is convention over configuration, applied to agent knowledge. A companion gem with no manifest at all installs its content universally; a gem-root hyperdrive.yml manifest exists only to declare where your content deviates from “applies everywhere”. Every key is optional; you configure the exception, not the rule. The layered-rails-skills companion shows why gating installing a file only when the app’s bundle calls for it earns its place. The skill ships reference manuals for nine specific gems: Alba https://github.com/okuramasafumi/alba , Action Policy https://github.com/palkan/action policy , ViewComponent https://viewcomponent.org , and six more. The companion’s rule: advice that helps you pick a gem installs everywhere, but a reference manual for a gem you don’t bundle is dead weight and dangling links. So the nine manuals are gated, and our bare demo app got none of them: of the skill’s 57 markdown files some 14,700 lines of guidance exactly 48 hit. Add two of those nine gems: bash $ bundle add alba action policy ... Bundler output omitted ... $ bundle install ... Bundler output omitted ... hyperdrive installed 2 artifact s : .claude/skills/layered-rails/references/gems/action-policy.md .claude/skills/layered-rails/references/gems/alba.md hyperdrive 1 artifact s need attention — run bin/rails hyperdrive:sync .claude/skills/layered-rails/SKILL.md layered-rails-skills@3.1.0 → layered-rails-skills@3.1.0 The manuals arrived during bundle install itself, courtesy of a Bundler https://bundler.io plugin that hyperdrive:init registered in the Gemfile. That’s why the transcript runs both commands: Bundler activates a newly declared plugin only on bundle install , so this first bundle add ran without it; from here on, bundle add triggers it too. The plugin is additive-only and quiet by contract: it never rewrites an installed file and never fails your bundle. Anything beyond adding new files, it defers. Specifically, that’s the “need attention” line, and it’s why the arrow shows the same version on both sides: the gem didn’t move, your bundle did. Run the sync, and the skill’s entry file re-renders its gem-reference table: bash $ bin/rails hyperdrive:sync force .claude/skills/layered-rails/SKILL.md ... 59 "unchanged" lines, lock update, and summary omitted ... $ git diff .claude/skills/layered-rails/SKILL.md @@ -194,6 +194,8 @@ For library-specific guidance: | Gem | Purpose | Reference | |-----|---------|-----------| +| action policy | Authorization framework | action-policy.md references/gems/action-policy.md | +| alba | JSON serialization | alba.md references/gems/alba.md | | archspec | Enforce layer boundaries in CI reference Archspec.rb config | archspec.md references/gems/archspec.md | Two rows joined a table that already existed the archspec https://github.com/crmne/archspec row is ungated and was there from init and each row lives only as long as its gem stays in the bundle. Now, bundle remove alba and sync again: bash $ bin/rails hyperdrive:sync force .claude/skills/layered-rails/SKILL.md remove .claude/skills/layered-rails/references/gems/alba.md ... lock update and summary omitted ... That force on SKILL.md is safe by construction. Rails Hyperdrive’s lock file more on it shortly records a content hash showing the file unedited, and a plain sync only overwrites files that still match what it installed. The manual and its table row are both gone, and no link in the skill dangles: your agent’s knowledge tracks your Gemfile in both directions. Installed skills are plain files in your repo, and you will edit them that’s the point of having them locally . This raises the question every dotfile manager, Rails generator, and config framework eventually faces: what happens when upstream ships a new version of a file you’ve changed? To show the upgrade story we need an upstream that moves, so let’s write a toy companion gem. Here’s its entire content, gemspec aside: rails-hyperdrive-sidekiq/ ├── hyperdrive.yml ├── skills/sidekiq-idempotency/SKILL.md or lib/