A robot in space holding the Rome logo sitting on top of clouds. Scattered around are various rockets and shapes.

Announcing Rome v10

The first stable release of Rome
Micha Reiser & Rome Team

We are thrilled to announce Rome v10, the first stable release since the start of the Rust rewrite. Rome is an ambitious project aiming to unify the dozens of frontend language tools into a single easy-to-use tool built from scratch.

This release includes our fast linter and formatter; they require minimal configuration, come with beautiful and descriptive diagnostics, and have built-in support for JavaScript and TypeScript.

Rome’s formatter is Prettier-inspired, allowing most users to migrate with minimal to zero changes. Our linter builds off a recommended ruleset following community standards and strives to be actionable and informative whenever it detects a problem.

This is just the beginning. In the upcoming year we will add support for other frontend languages and build the rest of the Rome stack, including compilation, bundling, testing, and more.

Getting Started

Three commands are all that’s required to try Rome. In a project with a package.json:

# Install
npm install --save-dev rome

# Create a configuration (optional)
npx rome init

# Format
npx rome format <files>

# Or, lint:
npx rome check <files>

We hope you enjoy using Rome as much as we enjoyed building it. If you run into any issues please don’t hesitate to use the #support channel in our Discord, or report issues on GitHub.

Keep reading if you are interested in why we decided to build Rome and what makes Rome different from the other tools in the web ecosystem.

Why Rome?

Traditional approach

The web development ecosystem has a rich offering of excellent tooling that fulfills different needs during the development cycle. Here is a small selection of well-known tools:

  • Code formatting: Prettier, dprint
  • Linting: ESLint, Stylelint
  • Test runner: Vitest, Jest, AVA
  • Transpilers: Babel, SWC, TypeScript
  • Bundlers: webpack, esbuild, Vite, SWC, Rollup, Parcel

It is nice to have a wide range of options. However, time spent evaluating, installing, and configuring is time spent not working on your project. Setting up your tool stack is only the start; maintaining and scaling it with your project requires expertise and continuous time investment.

Projects like Create React App (close to 100k stars) recognize this pain point and provide you with a configured development stack by composing existing tools for React. The downside of this approach is that it only partially hides the underlying tooling: Most tools use different diagnostic formats, configurations, and editor integrations.

Our approach

Rome is a monolithic runtime-agnostic multi-language toolchain built from the ground up. It is a dependency-free formatter, linter, and in the future: compiler, bundler, test runner, and more. Its monolithic architecture unlocks a new developer experience that is difficult to achieve with a many-tool development stack:

  • Avoid unnecessary work: Formatting your files with Prettier and linting them with ESLint means that both tools spend significant time traversing directories and parsing. Rome is fast because it never does the same work twice. It goes as far as to avoid parsing a file when bundling if it already linted the file in the editor.
  • Reduce repetition: Rome uses a single configuration for all tools to reduce the number of configuration files in your project and avoid repetition. You shouldn’t have to install the React plugins and configure React support for ESLint and webpack. All it should take is to change a single configuration to enable the React lint rules, the React JSX transpilation, and FastRefresh support.
  • Learn once: Many-tool development stacks suffer that engineers must interact with each tool, having to learn and remember the command names, configuration schemas, CLI arguments, and diagnostics formats. This is a lot to remember. It is why Rome is a single binary with standardized CLI arguments and diagnostics, so you only have to learn it once.
  • Remove entry barriers: Advanced analysis and checks, like analyzing the size of a bundle or bundle size budgeting, often require additional tools and lack editor or linter integration. This added complexity is an entry barrier for many. It prevents teams from using the information or automating checks in their CI pipeline. Rome’s editor-first design and end-to-end architecture significantly lower the barrier by bringing the information into your editor or exposing it to lint rules that can run as part of your CI.

We hope you are as excited as we are about the functionalities this architecture unlocks.

Shipping a toolchain rather than a set of tools is no guarantee for a delightful developer experience. Each tool must stand on its own and bring additional value. The following section will walk you through our new linter and explains how it improves the developer experience.

New Linter

Rome’s linter focuses on ease of adoption, editor integration, and comprehensible diagnostics. It supports more than 60 stable rules for JavaScript, TypeScript, JSX, and React and is fast; It processes 6’000 files in ~300ms 1.

The following sections explain why error recovery is vital for a first-class editor integration and our philosophy on diagnostics.

Error Recovery

An essential aspect of an editor integration is that it gracefully handles syntax errors the same as editors do. For example, syntax highlighting keeps functioning even if the code contains a syntax error. That means for linting that errors and warnings should not disappear because of an unrelated syntax error in the same file.

We created a small video that illustrates the problem by comparing ESLint’s and Rome’s VS Code extensions. Pay attention to how the lint promoting strict equality over == disappears and reappears for ESLint, where Rome always shows the error.

The video compares Rome’s and ESLint’s handling of syntax errors in VS Code.

The video shows VS Code with ESLint installed on the left and Rome’s plugin on the right. Both editors show a lint error promoting strict equality over == for if(a == b). The lint error disappears for ESLint when the user adds the unfinished statement console.. The error reappears after completing the statement to console.log("Test"). The Rome plugin handles the syntax error gracefully so that the lint error doesn’t disappear.

Rome can lint files with syntax errors because of its error-tolerant parser and AST design. You can learn more about the AST design from our Rust rewrite blog post.

Rich and Comprehensible Diagnostics

Reading and understanding diagnostics is part of a software engineer’s job. But staring at a diagnostic for minutes, entirely lost even to have the slightest clue what it’s trying to tell you, should not.

That’s why Rome sets high standards for its diagnostics to state what’s wrong, why it went wrong, and, if applicable, guide the user towards a fix. Diagnostics should not only tell but show by printing rich content like code frames or diffs because they are easier to understand.

Let’s look at the concrete diagnostic Rome emits when linting the following code:

function test(callback) {
  try {
    return callback();
  } catch (e) {
    throw e;

  return 20;

And here’s the diagnostic:

  main.tsx:9:3 lint/nursery/noUnreachable ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
     This code will never be reached ...
       7 │   }
       8 │ 
     > 9 │   return 20;
      10 │ }
     ... because either this statement will return from the function ...
      1 │ function test(callback) {
      2 │   try {
    > 3 │     return callback();
      4 │   } catch (e) {
      5 │     console.log(e);
     ... or this statement will throw an exception beforehand
      4 │   } catch (e) {
      5 │     console.log(e);
    > 6 │     throw e;
      7 │   }
      8 │ 

The diagnostic tells the user that the return 20 statement is unreachable and uses a code frame to show the problematic statement in context. It explains why the statement is unreachable and uses code frames to provide additional context.

Not all diagnostics have received as much love as the noUnreachable diagnostic yet, but we are committed to improving them over time. We ask you to file an issue if you find a diagnostic difficult to understand.

Try it.

Give Rome a try. Other users adopting Rome have reported massive speedups, simplified configurations, and considerable reduction of dependencies and size of the node_modules folder.

You don’t feel like installing new software just yet? That’s OK; play with Rome in our playground.


Rome wasn’t built in a day, and certainly not without the help of many. Many thanks to all contributors that helped build Rome. Especially:

  • Boshen for integrating the T262 parser test suite and parser benchmarks into our CI pipeline. This work has been a game changer in tracking the parser compliance and performance! Thank you for your many contributions to Rome’s JavaScript lexer and parser and insightful engagement on Twitter and our Discord channel.
  • IWANABETHATGUY for contributing close to 20 lint rules, adding syntax highlighting to the playground’s AST and IR tabs, and your numerous contributions to the JavaScript parser.
  • Denis Bezrukov for your countless contributions to the JavaScript formatter, most notably: formatting of assignment like nodes, whitespace handling in JSX, and last but not least, the trailing comma option.
  • rust-analzyer: A huge shoutout to the rust-analyzer team. Rust-analyzer makes it a joy to write Rust, and it inspired Rome’s AST representation and parser implementation.
  • RSLint: Especially to Stupremee and RDambrosio016 for their work on RSLint and help Rome forking their JavaScript parser and diagnostic system.
  • Prettier: Rome formatter is heavily inspired by Prettier’s architecture and style decisions. It’s impressive how Prettier changed formatting in the web ecosystem, and walking in its footsteps helped us save a huge amount of time and decision-making.
  • ESLint: Most of Rome’s rules have been inspired by their ESLint equivalents. A huge thanks to the ESLint team and community for establishing these recommended patterns. We would not have been able to pull this off without their fantastic work.


  1. Test Setup Device: MacBook Pro (13-inch, M1, 2020), Project and Revision: 9fcaa24, Command: hyperfine -N --warmup 5 'rome check webpack/' -i,