Skip to content
CAI
Software that uses CAICheck a score

iberianpig/fusuma

61.1

Adequate · 28 September 2026

3.1k

lines of production code

Ruby

primary language

2

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

Fusuma is a Linux multitouch gesture recognition service that monitors input devices via libinput and executes configured shell commands based on detected gestures. It employs a modular, plugin-based architecture to process input events through a pipeline of filtering, parsing, buffering, and detection stages. The system supports a wide range of gestures, including swipes, pinches, rotations, and holds, with logic adapted for different libinput versions.

How it got here

2016–2019 — Plugin architecture and type safety

18 changes.

The project underwent a major refactoring to replace its monolithic core with a modular, plugin-based input pipeline architecture. This shift introduced comprehensive RBS type-checking infrastructure and a robust RSpec test suite to ensure reliability. The work also included significant enhancements to gesture detection, device handling, and configuration management to support modern libinput versions and Ruby standards.

2022–2025 — Test coverage and type signatures

11 changes.

This period focused on establishing comprehensive test coverage for Fusuma's core components and plugin architecture, including configuration, device detection, and gesture handling logic. Additionally, RBS type signature files were generated for the library to improve static type checking and IDE support.

Features

Add RBS signature files for Fusuma prototype

Added RBS type signature files for the Fusuma prototype library, defining the structure of core classes and plugin components such as Runner, Config, Device, and various plugin base classes and detectors.

sig/prototype · high confidence

Add RBS type-checking infrastructure and update linting configuration

The project now includes a full RBS type-checking setup for Ruby 3.1+, featuring a Steepfile, RBS collection configuration, and Rake tasks to generate, validate, and check types. Additionally, the linting configuration has been updated to use the Standard Ruby gem and its plugins, with the target Ruby version set to 2.5.

(repo-wide) · high confidence

Added RBS type signatures for Fusuma

Generated RBS type signature files have been added for the Fusuma library, covering core classes such as Runner, Config, Device, and LibinputCommand, as well as the full plugin architecture including inputs, filters, parsers, detectors, buffers, and executors. These signatures provide static type definitions for the public and private interfaces of the application, enabling better type checking and IDE support for the codebase.

sig/generated · high confidence

Added development console and setup scripts

New executable scripts have been added to the bin directory to streamline local development. The bin/console script initializes an IRB session with the gem loaded and includes a reload! helper function to reload code from the lib directory, facilitating easier experimentation. The bin/setup script automates the initial environment configuration by running bundle install.

bin · high confidence

Introduce CLI entry point with configuration and device options

The executable \exe/fusuma\ is introduced as the new command-line interface for the application. It allows users to specify an alternative configuration file path (\-c\), daemonize the process (\-d\), list available input devices (\-l\), direct logs to a specific file (\--log\), display the loaded configuration in YAML format (\--show-config\), and select a specific device by name (deprecated \--device\). It also supports verbose output (\-v\) and version display (\--version\), passing these options to the \Fusuma::Runner\.

exe · high confidence

Introduce plugin-based event buffering system

Adds a new plugin architecture for managing input events, introducing \Buffer\, \GestureBuffer\, and \TimerBuffer\ classes. This allows the system to collect, cache, and expire input events (such as swipes or timer triggers) based on configurable parameters like \source\ and \seconds\_to\_keep\, enabling more robust gesture recognition and timing logic.

lib/fusuma/plugin/buffers · high confidence

Introduce plugin-based executor architecture with command execution support

The system now uses a plugin-based executor architecture, introducing a base \Executor\ class and a new \CommandExecutor\ plugin. This allows gesture events to trigger external shell commands defined in the configuration, with support for environment variable injection (including acceleration factors) and error logging. The base executor also standardizes interval handling for one-shot and repeat gestures, enabling more flexible and configurable command execution workflows.

lib/fusuma/plugin/executors · high confidence

Introduce plugin-based input pipeline architecture

The core library now uses a modular plugin system to handle input events, replacing the previous monolithic implementation. The new \Fusuma::Runner\ orchestrates a pipeline where events are processed through distinct plugin stages: Input, Filter, Parser, Buffer, Detector, and Executor. This allows for customizable gesture detection and command execution via installed or local plugins, while maintaining backward compatibility through base plugin loading and configuration-driven behavior.

lib · high confidence

Behavioural changes

Enhanced context matching and config validation

Configuration lookups now support complex context conditions, allowing users to define AND (multiple keys) and OR (array values) requirements in their config files via the new ContextMatcher. The system also validates YAML files for duplicate keys to prevent silent overwrites and introduces a new Index-based search mechanism with caching for more efficient config resolution.

lib/fusuma/config · high confidence

Fusuma v3.12.0 release with refactored configuration and device handling

This release updates Fusuma to version 3.12.0 and introduces a significant refactor of the core configuration system, moving to a new \Config\ class that supports custom config paths, plugin default merging, and YAML duplication validation. Device detection logic has been restructured into a dedicated \Device\ class with improved capability parsing and caching. The \LibinputCommand\ wrapper now explicitly handles CLI option differences for libinput versions 1.8 and 1.27.0+, ensuring compatibility with newer libinput releases. Additionally, a \CustomProcess\ module allows for better process management and renaming, while the \MultiLogger\ now supports configurable log file output and improved error handling for interrupted processes.

lib/fusuma · high confidence

Gesture detection engine refactored with new hold support and improved pinch/rotate logic

The gesture detection system in lib/fusuma/plugin/detectors has been rewritten to support a new hold gesture, improve pinch and rotate detection accuracy, and enhance overall performance. The HoldDetector now uses a timer-based approach to detect hold gestures, while the PinchDetector and RotateDetector have been updated to use moving averages for more accurate gesture detection. The SwipeDetector has also been improved to use moving averages for swipe detection. Additionally, the detection engine now supports high-frequency gesture detection and uses a more efficient timer mechanism.

lib/fusuma/plugin/detectors · high confidence

Introduce RBS type signatures for the Events plugin

The \lib/fusuma/plugin/events/event.rb\ file now includes RBS inline type signatures for the \Event\ class, its \initialize\ method, and its \inspect\ method. This adds static type information to the event handling component without altering its runtime behavior, supporting better tooling and type checking for the plugin's public interface.

lib/fusuma/plugin/events · medium confidence

Introduce structured event record types for gesture and index handling

The event system now uses distinct record classes to represent different input states, replacing the previous flat or vector-based approach. Users will see gestures represented by GestureRecord (containing status, gesture name, finger count, and movement delta), index sequences by IndexRecord (handling prefix/body/suffix positions and trigger types like oneshot or repeat), and raw text by TextRecord. A new ContextRecord allows passing named context values, and the base Record class enforces a type discriminator. This structure supports the new high-frequency gesture detection and config-based search context features by providing a more granular and mergeable event model.

lib/fusuma/plugin/events/records · high confidence

New libinput gesture parser with support for libinput 1.27.0+ and hold gestures

The parser plugin now includes a dedicated \LibinputGestureParser\ that handles \GESTURE\_HOLD\_BEGIN\ and \GESTURE\_HOLD\_END\ events, enabling hold gesture recognition. It also detects the installed libinput version and automatically switches parsing logic to accommodate the output format changes introduced in libinput 1.27.0 or later, ensuring compatibility with both older and newer libinput versions.

lib/fusuma/plugin/parsers · high confidence

New plugin architecture with automatic discovery and version compatibility checks

The plugin system has been refactored to use a new \Base\ class and \Manager\ that automatically register plugin subclasses upon definition. The \Manager\ now handles loading both local plugins and external gems, adding their paths to the load path for sibling file discovery. A key behavioral change is the addition of version compatibility checks for external plugins: if an installed gem's dependency on 'fusuma' does not match the running version, a warning is logged and the plugin is skipped, preventing silent failures from incompatible plugin versions.

lib/fusuma/plugin · high confidence

Refactored device filtering with dynamic reload support

The device filtering logic has been restructured into a new base Filter class and a specific LibinputDeviceFilter implementation. This change introduces the ability to dynamically reload the list of kept devices when a DEVICE\_ADDED event is detected, ensuring that newly connected input devices are immediately recognized without requiring a restart. The filter now uses a dedicated KeepDevice helper to manage device name patterns and caches, and it deprecates the previous --device command-line option in favor of the keep\_device\_names configuration parameter.

lib/fusuma/plugin/filters · high confidence

Refactored input plugin architecture with IO multiplexing and configurable libinput commands

The input handling system has been restructured to support multiple input sources via IO multiplexing, allowing the application to wait on and read from several inputs simultaneously. A new base \Input\ class and specific implementations like \LibinputCommandInput\ and \TimerInput\ provide a modular foundation. \LibinputCommandInput\ now supports configurable command paths (\libinput-command\, \libinput-debug-events\, \libinput-list-devices\) and options such as \disable-dwt\, \show-keycodes\, and \verbose\. The \TimerInput\ uses a dedicated thread for on-demand, configurable interval timing, replacing previous process-based approaches to improve reliability and reduce overhead.

lib/fusuma/plugin/inputs · high confidence

Test coverage

Added RSpec test suite and coverage configuration; Added RSpec tests for CommandExecutor and Executor classes; Added test coverage for Fusuma core components; Added test coverage for Fusuma plugin base and manager classes; Added test coverage for config context matching, key indexing, and search logic; Added test coverage for input plugins; Added test coverage for plugin gesture detectors; Added test helper for managing YAML configuration state; Added tests for buffer plugins; Added unit tests for Filter and LibinputDeviceFilter plugins; Added unit tests for libinput gesture parsing.

Dependencies

Initial release of Fusuma gem with Ruby 2.7+ support and RBS tooling

This entry introduces the Fusuma gem, a multitouch gesture recognizer for Linux using the libinput driver. The package now requires Ruby 2.7 or higher and includes development dependencies for testing (RSpec), linting (StandardRB, Reek), and code coverage (SimpleCov). For Ruby 3.0+, it adds REPL type completion via \repl\_type\_completor\, and for Ruby 3.1+, it integrates RBS-based type checking and generation tools (\rbs\, \rbs-inline\, \steep\), with \rbs\ pinned below version 4.0 to ensure compatibility.

(dependencies) · high confidence

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

Score

  • CAI 63 → 61 (-1.7)
  • Rubric changed (rubric-2026.09.8 → rubric-2026.09.16) — scores are not directly comparable.

Lenses

  • Code Health 97 → 97 (+0.0)
  • Architecture 100 → 68 (-31.8)
  • Maturity 50 → 50 (+0.0)
  • Readiness 67 → 67 (+0.0)
  • Security 67 → 73 (+6.6)

Resolved (1)

  • Documentation: no architecture or design documentation (README.md)

New (4)

  • Ambiguous method overloading/overriding. Having two methods with the same name run but different arities (one with an argument, one without) in the same class is confusing in Ruby (which doesn't support true overloading) and suggests either a design flaw or inconsistent usage patterns. It is unclear if run() is a wrapper for run(option) or if they serve distinct, unrelated purposes.
  • Inconsistent delegation and naming for search operations. Config exposes a simple search method, but the underlying Searcher class has multiple search variants (search, search_with_context, search_with_cache). It is unclear if Config.search delegates to a specific variant or if the Searcher methods are exposed inconsistently. The naming search_with_context vs search_with_cache mixes concerns (context vs caching) in the method name rather than using a consistent pattern like search(context: ..., cache: ...) or distinct methods like search_cached.
  • Projects may be oversized for their cohesion
  • Redundant definition of proctitle. The class defines both a Property proctitle and a Method proctitle(). In Ruby, this is typically redundant or indicates a misunderstanding of how properties (accessors) work. If proctitle is a reader, proctitle() is likely an alias or a duplicate implementation.

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

Survey your own repository

iberianpig/fusuma 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 28 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 43a7eb04fe6c0709a646be183a612e56e5f60a2e — the exact code this score is about.
  • Scored under rubric-2026.09.16 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-2d9048c36d26.