Necropsy
Necropsy is a Ruby dead-code detector built around a unified call graph. It collects method definitions with Prism, adds call-edge evidence from static and optional dynamic analyzers, then runs reachability from framework and configured entry points.
Necropsy includes:
- Prism-based method collection for ordinary, singleton, delegated, aliased, forwarded, and dynamically defined methods
- static name resolution, CHA, and RTA-style filtering over instantiated classes
- Prism-backed Rails route parsing plus callback, view, component, migration, plain Ruby, and test-suite entry points
-
unreachable,unused, andtest_only_reachableclassifications - confidence levels, compact JSON/YAML reports, SARIF/GitHub output, CI guardrails, dynamic collectors, and benchmarking
Installation
Add the gem to the development/test group:
gem "necropsy", require: falseUsage
Create a baseline:
bundle exec necropsy baseline --root .Run a report:
bundle exec necropsy analyze --root . --format human
bundle exec necropsy --versionFail CI only for new high-confidence findings:
bundle exec necropsy check --root . --fail-on highRecord dynamic evidence from a Ruby script:
bundle exec necropsy record --root . --output tmp/necropsy_trace_point.yml -- script/runner.rb
bundle exec necropsy coverage --root . --output tmp/necropsy_coverage.yml -- script/runner.rbRecord Ruby Coverage while running an external command:
bundle exec necropsy coverage --root . --output tmp/necropsy_coverage.yml -- bundle exec rspecChild Ruby processes inherit the collector and are merged into the same output for that run.
Evaluate against a gold standard:
bundle exec necropsy bench --root . --gold-standard gold.yml --ablationJSON and YAML omit the full call graph by default. Add --include-graph when
nodes, edges, evidence, and entry points are needed in machine-readable output.
Example configuration:
analyzers:
static: [name_resolution, cha, rta]
dynamic:
coverage:
source: tmp/necropsy_coverage.yml
min_observation_days: 30
coverband:
source: redis://prod-redis:6379/2?key=coverband
trace_point:
source: tmp/necropsy_trace_point.yml
custom:
- class: "MyCompany::GraphqlEntryAnalyzer"
require: "config/necropsy/graphql_entry_analyzer"
cache:
enabled: true
path: .necropsy_cache/scan.json
paths:
include: ["app/**/*.rb", "lib/**/*.rb"]
exclude: ["app/legacy/**/*.rb"]
entry_points:
extra:
- "PublicApi::*"
ci:
fail_on: high
baseline: .necropsy_baseline.yml
quarantine:
days: 30
bench:
precision_threshold: 0.85
logging:
verbose: falseThe scan cache is invalidated when scanned Ruby files or configuration values change.
Dynamic inputs may provide executed or nodes entries with method IDs,
edges with caller_id/callee_id, and an observation hash. SARIF and
GitHub Actions annotations are available via --format sarif and
--format github.
Coverband file, Redis string, and Redis hash exports are supported. Redis URLs
may include an ACL username and password; connect_timeout and read_timeout
can be set in the Coverband analyzer configuration. Rails route
entry point detection covers common resources, resource, namespace,
scope, controller, concerns, draw, mount, root, and verb route
forms.
necropsy quarantine --write adds # necropsy:quarantine since=YYYY-MM-DD.
When the configured quarantine window expires and no alive evidence appears,
the finding is raised to certain.
Development
After checking out the repo, run bin/setup to install dependencies. Then run
bundle exec rake for the specs and RuboCop checks. Use bin/console for an
interactive prompt.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub.
License
The gem is available as open source under the terms of the MIT License.