0.0
The project is in a healthy, maintained state
MonkeyLens captures method ownership, source locations, signatures, visibility, and ancestor order for selected Ruby classes and modules, then detects runtime drift against a committed baseline.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 13.0
~> 6.0
 Project Readme

MonkeyLens — make runtime patches visible

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

CI RubyGems Website MIT License

Official RubyGems gem · Documentation website · Latest GitHub release

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

Install directly from the official RubyGems release:

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
Super-method owner changed High
Method source changed High
Method removed High
Prepend/ancestor order changed High
Method signature changed Medium
Visibility changed Medium
Method aliases 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