runtimeanalyz.ing ● early access · sign-up open

← All capabilities

dead_api

LSP · CLI free

Find dead public API. Public methods no caller reached in any recorded run, including the ones whose only caller is their own spec. Greyed out in your editor.

Enrollment app code
unlocked_for ( student Student )
3,181 prod runs
Curriculum
class Curriculum
  def unlocked_for(student) = …
  def archived_books = …
end
curriculum_spec.rb:40 its own spec
archived_books
its only caller
nothing no caller
legacy_totals
never reached
Report
class Report
  def legacy_totals = …
end
Every public method with its recorded callers. archived_books is only reached by the spec written for it, and legacy_totals by nothing at all, so both are greyed out in your editor.

The problem

Public methods are easy to add and hard to remove. Nobody’s sure whether anything still calls Curriculum#archived_books, so it stays, gets tested, gets documented and gets maintained.

Static tools can’t settle it in Ruby. A method can be called through send, public_send, a callback or a name built from a string, so “no references found” proves nothing.

Test-first code adds a subtler kind: methods you wrote a test for, made pass, and then nothing else ever needed. The spec calls it, so it looks alive. That’s speculative generality, and it’s worth knowing about while the method is still new.

The fix

In your editor, the method is greyed out with a hint:

class Curriculum
  def unlocked_for(student) = eligible(student)

  def archived_books = @archived.dup
  # ⤷ only caller: spec/models/curriculum_spec.rb · no production code calls this
end

On the command line:

$ ra dead_api app/models

Curriculum#archived_books
  only caller: its own spec (curriculum_spec.rb:40)
Report#legacy_totals
  no caller in any recorded run

Delete the method and the spec that was keeping it alive:

class Curriculum
  def unlocked_for(student) = eligible(student)
end

The suite stays green, because nothing but that spec ever needed it. If a rake task or a job you didn’t record does need it, you’ll find out when you record that run, not months later in a code review.

How it works

The recording wraps every method defined in your app, so a call is recorded however it was made: directly, through send or public_send, or from a callback. dead_api lists each public method and its recorded callers.

Two kinds get flagged:

  • Methods with no recorded caller at all.
  • Methods whose only callers are their own spec examples. Because each call tree is stamped with the example that produced it, it can tell curriculum_spec.rb calling archived_books directly apart from production code calling it.

Limits

  • Only as complete as what you recorded. A method called by a rake task, a rarely hit path or a job you didn’t run looks dead. Record those runs, or treat the result as a question rather than a verdict.
  • A hint, not a deletion. It greys the method out and never removes it or fails a build.
  • For proof from production, prod_dead_api on the hosted tier pools real traffic across every deploy.

split_interface

CLI · LSP · MCP free

Split a fat interface. A class whose callers each use a different slice of it. It names the role interfaces to split it into, measured from who actually calls what.

See more →

specs_that_reach

CLI · LSP · MCP free

Run only the specs that matter. The spec examples whose recorded runs reach a method, so a change reruns those and nothing else. Keeps a red-green loop in seconds.

See more →

observed_shape

CLI · LSP · MCP free

The observed contract. The messages your code actually sends to a value, read from real runs. The interface a call depends on, whether or not anyone declared it.

See more →