groundy
Open Source

ESLint vs tsgolint: When Faster Linting Pays Off for Coding Agents

Vendor-reported data suggests tsgolint is faster than ESLint, but teams should profile agent loops and pilot one repo to verify gains before migrating CI.

Published 5 references
A skeptical green resin dinosaur tests a pointed yellow shoe beside a broad green boot, casting hard shadows across an ivory surface.
On this page11 sections

Cloudflare’s four-month update on VoidZero reports tsgolint stable and up to 18x faster than ESLint in large codebases, Vitest 5 up to 50% faster than Vitest 4, and Oxfmt’s Rust formatters 7x faster than Prettier. Every one of those figures is vendor-reported, and the post cites no independent benchmark. The practical answer for teams whose coding agents idle on lint and format steps: profile where your agent’s loop actually waits, check your rules against tsgolint’s quantified 59-of-61 typescript-eslint coverage, and pilot one repo before touching CI. One feature in the announcement, Bundled Dev, ships behind an experimental flag rather than as a stable feature, and should be treated that way throughout any planning.

What VoidZero shipped in four months, and who is reporting it

In its four-month update on the Cloudflare blog, VoidZero reports shipping more than 80 releases and closing over 1,200 issues since joining Cloudflare. The headline items:

  • tsgolint is stable, claimed up to 18x faster than ESLint in large codebases, supporting 59 of typescript-eslint’s 61 type-aware rules.
  • Vitest 5, released in September, claimed up to 50% faster than Vitest 4.
  • Oxfmt’s JSON, CSS, SCSS, Less, GraphQL, and YAML formatters rewritten in Rust, claimed 7x faster than Prettier.
  • Vite+ 1.0, which unifies the toolchain behind a set of defaults.
  • Oxc React Compiler, released in August, claimed to compile React apps 10x faster than the original Babel implementation.

One disclosure matters for how you read every number above: the reporter is also the sponsor. Cloudflare committed $1M to a Vite ecosystem fund in the original announcement and has since committed another $1M to open source, per the same post. And Vitest itself is MIT-licensed but copyrighted VoidZero Inc. and contributors, per the Vitest repository. None of that makes the numbers false. It means the incentive structure favors best-case framing, which is exactly what “up to” language signals. Treat each figure as a hypothesis to test on your own code, not a specification.

What the 18x claim and the 59/61 parity figure actually tell you

The tsgolint claim is the load-bearing one for the migrate-or-stay decision, and it deserves careful parsing.

The headline framing is “up to 18x faster than ESLint in large codebases,” but the tsgolint section of the post is more specific: the engine “catches bugs that require TypeScript type data while running 12 to 18 times faster than ESLint with typescript-eslint.” So the vendor is not just claiming a cherry-picked ceiling; it is claiming a floor of 12x. That floor is still a vendor measurement, taken on codebases the post does not describe, and the announcement cites no independent lint benchmark. What remains unknown is how the speedup scales with codebase size, and whether your repo resembles whatever was measured. Treat the 12x floor as the claim to falsify locally, not as a guaranteed minimum.

The parity figure is more useful because it is concrete and checkable: tsgolint supports 59 of typescript-eslint’s 61 type-aware rules. Type-aware rules are the ones that need type information to work (rules like no-floating-promises), and they are historically the slow ones, so covering them is the right priority. But the quantified coverage has two boundaries a migration decision has to respect:

  1. Two type-aware rules are unsupported. If your config enables either of them, you have a functional gap, not just a speed question. The announcement does not name which two, so step one of any pilot is enumerating your enabled type-aware rules against tsgolint’s support list.
  2. The 59/61 figure says nothing about the wider ESLint ecosystem. Framework plugins (react, vue, import, jsx-a11y and the like) and custom in-house rules are unquantified in the announcement. A repo whose lint config is mostly typescript-eslint type-aware rules is a good migration candidate. A repo carrying heavy framework-plugin or custom-rule coverage is an unknown.

The honest summary: tsgolint’s stability and parity story is strong for a specific, common profile of TypeScript repo, and unproven outside it.

Where does your coding agent actually wait?

The argument that makes this more than a routine toolchain release is about agent loops. Tools like Claude Code, Codex, and Cursor iterate in cycles: edit, then run some combination of lint, typecheck, test, and build, then read the output and edit again. When model inference was slow, toolchain latency hid inside it. As inference gets faster, the fixed per-cycle cost of lint and test becomes a larger share of wall-clock time, and agents amplify it because they run these steps far more often than a human does.

There is independent evidence that per-step executor overhead dominates agent economics, though not in linting. The Jev-Mobile paper (arXiv:2609.30186) reports that consolidating execution steps in mobile GUI agents cut mean end-to-end execution time by 32.7% and mean model API cost by 73.4% among successful trajectories, relative to a step-wise baseline. The same paper shows the trade: Jev-Mobile completed 79% of AndroidWorld tasks versus 84% for the step-wise baseline, trading five percentage points of task success for the speed gains. Different domain, same mechanism: the agent’s cost is not just tokens, it is tokens multiplied by how many times the loop turns. And loops turn a lot. On the WebArxiv benchmark (arXiv:2507.00938), the strongest model reached only 47.6% overall success, meaning agents fail and retry constantly; every retry re-pays the toolchain latency.

Two cautions before acting on this. First, neither paper measures linting, so they support the direction of the argument, not any VoidZero number. Second, the “toolchain is the agent’s bottleneck” thesis is only true if lint and test actually dominate your loop’s wait time. In many TypeScript repos the slow step is tsc typechecking or the test suite, not ESLint. Migrating the linter to save 20 seconds per cycle does nothing if the agent spends 90 seconds typechecking. That is why the first step is measurement, not migration.

The agent-security angle is worth a passing note too: any new binary you add to the agent’s execution path is new attack surface. Groundy’s audit of the ZCode agent is a useful template for vetting a tool before giving it repo access, and the same egress-capture discipline applies to toolchain components, not just agent harnesses.

The decision axes, compared

The migrate-or-stay call reduces to five axes. This table is the durable part of the article; the version numbers will age, the axes will not.

AxisMigrate now looks right if…Stay on ESLint/Prettier if…Evidence status
Where the loop waitsProfiling shows lint/format dominates agent idle timeTypecheck, tests, or build dominateReader-measurable; vendor silent
Rule parityYou use mostly typescript-eslint type-aware rules, and not the 2 unsupported onesYou depend on framework plugins or custom rules59/61 quantified; plugin parity unquantified
Speedup realityLocal re-benchmark reproduces a large gain on your repoVendor’s claimed 12-to-18x does not replicate locallyAll figures vendor-reported; the post cites no independent benchmark
Runtime floorYou already run Vite >=v6.4.0 and Node >=v22.12.0Upgrading the floor is its own projectPer Vitest’s README
Format churnYou can absorb a repo-wide reformat diff, or Oxfmt matches your Prettier outputA formatting swap would bury real changes in diff noiseVendor claims Prettier-compatible output; independently unverified

Two rows deserve expansion.

Runtime floor. The Vitest repository states current Vitest requires Vite >=v6.4.0 and Node >=v22.12.0. If you are pulling in the faster stack as a unit, that is the minimum platform. Teams pinned to older Node for production parity need to treat the runtime upgrade as a separate line item in the migration cost.

CI integration. Coverage artifacts are the usual sticking point when swapping test tooling. Vitest uses c8 for coverage reporting by default, per Better Stack’s guide, so CI pipelines that consume c8-compatible output have continuity on that axis. That covers the test runner; the announcement says nothing about whether tsgolint drops into existing ESLint-based CI steps (SARIF output, annotation formats, exit-code conventions) without adapter work. Assume integration cost until the pilot proves otherwise.

Run it yourself: a 30-minute verification protocol

Because the announcement cites no independent lint benchmark, the only number you should trust is one you measured. A minimal protocol:

  1. Profile the loop first. Instrument one real agent session (or simulate one: run your lint, typecheck, test, and build steps in sequence and time each). You want per-step wall time. If lint is under 15% of the cycle, stop here; the migration will not move your bottleneck.
  2. Inventory your rules. List every enabled ESLint rule, split into three buckets: typescript-eslint type-aware rules, other published plugins, and custom rules. Check bucket one against tsgolint’s 59/61 support. Buckets two and three are your risk.
  3. Baseline. Run your full ESLint pass three times on a clean checkout, record wall time for each run, and take the median. Same for Prettier. Warm-cache and cold-cache runs differ; record which you are measuring.
  4. Pilot on one repo. Enable tsgolint by turning on Oxlint’s type-aware mode (typeAware: true in the oxlint config) on a single non-critical repository, run the same three-pass protocol, and compare medians on identical hardware. Check the rule-finding output against your ESLint baseline: a faster linter that silently skips rules is not faster, it is wrong.
  5. Check formatting churn separately. VoidZero claims Oxfmt keeps “Prettier-compatible output and ergonomics,” so this step is about verifying that vendor claim on your tree. Run Oxfmt against a branch, diff against your Prettier-formatted tree, and count changed lines. A large diff is not a correctness problem, but it is a one-time cost that lands in every open PR and pollutes git blame. Decide whether you will absorb it.
  6. Only then touch CI, starting with a non-blocking parallel job.

This mirrors the advice Groundy gave for picking a coding-agent model: when vendors do not publish comparable numbers, A/B the candidates on your own repos and let your measurements decide. The same method applies to the toolchain underneath the model.

The rest of the stack is one decision, not four

Vite+ 1.0’s pitch is unification: lint, format, test, build, and dev server behind one set of defaults. That changes the migration math in both directions.

In favor of moving as a unit: the claimed speedups compound across steps an agent runs every cycle. If lint gets faster, formatting gets faster, and the test runner gets faster, the per-iteration saving stacks, and the Jev-Mobile result suggests per-step savings are exactly where agent economics live.

Against moving as a unit: every component you swap is a separate parity and integration risk, and bundling them means one blocked component stalls the whole migration. The runtime floor applies to the bundle. And the unification is partly unfinished: Bundled Dev, the development mode described as shaped by work with large apps including Cloudflare’s own dashboard, ships behind an experimental flag, and its stable version is still roadmap. Do not write stable Bundled Dev into any plan with a date attached.

The pragmatic reading is that Vitest 5 and Oxfmt are the lower-risk entries. Vitest’s 50% claim is against its own predecessor, so a Vitest 4 shop upgrading stays inside the same ecosystem, config model, and c8 coverage defaults. Oxfmt’s risk is concentrated in the one-time diff churn, which is measurable before you commit, and the vendor claims Prettier-compatible output plus a --migrate prettier command, which lowers that risk if the claim holds on your tree. tsgolint is the highest-potential and highest-uncertainty piece, because the parity boundary is quantified only for one rule family.

Bundled Dev is experimental, not stable

Bundled Dev (formerly Full Bundle Mode) is the item most likely to matter for agent workflows, since dev-server behavior is on the agent’s critical path too. It is shipped, but only just: you enable it with an experimental Vite flag (experimental: { bundledDev: true }), and the post says Cloudflare’s Dashboard already uses Bundled Dev for all internal developers. What has not shipped is the stable version; the announcement says the team has “made progress towards shipping” it and is “looking forward to bringing Bundled Dev out of experimental status soon.” Until that happens, benchmark it on a branch if you are curious, but any migration business case that counts on its benefits is built on unfinished software.

Verdict: pilot conditionally, and keep citing the evidence gap

Profile before you migrate. If measurement shows lint and format steps dominate your coding agent’s wait time, and your enabled rules sit inside typescript-eslint’s type-aware set minus the two unsupported ones, pilot tsgolint on one repository and re-run the vendor’s benchmark locally before letting it near CI. If your loop waits on typecheck or tests instead, an 18x linter will not fix your bottleneck, and if your config leans on framework plugins or custom rules, the parity question is simply unanswered. In those cases, stay on ESLint until independent benchmarks or broader plugin-parity data exist, and treat Bundled Dev as experimental until it ships stable.

The strongest limitation bears repeating plainly: every performance figure in this story, 12-to-18x lint, 50% test, 7x format, 10x React compile, comes from the vendor that sells the toolchain, framed as “up to” ceilings or vendor-measured ranges, with no independent replication cited in the announcement, and the one quantified parity boundary (59 of 61) covers a single rule family rather than the ecosystem most real configs actually run. The decision framework and the measurement protocol above are designed to work even if none of the vendor’s numbers survive contact with your repository. That is the part of this article worth keeping after the release notes age out.

Frequently Asked Questions

How many typescript-eslint type-aware rules does tsgolint support?

tsgolint supports 59 of typescript-eslint’s 61 type-aware rules. Type-aware rules are the ones that need type information to work (rules like no-floating-promises), and they are historically the slow ones, so covering them is the right priority.

Is Bundled Dev a stable feature in Vite+?

Bundled Dev (formerly Full Bundle Mode) is the item most likely to matter for agent workflows, since dev-server behavior is on the agent’s critical path too. It is shipped, but only just: you enable it with an experimental Vite flag (experimental: { bundledDev: true }), and the post says Cloudflare’s Dashboard already uses Bundled Dev for all internal developers. What has not shipped is the stable version; the announcement says the team has “made progress towards shipping” it and is “looking forward to bringing Bundled Dev out of experimental status soon.”

References

Follow the links in the article for context. The supporting material is collected here for further reading.

  1. four-month update on VoidZeroblog.cloudflare.comAccessed
  2. Vitest repositorygithub.comAccessed
  3. Jev-Mobile paperarxiv.orgAccessed
  4. WebArxiv benchmarkarxiv.orgAccessed
  5. Better Stack's guidebetterstack.comAccessed

Join the discussion

Share a useful perspective or ask a question about this article.

Discussion guidelinesComments privacy