skills/rails-stack-profiles/SKILL.md
Detects a Rails project's architecture axes — logic placement (native vs extracted) and delivery (html vs api) — so other skills load profile-appropriate guidance without inline conditionals. Use when planning architecture or when a recommendation depends on where business logic lives or whether the app renders HTML or serves JSON. NOT for test framework, job backend, cache store, or auth library choices — those are orthogonal facts detected by project-conventions.
npx skillsauth add ag0os/rails-dev-plugin rails-stack-profilesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Resolve a project's architecture once per session, as two independent binary axes. Other skills consume the resolved axes to load one flat, branch-free guidance file each — they never carry inline omakase / service-oriented conditionals.
See axis-a.md and axis-b.md for characteristic patterns and code per axis value.
A project is not one of three profiles. It is one value on each of two axes:
| Axis | Values | Question it answers |
|------|--------|---------------------|
| A — logic placement | native | extracted | Where does non-trivial business logic live? |
| B — delivery | html | api | Does the surface render HTML or serve JSON? |
native — logic lives in models, concerns, and POROs. The Rails-omakase way. Callbacks are acceptable for simple side effects.extracted — service/command objects are the default home for non-trivial logic. Common in larger teams and complex domains.html — server-rendered views, Hotwire (Turbo + Stimulus).api — headless JSON, serializers, no app/views/ (mailer views aside).The axes are independent. All four combinations are valid, including native + api (a Rails 8 omakase-style API-only app — a combination the old three-profile enum could not express).
The legacy names map cleanly: omakase = native + html, service-oriented = extracted + html, api-first = extracted + api.
Test framework, test data strategy, job backend, cache store, and auth library are orthogonal project facts, not architecture axes. A project with extracted services can still use Minitest; an omakase app can run Sidekiq. Inferring these from architecture is the central mistake this restructure removes.
Detect them directly via the project-conventions fingerprint. Skills consume those fingerprint fields; they never branch on a "profile" for them.
| Signal | Points to |
|--------|-----------|
| app/services/ with ~5+ files | extracted |
| Custom ApplicationService / BaseService base class | extracted |
| gem "dry-monads", gem "interactor", gem "trailblazer" | extracted |
| app/services/ absent or near-empty | native |
| Domain logic in models + app/models/concerns/ | native |
| Callbacks orchestrating multi-step workflows | native |
| POROs for operations, often in app/models/ | native |
Weight the dominant pattern. A project with 50 service classes is extracted even if a few models are still fat.
| Signal | Points to |
|--------|-----------|
| App base controller is ActionController::API | api |
| No app/views/ (or mailer views only) | api |
| gem "jwt", rack-cors, serializer gems and no ERB | api |
| app/views/**/*.erb present | html |
| Hotwire (turbo-rails, stimulus-rails), turbo_stream responses | html |
1. Glob app/services/**/*.rb → count → Axis A
2. Grep Gemfile for dry-monads / interactor / trailblazer → Axis A
3. Grep app/ for class Application\w+ < / class Base\w+ < → Axis A
4. Read the app base controller class → ActionController::API? → Axis B
5. Glob app/views/**/*.erb → presence → Axis B
6. Grep Gemfile for turbo-rails / jwt → Axis B
Most real projects are mixed: an omakase app with an extracted billing module, or an html app with an /api/v1 namespace. Do not force one repo-wide answer.
Resolve the axes for the module or namespace in focus, not the whole codebase. The directory being worked on (app/billing/, app/controllers/api/) has one clear answer on each axis. Ask the sharp question — "what is this surface?" — not the blurry one.
When reporting resolved axes:
## Stack Axes
- **logic:** [native | extracted] — resolved from: [signal]
- **delivery:** [html | api] — resolved from: [signal]
- **scope:** [whole app | namespace/module in focus]
Cache this for the session. Other skills read it; they do not re-detect.
If the axes cannot be resolved (empty or greenfield project), default to native + html (the Rails default posture) and state the assumption in one line.
development
WHAT: Language-agnostic corrective guidance for the refactoring phase. WHEN: Agent is restructuring code, fixing code smells, reducing complexity, or improving maintainability. NOT FOR: Writing new features, debugging runtime errors, performance tuning, or object design decisions.
tools
Analyzes Rails view templates, partials, layouts, helpers, and form patterns for best practices. Use when reviewing ERB templates, improving view performance with fragment caching, fixing form helpers, organizing partials, adding accessibility attributes, or evaluating collection rendering. NOT for Stimulus/Turbo logic (use hotwire-patterns), controller concerns, or API-only responses.
testing
Analyzes Rails test suites and recommends testing best practices for RSpec and Minitest. Use when writing new tests, reviewing test coverage, fixing flaky tests, improving test performance, choosing between test types (unit, integration, system, request), or setting up factories and fixtures. NOT for production monitoring, deployment verification, or load/stress testing infrastructure.
data-ai
Action Mailer patterns for Rails applications. Automatically invoked when working with email delivery, mailer classes, email templates, mailer previews, interceptors, or delivery configuration. Triggers on "mailer", "email", "ActionMailer", "deliver_later", "deliver_now", "mail template", "email preview", "SMTP", "SendGrid", "Postmark", "notification email". NOT for push notifications, SMS, or in-app messaging.