rails-audit
Skill2 starsChanged 8 days agoMITView on GitHub
Use to audit or health-check an existing or inherited Rails app: onboarding to a legacy codebase, a tech-debt assessment, a pre-engagement code review, or \"review my Rails app\".
- Reads credentials
2 other projects use a version of this.
Adopted by
Most recently taken up by
- RoleModel/skillstheir own version, first seen Oct 13, 2026
- jcuervo/rails-audit-claude-skilltheir own version, first seen Feb 12, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- jcuervo/rails-audit-claude-skill★ 7same name
- RoleModel/skills★ 7same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository24 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- rails-activestorageSkill
- rails-apiSkill
- rails-clean-test-outputSkill
- rails-controllersSkill
- rails-coreSkill
- rails-database-performanceSkill
- rails-i18nSkill
- rails-jobsSkill
- rails-loggingSkill
- rails-mailersSkill
- rails-migrationsSkill
- rails-modelsSkill
- rails-multi-tenancySkill
- rails-performanceSkill
- rails-philosophySkill
- rails-project-setupSkill
- rails-securitySkill
- rails-stimulusSkill
- rails-styleSkill
- rails-testingSkill
- rails-turboSkill
- rails-upgradeSkill
- rails-viewcomponentsSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 31
When a section hands off to another skill (shown as "→ [[skill-name]]"), run only the quick detection here and note the handoff.
- Distinctive: line 156
If those two numbers are drastically different, indexes have likely been overlooked → 🟡.
- Very specific: line 252
Reporting from memory instead of running the commands: Every finding must cite a real grep hit / scanner line / file:line.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Rails App Audit
Overview
A top-level health-check for an existing Rails app — inheriting a legacy codebase, onboarding to an unfamiliar project, or doing a pre-engagement review. This skill is the entry point for reviewing an app, the counterpart to [[rails-core]] which is the entry point for writing one.
It orchestrates: it owns the broad health-check items nothing else covers (version pinning, dependency CVEs, exposed secrets, seeds, tech-debt) and hands off the deep dives to the specialist skills ([[rails-database-performance]], [[rails-security]], [[rails-performance]], [[rails-testing]], [[rails-upgrade]]). Do not re-derive what those skills already do — run the cheap detection here, then delegate the fix.
The audit ends in a written, severity-ranked report (see Producing the Report).
How to Run This Audit
- Confirm you are at the app root (
Gemfile,app/,config/present). - Work through every numbered section below — do not stop early.
- For each finding, record three things:
- Severity — 🔴 high (security / data loss / broken in prod), 🟡 medium (tech debt, performance, missing safety net), 🟢 low (polish, style, docs).
- Location —
file:line(the audit must point at real code, not generalities). - Fix — the concrete remediation, and which skill owns the deep fix if it's a delegated area.
- When a section hands off to another skill (shown as "→ [[skill-name]]"), run only the quick detection here and note the handoff; the named skill carries the authoritative checklist.
1. Ruby & Rails Version Pinning
A shared, explicit version is the baseline for reproducible builds. Check the version is pinned and still supported.
cat .ruby-version 2>/dev/null || echo "MISSING .ruby-version"
grep -nE '^\s*ruby\s+["'\'']' Gemfile
grep -nE '^\s*gem\s+["'\'']rails["'\'']' Gemfile
ruby -v; bin/rails -v 2>/dev/null- No
.ruby-version→ 🟡 add one so every dev/CI uses the same interpreter. - Rails not locked to a specific version (
gem "rails"with no version, or a loose>=) → 🟡 abundle updatecan silently jump majors. Lock it. - EOL Ruby or Rails → 🔴/🟡. Check the running version against the support schedule. An upgrade is its own project — hand off to [[rails-upgrade]] (do not hand-roll the version bump).
2. Gemfile Hygiene
head -1 Gemfile # source must be HTTPS
grep -nE 'cooldown' Gemfile .bundle/config 2>/dev/null # supply-chain cooldown set?
grep -A1 'BUNDLED WITH' Gemfile.lock # Bundler >= 4.0.13? (older ignores cooldown)
grep -nE 'group\s+:' Gemfile # dev/test gems grouped out of production?source 'http://...'(not HTTPS) → 🔴.- No supply-chain cooldown → 🟡. Recommend
source "https://rubygems.org", cooldown: 3so freshly-hijacked gem releases can't resolve for 3 days. Rationale and scope rules: [[rails-project-setup]]. - Cooldown set but
BUNDLED WITHbelow 4.0.13 → 🟡. Older Bundler silently ignorescooldown, so the protection isn't actually on; recommend pinning an explicit version, e.g.bundle update --bundler=4.0.13(a bare--bundlerjumps to the newest release, itself bypassing any cooldown). - Dev/test gems not grouped → 🟡. Wrap development- and test-only gems (rspec-rails, capybara, debug, factory_bot, brakeman, rubocop) in
group :development, :test do … end, so a production deploy run withBUNDLE_WITHOUT=development:test(orbundle install --without development test) neither installs nor loads them: smaller image, faster boot, smaller attack surface. - Undocumented/obscure gems → 🟢 add a one-line comment for the next maintainer.
Don't flag missing per-gem version pins. With a committed
Gemfile.lock(andbundle install --deployment/BUNDLE_FROZEN=trueon deploy), every version is already frozen; loose constraints in theGemfileare fine.
3. Dependency Vulnerabilities & Static Security Scan
Two free, fast scanners. Run both.
gem install bundler-audit 2>/dev/null; bundle exec bundler-audit check --update 2>/dev/null || bundler-audit check --update
gem install brakeman 2>/dev/null; bundle exec brakeman -q -A 2>/dev/null || brakeman -q -Abundler-auditflagsGemfile.lockgems with known CVEs and the patched version → 🔴/🟡 by criticality. Record each advisory + the upgrade target.brakemanflags code-level issues (SQLi, mass-assignment, unsafe redirects, XSS). Triage each warning; confidenceHighfirst → 🔴.- For the design of auth/authorization behind these findings, hand off to [[rails-security]].
4. Exposed Secrets
Secrets in the repo (or in git history) are the highest-impact, easiest-to-miss finding.
grep -rinE '(password|secret|api[_-]?key|access[_-]?key|token)\s*[:=]\s*["'\''][^"'\'' ]{6,}' config/ app/ lib/ 2>/dev/null
git log --oneline -- config/master.key config/credentials.yml.enc 2>/dev/null
grep -nE 'config/master.key|config/credentials.*\.key|\.env' .gitignore 2>/dev/null- Literal credentials in
config/environments/production.rb, initializers, or*.yml→ 🔴. Move to encrypted credentials (bin/rails credentials:edit) or ENV. config/master.keyor any.envNOT gitignored → 🔴. Modern Rails stores secrets inconfig/credentials.yml.enc(encrypted, committable) decrypted bymaster.key(which must stay out of git).- A secret already committed → 🔴. Rotate it first (assume it's compromised), then purge history. See [[rails-security]] for what to rotate and how to scope it.
5. Test Health
A suite that nobody has touched in a year is a liability, not a safety net.
git log -1 --pretty=format:'%ci %s' -- test/ spec/ 2>/dev/null; echo
ls -d test spec 2>/dev/null
grep -c . <(find app -name '*.rb') ; find test spec -name '*_test.rb' -o -name '*_spec.rb' 2>/dev/null | wc -l- Tests last touched long before app code → 🟡 likely abandoned after an upgrade broke them, or never written. Note the staleness.
- No
test//spec/at all, or near-empty → 🔴 no regression safety net. - For coverage strategy, fixtures vs factories, system tests, and parallelization → hand off to [[rails-testing]]. To quantify, run the suite and a coverage tool (SimpleCov) and report the percentage.
6. Seed Data
Developers must be able to stand up a working local DB without a production dump.
test -s db/seeds.rb && echo "seeds.rb present ($(wc -l < db/seeds.rb) lines)" || echo "MISSING/empty db/seeds.rb"
grep -nE 'find_or_create_by|destroy_all|delete_all' db/seeds.rb 2>/dev/null- Missing or empty
db/seeds.rb→ 🟡 onboarding requires copying prod data (privacy + size risk). - Seeds that aren't idempotent (plain
create!that dupes on re-run) → 🟢 preferfind_or_create_byso seeds can be loaded, cleared, and re-loaded cleanly.
7. Lint & Style Drift
bundle exec rubocop --format offenses 2>/dev/null | tail -20 || bundle exec standardrb 2>/dev/null | tail -20
ls .rubocop.yml .standard.yml 2>/dev/null- No linter configured → 🟢 add
rubocop-railsorstandardfor consistent style. - Configured but thousands of offenses → 🟡 style has drifted; consider
rubocop --auto-gen-configto baseline, then fix incrementally. - For the project's actual conventions (method ordering, conditionals, REST routing, naming) → [[rails-style]].
8. Schema & Index Quick Heuristic
A fast smell test before the full schema audit. Foreign keys without indexes are the most common Rails performance bug.
echo "FK-ish columns:"; grep -E '_id' db/schema.rb | grep -v 'add_index\|t\.index' | wc -l
echo "indexes:"; grep -E 'add_index|t\.index' db/schema.rb | wc -l- If those two numbers are drastically different, indexes have likely been overlooked → 🟡.
- This is only a heuristic. The authoritative index/query/N+1-at-the-DB audit (polymorphic, scope, status, auth, counter-cache, pagination) lives in [[rails-database-performance]] — run it next.
9. Performance & N+1 Quick Scan
grep -rnE '\.(each|map)\b' app/views/ app/controllers/ 2>/dev/null | head -20 # loops that may trigger per-row queries
grep -rnE '\.includes\(|\.preload\(|\.eager_load\(' app/ 2>/dev/null | wc -l # is eager loading used at all?- Views/controllers iterating an association with no matching
includes/preload→ 🟡 probable N+1. Spot-check the dev log (or addprosopite— near-zero false positives, unlikebullet) to confirm. - For caching, ETags, batching, and the full N+1 treatment → [[rails-performance]].
Production footguns — cheap greps for configurations that cause outages, not just slowness:
grep -nE 'puma_worker_killer|unicorn-worker-killer' Gemfile # memory-threshold worker killers
grep -rnE 'send_data|send_file' app/controllers/ | head # large files served from the web process
grep -rnE 'queue_adapter\s*=\s*:inline|Resque\.inline' config/ | grep -v development # inline jobs outside dev
grep -rnE 'timeout' config/initializers/*elastic* config/initializers/*search* config/initializers/*redis* 2>/dev/null # client timeouts set at all?- Worker-killer gem present → 🟡 hidden ENV thresholds silently turn the app into a restart loop (processes recycled after a handful of requests); removal has halved response times in practice. Modern instances have the RAM — fix leaks instead. → [[rails-performance]]
send_dataof generated content (CSV/zip/PDF) → 🟡 memory bloat + blocked threads; move generation to a job, serve from storage. → [[rails-jobs]]:inlinejob adapter in test/production config → 🟡 → [[rails-testing]]- No timeout configured on search/cache clients → 🟡 default 30s timeouts let a degraded Elasticsearch/Redis hold every Puma thread and take the app down. → [[rails-performance]]
10. Architecture Smells
Cheap size heuristics surface the files most likely to hide problems.
echo "Fattest models:"; wc -l app/models/**/*.rb 2>/dev/null | sort -rn | head -10
echo "Fattest controllers:"; wc -l app/controllers/**/*.rb 2>/dev/null | sort -rn | head -10
echo "Service-object sprawl:"; ls app/services 2>/dev/null | wc -l
grep -rnE '^\s*def ' app/controllers/ 2>/dev/null | grep -vE 'index|show|new|create|edit|update|destroy' | head # non-REST actions
echo "ApplicationController methods:"; grep -cE '^\s*def ' app/controllers/application_controller.rb 2>/dev/null # dumping-ground smell- Controllers fat with business logic / many non-REST actions → 🟡 push behaviour into models, extract concerns. See [[rails-controllers]] and [[rails-style]] (REST routing).
ApplicationControlleris a dumping ground (many methods — say 8+ — especially unrelated ones not backing abefore_action, with no grouping) → 🟡. It accretes current-user checks, default redirects, env (production?/staging?) checks,www-canonicalisation, response-header setters, etc., that nobody dares move. Group related methods under comments, push any method used by only 1–2 controllers into a concernincluded just there, and extract each cluster of 2+ related methods into a named concern (e.g.include Akamai). The base controller should read as a manifest ofincludes. → [[rails-controllers]] (Pattern 1).- God models (many hundreds of lines) → 🟡 extract concerns / POROs. See [[rails-models]].
- A large
app/services/tree → 🟡 in 37signals-style Rails this is usually logic that belongs on rich models, not a service layer. Weigh against [[rails-philosophy]] before recommending more of it.
11. Technical-Debt Inventory
grep -rinE 'todo|fixme|hack|xxx|deprecated' app/ lib/ 2>/dev/null | wc -l
grep -rinE 'todo|fixme|hack|xxx' app/ lib/ 2>/dev/null | head -40
grep -rnE '^\s*#\s*[a-z].*\b(def|end|do|=)\b' app/ lib/ 2>/dev/null | head # commented-out code- Inventory every
TODO/FIXME/HACK→ 🟢/🟡. Decide per item: do it, ticket it, or delete the stale note. - Large blocks of commented-out code → 🟢 delete; git is the history.
Producing the Report
End the audit with a written report, grouped by severity (🔴 → 🟡 → 🟢). Each item:
### 🔴 <short title>
- **Where:** path/to/file.rb:42 (or: Gemfile, db/schema.rb)
- **Finding:** what's wrong, with the evidence (the grep hit / scanner line).
- **Impact:** why it matters (security / perf / maintainability / onboarding).
- **Fix:** the concrete change, and **→ which skill** to use for the deep fix.Close with a one-paragraph summary: overall health, the top 3 things to fix first, and the recommended order (security & exposed secrets before refactors).
Quick Reference
| # | Check | Command / signal | Deep-dive skill |
| 1 | Version pinning | .ruby-version, locked gem "rails", EOL? | [[rails-upgrade]] |
| 2 | Gemfile hygiene | HTTPS source, cooldown, dev/test groups | — |
| 3 | Vulnerabilities | bundler-audit, brakeman | [[rails-security]] |
| 4 | Exposed secrets | grep config/, master.key gitignored | [[rails-security]] |
| 5 | Test health | git log -1 -- test/ spec/, coverage | [[rails-testing]] |
| 6 | Seed data | db/seeds.rb present & idempotent | — |
| 7 | Lint/style | rubocop / standard offenses | [[rails-style]] |
| 8 | Schema/index | FK-count vs index-count | [[rails-database-performance]] |
| 9 | N+1/perf | loops without includes | [[rails-performance]] |
| 10 | Architecture | fat models/controllers, service sprawl | [[rails-philosophy]], [[rails-models]], [[rails-controllers]] |
| 11 | Tech debt | TODO/FIXME, dead code | — |
Common Mistakes
- Reporting from memory instead of running the commands. Every finding must cite a real grep hit / scanner line /
file:line. No evidence, no finding. - Re-deriving a deep-dive skill inline. Sections 8–10 are detection heuristics only; the authoritative checklist lives in the linked skill. Delegate, don't duplicate.
- Findings without severity or location. A report the user can't triage or act on is noise.
- Burying the lede. Lead with 🔴 security/secrets; refactors and style come last.
- Treating an EOL version as a quick fix. Version upgrades are a project — route to [[rails-upgrade]], don't bump in place.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

