# lpm fmt (/docs/dev/fmt)



```bash
lpm fmt [path...]              # format and write
lpm fmt --check [path...]      # check only, exit 1 if unformatted
```

Runs [Biome](https://biomejs.dev) `format` across the project. The binary is downloaded the first time you run `lpm fmt`, cached under `~/.lpm/cache/`, and reused thereafter.

Faster than `npx biome` (`3 ms` vs `340 ms` on the [reference fixture](https://github.com/lpm-dev/rust-client#benchmarks)) because there's no per-invocation `npx` resolution overhead.

## Examples [#examples]

```bash
lpm fmt                       # format the whole project, write changes
lpm fmt src/                  # format one directory
lpm fmt --check               # check without writing — CI mode
lpm fmt --check src/          # check one directory
lpm fmt --all                 # workspace: format every member
lpm fmt --filter web          # workspace: format one member
lpm fmt --filter './apps/*'   # workspace: path glob
lpm fmt --affected            # workspace: only members affected vs main
```

## Default vs `--check` [#default-vs---check]

| Mode                | What happens                                                                                        |
| ------------------- | --------------------------------------------------------------------------------------------------- |
| `lpm fmt` (default) | Runs `biome format <path> --write` — actually formats files                                         |
| `lpm fmt --check`   | Runs `biome format <path>` (no `--write`) — exits non-zero if any file is unformatted, useful in CI |

Without an explicit path argument, both modes operate on `.` (the project root).

## Pinning a version [#pinning-a-version]

By default, `lpm fmt` uses the version baked into LPM CLI's plugin registry. Override per-project in `lpm.json`:

```json title="lpm.json"
{
  "tools": {
    "biome": "2.4.8"
  }
}
```

Run `lpm plugin update biome` to pull the latest release into the cache.

## Workspaces [#workspaces]

```bash
lpm fmt --all                              # every member
lpm fmt --filter web                       # exact name
lpm fmt --filter '@scope/*'                # glob
lpm fmt --filter './apps/*' --check        # path glob, CI mode
lpm fmt --filter-prod ...shared            # prod graph closure
lpm fmt --affected --base develop          # affected vs a non-main branch
lpm fmt --filter web --fail-if-no-match    # exit non-zero on typo'd filter
```

Members run in topological levels, with packages inside each level executing in parallel up to the available CPU count. The Biome binary is resolved once at the workspace root before fan-out, so the homogeneous-version case never races on cold-cache install.

Filter grammar is documented in [Workspaces](/docs/packages/workspaces#filter-grammar).

`--all` and `--affected` are mutually exclusive; filters compose with `--affected` (the affected set is unioned with the filter result). `--filter-prod` uses the same grammar as `--filter`, but closure operators ignore `devDependencies`.

## Flags [#flags]

| Flag                                    | Effect                                                                                                                 |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `--check`                               | Check only, don't write — exits non-zero on unformatted files                                                          |
| `--all`                                 | Run in every workspace member                                                                                          |
| `--filter <expr>`                       | Select workspace members by the [filter grammar](/docs/packages/workspaces#filter-grammar) (repeatable; entries union) |
| `--filter-prod <expr>`                  | Select workspace members with production-only dependency closures                                                      |
| `--affected`                            | Run only in members affected by changes vs `--base`                                                                    |
| `--base <REF>`                          | Git base ref for `--affected` (default: `main`)                                                                        |
| `--changed-files-ignore-pattern <glob>` | Ignore matching git-diff paths for `--affected` / `[git-ref]` filters                                                  |
| `--test-pattern <glob>`                 | Treat matching git-diff paths as test-only for `--affected` / `[git-ref]` fan-out decisions                            |
| `--fail-if-no-match`                    | Exit non-zero if no member matches the filter set (recommended in CI)                                                  |

Anything after `--` (or trailing path) is forwarded to Biome.

Plus the [global flags](/docs/commands#global-flags).

## `--json` in workspace mode [#--json-in-workspace-mode]

Single-package mode (`lpm fmt`) preserves Biome's stdout — LPM CLI does not wrap it. Workspace mode emits a single LPM CLI envelope on stdout; per-member stdout/stderr is captured and surfaced inside the envelope only on failure. See [`lpm lint`](/docs/dev/lint#json-in-workspace-mode) for the exact envelope shape.

## See also [#see-also]

* [`lpm lint`](/docs/dev/lint) — Oxlint, same lazy-download mechanism
* [`lpm check`](/docs/dev/check) — TypeScript type-check
* [`lpm plugin`](/docs/dev/plugin) — manage tool versions and updates
* [Built-in tools](/docs/dev/builtin-tools) — how the plugin system works
