Open-source project
eslint/js avatar
eslint/js

eslint/js: the parser and scope analyser under ESLint, not the linter itself

Monorepo for the JS language tools.

2,390 stars235 forksJavaScriptBSD-2-Clause

At a glance

What is it?
The ESLint monorepo that ships espree, eslint-scope, and eslint-visitor-keys, which is a different thing from the ESLint plugin you install to check your code.
Who is it for?
The most common misunderstanding here is naming: eslint/js is a library monorepo, and the package you want when you want ESLint to check your source is a different artefact entirely. Adopt this repository when you are building a tool that needs to parse JavaScript the way ESLint does, or when you are pinning the parser and scope analyser underneath your own lint setup, because those are the three packages it publishes.
Can I use it commercially?
Yes. BSD-2-Clause 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 JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • eslint/js2,390 ★ · +4
Star history
Repository2026-10-072026-10-23
eslint/js2.4k2.4k

4 Stars in the last 16 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Three packages, and the repository name explains the confusion

The README is four lines of substance. The repository is described as a monorepo for the JS language tools, and it lists what it is the home of:

- [`espree`](packages/espree) - [`eslint-scope`](packages/eslint-scope) - [`eslint-visitor-keys`](packages/eslint-visitor-keys)

That list is the whole scope of the project. There is no rule set here, no configuration format, and no plugin. If you have configured ESLint before, you were using a different package: the linter itself is what applies rules to your code, and it depends on these three packages to do the parsing and analysis work underneath.

The names map onto that division of labour in a fairly obvious way once you know them. espree is the parser, the component that turns source text into an abstract syntax tree. eslint-scope is the analyser that works out which identifiers are in scope where, which is what makes rules about unused variables and shadowing possible at all. eslint-visitor-keys is the shared list of which node types have which visitor keys, so that a traversal does not have to be reinvented per package.

The repository is not archived and the last push was on 2026-09-27. Its licence is BSD-2-Clause, which is the permissive end of the spectrum and the reason these packages can sit inside commercial tooling without a licensing discussion.

Release tags are per package, which is the detail that trips people up

The release list shows three tags and none of them is named after the repository. They are `espree-v11.2.0`, `eslint-scope-v9.1.2`, and `espree-v11.1.1`. Each package versions independently, and each tag names the package it belongs to.

The release notes carry real information. The `espree-v11.2.0` release, published on 2026-03-06, adds a feature allowing a top level `using` declaration in `"commonjs"`. Explicit resource management, with `using` and `await using`, is a syntax change that a parser either accepts or produces a syntax error on, and a parser lagging behind the language means your linter reports a parse failure on valid code. That is a good illustration of what this repository actually does: it tracks the language.

The `espree-v11.1.1` release, published on 2026-02-20, is a bug fix release with two entries that both point at tooling rather than syntax. One improves tree-shaking, and one updates acorn and fixes tests. espree is built on acorn, so an acorn update lands here as a dependency bump, and the release notes record eslint-visitor-keys moving from 5.0.0 to 5.0.1 as a consequence.

The `eslint-scope-v9.1.2` release published on the same day as `espree-v11.2.0` records only a workspace dependency update, with espree bumped from 11.1.1 to 11.2.0. Read together, the three releases show a monorepo where packages are released separately but in a coordinated order, because a scope analyser bump has to follow the parser it understands.

Workspaces, ESM, and a release process managed by tooling

The root `package.json` is worth reading even though the README is short, because it shows how the project is put together. It is named `eslint-js`, marked private, and set to `type: module`, so the workspace root is ESM. Workspaces are declared as `packages/*`, matching the three package directories in the tree.

Every build and test command fans out across workspaces with `--if-present`, which means a package without a build script does not break the root command:

json
"build": "npm run build --workspaces --if-present",
"test": "npm test --workspaces --if-present"

The `prepare` script runs the build, so a plain install compiles the workspace automatically.

Releases are handled by tooling rather than by hand. The tree contains `.release-please-manifest.json` and `release-please-config.json`, and `package.json` allows the `yorkie` script explicitly in `allowScripts`. Release Please derives a version bump and changelog from conventional commits, which is why the release bodies read like a generated changelog with commit hashes and compare links, and why the tags carry package names: the tool is configured to version each workspace separately.

For a reader trying to work out where a change landed, that convention is the whole answer. A diff between `espree-v11.1.1` and `espree-v11.2.0` is parser work. A diff on an `eslint-scope` tag is scope analysis work.

How the project lints and tests itself

The toolchain is a reasonable picture of a modern JavaScript monorepo, and some of it is directly interesting. Prettier handles formatting with a dedicated config in the tree and separate write and check scripts:

json
"fmt": "prettier --write .",
"fmt:check": "prettier --check ."

ESLint lints the repository, so the dogfooding is real, with `eslint` and `eslint --fix` as the two scripts. `knip` runs as `lint:unused`, which finds unused files, dependencies, and exports, a check that pays for itself in a monorepo where a dependency can go stale in one package while another still needs it.

Commit hooks wire it together. The package declares a `pre-commit` git hook running `lint-staged`, and lint-staged sends JavaScript and TypeScript files through `eslint --fix` and `prettier --write`, sending everything else through prettier with `--ignore-unknown`.

json
"gitHooks": {
  "pre-commit": "lint-staged"
},

Tests run on mocha with `c8` for coverage, and rollup handles bundling. Type checking is the more unusual part. Rather than pinning one compiler, the project checks its declarations against several TypeScript versions, including the native preview:

json
"test:types:7.x": "npx -p @typescript/native-preview@latest -y -- tsgo -p tsconfig.dist.json"

There is a `tsconfig.dist.json`, a `tsconfig.dist-legacy.json`, and a `tsconfig.base.json`, and `@arethetypeswrong/cli` sits in dev dependencies. All of that exists because these packages publish type declarations, and a declaration that compiles under one TypeScript version can still break consumers on another.

ESLint against Prettier, which is a question about different jobs

This question comes up constantly and the two projects are not really competing. Prettier reformats code. It has opinions about whitespace, quotes, and line breaks, and it applies them without understanding what the code means. ESLint analyses code. It builds a syntax tree, resolves scope, and reports patterns that can be wrong in ways formatting cannot express.

The concrete example is a floating promise. Prettier has no opinion about it because it cannot see the bug. A lint rule can, because it has the parsed program and the scope analysis, which is exactly why eslint-scope exists as a separate package in this repository. An unused variable is the same story: removing or renaming it is a formatting-neutral edit that a formatter will happily leave alone and a linter will flag.

Running both is normal rather than redundant, and the root `package.json` here does precisely that, with prettier scripts and eslint scripts side by side, and lint-staged running both in the same pre-commit hook. If you were choosing only one, formatting alone gives you consistency without correctness, and correctness alone leaves you arguing about indentation.

The related searches attached to this project include Eslint/js vs eslint and Eslint vs eslint/js, which is the distinction this section exists to settle: one is a library monorepo published under the ESLint organisation, the other is the linter you install.

Where the README stops and the wider ESLint documentation starts

The README covers three things: what the packages are, a security policy link, and the sponsor list. The security policy is hosted in the shared ESLint organisation repository rather than in this one, and the wording asks readers to consider that the packages inside are safe for everyone and that security issues are addressed quickly and responsibly.

That is the limit of what is documented here. There is no usage guide, no API documentation, no configuration reference, and no migration notes beyond what lands in individual release bodies. Each package directory under `packages/` is where its own documentation would live, and the main ESLint documentation and website are referenced rather than reproduced.

Two things are worth noting about that. First, it is a reasonable arrangement: these are libraries consumed by the linter and by third-party tools, and their reference material is versioned with each package rather than in one monorepo-level document that would drift. Second, it means evaluating this repository means evaluating three projects rather than one, and the release tags are the only place in the README-visible surface that tells you the current state of each.

The sponsorship section, which occupies most of the file's rendered length, records that companies and individuals support ongoing maintenance and development, with tiers from platinum down to technology sponsors. That is a fact about funding rather than about the code, and the packages themselves are what you would install.

Editorial conclusion

The most common misunderstanding here is naming: eslint/js is a library monorepo, and the package you want when you want ESLint to check your source is a different artefact entirely. Adopt this repository when you are building a tool that needs to parse JavaScript the way ESLint does, or when you are pinning the parser and scope analyser underneath your own lint setup, because those are the three packages it publishes. What it will not give you is a config, a plugin, or a set of rules, and the README is honest enough to say so by listing three packages and pointing at eslint.org for the rest. Start by comparing the release tags, which are versioned per package, then decide whether espree or a different parser fits the syntax you need to accept.

Frequently asked questions

What is ESLint and why is it used?

This repository is not the linter, it is the monorepo for three libraries the linter depends on: espree as the parser, eslint-scope for scope analysis, and eslint-visitor-keys for shared visitor key data. The README describes the project as the home of those three packages and nothing else.

What is ESLint vs prettier?

Prettier reformats code based on whitespace and layout, while ESLint parses the code and reports semantic problems such as unused variables or an unawaited promise, which needs the syntax tree and scope analysis to detect. Running both is normal, and this repository's own package.json does it, with prettier scripts alongside eslint scripts.

Can I use ESLint with TypeScript?

The README does not document TypeScript usage, and this repository is not the package you install to lint a TypeScript project. What it shows is that the published packages ship type declarations checked against several TypeScript versions, using tsconfig.dist.json, tsconfig.dist-legacy.json, and a separate native preview compiler run.

Official sources

  1. eslint/js on GitHub
  2. Issues
  3. License: BSD-2-Clause
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/eslint-js.svg)](https://hysenlabs.com/projects/eslint-js)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/eslint-js.svg)](https://hysenlabs.com/projects/eslint-js)

Was this useful?