Project

rfmt

0.0
There's a lot of open issues
A long-lived project that still receives updates
Write a longer description or delete this line.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Runtime

~> 0.9.91
 Project Readme

rfmt

A Ruby code formatter written in Rust

Gem Version License: MIT

Installation • Usage • Features • Editor Integration • Documentation • Contributing


What is rfmt?

RubyGems reference

rfmt is a Ruby code formatter that enforces consistent style across your codebase. Key characteristics:

  • Opinionated: Minimal configuration with consistent output
  • Idempotent: Running multiple times produces identical results
  • Comment preservation: Maintains existing comment placement
  • Rust implementation: Core formatter implemented in Rust

Features

Performance

Built with Rust for improved execution speed. See Performance Benchmarks section for details.

Consistent Style

Enforces code style rules:

  • Automatic indentation
  • Spacing and alignment normalization
  • Quote style standardization
  • Method definition formatting

Performance Benchmarks

Execution time comparison on a Rails project (111 files, 3,241 lines):

Test Type Files rfmt RuboCop Ratio
Single File 1 191ms 1.38s 7.2x
Directory 14 176ms 1.68s 9.6x
Full Project (check) 111 172ms 4.36s 25.4x

About this comparison:

  • RuboCop times include startup overhead and loading all cops (linting rules)
  • RuboCop was run with default configuration (all cops enabled)
  • rfmt is a formatting-only tool with minimal overhead
  • Both tools were measured in check mode (no file modifications)
  • Results are averages from 10 runs per test

Observations:

  • rfmt execution time remains constant (172-191ms) regardless of file count
  • Low variance across runs (standard deviation: 8-23ms)

Test Environment:

  • CPU: Apple Silicon (arm64)
  • Ruby: 3.4.5
  • rfmt: 0.3.0, RuboCop: 1.81.7

See detailed benchmark report for complete data.

Installation

Requirements

  • Ruby 3.0 or higher
  • Rust 1.70 or higher (for building from source)

From RubyGems

gem install rfmt

In Your Gemfile

gem 'rfmt'

Then run:

bundle install

From Source

git clone https://github.com/fujitanisora/rfmt.git
cd rfmt
bundle install
bundle exec rake compile

Usage

Initialize Configuration

First, create a configuration file with default settings:

rfmt init

This creates a .rfmt.yml file with default settings:

version: "1.0"

formatting:
  line_length: 100        # Maximum line length (40-500)
  indent_width: 2         # Spaces/tabs per indent (1-8)
  indent_style: "spaces"  # "spaces" or "tabs"
  quote_style: "double"   # "double", "single", or "consistent"

include:
  - "**/*.rb"
  - "**/*.rake"
  - "**/Rakefile"
  - "**/Gemfile"

exclude:
  - "vendor/**/*"
  - "tmp/**/*"
  - "node_modules/**/*"
  - "db/schema.rb"

Options:

# Specify custom path
rfmt init --path config/.rfmt.yml

# Overwrite existing configuration
rfmt init --force

Command Line

Format a single file:

rfmt lib/user.rb

Format multiple files:

rfmt lib/**/*.rb

Check if files need formatting (CI/CD):

rfmt check .

Show diff without modifying files:

rfmt lib/user.rb --diff

Enable verbose output for debugging:

rfmt lib/user.rb --verbose
# or use environment variable
DEBUG=1 rfmt lib/user.rb

Ruby API

Input (unformatted code):

require 'rfmt'

source = <<~RUBY
  class User
  def initialize(name)
  @name=name
  end
  end
RUBY

formatted = Rfmt.format(source)
puts formatted

Output (formatted code):

class User
  def initialize(name)
    @name=name
  end
end

Configuration

Configuration File Discovery

rfmt automatically searches for configuration files in this order:

  1. Current directory (.rfmt.yml, .rfmt.yaml, rfmt.yml, or rfmt.yaml)
  2. Parent directories (up to root)
  3. User home directory (.rfmt.yml, .rfmt.yaml, rfmt.yml, or rfmt.yaml)
  4. Default settings (if no file found)

Ruby API for Configuration

require 'rfmt'

# Generate configuration file
Rfmt::Config.init('.rfmt.yml', force: false)

# Find configuration file
config_path = Rfmt::Config.find
# => "/Users/username/project/.rfmt.yml"

# Check if configuration exists
Rfmt::Config.exists?
# => true

# Load configuration
config = Rfmt::Config.load
# => {"version"=>"1.0", "formatting"=>{"line_length"=>100, ...}, ...}

Examples

Before Formatting

class User<ApplicationRecord
has_many :posts
validates :email,presence: true
def full_name
"#{first_name} #{last_name}"
end
end

After Formatting

class User < ApplicationRecord
  has_many :posts
  validates :email, presence: true

  def full_name
    "#{first_name} #{last_name}"
  end
end

Editor Integration

Neovim

Format Ruby files on save using autocmd:

-- ~/.config/nvim/init.lua

vim.api.nvim_create_autocmd("BufWritePre", {
  pattern = { "*.rb", "*.rake", "Gemfile", "Rakefile" },
  callback = function()
    local filepath = vim.fn.expand("%:p")
    local result = vim.fn.system({ "rfmt", filepath })
    if vim.v.shell_error == 0 then
      vim.cmd("edit!")
    end
  end,
})

Coming Soon

  • VS Code - Extension in development
  • RubyMine - Plugin in development
  • Zed - Extension in development

Development

Setup

After cloning the repository:

bundle install
bundle exec lefthook install

Git Hooks

This project uses lefthook for automated validation before push:

Pre-push checks:

  • RuboCop (Ruby linting)
  • cargo fmt --check (Rust formatting)
  • cargo clippy (Rust linting)

Skip hooks temporarily:

# Skip all hooks for this push
LEFTHOOK=0 git push

# Skip specific hook
LEFTHOOK_EXCLUDE=rubocop git push

Running Tests

# Ruby tests
bundle exec rspec

# Rust tests
cargo test --manifest-path ext/rfmt/Cargo.toml

# All tests
bundle exec rake dev:test_all

Documentation

Documentation is available in the docs directory:

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Comparison with Other Tools

rfmt vs RuboCop

Feature rfmt RuboCop
Primary Purpose Code formatting Linting + formatting
Configuration Minimal Extensive
Code Quality Checks No Yes
Bug Detection No Yes

Note: rfmt focuses on code formatting, while RuboCop provides additional code quality analysis. They can be used together.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the rfmt project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

Support

Acknowledgments

  • Built with Prism - Modern Ruby parser
  • Powered by Rust - Performance and safety
  • FFI via Magnus - Ruby-Rust bridge

Created by Fujitani Sora