Spoom
Useful tools for Sorbet projects.
Spoom provides a CLI and a Ruby API to inspect Sorbet projects, improve typing coverage, translate signatures, query Sorbet LSP, and find dead code.
Installation
Add Spoom to your application's Gemfile:
gem "spoom"
Then install it:
bundle install
Or install it directly:
gem install spoom
Spoom requires Ruby 3.3 or newer.
Command line interface
Run spoom help or spoom help COMMAND to list all available commands.
Typechecking errors
spoom srb tc runs srb tc and can sort, filter, format, and export errors.
List errors sorted by location:
spoom srb tc --sort loc
List errors sorted by error code:
spoom srb tc --sort code
List only errors with a specific code:
spoom srb tc --code 7004
Limit the number of displayed errors:
spoom srb tc --limit 10
Options can be combined:
spoom srb tc --sort code --code 7004 --limit 10
Remove duplicated error lines:
spoom srb tc --uniq
Format each error line:
spoom srb tc --format "%C - %F:%L: %M"
Format tokens:
%C: error code%F: file path%L: line number%M: error message
Hide the final Errors: X count:
spoom srb tc --no-count
List only errors from specific files or directories:
spoom srb tc file1.rb path1/ path2/
Write errors to a JUnit XML file:
spoom srb tc --junit-output-path junit.xml
Pass extra options to Sorbet:
spoom srb tc --sorbet-options="--typed=true"
Typing coverage
spoom srb coverage collects Sorbet coverage metrics and can generate an HTML report from Sorbet and Git data.

Show a coverage snapshot:
spoom srb coverage
Save a snapshot under spoom_data/:
spoom srb coverage --save
Save a snapshot under a specific directory:
spoom srb coverage --save my_data/
Show typing coverage evolution based on Git history:
spoom srb coverage timeline
Replay a specific date range:
spoom srb coverage timeline --from YYYY-MM-DD --to YYYY-MM-DD
Save timeline snapshots under spoom_data/:
spoom srb coverage timeline --save
Save timeline snapshots under a specific directory:
spoom srb coverage timeline --save my_data/
Run bundle install before collecting each timeline snapshot:
spoom srb coverage timeline --bundle-install
Generate an HTML coverage report from saved snapshots:
spoom srb coverage report
The report is generated at spoom_report.html by default.
Generate a report from a custom data directory:
spoom srb coverage report --data my_data/
Change the generated report path:
spoom srb coverage report --file coverage.html
Change report colors:
spoom srb coverage report \
--color-true "#648ffe" \
--color-false "#fe6002" \
--color-ignore "#feb000" \
--color-strict "#795ef0" \
--color-strong "#6444f1"
Open the HTML coverage report:
spoom srb coverage open
Open a report at a custom path:
spoom srb coverage open coverage.html
Sorbet sigils
spoom srb bump changes # typed: sigils when the change does not introduce typechecking errors.
Bump files from typed: false to typed: true:
spoom srb bump --from false --to true
Force the change without typechecking:
spoom srb bump --from false --to true --force
Bump only files listed in a file, one path per line:
spoom srb bump --from false --to true --only list.txt
Check which files can be bumped without applying changes:
spoom srb bump --from false --to true --dry
This command exits with a non-zero status when files can be bumped, which is useful in CI.
Use a custom Sorbet executable:
spoom srb bump --from false --to true --sorbet /path/to/sorbet/bin
Count typechecking errors if all files were bumped:
spoom srb bump --from false --to true --count-errors --dry
Signatures and type assertions
spoom srb sigs translates signatures between Sorbet RBI syntax and RBS comments.
Translate signatures from RBI to RBS comments:
spoom srb sigs translate
Translate signatures from RBS comments to RBI:
spoom srb sigs translate --from rbs --to rbi path/to/file.rb
Strip Sorbet signatures from files:
spoom srb sigs strip path/to/file.rb
Export gem signatures to an RBI file:
spoom srb sigs export
Check that the exported RBI file is up to date:
spoom srb sigs export --check-sync
spoom srb assertions translates Sorbet type assertions to RBS comments:
spoom srb assertions translate path/to/file.rb
Sorbet LSP
spoom srb lsp sends requests to Sorbet LSP.
This command group is experimental.
Find symbols matching Foo:
spoom srb lsp find Foo
List symbols in a file:
spoom srb lsp symbols file.rb
List definitions for a code location:
spoom srb lsp defs file.rb 10 4
List references for a code location:
spoom srb lsp refs file.rb 10 4
Show hover information for a code location:
spoom srb lsp hover file.rb 10 4
Show signature information for a code location:
spoom srb lsp sigs file.rb 10 4
Show type information for a code location:
spoom srb lsp types file.rb 10 4
Sorbet code metrics
spoom srb metrics collects metrics about Sorbet usage in Ruby files.
Show metrics for the current project:
spoom srb metrics
Show metrics for specific files or directories:
spoom srb metrics lib/ test/foo_test.rb
Dump raw metric keys and values:
spoom srb metrics --dump
Dead code
spoom deadcode indexes a project and reports definitions that do not appear to be referenced.
Analyze the current project:
spoom deadcode
Analyze specific paths:
spoom deadcode lib/ app/models/
Show files, loaded plugins, definitions, or references used during analysis:
spoom deadcode --show-files
spoom deadcode --show-plugins
spoom deadcode --show-defs
spoom deadcode --show-refs
Remove a reported dead code candidate:
spoom deadcode remove path/to/file.rb:42:18-47:23
Ruby API
Parsing Sorbet config
Parse a Sorbet config file:
config = Spoom::Sorbet::Config.parse_file("sorbet/config")
puts config.paths
Parse a Sorbet config string:
config = Spoom::Sorbet::Config.parse_string(<<~CONFIG)
a
--file=b
--ignore=c
CONFIG
puts config.paths
puts config.ignore
List all files typechecked by Sorbet:
config = Spoom::Sorbet::Config.parse_file("sorbet/config")
puts Spoom::Context.new(".").srb_files(with_config: config)
Parsing Sorbet metrics
Display metrics collected during typechecking:
puts Spoom::Context.new(".").srb_metrics(capture_err: false)
Interacting with LSP
Create an LSP client:
client = Spoom::LSP::Client.new(
Spoom::Sorbet::BIN_PATH,
"--lsp",
"--enable-all-experimental-lsp-features",
"--disable-watchman",
)
client.open(".")
Find symbols matching a string:
puts client.symbols("Foo")
Find symbols in a file:
puts client.document_symbols("file://path/to/my/file.rb")
Backtrace filtering
Spoom provides a Minitest backtrace filter that removes Sorbet frames from test failures.
Enable it in your test helper:
# test/test_helper.rb
require "spoom/backtrace_filter/minitest"
Minitest.backtrace_filter = Spoom::BacktraceFilter::Minitest.new
Development
After checking out the repo, install dependencies:
bin/setup
Run the tests:
bin/test
Run an interactive console:
bin/console
Run the full local sanity check before pushing:
bin/sanity
Install this gem locally:
bundle exec rake install
Releasing
Bump the gem version
- [ ] Update the version number in
lib/spoom/version.rb - [ ] Run
bundle installto update the version number inGemfile.lock - [ ] Commit the change with
Bump version to vx.y.z - [ ] Push the change directly to
mainor open a pull request
Create a new tag
- [ ] Create a tag with the new version number:
git tag vx.y.z - [ ] Push the tag:
git push origin vx.y.z
Publish the release
The release workflow publishes new gem versions to RubyGems through Trusted Publishing.
A member of the Ruby and Rails Infrastructure team at Shopify must approve the workflow before it runs. Once approved, it publishes the gem and creates a GitHub release.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/Shopify/spoom.
This project is intended to be a safe, welcoming space for collaboration. Contributors are expected to follow the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in Spoom's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the code of conduct.