MonkeyLens — make runtime patches visible

Audit monkey patches, method ownership, prepend layers, and Ruby runtime drift.

CI RubyGems Website MIT License

MonkeyLens captures the effective Ruby method table for selected classes and modules, records who owns every method, tracks source locations, visibility, signatures, and ancestor order, then compares that runtime against a committed baseline.

It turns invisible runtime mutation into reviewable evidence.

Why MonkeyLens?

Ruby deliberately makes classes open. That flexibility is powerful, but a production process can behave differently because a gem reopened a core class, a concern used prepend, a test helper redefined a method, or load order changed which implementation won.

MonkeyLens answers:

  • Which methods were added, removed, or redefined?
  • Which module currently owns the method Ruby will dispatch?
  • Did a prepend layer enter or leave the ancestor chain?
  • Did arity, parameters, visibility, or source location change?
  • Does CI boot with the same runtime shape as the approved baseline?

Install

Add the gem to your bundle:

gem "monkey_lens"

Then run:

bundle install

After release, direct installation will be:

gem install monkey_lens

Quick start

Create .monkeylens.yml:

targets:
  - String
  - Array
  - MyApp::User
fail_on: high
format: text

Capture the approved runtime:

bundle exec monkeylens capture --output .monkeylens.json

Check for drift:

bundle exec monkeylens check

CLI

monkeylens capture   Capture a runtime baseline
monkeylens check     Compare the current runtime with a baseline
monkeylens diff      Compare two saved snapshots
monkeylens inspect   Explain one target's effective method table
monkeylens doctor    Validate configuration and runtime support
monkeylens version   Print the installed version

Load an application before capture

bundle exec monkeylens capture \
  --require ./config/environment \
  --output .monkeylens.json

JSON or SARIF output

bundle exec monkeylens check --format json
bundle exec monkeylens check --format sarif > monkeylens.sarif

SARIF output can be uploaded to GitHub code scanning or processed by other security tooling.

Library API

require "monkey_lens"

baseline = MonkeyLens.capture(targets: ["String", "MyApp::User"])
baseline.write(".monkeylens.json")

current = MonkeyLens.capture(targets: ["String", "MyApp::User"])
result = MonkeyLens.diff(baseline, current)

abort result.to_text unless result.clean?

Rake integration

require "monkey_lens/rake_task"

MonkeyLens::RakeTask.new do |task|
  task.config = ".monkeylens.yml"
  task.baseline = ".monkeylens.json"
end

This creates monkey_lens:capture and monkey_lens:check tasks.

Rails integration

Add MonkeyLens to your development and test groups. Its Railtie adds the same Rake tasks after the application environment loads.

group :development, :test do
  gem "monkey_lens"
end

Change severities

Change Default severity
Method owner changed Critical
Method source changed High
Method removed High
Prepend/ancestor order changed High
Method signature changed Medium
Visibility changed Medium
Method added Low

The threshold is configured with fail_on: low|medium|high|critical.

Design guarantees

  • Does not execute arbitrary project files unless explicitly passed with --require.
  • Does not upload runtime information.
  • Produces deterministic JSON for the same runtime state.
  • Uses Ruby's public reflection APIs.
  • Supports Ruby 3.2 and newer.

Documentation

Funding

MonkeyLens supports:

License

MIT © 2026 Matthew Looney