Tapioca: giving Sorbet a view of the gems it cannot read
The swiss army knife of RBI generation
At a glance
- What is it?
- Tapioca generates RBI files so Sorbet can see the constants and methods that live inside your gem dependencies and inside the DSLs your framework invents at runtime. It is Shopify's answer to a problem Sorbet deliberately does not solve, and it covers both gems and metaprogrammed DSL patterns, with an extension interface for the rest.
- Who is it for?
- Use Tapioca when you are adopting Sorbet incrementally in a Rails or gem-heavy application and the blind spots are the problem, because it converts the constants and methods Sorbet cannot infer into files Sorbet can read. Do not adopt it as a way to avoid writing types for your own code, because everything it generates is a description of code Sorbet still cannot check, and it is explicitly unstable before a 1.0 release.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap Sorbet leaves open on purpose
Sorbet does not read the code in your gem dependencies, so it does not know the constants and methods declared inside them. That is a design choice rather than a missing feature, and it is what makes Sorbet fast, since it never has to load and analyse every gem you depend on. The cost is that the type checker is blind to a large part of your application's surface. Tapioca is described as the swiss army knife of RBI generation, and its job is to fill that gap by loading your gem dependencies from your application's Gemfile and compiling RBI files that represent their content. RBI files are Sorbet's own interface format for describing types from outside the source, so the output is something Sorbet reads natively rather than a parallel type system.
Installation and the one command that starts it
The package goes into the development and test group of your Gemfile, and it is important that it is not required at runtime.
group :development, :test do
gem 'tapioca', require: false
endAfter a bundle install, one command does the setup.
$ bundle exec tapioca initThe README lists what that does. It creates the Sorbet configuration file, the Tapioca configuration file and the require.rb file. It installs the binstub for Tapioca in your application's bin folder so that you can run bin/tapioca. It pulls the community RBI annotations from the central repository matching your application's gems. It generates the RBIs for your application's gems. And it generates the RBI file for missing constants. So a single command stands up the whole pipeline, which is the right amount of ceremony for a tool whose output is meant to be committed and then forgotten about.
The command surface, and what each command is for
The help output lists the commands, and the list is short enough to hold in your head. tapioca annotations pulls gem RBI annotations from remote sources. tapioca check-shims checks duplicated definitions in shim RBIs. tapioca configure initialises the folder structure and the type checking configuration. tapioca dsl generates RBIs for dynamic methods, taking optional constant names. tapioca gem generates RBIs from gems, also taking optional names. tapioca init gets the project ready for type checking. tapioca require generates the list of files to be required by Tapioca. tapioca todo generates the list of unresolved constants, and tapioca tree prints a tree of all available commands. The two global options are a config file path, defaulting to sorbet/tapioca/config.yml, and a verbosity switch for debugging.
Gems and DSLs are two separate problems
The feature list splits the work in two, and the split reflects two different kinds of blindness in the type checker. The gem side is the mechanical part: automatic generation from the Gemfile, importing of signatures from a gem's source code, importing of documentation from that source, and synchronisation validation for CI. The DSL side is the harder part, because a DSL's methods do not exist in the source at all, they exist only after the framework's metaprogramming runs. Tapioca handles this by generating from your application's content, supporting many DSL patterns out of the box, including Rails, Google Protobuf and SmartProperties, providing an extensible interface for writing your own DSL compilers, generating automatic signatures for methods from the known DSLs, and again offering synchronisation validation for CI. The DSL compilers are the part of the project where the real work lives, and the README has a section on contributing one.
Annotations from remote sources and authentication
The annotations command pulls RBI annotations for gems from remote sources, and the README documents the authentication options in some detail, which tells you this is a feature that has to deal with hosts that require credentials. There is basic authentication, there is a .netrc file, and there is a way to change the typed strictness of the annotations files. This is the same idea as the shim annotations that Sorbet itself ships for core and standard library, extended to third-party gems, and the community annotations live in a central repository that the init command pulls from automatically. The strictness control matters more than it might appear, because an annotation that declares a method as strongly typed when the gem actually returns something looser will move the error from a runtime surprise to a type error, and a strictness setting lets you decide per annotations file which side of that trade you want.
Shim RBIs and the check that keeps them honest
The third feature group is management of shim RBI files, and it addresses a problem anyone who has typed a Ruby codebase will recognise. A shim RBI is a hand-written file that describes a constant or method Sorbet cannot see, and over time these accumulate definitions that have since been fixed upstream or replaced by a generated RBI. Tapioca's check-shims command looks for useless definitions in shim RBIs in three categories: those that overlap with the RBI files generated from gems, those that overlap with the RBIs generated for DSLs, and those that overlap with Sorbet's own embedded RBI for core and the standard library. Alongside that is synchronisation validation for CI. The combination means the generated files can be regenerated on demand and checked for drift in a pipeline, so the RBI set is a checked-in artefact rather than an accumulation nobody dares touch.
RBI files for what is missing
Tapioca also generates an RBI file for missing constants and unresolved ones, which the todo command lists, and there is a command to generate the list of files that need to be required so that Tapioca can load them. The RBS rewriting section is a smaller feature with a specific purpose: converting RBS comments into Sorbet signatures, with an option to cache the rewrites using Bootsnap. The practical workflow the README describes for gems is the one worth internalising. You run the generation, you commit the result, and when a gem version changes you regenerate so the types track the dependency. That is the model that works: the RBI files are checked in, a synchronisation check in CI fails when they drift from the Gemfile, and the human work is limited to the shim files that only a person can write.
Where Tapioca is the wrong choice
Four limits apply. It does not make Sorbet understand your gems, it makes Sorbet read a description of them, so every error Sorbet reports against a gem type is now an error against a generated file that you did not write and will regenerate. The tool is explicitly unstable: the README carries a warning that the software is under active development and that the API and interface should be considered unstable until a 1.0 release, and the version history shows releases like v0.20.0 and v0.19.2 rather than a stable line. It also does not cover your own application code, which is the part of a gradual typing effort you cannot delegate. And the DSL compilers, which are where the value is for a Rails application, are per-pattern work that somebody has to write, so the coverage you get depends on whether your framework's DSL is one of the ones implemented.
Editorial conclusion
Use Tapioca when you are adopting Sorbet incrementally in a Rails or gem-heavy application and the blind spots are the problem, because it converts the constants and methods Sorbet cannot infer into files Sorbet can read. Do not adopt it as a way to avoid writing types for your own code, because everything it generates is a description of code Sorbet still cannot check, and it is explicitly unstable before a 1.0 release. Verify first that the commands your project needs exist in the version you install, that the RBI files are committed and the synchronisation check runs in CI so the generated output cannot drift from the Gemfile, and that you read the configuration file it writes, since the strictness it applies per gem is what determines whether the generated types are useful or noise.
Frequently asked questions
What problem does Tapioca solve?
Sorbet does not read the code in your gem dependencies, so it does not know the constants and methods declared inside gems. Tapioca loads those gems from your Gemfile and compiles RBI files representing their content, which Sorbet can then read.
How do I install Tapioca and get started?
Add gem 'tapioca', require: false to the development and test group of your Gemfile, run bundle install, then run bundle exec tapioca init. That creates the Sorbet and Tapioca configuration files, installs the binstub, pulls community annotations and generates the gem and missing-constant RBIs.
Which DSLs does Tapioca support out of the box?
Many DSL patterns are supported, with Rails, Google Protobuf and SmartProperties named among them. Beyond those, the tool offers an extensible interface so you can write your own DSL compilers, and automatic signature generation for methods from the known DSLs.
What does tapioca check-shims do?
It finds useless definitions in shim RBI files, in three categories: definitions duplicated in RBIs generated from gems, definitions duplicated in RBIs generated for DSLs, and definitions duplicated in Sorbet's embedded RBI for core and the standard library. Synchronisation validation for CI is available for the generated RBI files.
Is Tapioca stable enough to depend on?
The README carries a warning that the software is under active development and that the API and interface should be considered unstable until a 1.0.0 release. The recent versions are v0.20.0 from 2026-09-15 and v0.19.2 from 2026-06-25, and the last push to the repository was on 2026-10-19.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/shopify-tapioca)