Project

cruise

0.0
A long-lived project that still receives updates
Cruise is a Rust-powered file system watcher with native OS integration. Uses FSEvents on macOS and inotify on Linux.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

>= 0
 Project Readme

Cruise

A fast, native file watcher for Ruby.

Gem Version License

Rust-powered file system watcher with native OS integration.
Uses FSEvents on macOS and inotify on Linux.

Installation

Add to your Gemfile:

gem "cruise"

Or install directly:

gem install cruise

Precompiled native gems are available for macOS and Linux. If a precompiled gem isn't available for your platform, it will compile from source (requires Rust).

Usage

Basic Example

Watch a directory for changes:

require "cruise"

Cruise.watch("app/views") do |event|
  puts "#{event.kind}: #{event.path}"
end

The callback receives a Cruise::Event with two attributes:

Attribute Description
event.path Absolute path to the changed file
event.kind One of: "created", "modified", "renamed", "removed", "accessed", "changed"

Multiple Directories

Watch several paths at once:

Cruise.watch("app/views", "app/components", "lib/templates") do |event|
  puts event.inspect
  # => #<Cruise::Event kind="modified" path="/app/views/users/show.html.erb">
end

Ruby Threads

Cruise releases the GVL while waiting for filesystem events, so Ruby threads run freely:

Thread.new { do_background_work }

Cruise.watch("src") do |event|
  puts event
end

Glob Filtering

Only receive events for files matching a pattern:

Cruise.watch("app/views", glob: "**/*.html.erb") do |event|
  puts event
end

Multiple patterns:

Cruise.watch("app", glob: ["**/*.html.erb", "**/*.html"]) do |event|
  puts event
end

Debounce

Configure the debounce interval (default: 100ms):

Cruise.watch("src", debounce: 0.5) do |event|
  puts event
end

Proc Callback

You can also pass a Proc via the callback: keyword:

handler = proc { |event| puts event }

Cruise.watch("app/views", callback: handler)

Stopping

The watcher runs in a blocking loop. Use Interrupt to stop it cleanly:

begin
  Cruise.watch("app") do |event|
    # process event
  end
rescue Interrupt
  puts "Stopped."
end

How It Works

Cruise is a Ruby binding (via Magnus and rb-sys) around the Rust notify crate.

  1. Cruise.watch sets up a notify watcher with event debouncing (100ms)
  2. A background thread monitors filesystem events using the OS-native API
  3. The main loop calls rb_thread_call_without_gvl to wait without blocking Ruby
  4. When an event arrives, the GVL is re-acquired and your callback is invoked

Platform Backends

Platform Backend API
macOS FSEvents CoreServices framework
Linux inotify inotify_init1 syscall

All backends watch recursively by default.

Development

Requirements: Rust toolchain, Ruby 3.2+

git clone https://github.com/marcoroth/cruise
cd cruise
bundle install
bundle exec rake compile
bundle exec rake test

Cross-compilation

Cruise uses rake-compiler and rake-compiler-dock for building native gems:

bundle exec rake gem:native

License

MIT License. See LICENSE.txt.