Internals, Architecture, and Language Support

Purpose and Scope

This page gives contributors and integrators a map of Biome from the public package boundary inward. Biome is distributed to JavaScript users as @biomejs/biome, whose package metadata describes it as a web toolchain that provides a formatter, linter, and more. That package exposes the biome executable and delegates the native executable selection to platform-specific optional dependencies. For internal readers, this is the first architectural seam: the npm package is not the formatter or analyzer itself, but the install-time and run-time bridge that makes the compiled Biome engine available to Node-based projects.

Sources: packages/@biomejs/biome/package.json, packages/@biomejs/cli-darwin-arm64/package.json

The official internals documentation frames Biome around subsystems such as the scanner, parser and concrete syntax tree, formatters, analyzers, and service-facing workspace operations. The targeted source evidence here shows the integration layer that sits above those Rust internals: a JSON-RPC backend client for the daemon, a WebAssembly JavaScript API, a plugin API guard package, and platform packages for native binaries. Read this page as an orientation to how those public entry points select a runtime, connect to a workspace, and expose the engine without duplicating implementation logic in JavaScript.

Sources: packages/@biomejs/backend-jsonrpc/src/index.ts, packages/@biomejs/js-api/src/index.ts, packages/@biomejs/plugin-api/index.js

Relevant Source Files

  • packages/@biomejs/backend-jsonrpc/src/index.ts - exports the JSON-RPC workspace client factory, initializes a daemon connection, and re-exports the workspace wrapper API.
  • packages/@biomejs/js-api/src/index.ts - exports the JavaScript API facade, WebAssembly distribution selector, shared configuration and diagnostic types, and Biome.create.
  • packages/@biomejs/plugin-api/index.js - prevents accidental direct use of the plugin package by throwing an error that points users to @biomejs/js-api.
  • packages/@biomejs/backend-jsonrpc/package.json - describes the JSON-RPC package as bindings to the daemon workspace API and lists native CLI packages as optional dependencies.
  • packages/@biomejs/biome/package.json - defines the main npm toolchain package, the biome binary, supported package keywords, files, Node engine, and optional native CLI dependencies.
  • packages/@biomejs/cli-darwin-arm64/package.json - shows the shape of a platform-specific binary package through its os, cpu, repository directory, and version metadata.

System-to-Code Mapping

Biome has multiple public runtime surfaces because the same core capabilities must work in different environments. The CLI distribution serves project automation and local developer commands. The JSON-RPC backend serves editor, daemon, and long-lived workspace clients. The JavaScript API serves programmatic consumers that want to call Biome through WebAssembly builds. These surfaces should be treated as adapters over the same conceptual toolchain rather than as separate implementations of formatting, linting, or parsing. The package metadata and TypeScript entry points make this layering explicit by focusing on binary selection, transport initialization, and WebAssembly module selection.

Sources: packages/@biomejs/biome/package.json, packages/@biomejs/backend-jsonrpc/package.json, packages/@biomejs/js-api/src/index.ts

Architectural conceptRepository surface in this pageWhat it means for readers
Native CLI distributionpackages/@biomejs/biome/package.jsonInstalls the biome command and depends optionally on platform-specific native packages.
Platform executable packagepackages/@biomejs/cli-darwin-arm64/package.jsonConstrains a binary package to darwin and arm64, illustrating how npm selects a matching binary.
Daemon workspace clientpackages/@biomejs/backend-jsonrpc/src/index.tsCreates a Workspace client by spawning or locating a binary, opening a socket, and speaking JSON-RPC.
WebAssembly programmatic APIpackages/@biomejs/js-api/src/index.tsDynamically imports the bundler, Node.js, or web WebAssembly implementation and wraps it in BiomeCommon.
Plugin package guardpackages/@biomejs/plugin-api/index.jsSignals that this package is intended for Biome JS plugins and not for general user code.

The native package metadata also documents the language-facing scope that users recognize before they ever read Rust internals. The main package keywords name JavaScript, TypeScript, JSON, JSONC, JSX, TSX, CSS, and GraphQL, matching the public identity of Biome as a multi-language web toolchain. The official language-support page expands that matrix with statuses for HTML, SVG, Vue, Svelte, Astro, SCSS, YAML, Markdown, GritQL, and plugin support. Internally, that means architecture discussions should distinguish language support status from distribution support: npm packages deliver the engine, while parser, formatter, analyzer, and plugin capabilities determine what happens for a particular file kind.

Sources: packages/@biomejs/biome/package.json

Runtime Entry Points and Execution Flow

A standard npm installation begins with @biomejs/biome. Its bin field maps the public command name biome to bin/biome, and its optional dependencies enumerate native packages for Windows, macOS, Linux, ARM, x64, and musl variants. The macOS ARM package demonstrates the platform-package contract directly: it declares os: ["darwin"] and cpu: ["arm64"]. This structure lets one logical npm package serve many platforms while keeping each native executable in a package that npm can include or skip according to the host.

Sources: packages/@biomejs/biome/package.json, packages/@biomejs/cli-darwin-arm64/package.json

The JSON-RPC backend follows a different flow because it is designed to connect a JavaScript client to a remote daemon workspace. createWorkspace() first calls getCommand() and returns null when no supported command can be found. When a command is available, it delegates to createWorkspaceWithBinary(command). That function creates a socket for the command, constructs a Transport, sends an initialize request with empty capabilities and client_info, and then wraps the transport as a Workspace. The important internal idea is that workspace operations are transport-backed: JavaScript code holds a client object, while the daemon process owns the engine state.

Sources: packages/@biomejs/backend-jsonrpc/src/index.ts

The WebAssembly API has a simpler but equally important runtime split. Biome.create({ distribution }) switches on a Distribution enum and dynamically imports @biomejs/wasm-bundler, @biomejs/wasm-nodejs, or @biomejs/wasm-web. The resulting module is passed into new Biome(...), where Biome extends BiomeCommon<Configuration, Diagnostic>. This gives programmatic consumers a stable TypeScript-facing shape while letting the build target decide which WebAssembly package is loaded. Unknown distribution values are rejected with an explicit error, so the API fails fast when the caller requests an unsupported runtime.

Sources: packages/@biomejs/js-api/src/index.ts

Language Support and Internal Subsystems

The official internals documentation describes the scanner as the component responsible for crawling project files to discover nested biome.json or biome.jsonc files, nested .gitignore files when VCS ignore support is enabled, and package manifests or source files needed by project-domain rules. That scanning behavior explains why the higher-level workspace abstraction matters: operations such as checking or formatting are not isolated string transforms in a real project. They depend on configuration discovery, ignore files, file targeting, and sometimes project metadata. The JSON-RPC workspace client is therefore the natural boundary for editor and daemon scenarios.

Sources: packages/@biomejs/backend-jsonrpc/src/index.ts, packages/@biomejs/backend-jsonrpc/package.json

The same official architecture page defines Biome parsers around a concrete syntax tree, or CST, that keeps trivia such as spaces, tabs, and comments. This design is central to formatting and diagnostics because a formatter must preserve or deliberately rewrite trivia, and an analyzer must report precise ranges against original source. The source files on this page do not expose parser nodes directly; instead, they expose transport, package, and WebAssembly boundaries that let clients invoke the parser-backed engine. For contributors, that distinction is useful: if you are changing syntax behavior, you work below these packages; if you are embedding Biome, you work at these packages.

Sources: packages/@biomejs/js-api/src/index.ts, packages/@biomejs/backend-jsonrpc/src/index.ts

Language support is also a capability matrix, not just a file-extension list. The official language-support page marks JavaScript, TypeScript, JSX, TSX, JSON, JSONC, CSS, GraphQL, HTML, and SVG as supported across major areas, while several other languages are experimental or in progress. It also notes JavaScript support for ES2024, TypeScript support for version 5.9, JSONC behavior through JSON parser and formatter options, and experimental embedded snippets for CSS and GraphQL template literals. The package keywords surface a compact subset of that promise to npm users, while deeper configuration and analyzer behavior live in the engine and configuration schema.

Sources: packages/@biomejs/biome/package.json

API Components Reference

@biomejs/backend-jsonrpc exports two workspace factories. createWorkspace(): Promise<Workspace | null> locates a command automatically and may return null when the platform is not supported. createWorkspaceWithBinary(command: string): Promise<Workspace> uses the provided binary path, opens a socket, creates a Transport, sends the JSON-RPC initialize request, and returns the wrapped workspace client. The package description calls this package “Bindings to the JSON-RPC Workspace API of the Biome daemon,” which is the key term to use when documenting editor-like integrations or custom daemon clients.

Sources: packages/@biomejs/backend-jsonrpc/src/index.ts, packages/@biomejs/backend-jsonrpc/package.json

@biomejs/js-api exports shared types and a runtime selector. Configuration is a union of configuration types from the bundler, Node.js, and web WebAssembly packages. Diagnostic is the matching diagnostic union. Distribution has three public enum members: BUNDLER = 0, NODE = 1, and WEB = 2. BiomeCreate contains one field, distribution: Distribution. Biome.create is asynchronous because it imports the selected WebAssembly package dynamically before constructing the Biome instance. Consumers should choose this API when they want in-process WebAssembly behavior instead of a daemon transport.

Sources: packages/@biomejs/js-api/src/index.ts

@biomejs/plugin-api is intentionally not a general embedding API. Its entry file throws an error that says the package is intended to be used in Biome JS plugins and asks whether the caller meant @biomejs/js-api. That guard is a small but important architectural signal: plugin authors and embedders are separate audiences. General integrations should use either the JavaScript API or the JSON-RPC backend depending on whether they need WebAssembly or a daemon-backed workspace.

Sources: packages/@biomejs/plugin-api/index.js, packages/@biomejs/js-api/src/index.ts

Contributor Next Steps

When tracing behavior from a user report, start by identifying the runtime boundary. A failure to install or execute biome belongs near the main package and platform packages. A failure in editor or daemon communication belongs near the JSON-RPC backend, socket, transport, and workspace wrapper. A programmatic embedding issue belongs near @biomejs/js-api and its selected WebAssembly distribution. A language-specific parsing, formatting, or linting change usually lives below these adapters in the engine, but the adapter still tells you how the engine is invoked by users.

Sources: packages/@biomejs/biome/package.json, packages/@biomejs/backend-jsonrpc/src/index.ts, packages/@biomejs/js-api/src/index.ts

For a practical reading path, pair this page with the CLI, formatter, linter, analyzer, and editor pages. Those pages explain the user-facing commands and features in more detail, while this page explains why the repository contains several packages that all appear to “run Biome.” They are not competing toolchains: they are distribution and integration surfaces over a shared architecture shaped by scanning, CST-based parsing, formatting, diagnostics, analyzer rules, and workspace services.