Skip to content
CAI
Software that uses CAICheck a score

guard/listen

59.8

Adequate · 19 September 2026

1.9k

lines of production code

Ruby

primary language

1

measurement over time

CAI band scale
CAI lens gauges

What this system is

This system is a Ruby gem designed to monitor file system changes across multiple operating systems, including Linux, macOS, Windows, and BSD. It provides a robust, cross-platform file-watching service that detects additions, modifications, removals, and moves of files and directories. The library features a modular architecture with OS-specific adapters, a finite state machine for lifecycle management, and configurable event processing to handle file system events reliably.

How it got here

2012 — v3.10.0 architecture rewrite and gem rename

5 changes.

The project underwent a major internal rewrite for version 3.10.0, replacing the Celluloid-based implementation with a new architecture featuring a dedicated backend system and finite state machine. Concurrently, the gem was renamed from Listener to Listen, requiring updates to the module namespace and entry points. The period also included significant infrastructure improvements, such as migrating CI to GitHub Actions, updating RSpec configurations, and adding comprehensive test support for acceptance and platform-specific scenarios.

2013 — Adapter architecture rewrite and test coverage

5 changes.

The file-watching adapter architecture was completely rewritten to use OS-specific implementations and a new configuration class, replacing the previous concurrency model. Comprehensive test suites were added to verify the new modular components, platform-specific adapters, and core file-watching functionality across various operating systems.

2014–2015 — Event architecture refactoring

6 changes.

The project underwent a significant refactoring of its core event processing and lifecycle management systems, introducing a Finite State Machine and dedicated configuration classes to improve reliability and cross-platform consistency. This work included adding a CLI entry point with proper signal handling, implementing symlink loop detection, and centralizing file-watching options. Comprehensive test coverage was added to validate the new event subsystem and configuration structures.

Features

Add bin/listen script with signal handling for stopping the listener

A new executable script, bin/listen, has been added to allow users to start the Listen CLI. This script includes specific signal handling for the INT signal (Ctrl-C) to ensure the listener stops cleanly when interrupted, particularly for non-JRuby environments.

bin · high confidence

Behavioural changes

Introduce Listener::Config for centralized file-watching options

The library now includes a dedicated \Listener::Config\ class to manage file-watching settings. This change centralizes configuration options such as \debug\, \wait\_for\_delay\, \relative\, \force\_polling\, and \polling\_fallback\_message\ into a single structure, replacing the previous approach of passing these options directly to the listener. Users can now configure these behaviors through a unified config object, which also handles filtering options for specific adapters and the silencer component.

lib/listen/listener · high confidence

Listen gem v3.10.0: complete internal rewrite with new architecture

The lib/listen directory has been completely rewritten for version 3.10.0, replacing the previous Celluloid-based implementation with a new architecture. This change introduces a dedicated Backend class for adapter selection (supporting Darwin, Linux, BSD, Windows, and Polling fallbacks), a new FSM (Finite State Machine) for managing listener states (initializing, backend\_started, processing\_events, paused, stopped), and a new Event::Loop for processing changes. The Silencer logic has been refactored into a Controller pattern, and the Change class now uses an 'invalidate' method instead of 'change'. The CLI has been updated to use Thor, and the gem now includes a MonotonicTime module for more accurate timing. The default latency has been increased to 0.25 seconds, and the gem now uses SHA256 for file checksums instead of MD5 for FIPS compatibility. The Listener class now has non-blocking start and blocking start! methods, and the relative\_paths option has been renamed to relative\_paths.

lib/listen · high confidence

Migrate CI to GitHub Actions and update RuboCop configuration

The project has replaced Travis CI with GitHub Actions for continuous integration, removing the \.travis.yml\ file and adding a new \.rubocop.yml\ that sets the target Ruby version to 3.0.4 and enforces stricter style guidelines. The release process has also been updated to use GitHub Releases, with the \Rakefile\ now including a \Releaser\ class to publish gems to RubyGems and create GitHub releases, while the \CHANGELOG.md\ notes that release notes are now managed via GitHub releases.

(repo-wide) · high confidence

Refactored directory entry handling and symlink loop detection

The library now uses a dedicated \Listen::Record::Entry\ class to manage directory and file metadata, including size and modification time, and introduces a \SymlinkDetector\ to explicitly detect and abort on symlink loops. This change ensures consistent behavior across JRuby and MRI by handling \ENOTDIR\ errors uniformly and prevents infinite loops when watching directories containing symlinks that point back to themselves or already watched paths.

lib/listen/record · high confidence

Refactored event processing loop and state management

The event handling subsystem has been restructured to improve reliability and clarity. A new Finite State Machine (FSM) now manages the listener's lifecycle with explicit states (pre\_start, starting, started, stopped), replacing the previous implicit logic. The background processing loop has been extracted into a dedicated \Event::Processor\ class, which uses a queue-based wakeup mechanism instead of sleep/wakeup polling to handle events more efficiently. Additionally, a new \Event::Config\ class centralizes configuration options, and the \Event::Queue\ class now validates event types and paths before queuing. These changes ensure that the listener starts reliably within a timeout and handles stop requests more gracefully.

lib/listen/event · high confidence

Rename library from Listener to Listen

The gem has been renamed from 'Listener' to 'Listen'. This involves moving the main entry point to lib/listen.rb, deleting the old lib/listener.rb and lib/listener/version.rb files, and updating the module namespace from Listener to Listen. Users will need to update their require statements and references from Listener to Listen.

lib · high confidence

Rewritten adapter architecture with OS-specific implementations

The file-watching adapters have been completely rewritten to use a new base class and dedicated implementations for each operating system (Linux, Darwin/macOS, Windows, BSD, and a cross-platform Polling fallback). This change introduces a new \Adapter::Config\ class for configuration, replaces the previous Celluloid-based concurrency model with custom \Listen::Thread\ handling, and adds specific support for macOS Big Sur. Users benefit from more robust event processing, better error handling (such as explicit warnings for missing native gems like \rb-kqueue\ or \wdm\), and improved stability across different platforms.

lib/listen/adapter · high confidence

Test coverage

Added acceptance tests for file system change detection; Added comprehensive test coverage for Listen core components; Added specs for Listen class initialization and stop functionality; Added test coverage for adapter configuration and platform-specific adapters; Added test coverage for the new Listen::Event subsystem; Added tests for Listen::Listener::Config; New test support infrastructure for acceptance and platform-specific specs; Updated RSpec configuration and added test helpers.

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Baseline

  • First survey — no prior run to compare against. CAI 60.

Lenses

  • Code Health 88
  • Architecture 83
  • Maturity 46
  • Readiness 65
  • Security 74

Changes since last survey

  • 300 commits — 273 feature/other, 27 fixes

By area

  • lib/listen — 126 commits
  • (root) — 78 commits
  • (repo) — 38 commits
  • spec/lib — 32 commits
  • .github/workflows — 14 commits
  • spec/support — 5 commits
  • lib/listen.rb — 2 commits
  • spec/acceptance — 2 commits
  • bin/listen — 1 commit
  • spec/spec_helper.rb — 1 commit
  • vendor/hound — 1 commit

Notable commits

  • fix: Add size key and fix specs on macos.
  • fix: Fix Rubocop deprecations
  • fix: Fix compatibility with bundler 2.0
  • fix: Fix handling of file size.
  • fix: Fix issue with 2.6.
  • fix: Fix kwargs matching with rspec-mock 3.12 and Ruby 3+
  • fix: Fix the Rubocop offence
  • fix: Fix: Add Rspect tets to handle removed subdirectories
  • fix: Fix: Hound CI notes
  • fix: Fix: Not tracking directory removal
  • fix: Merge pull request #393 from robmckinnon/392-fix-os-x-10.6-10.8
  • fix: Merge pull request #417 from jirutka/fix-rb-fsevent
  • fix: Merge pull request #419 from jirutka/fix-rb-fsevent-2
  • fix: Merge pull request #464 from floehopper/fix-warnings-in-spec-output
  • fix: Use raw Pathname to fix Linux specs.
  • fix: fix github workflows link
  • fix: fix small markdown syntax issue in README
  • fix: fix test stubs of Listen::Record
  • fix: fix: Avoid scanning and building entries for silenced directories
  • fix: issue #481: fix duplicate start test to not expect AlreadyStarted to be raised
  • …and 280 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

guard/listen was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 19 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 2fa1a742d8c20cd3394d60f1c54dcbcd27b39ded — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-13a154b7f5d1.