# lpm lint (/docs/dev/lint)



```bash
lpm lint [-- args...]
```

Runs [Oxlint](https://oxc.rs/docs/guide/usage/linter.html) — a fast Rust-based linter — across the project. The binary is downloaded the first time you run `lpm lint`, cached under `~/.lpm/cache/`, and reused thereafter.

Faster than `npx oxlint` (`3 ms` vs `273 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 lint                       # lint the whole project
lpm lint src/                  # lint a directory
lpm lint -- --fix              # auto-fix where Oxlint can
lpm lint -- --rules typescript # forward Oxlint flags
lpm lint --all                 # workspace: lint every member
lpm lint --filter web          # workspace: lint one member
lpm lint --filter './apps/*'   # workspace: lint a path glob
lpm lint --affected            # workspace: only members affected vs main
lpm lint --affected --base develop
```

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

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

```json title="lpm.json"
{
  "tools": {
    "oxlint": "1.57.0"
  }
}
```

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

## Workspaces [#workspaces]

```bash
lpm lint --all                            # every member
lpm lint --filter web                     # exact name
lpm lint --filter '@scope/*'              # glob
lpm lint --filter './apps/*'              # path glob
lpm lint --filter web --filter api        # union
lpm lint --filter-prod ...shared          # prod graph closure
lpm lint --filter '!web-tests'            # exclusion
lpm lint --affected                       # only members touched since the base ref
lpm lint --affected --base main           # change the base (default: main)
lpm lint --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 Oxlint 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                                                                                                                 |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `--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) is forwarded to Oxlint.

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

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

Single-package mode (`lpm lint`) preserves Oxlint's stdout — LPM CLI does not wrap it. Workspace mode (`--all` / `--filter` / `--affected`) emits a single LPM CLI envelope on stdout, with each member's stdout/stderr captured per-member and surfaced inside the envelope only on failure:

```json
{
  "success": false,
  "packages": 5, "succeeded": 4, "failed": 1,
  "duration_ms": 12340,
  "members": [
    { "name": "web", "success": true,  "exit_code": 0, "duration_ms": 2100 },
    { "name": "api", "success": false, "exit_code": 1, "duration_ms": 800,
      "stdout": "...", "stderr": "..." }
  ]
}
```

Spawn / config / plugin failures surface as `exit_code: null` paired with an `error` string, distinguishing "ran and exited non-zero" from "couldn't even launch."

## See also [#see-also]

* [`lpm fmt`](/docs/dev/fmt) — Biome formatter, 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
