rslint is a forked linter in three toolchains whose README shows no command at all
High-performance, ESLint-compatible linter for JavaScript and TypeScript.
At a glance
- What is it?
- rslint is an ESLint-compatible JavaScript and TypeScript linter written in Go on top of TypeScript's own compiler, with 600 or more native rules and type-aware linting on by default. Its engineering story is legible in the repository, its compatibility story is hedged in the README, and its getting-started section is a link to a website rather than a single command.
- Who is it for?
- rslint is a serious candidate for a TypeScript-heavy repo that wants type-aware rules without wiring up a separate type check, and a poor fit if you need guaranteed rule-for-rule parity with ESLint, since the project only claims best effort compatibility. Before switching, run both linters over your codebase and diff the output, budget for a whole-program analysis on first run, and confirm your plugins work under flat config rather than trusting the compatibility line.
- 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 received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- web-infra-dev/rslint463 ★ · +34
| Repository | 2026-07-31 | 2026-11-14 |
|---|---|---|
| web-infra-dev/rslint | 429 | 463 |
34 Stars in the last 106 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The getting started section is a link, not a command
The entire installation and usage section of the README is one sentence pointing at a guide hosted on the project's own site, and the next section points at an architecture document in the repository. There is no install command, no example invocation, no configuration snippet and no rules table anywhere in the visible text.
For a project whose entire pitch is being a drop-in replacement for a tool most JavaScript developers already have installed, that is a notable choice. A reader who arrives from a search result gets the goals list and then has to leave.
What the repository does show is how the project itself runs the tool, and it lints itself. The monorepo manifest carries a lint script that invokes the binary with its own configuration file:
"lint": "rslint --config rslint.config.ts"A TypeScript configuration file sits at the repository root next to a JSON schema file, which is what makes editor completion and validation work for anyone adopting the same setup. The configuration is also a TypeScript file rather than JSON, so it can be computed.
For the rest of the mechanics, the linked guide and the in-repository architecture document are the sources, and neither is visible from this README.
Go, Rust and TypeScript share one repository
The top-level tree carries three separate build systems and one submodule. The Go side is a module named after the repository declaring Go 1.27.0, with command, internal and test directories, a workspace file and a workspace checksum. The Rust side is a Cargo workspace whose members are a glob over the crates directory, with edition 2024 and a release profile tuned hard: optimization level 3, link-time optimization on and a single codegen unit.
The Node side is a pnpm workspace with a lockfile, four separate tsconfig files covering the base, build, root and spec configurations, and a pinned Node version file.
On top of that sits a TypeScript compiler checkout as a git submodule, which is the dependency the whole design rests on.
The tuning numbers are worth pausing on. A single codegen unit and link-time optimization are choices that cost build time to buy runtime performance, which is consistent with a linter being sold on speed, and it implies the Rust side is not incidental.
Three toolchains also mean three lint configurations in one repository: a Go lint file, Rust formatting through the Rstack `rs` command for both formatting and format checking, the Rslint self-check for TypeScript, plus a spell checker configuration and a separate ast-grep rule file.
The Go module replaces two dozen upstream TypeScript modules with local copies
The most revealing file in the repository is the Go module manifest, and most of it is a replace block. Paths under the upstream TypeScript compiler's shim module are redirected to directories inside this repository, one replace directive per shim package: api, ast, binder, bundled, checker, collections, compiler, core, diagnostics, evaluator, jsnum, jsonrpc, locale, the language server and its protocol, module, parser, project, scanner, semver, the JSX transformers, tsoptions, tspath and vfs, with the encoder and JSX transform packages split out as their own entries.
That is the mechanism behind the central claim. A Go linter does not parse TypeScript itself and does not approximate TypeScript semantics, it drives the compiler's own shim packages and substitutes local copies so it can build and modify them. The stated consequence is TypeScript compiler semantics as the single source of truth, which the project frames as removing edge cases rather than closing them.
The cost of that approach is visible in the same file. Roughly two dozen replace directives is a large surface to keep aligned with an upstream project that ships on its own schedule, and a Go workspace file sits alongside to make multi-module development work.
Two structural facts compound it: the compiler itself arrives as a submodule rather than a versioned dependency, and the release script excludes the packages that serve the TypeScript language server from the normal npm publish path.
It is a fork of tsgolint with rules adapted from typescript-eslint
The credits section is unusually specific about lineage, and the first entry is the one that matters. Rslint is forked from tsgolint, whose original author is credited by handle, and the project describes itself as grateful for pioneering work on TypeScript linting.
Rule provenance is credited next. The typescript-eslint team is credited for the configuration design and test cases, described as significantly influenced by and adapted from their implementation, which is also the origin of the 600-plus rule set: all typescript-eslint rules plus all rules from the ESLint core recommended package, implemented natively rather than ported.
Two architectural influences are named beyond the JavaScript ecosystem. The Rust Clippy team is credited for the approach of compiler-integrated linting, and the TypeScript project for powering parsing and semantic analysis through its Go compiler.
Individual credits are also specific. The creator of typescript-eslint is credited with guidance during development, and a separate blog series on writing a linter is credited with architectural insight.
So the honest summary is that this is a fork, of a Go linter for TypeScript, whose rule set and configuration design came from the existing JavaScript tooling.
Compatibility is described as best effort while consistency is claimed as total
Two claims sit next to each other in the goals list and need separating.
The first is compatibility, hedged twice. The goal is labelled best effort ESLint compatibility, described as compatible with most ESLint and TypeScript-ESLint configurations, and credited with significantly reducing migration costs rather than eliminating migration work. The status section repeats it as compatible with ESLint flat config and most ESLint plugins.
The second is consistency, stated absolutely: using TypeScript compiler semantics as the single source of truth is described as ensuring 100 percent consistency and eliminating edge cases.
Both can be true at once, and reading them together explains the actual product. Behaviour that comes from the compiler is consistent, because it is the same compiler. Rule coverage and configuration semantics are best effort, because those came from another project and were adapted rather than reimplemented identically.
The practical consequence for a migrating team is that the risk lives in the configuration layer and in third-party plugins, not in how the compiler understands types. A plugin that relies on ESLint internals rather than on the rule contract is where a best-effort claim turns into work.
Type-aware linting is on by default, so the first run is a program analysis
Typed linting is enabled by default, the stated requirement being no complex configuration, and optional type checking can happen in the same run as the lint. Analysis is at the project level rather than the file level, which the goals describe as enabling more semantic analysis than file-level linting, and cross-module analysis is what the default means in practice.
That is the single most consequential operational fact about the tool, and it is easy to read past. A file-level linter can fail fast on one file and a team can adopt it incrementally. A project-level type-aware linter has to resolve the whole graph first, so the first invocation in a repository behaves like a type check in cost and in failure mode, and errors surface as a graph-wide result rather than as a per-file list.
The features around it are consistent with that orientation. Monorepo support is listed as first class, with TypeScript project references and workspace configurations, which is what a cross-module analyzer needs in order to answer questions that span packages.
For an extension author, the extensibility claim is also oriented around the program rather than the file: the AST, type information and global checker data are exposed so custom rules can do cross-module analysis.
The 20 to 40 times claim has benchmark scripts behind it and no numbers in front
The headline performance goal is 20 to 40 times faster linting than traditional ESLint setups. No hardware is named, no repository is linted, no rule set is specified, no ESLint version is given and no measurement method is described.
What sits behind the claim is real infrastructure. The monorepo manifest defines a benchmark suite that runs through a dedicated CLI package, and a separate Go benchmark target:
"bench:go": "go test -bench=. -benchtime=5s ./tests/bench-go/"A five-second benchtime per case is a deliberate choice, enough to smooth scheduling noise without making a suite slow. The repository also links a CodSpeed badge, which points to continuous tracking rather than a one-off number, and the presence of both a Node-side and a Go-side benchmark target matches the three-toolchain layout.
So the tooling to verify the claim exists and is wired into CI-style scripts, but the README reports only the ratio. The comparison target is also soft: traditional ESLint setups is not a fixed baseline, since the number moves with which rules are enabled, whether type information is requested, and whether the comparison includes ESLint's own startup cost.
Continuous benchmark data is the way to settle it, and it lives on the badge rather than in the repository.
Editorial conclusion
rslint is a serious candidate for a TypeScript-heavy repo that wants type-aware rules without wiring up a separate type check, and a poor fit if you need guaranteed rule-for-rule parity with ESLint, since the project only claims best effort compatibility. Before switching, run both linters over your codebase and diff the output, budget for a whole-program analysis on first run, and confirm your plugins work under flat config rather than trusting the compatibility line.
Frequently asked questions
What is rslint and what is it built on?
It is a high-performance, best effort ESLint-compatible linter for JavaScript and TypeScript written in Go, built on TypeScript's native Go compiler, with 600 or more natively implemented rules including all typescript-eslint rules and all rules from the ESLint core recommended package.
Does the rslint README show how to install or run it?
No. The getting started section is a single link to a hosted guide, and architecture details are pointed at a document in the repository. The only command visible in the project is its own lint script, which runs the binary against a TypeScript configuration file at the repository root.
How complete is rslint's ESLint compatibility?
The project states best effort compatibility, describing itself as compatible with most ESLint and TypeScript-ESLint configurations and with ESLint flat config and most plugins, and credits itself with reducing migration costs rather than removing migration work.
Why does rslint use so many replace directives in go.mod?
They redirect roughly two dozen upstream TypeScript compiler shim packages to directories inside the repository, including the checker, binder, parser, scanner and program modules, which is how the Go linter drives the compiler's own semantics instead of reimplementing them.
Do I need type information to use rslint?
Typed linting is enabled by default with minimal configuration, analysis is project-level with cross-module analysis on by default, and optional type checking can run in the same pass. Monorepos with TypeScript project references and workspace configurations are supported directly.
Where does rslint come from and who is behind it?
It is forked from tsgolint by its original author, follows the compiler-integrated approach pioneered by Rust Clippy, and takes its configuration design and test cases from typescript-eslint. It is part of Rstack alongside Rspack, Rsbuild, Rslib, Rspress, Rsdoctor and Rstest.
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/web-infra-dev-rslint)Star history chart for your README
[](https://hysenlabs.com/projects/web-infra-dev-rslint)Was this useful?