npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details


  • User packages



Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.


Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner




JavaScript/TypeScript linter (ESLint wrapper) with great defaults




JavaScript/TypeScript linter (ESLint wrapper) with great defaults

Coverage Status XO code style

Opinionated but configurable ESLint wrapper with lots of goodies included. Enforces strict and readable code. Never discuss code style on a pull request again! No decision-making. No .eslintrc to manage. It just works!

It uses ESLint underneath, so issues regarding built-in rules should be opened over there.

XO requires your project to be ESM.



$ npm install xo --save-dev

You must install XO locally. You can run it directly with $ npx xo.

JSX is supported by default, but you'll need eslint-config-xo-react for React specific linting. Vue components are not supported by default. You'll need eslint-config-xo-vue for specific linting in a Vue app.


$ xo --help

    $ xo [<file|glob> ...]

    --fix             Automagically fix issues
    --reporter        Reporter to use
    --env             Environment preset  [Can be set multiple times]
    --global          Global variable  [Can be set multiple times]
    --ignore          Additional paths to ignore  [Can be set multiple times]
    --space           Use space indent instead of tabs  [Default: 2]
    --no-semicolon    Prevent use of semicolons
    --prettier        Conform to Prettier code style
    --node-version    Range of Node.js version to support
    --plugin          Include third-party plugins  [Can be set multiple times]
    --extend          Extend defaults with a custom config  [Can be set multiple times]
    --open            Open files with issues in your editor
    --quiet           Show only errors and no warnings
    --extension       Additional extension to lint [Can be set multiple times]
    --cwd=<dir>       Working directory for files
    --stdin           Validate/fix code from stdin
    --stdin-filename  Specify a filename for the --stdin option
    --print-config    Print the ESLint configuration for the given file

    $ xo
    $ xo index.js
    $ xo *.js !foo.js
    $ xo --space
    $ xo --env=node --env=mocha
    $ xo --plugin=react
    $ xo --plugin=html --extension=html
    $ echo 'const x=true' | xo --stdin --fix
    $ xo --print-config=index.js

    - Add XO to your project with `npm init xo`.
    - Put options in package.json instead of using flags so other tools can read it.

Default code style

Any of these can be overridden if necessary.

  • Tab indentation (or space)
  • Semicolons (or not)
  • Single-quotes
  • Trailing comma for multiline statements
  • No unused variables
  • Space after keyword if (condition) {}
  • Always === instead of ==

Check out an example and the ESLint rules.


The recommended workflow is to add XO locally to your project and run it with the tests.

Simply run $ npm init xo (with any options) to add XO to your package.json or create one.


 	"name": "awesome-package",
 	"scripts": {
-		"test": "ava",
+		"test": "xo && ava"
 	"devDependencies": {
-		"ava": "^3.0.0"
+		"ava": "^3.0.0",
+		"xo": "^0.41.0"

Then just run $ npm test and XO will be run before your tests.


You can configure XO options with one of the following files:

  1. As JSON in the xo property in package.json:
	"name": "awesome-package",
	"xo": {
		"space": true
  1. As JSON in .xo-config or .xo-config.json:
	"space": true
  1. As a JavaScript module in .xo-config.js or xo.config.js:
module.exports = {
	space: true
  1. For ECMAScript module (ESM) packages with "type": "module", as a JavaScript module in .xo-config.cjs or xo.config.cjs:
module.exports = {
	space: true

Globals and rules can be configured inline in files.


Type: string[]
Default: ['es2021', 'node']

Which environments your code is designed to run in. Each environment brings with it a certain set of predefined global variables.


Type: string[]

Additional global variables your code accesses during execution.


Type: string[]

Some paths are ignored by default, including paths in .gitignore and .eslintignore. Additional ignores can be added here.


Type: boolean | number
Default: false (tab indentation)

Set it to true to get 2-space indentation or specify the number of spaces.

This option exists for pragmatic reasons, but I would strongly recommend you read "Why tabs are superior".


Type: object

Override any of the default rules. See the ESLint docs for more info on each rule.

Please take a moment to consider if you really need to use this option.


Type: boolean
Default: true (Semicolons required)

Set it to false to enforce no-semicolon style.


Type: boolean
Default: false

Format code with Prettier.

Prettier options will be based on your Prettier config. XO will then merge your options with its own defaults:

To stick with Prettier's defaults, add this to your Prettier config:

module.exports = {
	trailingComma: 'es5',
	singleQuote: false,
	bracketSpacing: true,

If contradicting options are set for both Prettier and XO an error will be thrown.


Type: string | boolean
Default: Value of the engines.node key in the project package.json

Enable rules specific to the Node.js versions within the configured range.

If set to false, no rules specific to a Node.js version will be enabled.


Type: string[]

Include third-party plugins.


Type: string | string[]

Use one or more shareable configs or plugin configs to override any of the default rules (like rules above).


Type: string[]

Allow more extensions to be linted besides .js, .jsx, .mjs, and .cjs. Make sure they're supported by ESLint or an ESLint plugin.


Type: object

Shared ESLint settings exposed to rules.


Type: string

ESLint parser. For example, @babel/eslint-parser if you're using language features that ESLint doesn't yet support.


Type: string

ESLint processor.


Type: boolean | object Default: false

Use eslint-import-resolver-webpack to resolve import search paths. This is enabled automatically if a webpack.config.js file is found.

Set this to a boolean to explicitly enable or disable the resolver.

Setting this to an object enables the resolver and passes the object as configuration. See the resolver readme along with the webpack documentation for more information.


XO will automatically lint TypeScript files (.ts, .d.ts and .tsx) with the rules defined in eslint-config-xo-typescript#use-with-xo.

XO will handle the @typescript-eslint/parser project option automatically even if you don't have a tsconfig.json in your project.

GitHub Actions

XO uses a different formatter when running in a GitHub Actions workflow to be able to get inline annotations. XO also disables warnings here.

Note: For this to work, the setup-node action must be run before XO.

Config Overrides

XO makes it easy to override configs for specific files. The overrides property must be an array of override objects. Each override object must contain a files property which is a glob string, or an array of glob strings, relative to the config file. The remaining properties are identical to those described above, and will override the settings of the base config. If multiple override configs match the same file, each matching override is applied in the order it appears in the array. This means the last override in the array takes precedence over earlier ones. Consider the following example:

	"xo": {
		"semicolon": false,
		"space": 2,
		"overrides": [
				"files": "test/*.js",
				"space": 3
				 "files": "test/foo.js",
				 "semicolon": true
  • The base configuration is simply space: 2, semicolon: false. These settings are used for every file unless otherwise noted below.

  • For every file in test/*.js, the base config is used, but space is overridden with 3. The resulting config is:

	"semicolon": false,
	"space": 3
  • For test/foo.js, the base config is first applied, followed the first overrides config (its glob pattern also matches test/foo.js), finally the second override config is applied. The resulting config is:
	"semicolon": true,
	"space": 3


Using a parent's config

If you have a directory structure with nested package.json files and you want one of the child manifests to be skipped, you can do so by ommiting the xo property in the child's package.json. For example, when you have separate app and dev package.json files with electron-builder.


Put a package.json with your config at the root and omit the xo property in the package.json of your bundled packages.


If some files in your project are transpiled in order to support an older Node.js version, you can use the config overrides option to set a specific nodeVersion to target your sources files.

For example, if your project targets Node.js 8 but you want to use the latest JavaScript syntax as supported in Node.js 12:

  1. Set the engines.node property of your package.json to >=8
  2. Configure Babel to transpile your source files (in src directory in this example)
  3. Make sure to include the transpiled files in your published package with the files and main properties of your package.json
  4. Configure the XO overrides option to set nodeVersion to >=12 for your source files directory
	"engines": {
		"node": ">=12"
	"scripts": {
		"build": "babel src --out-dir dist"
	"main": "dist/index.js",
	"files": ["dist/**/*.js"],
	"xo": {
		"overrides": [
				"files": "{src}/**/*.js",
				"nodeVersion": ">=16"

This way your package.json will contain the actual minimum Node.js version supported by your published code, but XO will lint your source code as if it targets Node.js 16.

Including files ignored by default

To include files that XO ignores by default, add them as negative globs in the ignores option:

	"xo": {
		"ignores": [


What does XO mean?

It means hugs and kisses.

Why not Standard?

The Standard style is a really cool idea. I too wish we could have one style to rule them all! But the reality is that the JS community is just too diverse and opinionated to create one code style. They also made the mistake of pushing their own style instead of the most popular one. In contrast, XO is more pragmatic and has no aspiration of being the style. My goal with XO is to make it simple to enforce consistent code style with close to no config. XO comes with my code style preference by default, as I mainly made it for myself, but everything is configurable.

Why not ESLint?

XO is based on ESLint. This project started out as just a shareable ESLint config, but it quickly grew out of that. I wanted something even simpler. Just typing xo and be done. No decision-making. No config. I also have some exciting future plans for it. However, you can still get most of the XO benefits while using ESLint directly with the ESLint shareable config.

Editor plugins

Build-system plugins





Show the world you're using XO → XO code style

[![XO code style](](

You can also find some nice dynamic XO badges on