xo vs eslint vs prettier vs standard
JavaScript Code Quality Tools
xoeslintprettierstandardSimilar Packages:

JavaScript Code Quality Tools

JavaScript code quality tools are essential for maintaining high standards in code readability, consistency, and overall quality. These tools help developers enforce coding standards, automatically format code, and catch potential errors before they become problematic. By integrating these tools into the development workflow, teams can ensure that their codebase remains clean, maintainable, and free from common pitfalls. Each tool has its unique features and philosophies, catering to different preferences and project requirements.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
xo131,6057,99493.8 kB3a month agoMIT
eslint027,4612.92 MB12813 days agoMIT
prettier052,2079.95 MB1,419a month agoMIT
standard029,428164 kB1282 years agoMIT

Feature Comparison: xo vs eslint vs prettier vs standard

Configuration Flexibility

  • xo:

    XO provides a balanced approach with sensible defaults and some configurable options. It aims to enforce best practices while still allowing for some customization, making it a good middle ground for teams.

  • eslint:

    ESLint offers extensive configuration options, allowing developers to customize rules, set environments, and define plugins tailored to their specific needs. This flexibility makes it suitable for a wide range of projects and coding styles.

  • prettier:

    Prettier is designed to require minimal configuration, focusing on enforcing a consistent code style with sensible defaults. While it can be configured to some extent, its opinionated nature means that most users will benefit from using it without extensive adjustments.

  • standard:

    Standard is completely zero-config, meaning it comes with a predefined set of rules that cannot be changed. This simplicity is beneficial for teams that want to avoid configuration overhead and adhere to a consistent style without debate.

Integration with Build Tools

  • xo:

    XO supports integration with various build tools and editors, providing real-time feedback during development. It can also be used in CI environments to enforce code quality checks.

  • eslint:

    ESLint integrates seamlessly with various build tools and IDEs, enabling real-time linting during development. It can be easily incorporated into CI/CD pipelines to ensure code quality before merging changes.

  • prettier:

    Prettier can be integrated into build processes and editors, allowing for automatic code formatting on save or during builds. This ensures that all code adheres to the same formatting rules consistently across the project.

  • standard:

    Standard can be integrated into build tools and CI environments, but its zero-config nature means it may require additional setup for specific integrations. It is straightforward to use in most scenarios without much overhead.

Community and Ecosystem

  • xo:

    XO is a newer tool with a growing community. While it may not have as many plugins as ESLint, it is designed to be modern and user-friendly, appealing to developers looking for a straightforward linting solution.

  • eslint:

    ESLint has a large and active community, with numerous plugins and extensions available for various frameworks and libraries. This extensive ecosystem allows developers to enhance their linting experience significantly.

  • prettier:

    Prettier also has a robust community and is widely adopted across many projects. Its popularity has led to numerous integrations with other tools and platforms, making it a standard choice for code formatting.

  • standard:

    Standard has a smaller community compared to ESLint but is still widely used. Its simplicity and zero-config approach have garnered a dedicated user base, especially among those who prefer convention over configuration.

Learning Curve

  • xo:

    XO has a moderate learning curve, as it offers some configuration options while still being user-friendly. Developers familiar with ESLint will find it relatively easy to adapt.

  • eslint:

    ESLint has a steeper learning curve due to its extensive configuration options and flexibility. New users may need time to understand how to set up and customize their linting rules effectively.

  • prettier:

    Prettier is easy to learn and use, as it focuses solely on formatting and requires minimal configuration. Developers can quickly adopt it without needing to understand complex rules.

  • standard:

    Standard is very easy to pick up since it requires no configuration. Developers can start using it immediately, making it a great choice for teams looking for simplicity.

Error Detection

  • xo:

    XO offers good error detection capabilities, combining some of the best practices from ESLint while maintaining a simpler setup. It helps catch common issues while promoting a clean code style.

  • eslint:

    ESLint excels in error detection, identifying a wide range of issues from stylistic problems to potential bugs in the code. Its ability to catch errors early in the development process is one of its key strengths.

  • prettier:

    Prettier focuses primarily on formatting rather than error detection. While it ensures consistent code style, it does not catch logical errors or potential bugs in the code.

  • standard:

    Standard provides basic error detection based on its predefined rules, but it may not catch as many issues as ESLint due to its limited configurability.

How to Choose: xo vs eslint vs prettier vs standard

  • xo:

    Choose XO if you want a modern linter with a focus on simplicity and a built-in set of rules that align with best practices. XO also supports TypeScript and offers a straightforward setup, making it a great choice for projects that want to enforce quality without extensive configuration.

  • eslint:

    Choose ESLint if you need a highly configurable linter that allows you to define your own rules and integrate with various plugins for specific frameworks or libraries. ESLint is ideal for teams that want to enforce custom coding standards and catch a wide range of issues in their code.

  • prettier:

    Choose Prettier if your primary goal is to maintain consistent code formatting across your project with minimal configuration. Prettier is opinionated and focuses solely on formatting, making it perfect for teams that want to avoid debates over code style and ensure uniformity in code appearance.

  • standard:

    Choose Standard if you prefer a zero-configuration approach to JavaScript coding standards. Standard enforces a set of predefined rules without the need for configuration files, making it suitable for projects where simplicity and convention over configuration is desired.

README for xo


XO


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 eslint.config.js 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.

Highlights

Install

npm install xo --save-dev

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

For framework-specific linting, see Astro, React, Svelte, and Vue.

Usage

$ xo --help

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

	Options
		--fix                     Automagically fix issues
		--fix-dry-run             Automagically fix issues without saving the changes to the file system
		--reporter                Reporter to use
		--space                   Use space indent instead of tabs [Default: 2]
		--config                  Path to a XO configuration file
		--semicolon               Use semicolons [Default: true]
		--prettier                Format with prettier or turn off Prettier-conflicted rules when set to 'compat' [Default: false]
		--print-config            Print the effective ESLint config for the given file
		--version                 Print XO version
		--open                    Open files with issues in your editor
		--quiet                   Show only errors and no warnings
		--max-warnings            Number of warnings to trigger nonzero exit code [Default: -1]
		--stdin                   Validate/fix code from stdin
		--stdin-filename          Specify a filename for the --stdin option
		--ignore                  Ignore pattern globs, can be set multiple times
		--suppressions-location   Path to a custom ESLint suppressions file
		--cwd=<dir>               Working directory for files [Default: process.cwd()]

	Examples
		$ xo
		$ xo index.js
		$ xo *.js !foo.js
		$ xo --space
		$ xo --print-config=index.js
		$ echo 'const x=true' | xo --stdin --fix

	Tips
		- Add XO to your project with `npm init xo`.
		- Put options in xo.config.js 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.

Workflow

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 create an xo.config.js.

Config

You can configure XO options by creating an xo.config.js or an xo.config.ts file in the root directory of your project, or you can add an xo field to your package.json. XO supports all js/ts file extensions (js,cjs,mjs,ts,cts,mts) and popular framework extensions (vue,svelte,astro) automatically. A XO config is an extension of ESLint's Flat Config. Like ESLint, an XO config exports an array of XO config objects. XO config objects extend ESLint Configuration Objects. This means all the available configuration params for ESLint also work for XO. However, XO enhances and adds extra params to the configuration objects to make them easier to work with.

Config types

XO exports the types FlatXoConfig, XoConfigItem, and other types for you to get TypeScript validation on your config files.

examples: xo.config.js

/** @type {import('xo').FlatXoConfig} */
const xoConfig = [...]

xo.config.ts

import {type FlatXoConfig} from 'xo';

const xoConfig: FlatXoConfig = [...]
export default [...] satisfies import('xo').FlatXoConfig

files

Type: string | (string | string[])[]
Default: **/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,vue,svelte,astro}

A glob string, array of globs, or ESLint's native format (where nested arrays create AND patterns) indicating which files the config object applies to. By default XO will apply the configuration to all files. This is compatible with ESLint plugin configs, so you can spread them directly into your XO config.

Tip: If you are adding additional @typescript-eslint rules to your config, these rules will apply to JS files as well unless you separate them appropriately with the files option. @typescript-eslint rules set to 'off' or 0, however, will have no effect on JS linting.

ignores

Type: string | string[]

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

Tip: For global ignores, keep ignores as the only key in the config item. You can optionally set a name property. Adding more properties will cause ignores to be scoped down to your files selection, which may have unexpected effects.

Global negated ignores are supported in both config files and the CLI for reopening XO's built-in ignored paths. This includes directory globs like !dist/**, file globs like !**/*.min.js, and literal file paths like !dist/src/index.js.

When global ignores are involved, XO uses them in this order:

  1. Built-in default ignores
  2. Global config ignores
  3. CLI ignores

XO keeps positive ignores for fast file discovery and only rechecks XO's own default-ignored paths. ESLint makes the final ignore decision.

space

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”.

semicolon

Type: boolean
Default: true (Semicolons required)

Set it to false to enforce no-semicolon style.

prettier

Type: boolean | 'compat'
Default: false

Format code with Prettier.

XO applies its own Prettier options:

Any options you set in a Prettier config still apply for anything XO does not configure (like printWidth or plugins), but XO's own style settings take precedence.

Compat

If the Prettier option is set to compat, instead of formatting your code automatically, XO will turn off all rules that conflict with Prettier code style and allow you to pass your formatting to the Prettier tool directly.

Astro

To lint Astro files, install eslint-plugin-astro:

npm install --save-dev eslint-plugin-astro

Then spread its recommended config in your xo.config.js:

import astroPlugin from 'eslint-plugin-astro';

const xoConfig = [
	...astroPlugin.configs.recommended,
];

export default xoConfig;

React

To lint React files, install eslint-config-xo-react:

npm install --save-dev eslint-config-xo-react

Then spread it in your xo.config.js:

import xoReact from 'eslint-config-xo-react';

const xoConfig = [
	...xoReact(),
];

export default xoConfig;

[!NOTE] Until eslint-plugin-react supports ESLint 10 natively, you may need to wrap the config with fixupConfigRules from @eslint/compat.

Svelte

To lint Svelte files, install eslint-plugin-svelte:

npm install --save-dev eslint-plugin-svelte

Then spread its recommended config in your xo.config.js:

import sveltePlugin from 'eslint-plugin-svelte';

const xoConfig = [
	...sveltePlugin.configs.recommended,
];

export default xoConfig;

Vue

To lint Vue files, install eslint-plugin-vue:

npm install --save-dev eslint-plugin-vue

Then spread its recommended config in your xo.config.js:

import vuePlugin from 'eslint-plugin-vue';

const xoConfig = [
	...vuePlugin.configs['flat/recommended'],
];

export default xoConfig;

Shareable configs

If you want to extend a shareable ESLint config or any other npm package, use xo.config.js instead of package.json, since package.json only supports serializable values and cannot import.

xo.config.js

export {default} from 'my-shareable-config';

You can also extend and override:

import myConfig from 'my-shareable-config';

export default [
	...myConfig,
	{
		rules: {
			// Your overrides
		},
	},
];

TypeScript

XO will automatically lint TypeScript files (.ts, .mts, .cts, 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.

You can opt out of XO's automatic tsconfig handling by specifying your own languageOptions.parserOptions.project, languageOptions.parserOptions.projectService, or languageOptions.parserOptions.tsconfigRootDir. Files in a config with these properties will be excluded from automatic tsconfig handling.

Usage as an ESLint Configuration

There are two different ways to use XO's rules with ESLint directly, depending on whether you use the xo CLI.

Without the xo CLI

If you don't use the xo CLI and just want XO's rules in ESLint, use eslint-config-xo. It accepts the same core style options as XO, including Prettier integration:

eslint.config.js

import eslintConfigXo from 'eslint-config-xo';

export default [
	...eslintConfigXo({space: true, prettier: true}),
];

[!NOTE] This replaces the old xoToEslintConfig helper. For example, xoToEslintConfig([{space: true, prettier: true}]) becomes eslintConfigXo({space: true, prettier: true}). For per-file overrides, add normal ESLint config objects alongside it.

With the xo CLI (editor integration)

If you use the xo CLI but your editor only has the ESLint extension (not XO's), add an eslint.config.js that re-exports the adapter. It reads your xo.config.js and generates the matching ESLint config automatically, so your editor shows the same errors as running xo — without duplicating your config.

eslint.config.js

export {default} from 'xo/eslint-adapter';

Tips

Monorepo

Put a xo.config.js with your config at the root and do not add a config to any of your bundled packages.

Including files ignored by default

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

const xoConfig = [{ignores: ['!vendor/**']}];

export default xoConfig;

This also works for narrower carve-outs:

const xoConfig = [{ignores: ['!dist/src/**', '!dist/src/index.js']}];

export default xoConfig;

Warnings are hidden when there are errors

When XO finds errors, warnings are automatically hidden to reduce noise and let you focus on what matters. Warnings are shown normally when there are no errors. Use --quiet to always suppress warnings, or --max-warnings to treat warnings as errors.

Bulk suppression

XO automatically respects an eslint-suppressions.json file if one exists in the working directory. This lets you suppress existing violations while still enforcing rules on new code — useful for incrementally adopting stricter rules in a large codebase.

To generate the suppressions file, create a temporary eslint.config.js using xo/eslint-adapter and run ESLint with --suppress-all:

npx eslint --suppress-all

Commit the resulting eslint-suppressions.json to share suppressions across your team.

To use a custom suppressions file path, pass --suppressions-location:

xo --suppressions-location config/suppressions.json

FAQ

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

Configs

Support

Related

Badge

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

[![XO code style](https://shields.io/badge/code_style-5ed9c7?logo=xo&labelColor=gray&logoSize=auto)](https://github.com/xojs/xo)

Large badge: XO code style

[![XO code style](https://shields.io/badge/code_style-5ed9c7?style=for-the-badge&logo=xo&labelColor=gray&logoSize=auto)](https://github.com/xojs/xo)

Or customize the badge.

You can also find some nice dynamic XO badges on badgen.net.