Ratchets Run Faster with Resharp | A Danver Braganza Extravaganza
Ratchets Run Faster with Resharp
Switching from the regex crate in Rust to Resharp makes Ratchets run 15% faster on the Sculptor codebase
by Danver Braganza on 2026-06-22
Yesterday, I released Ratchets v0.4.0, a breaking change which switched the<br>regular expression engine from the widely-used Rust regex crate to Resharp.<br>Although this was originally driven by my desire to support lookaround assertions, I noticed a healthy speed-up when<br>using the new version of Ratchets on the Sculptor codebase. With no other<br>changes, Ratchets is now approximately 15% faster on our codebase.
Fig. 1. A comparison of run times of `ratchets check` on Sculptor, using `Resharp` vs `regex`
What is a ratchet?
I was first introduced to the concept of ratchets by this qntm blog article, which describes<br>a system to prevent developers from adding more instances of a particular pattern to a codebase. A ratchet system<br>tolerates existing instances of a forbidden pattern by maintaining a count, and it forbids increases while enforcing<br>that decreases are recorded and committed. The count is therefore encouraged to decrease over time, tightening the<br>strictness on the codebase–hence the name. The ratchet system saves you the effort of migrating the entire codebase<br>whenever you introduce a new rule.
At Imbue, we’ve embraced ratchets since before the dawn of agentic coding, and we started out deploying<br>them in the fashion above. That is, we used ratchets to encourage our human developers to adhere to our evolving style<br>guide and to ensure that our code evolved in a good direction. But as agentic engineering has taken off, we’ve found<br>that the use-case for ratchets has changed. Today, it is fairly simple to launch a swarm of agents to migrate your entire<br>codebase away from a bad pattern, and so the use-case for ratchets would apparently be removed.
However, I’ve found that there’s still a good reason to use a ratchet system. Although I can’t speak for Fable because<br>my time with it was extremely brief, my experience with other coding agent models testifies poorly to their ability to<br>adhere to a style guide. Because their tendency is to generate code in line with their training set, you find yourself<br>in tension with that tendency when you attempt to constrain them with elaborate rules. This costs input tokens,<br>and using an agent-as-judge to validate style is even more expensive. If you still care about code style—as we<br>do—then a ratchet enforcement system which flags problems to the agent can be very helpful.
Ratchets are even more useful when you really need that escape hatch to allow a forbidden pattern into your codebase.<br>One example we find is type-checker suppressions. A coding agent’s propensity might be to reach for # pyrefly: ignore<br>rather than understanding the type boundary. However, sometimes that might be the right decision, and the coding agent<br>itself does not have sufficient context and judgement to come to the right decision. In this case, you can separate<br>the judgement of whether to use the expedient path from the coding agent, and leave it up to a planning agent. Only the<br>planning agent has the authority to bump the ratchet, and it does that with a wider perspective than a particular coding<br>agent. In this way, certain language features can be used only sparingly, if there is no other way to achieve a goal.<br>This is the approach I’ve taken in Rust Bucket, my agentic workflow and<br>scaffold for Rust programs.
How Ratchets uses regular expressions
I could dedicate a separate article to the implementation details of Ratchets,<br>so to keep this short, it has two mechanisms for detecting forbidden patterns:
abstract syntax tree queries,
and regular expressions
I decided to implement abstract syntax tree queries via tree-sitter<br>since they are much more precise than regular expressions. For example, regular expressions can be sensitive to<br>formatting and line-wrapping, which were specific issues that led to miscounting by our previous implementation. The<br>tree-sitter queries are syntax-aware, and are robust to these kinds of problems.
However, there were still a few rules that were best expressed as regular expressions–most commonly rules about comment<br>style. I’d initially used the regex crate, but I was surprised to find that it did not<br>support proper lookaround. It was this need, rather than a desire for performance optimization, that led me to look into<br>replacing it with Resharp. I’d remembered reading their article on Hacker<br>News and had been pleased to see they’d released a Rust<br>port.
An agent was able to perform the replacement with ease, and the copious tests we had on the codebase gave me confidence.<br>Once the replacement was completed, I wanted to check whether there was going to be a performance difference. I was very<br>pleased to find that replacing regex with Resharp, and no other changes, made...