lintlane 0.0.0-stage → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +614 -2
- package/bin/check-commit.mjs +183 -0
- package/bin/ci.mjs +162 -0
- package/bin/cli.mjs +428 -0
- package/bin/commit-cli.mjs +148 -0
- package/bin/commit-config.mjs +24 -0
- package/bin/commit-lint.mjs +143 -0
- package/bin/commit-msg.mjs +18 -0
- package/bin/commit-prompt.mjs +110 -0
- package/bin/pre-push-check.mjs +48 -0
- package/bin/prepare-commit-msg.mjs +46 -0
- package/bin/ui-server.mjs +183 -0
- package/package.json +45 -4
- package/presets/base.json +45 -0
- package/presets/next.json +10 -0
- package/presets/strict.json +23 -0
- package/templates/commit-msg +2 -0
- package/templates/pre-commit +2 -0
- package/templates/pre-push +2 -0
- package/templates/prepare-commit-msg +2 -0
- package/ui/index.html +637 -0
package/README.md
CHANGED
|
@@ -1,3 +1,615 @@
|
|
|
1
|
-
#
|
|
1
|
+
# lintlane
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Pre-push checks for React apps. One command sets up a shared
|
|
4
|
+
[Biome](https://biomejs.dev) lint/format preset, git hooks, a Conventional
|
|
5
|
+
Commits workflow and a CI workflow; a local dashboard lets you run the same
|
|
6
|
+
checks your CI will run — and see exactly what would fail — before you push.
|
|
7
|
+
|
|
8
|
+
**What you get**
|
|
9
|
+
|
|
10
|
+
- A shared Biome preset (`base`, `strict`, `next`) with auto-detection.
|
|
11
|
+
- A pre-commit hook that formats and lints staged files.
|
|
12
|
+
- Conventional Commits, enforced and guided: a step-by-step prompt, a
|
|
13
|
+
commit-message check, a pre-push check and a CI check.
|
|
14
|
+
- A GitHub Actions workflow running `biome ci`.
|
|
15
|
+
- `lintlane ui`: a local dashboard with a Lint tab (errors and fixes as a
|
|
16
|
+
diff) and a CI tab (lint, typecheck, build and tests run locally).
|
|
17
|
+
|
|
18
|
+
## Contents
|
|
19
|
+
|
|
20
|
+
- [Quick start](#quick-start)
|
|
21
|
+
- [Commands at a glance](#commands-at-a-glance)
|
|
22
|
+
- [Requirements](#requirements)
|
|
23
|
+
- [`init`](#init--one-time-project-setup)
|
|
24
|
+
- [`check`, `check:fix`, `ci`](#check-checkfix-ci--run-biome)
|
|
25
|
+
- [Commit workflow](#commit-workflow)
|
|
26
|
+
- [`commit`](#commit--guided-conventional-commit)
|
|
27
|
+
- [`check-commit`](#check-commit--validate-commit-messages)
|
|
28
|
+
- [Hooks: how a bad commit gets caught](#hooks-how-a-bad-commit-gets-caught)
|
|
29
|
+
- [Settings](#settings)
|
|
30
|
+
- [Skipping a check](#skipping-a-check)
|
|
31
|
+
- [Dashboard (`ui`)](#dashboard-ui)
|
|
32
|
+
- [Presets](#presets)
|
|
33
|
+
- [Manual setup (without the CLI)](#manual-setup-without-the-cli)
|
|
34
|
+
- [Troubleshooting](#troubleshooting)
|
|
35
|
+
- [Reference](#reference)
|
|
36
|
+
- [Developing lintlane](#developing-lintlane)
|
|
37
|
+
|
|
38
|
+
## Quick start
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
# 1. In your React project (a git repository with a package.json):
|
|
42
|
+
bunx lintlane init
|
|
43
|
+
|
|
44
|
+
# 2. Fix what Biome can fix, see what's left:
|
|
45
|
+
bunx lintlane check:fix
|
|
46
|
+
bunx lintlane check
|
|
47
|
+
|
|
48
|
+
# 3. Open the dashboard to review issues and run your CI checks locally:
|
|
49
|
+
bunx lintlane ui
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
From then on, `git commit` is guided and checked, and every push is checked
|
|
53
|
+
before it leaves your machine.
|
|
54
|
+
|
|
55
|
+
> The first `bunx lintlane init` downloads the package. After that it's
|
|
56
|
+
> installed in your project, so `bunx lintlane …` (or `npx lintlane …`,
|
|
57
|
+
> `bun run lintlane …`) runs your local copy without touching the network.
|
|
58
|
+
|
|
59
|
+
## Commands at a glance
|
|
60
|
+
|
|
61
|
+
| Command | What it does |
|
|
62
|
+
| ----------------------------------------------- | --------------------------------------------------------------- |
|
|
63
|
+
| `lintlane init [flags]` | One-time setup: installs, writes config, scripts, hooks and CI. |
|
|
64
|
+
| `lintlane check [paths]` | Run `biome check` (lint + format), no changes. |
|
|
65
|
+
| `lintlane check:fix [paths]` | Run `biome check --write`: apply safe fixes. |
|
|
66
|
+
| `lintlane ci [paths]` | Run `biome ci --reporter=github` (what CI runs). |
|
|
67
|
+
| `lintlane commit [flags] [-- <git args>]` | Guided Conventional Commit (alias `c`). |
|
|
68
|
+
| `lintlane check-commit [flags]` | Validate commit messages (a message, a file or a git range). |
|
|
69
|
+
| `lintlane ui [flags]` | Open the local dashboard (Lint + CI tabs). |
|
|
70
|
+
| `lintlane -h` / `commit -h` / `check-commit -h` | Show help. |
|
|
71
|
+
|
|
72
|
+
Every command except `init` runs from the project root. Examples below use
|
|
73
|
+
`bunx lintlane …`; if you've installed it, `bun run lintlane …`,
|
|
74
|
+
`npx lintlane …` or `node_modules/.bin/lintlane …` work too.
|
|
75
|
+
|
|
76
|
+
## Requirements
|
|
77
|
+
|
|
78
|
+
- **Bun 1.2 or newer** to run the CLI (`init`, `check`, `check:fix`, `ci`,
|
|
79
|
+
`commit`, `check-commit`, `ui`). The CLI is a Bun script.
|
|
80
|
+
- **Your project does not need to use Bun.** `init` detects npm, pnpm, Yarn or
|
|
81
|
+
Bun and uses that package manager.
|
|
82
|
+
- **Git hooks only need Node** (18 or newer): they're plain Node scripts with no
|
|
83
|
+
extra dependencies, so teammates don't need Bun to commit or push.
|
|
84
|
+
- **Biome 2.2 up to (not including) 3.** It's a peer dependency; `init` installs it.
|
|
85
|
+
- **Git**, for the commit workflow.
|
|
86
|
+
- **macOS or Linux** for the guided prompt on a plain `git commit` (it reads the
|
|
87
|
+
terminal through `/dev/tty`). Elsewhere that prompt is skipped; messages are
|
|
88
|
+
still validated, and `lintlane commit` still works. Not tested on Windows.
|
|
89
|
+
|
|
90
|
+
## `init` — one-time project setup
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
bunx lintlane init
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`init` installs `@biomejs/biome`, `lintlane` and (unless `--no-hooks`)
|
|
97
|
+
`husky`, then writes:
|
|
98
|
+
|
|
99
|
+
| File / change | Purpose |
|
|
100
|
+
| ----------------------------- | ----------------------------------------------------------------- |
|
|
101
|
+
| `biome.json` | Extends the preset. If one exists, it only tells you what to add. |
|
|
102
|
+
| `package.json` scripts | `check`, `check:fix`, and `prepare` (runs husky). |
|
|
103
|
+
| `.husky/pre-commit` | Biome on staged files, auto-fixing what it can. |
|
|
104
|
+
| `.husky/commit-msg` | Rejects messages that aren't Conventional Commits. |
|
|
105
|
+
| `.husky/prepare-commit-msg` | Guided prompt when you run a plain `git commit`. |
|
|
106
|
+
| `.husky/pre-push` | Checks every commit about to be pushed. |
|
|
107
|
+
| `.github/workflows/biome.yml` | `biome ci`, plus a commit-message check on pull requests. |
|
|
108
|
+
|
|
109
|
+
### Flags
|
|
110
|
+
|
|
111
|
+
| Flag | Effect |
|
|
112
|
+
| ------------------ | ----------------------------------------------------------------------- |
|
|
113
|
+
| `--preset <name>` | `base`, `strict` or `next`; overrides auto-detection. |
|
|
114
|
+
| `--no-hooks` | Skip husky and every git hook (also leaves the commit check out of CI). |
|
|
115
|
+
| `--no-commit-lint` | Keep the pre-commit hook; skip the commit-message hooks and CI check. |
|
|
116
|
+
| `--no-ci` | Skip the GitHub Actions workflow. |
|
|
117
|
+
| `--skip-install` | Print the install command instead of running it. |
|
|
118
|
+
| `-h`, `--help` | Show usage. |
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
bunx lintlane init # everything, preset auto-detected
|
|
122
|
+
bunx lintlane init --preset strict # force a preset
|
|
123
|
+
bunx lintlane init --no-commit-lint # lint hook only, no commit rules
|
|
124
|
+
bunx lintlane init --no-hooks --no-ci # just biome.json and scripts
|
|
125
|
+
bunx lintlane init --skip-install # you install packages yourself
|
|
126
|
+
bunx lintlane init --preset next --no-ci
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Preset auto-detection
|
|
130
|
+
|
|
131
|
+
Without `--preset`, `init` reads your `package.json` dependencies:
|
|
132
|
+
|
|
133
|
+
| Found in dependencies | Preset used |
|
|
134
|
+
| ------------------------------------------------- | ----------- |
|
|
135
|
+
| `next` | `next` |
|
|
136
|
+
| `@tanstack/react-start`, `@tanstack/start` | `base` |
|
|
137
|
+
| `@react-router/dev` (React Router framework mode) | `base` |
|
|
138
|
+
| `@remix-run/react`, `@remix-run/node` | `base` |
|
|
139
|
+
| `react` (no framework above) | `base` |
|
|
140
|
+
| none of the above | `base` |
|
|
141
|
+
|
|
142
|
+
Only Next.js has its own Biome lint domain, so it's the only framework that
|
|
143
|
+
changes which preset is used. `init` says what it detected either way.
|
|
144
|
+
`strict` is never auto-selected; pass `--preset strict` when you want it.
|
|
145
|
+
|
|
146
|
+
### Package manager detection
|
|
147
|
+
|
|
148
|
+
`init` reads the `packageManager` field in `package.json`, otherwise whichever
|
|
149
|
+
lockfile is present (`bun.lock`, `package-lock.json`, `pnpm-lock.yaml`,
|
|
150
|
+
`yarn.lock`), and falls back to Bun. It uses that package manager's install
|
|
151
|
+
command and writes matching CI setup steps.
|
|
152
|
+
|
|
153
|
+
### Safe to re-run
|
|
154
|
+
|
|
155
|
+
`init` never overwrites an existing `biome.json`/`biome.jsonc`, script, hook or
|
|
156
|
+
workflow file; it prints a `!` warning for whatever already exists and writes
|
|
157
|
+
only what's missing. That makes it the way to **upgrade**: update the package,
|
|
158
|
+
then run `init` again to pick up hooks added in newer versions.
|
|
159
|
+
|
|
160
|
+
## `check`, `check:fix`, `ci` — run Biome
|
|
161
|
+
|
|
162
|
+
These wrap the Biome binary installed in your project, so you never need
|
|
163
|
+
Biome's own flags:
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
bunx lintlane check # biome check . (read-only)
|
|
167
|
+
bunx lintlane check:fix # biome check --write . (applies safe fixes)
|
|
168
|
+
bunx lintlane ci # biome ci --reporter=github . (CI-formatted output)
|
|
169
|
+
|
|
170
|
+
bunx lintlane check src/ # limit to paths
|
|
171
|
+
bunx lintlane check:fix src/components/Button.tsx
|
|
172
|
+
bunx lintlane ci src/ tests/
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The exit code is Biome's, so they work in scripts and CI. If Biome isn't
|
|
176
|
+
installed yet they say so and point you to `init`.
|
|
177
|
+
|
|
178
|
+
`init` also adds plain `check` and `check:fix` scripts to `package.json` that
|
|
179
|
+
call `biome` directly, so `npm run check` (or `pnpm`/`yarn`/`bun run check`)
|
|
180
|
+
works without Bun:
|
|
181
|
+
|
|
182
|
+
```sh
|
|
183
|
+
npm run check
|
|
184
|
+
npm run check:fix
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Commit workflow
|
|
188
|
+
|
|
189
|
+
`init` sets up [Conventional Commits](https://www.conventionalcommits.org)
|
|
190
|
+
(`type(scope): subject`), which keeps history readable and works with changelog
|
|
191
|
+
and release tooling. The `commit` and `check-commit` commands and flags follow
|
|
192
|
+
[Commitizen](https://commitizen-tools.github.io/commitizen/) where they overlap
|
|
193
|
+
(`check-commit` is Commitizen's `cz check`; it isn't called `check` because
|
|
194
|
+
`lintlane check` runs Biome).
|
|
195
|
+
|
|
196
|
+
**The format**
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
type(scope): subject
|
|
200
|
+
|
|
201
|
+
optional body
|
|
202
|
+
|
|
203
|
+
optional footer, e.g. Closes #123
|
|
204
|
+
BREAKING CHANGE: what breaks and how to migrate
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
- **Types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`,
|
|
208
|
+
`build`, `ci`, `chore`, `revert`.
|
|
209
|
+
- The scope is optional. The subject is required, shouldn't end in a period,
|
|
210
|
+
and the header must stay under 100 characters.
|
|
211
|
+
- A breaking change is marked with `!` (`feat(api)!: …`) plus a
|
|
212
|
+
`BREAKING CHANGE:` footer.
|
|
213
|
+
- Messages starting with `Merge`, `Revert`, `Pull request`, `fixup!`,
|
|
214
|
+
`squash!` or `amend!` are left alone.
|
|
215
|
+
|
|
216
|
+
### `commit` — guided Conventional Commit
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
git add <files>
|
|
220
|
+
bunx lintlane commit # alias: bunx lintlane c
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Asks seven questions — **type, scope, subject, body, breaking change, footer,
|
|
224
|
+
confirm** — then runs `git commit` with the result, so your pre-commit and
|
|
225
|
+
commit-msg hooks still run. It refuses if nothing is staged. Ctrl+C at any
|
|
226
|
+
step cancels with no commit made. Invalid answers (an empty subject, a trailing
|
|
227
|
+
period, an over-long header) are explained and asked again.
|
|
228
|
+
|
|
229
|
+
| Flag | Effect |
|
|
230
|
+
| -------------------------------- | -------------------------------------------------------------------- |
|
|
231
|
+
| `--dry-run` | Show the message without committing. |
|
|
232
|
+
| `--write-message-to-file <file>` | Write the message to a file (combine with `--dry-run`). |
|
|
233
|
+
| `--retry` | Reuse your last message after a failed commit, without asking again. |
|
|
234
|
+
| `--no-retry` | Always ask, even if `retryAfterFailure` is set. |
|
|
235
|
+
| `-l`, `--message-length-limit` | Maximum header length (`0` = no limit). |
|
|
236
|
+
| `-h`, `--help` | Show help for this command. |
|
|
237
|
+
| `-- <git args>` | Everything after `--` is passed to `git commit`. |
|
|
238
|
+
|
|
239
|
+
```sh
|
|
240
|
+
bunx lintlane commit # ask, then commit the staged changes
|
|
241
|
+
bunx lintlane commit -- -a # stage all tracked changes, then commit
|
|
242
|
+
bunx lintlane commit -- -a -S # …and sign the commit
|
|
243
|
+
bunx lintlane commit -- -s # add a Signed-off-by line
|
|
244
|
+
bunx lintlane commit -- -n # skip git hooks
|
|
245
|
+
bunx lintlane commit --dry-run # just print the message
|
|
246
|
+
bunx lintlane commit --dry-run --write-message-to-file msg.txt
|
|
247
|
+
bunx lintlane commit -l 72 # stricter header limit for this commit
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Retrying after a failed commit.** If a hook (for example Biome in pre-commit)
|
|
251
|
+
rejects the commit after you've answered the questions, the message is kept.
|
|
252
|
+
Fix the problem, stage the fix, then run `bunx lintlane commit --retry` — no
|
|
253
|
+
re-typing. The saved message is cleared once a commit succeeds. Set
|
|
254
|
+
`retryAfterFailure` (see [Settings](#settings)) to reuse it automatically.
|
|
255
|
+
|
|
256
|
+
### `check-commit` — validate commit messages
|
|
257
|
+
|
|
258
|
+
Give it exactly one thing to check:
|
|
259
|
+
|
|
260
|
+
```sh
|
|
261
|
+
bunx lintlane check-commit --message "feat: add login" # a message
|
|
262
|
+
echo "feat: add login" | bunx lintlane check-commit # …or from stdin
|
|
263
|
+
bunx lintlane check-commit --commit-msg-file .git/COMMIT_EDITMSG
|
|
264
|
+
bunx lintlane check-commit --rev-range origin/main..HEAD # every commit in a range
|
|
265
|
+
bunx lintlane check-commit -d # shorthand for <default branch>..HEAD
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
| Flag | Effect |
|
|
269
|
+
| ------------------------------ | ----------------------------------------------------- |
|
|
270
|
+
| `--message <msg>` | Check this message (or pipe one in on stdin). |
|
|
271
|
+
| `--commit-msg-file <path>` | Check the message in a file. |
|
|
272
|
+
| `--rev-range <range>` | Check every commit in a git range, e.g. `main..HEAD`. |
|
|
273
|
+
| `-d`, `--use-default-range` | Same as `--rev-range <default branch>..HEAD`. |
|
|
274
|
+
| `--allow-abort` | Accept an empty message. |
|
|
275
|
+
| `--allowed-prefixes <prefix>` | Skip messages starting with this (repeatable). |
|
|
276
|
+
| `-l`, `--message-length-limit` | Maximum header length (`0` = no limit). |
|
|
277
|
+
|
|
278
|
+
Exit codes: `0` everything passed, `1` a message was rejected, `2` a usage or
|
|
279
|
+
git error. For a range, the output lists each bad commit with its hash and why.
|
|
280
|
+
|
|
281
|
+
### Hooks: how a bad commit gets caught
|
|
282
|
+
|
|
283
|
+
Four layers, so a mistake is stopped somewhere:
|
|
284
|
+
|
|
285
|
+
| Layer | Catches |
|
|
286
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
287
|
+
| `prepare-commit-msg` | A plain `git commit` (no `-m`): walks you through the steps instead of opening an empty editor. |
|
|
288
|
+
| `commit-msg` | `git commit -m "test"`: rejects a message in the wrong format, and says why. |
|
|
289
|
+
| `pre-push` | Commits that skipped the hooks (`--no-verify`, GUI clients, a fresh clone): checks every commit about to be pushed. |
|
|
290
|
+
| CI (pull requests) | Anything that still got through: checks the commits in the PR. |
|
|
291
|
+
|
|
292
|
+
```text
|
|
293
|
+
$ git commit -m "test"
|
|
294
|
+
|
|
295
|
+
✘ Commit message rejected
|
|
296
|
+
|
|
297
|
+
• The header must look like "type(scope): subject", e.g. "feat(auth): add login form".
|
|
298
|
+
|
|
299
|
+
Format: type(scope): subject
|
|
300
|
+
Example: feat(auth): add login form
|
|
301
|
+
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Notes:
|
|
305
|
+
|
|
306
|
+
- On a plain `git commit` the prompt's answer pre-fills your editor, and the
|
|
307
|
+
message is validated again afterwards. `git commit --amend`, `-m` and `-F`
|
|
308
|
+
skip the prompt but not the validation.
|
|
309
|
+
- The prompt steps aside in CI, when `LINTLANE_NO_PROMPT` is set, and
|
|
310
|
+
whenever there's no terminal (editors and GUI clients that commit for you).
|
|
311
|
+
- Hooks run only once git hooks are installed. `init` does this, and teammates
|
|
312
|
+
get them from `install` through the `prepare` script (`husky`).
|
|
313
|
+
- The pre-push hook checks the commits being pushed (for a new branch: those
|
|
314
|
+
not already on the remote). Tag pushes and branch deletions are ignored.
|
|
315
|
+
|
|
316
|
+
### Settings
|
|
317
|
+
|
|
318
|
+
Optional, in your `package.json`:
|
|
319
|
+
|
|
320
|
+
```json
|
|
321
|
+
{
|
|
322
|
+
"lintlane": {
|
|
323
|
+
"commit": {
|
|
324
|
+
"types": ["feat", "fix", "chore"],
|
|
325
|
+
"messageLengthLimit": 72,
|
|
326
|
+
"allowedPrefixes": ["WIP"],
|
|
327
|
+
"retryAfterFailure": true
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
| Key | Meaning |
|
|
334
|
+
| -------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
335
|
+
| `types` | Allowed types. A list of names, or `{ "feat": "A new feature" }` to give each a description in the prompt. |
|
|
336
|
+
| `messageLengthLimit` | Maximum header length. `0` turns the check off. Default `100`. |
|
|
337
|
+
| `allowedPrefixes` | Extra message prefixes to skip (added to the built-in ones). |
|
|
338
|
+
| `retryAfterFailure` | Reuse your last message automatically after a failed commit. Default `false`. |
|
|
339
|
+
|
|
340
|
+
The settings apply to the hooks, `commit` and `check-commit`. Command-line flags
|
|
341
|
+
override them for that run.
|
|
342
|
+
|
|
343
|
+
### Skipping a check
|
|
344
|
+
|
|
345
|
+
| To skip… | Do this |
|
|
346
|
+
| ------------------------- | ----------------------------------------------------------------------- |
|
|
347
|
+
| The commit hooks, once | `git commit --no-verify` (the pre-push hook and CI still check it). |
|
|
348
|
+
| The pre-push check, once | `git push --no-verify` (CI still checks pull requests). |
|
|
349
|
+
| Only the guided prompt | Set `LINTLANE_NO_PROMPT=1`. |
|
|
350
|
+
| Commit rules for everyone | Re-run `init --no-commit-lint` on a fresh project, or delete the hooks. |
|
|
351
|
+
|
|
352
|
+
### Adding the CI step to an existing workflow
|
|
353
|
+
|
|
354
|
+
`init` adds the commit-message check only to newly generated workflows. To add
|
|
355
|
+
it to one you already have:
|
|
356
|
+
|
|
357
|
+
```yaml
|
|
358
|
+
- uses: actions/checkout@v4
|
|
359
|
+
with:
|
|
360
|
+
fetch-depth: 0
|
|
361
|
+
# …after your install step:
|
|
362
|
+
- name: Check commit messages
|
|
363
|
+
if: github.event_name == 'pull_request'
|
|
364
|
+
run: node node_modules/lintlane/bin/check-commit.mjs --rev-range origin/${{ github.base_ref }}..HEAD
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Dashboard (`ui`)
|
|
368
|
+
|
|
369
|
+
`lintlane ui` starts a local dashboard in your browser so you can see what
|
|
370
|
+
would fail before you push:
|
|
371
|
+
|
|
372
|
+
```sh
|
|
373
|
+
bunx lintlane ui # opens http://127.0.0.1:4321
|
|
374
|
+
bunx lintlane ui --port 5000 # use another port
|
|
375
|
+
bunx lintlane ui --no-open # print the URL without opening a browser
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
| Flag | Effect |
|
|
379
|
+
| ------------ | ------------------------------------- |
|
|
380
|
+
| `--port <n>` | Port to listen on (default `4321`). |
|
|
381
|
+
| `--no-open` | Don't open the browser automatically. |
|
|
382
|
+
|
|
383
|
+
It needs Biome installed in the project (run `init` first). Press Ctrl+C in the
|
|
384
|
+
terminal to stop it. The ☀/☾ button in the header switches between light and
|
|
385
|
+
dark mode; it follows your system setting until you click it, then remembers
|
|
386
|
+
your choice.
|
|
387
|
+
|
|
388
|
+
### Lint tab
|
|
389
|
+
|
|
390
|
+
Runs `biome check` and shows the result:
|
|
391
|
+
|
|
392
|
+
- **Summary cards:** errors, warnings, files with issues, check time.
|
|
393
|
+
- **File table:** each file's worst level, issue count, and whether Biome can fix
|
|
394
|
+
it. Rows with errors are tinted. Search by file name, message or rule, and
|
|
395
|
+
filter by All / Errors / Warnings.
|
|
396
|
+
- **Detail panel:** click a file to see each issue (rule, line and column) and
|
|
397
|
+
the proposed fix as a red/green diff, like `git diff`. Use ↑/↓ (or `j`/`k`) to
|
|
398
|
+
move between files and `Esc` to close.
|
|
399
|
+
- **Apply fix** writes the fix for one file; **Apply all fixes** applies them to
|
|
400
|
+
every listed file in one batch. Nothing is written until you click, and the
|
|
401
|
+
page re-checks afterwards.
|
|
402
|
+
|
|
403
|
+
Only Biome's _safe_ fixes are applied (the same ones as `check:fix`). Issues
|
|
404
|
+
with no automatic fix are labelled "Manual". The page lists the first 200 files
|
|
405
|
+
with issues; if there are more, a notice says so and "Apply all fixes" only
|
|
406
|
+
touches the files shown — click it again after the re-check to continue.
|
|
407
|
+
|
|
408
|
+
### CI tab
|
|
409
|
+
|
|
410
|
+
Runs the checks your CI would run, locally. The steps are detected from your
|
|
411
|
+
project:
|
|
412
|
+
|
|
413
|
+
| Step | Runs | On by default |
|
|
414
|
+
| ------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------- |
|
|
415
|
+
| Install (frozen lockfile) | `bun install --frozen-lockfile`, `npm ci`, or the `pnpm`/`yarn` equivalent | No |
|
|
416
|
+
| Biome CI (lint + format) | `biome ci .` — the same check the generated GitHub workflow runs | Yes |
|
|
417
|
+
| Typecheck | your `typecheck` script (or `type-check`, `check-types`, `tsc`), else `tsc --noEmit` if there's a `tsconfig.json` | Yes |
|
|
418
|
+
| Build | your `build` script | Yes |
|
|
419
|
+
| Tests | your `test` script (skipped if it's npm's "no test specified" placeholder) | Yes |
|
|
420
|
+
|
|
421
|
+
Tick the steps you want, then **Run CI**. Steps run in order with `CI=true`,
|
|
422
|
+
and their output streams into the panel as they run. **Stop on first failure**
|
|
423
|
+
(on by default, like real CI) skips the remaining steps after one fails. At the
|
|
424
|
+
end a banner says either "All N steps passed — safe to push" or "CI would
|
|
425
|
+
fail", naming the first failing step. **Stop** cancels the run and kills the
|
|
426
|
+
running process.
|
|
427
|
+
|
|
428
|
+
This is a script-based simulation, not a replica of your workflow: it runs the
|
|
429
|
+
commands above, not the steps in `.github/workflows/*.yml`, and it doesn't
|
|
430
|
+
reproduce CI's environment variables, secrets or Node version. A pass here is a
|
|
431
|
+
strong signal, not a guarantee.
|
|
432
|
+
|
|
433
|
+
### Safety
|
|
434
|
+
|
|
435
|
+
The server listens on `127.0.0.1` only. Every request needs a random token that
|
|
436
|
+
is part of the URL printed at startup — opening the dashboard without it gives a
|
|
437
|
+
403. The page only sends step ids and file paths; the server decides which
|
|
438
|
+
commands run and refuses paths outside the project.
|
|
439
|
+
|
|
440
|
+
## Presets
|
|
441
|
+
|
|
442
|
+
| Name | Extends path | Use case |
|
|
443
|
+
| ----------------------- | ----------------------- | ------------------------------------------------------------------------------------------------ |
|
|
444
|
+
| `lintlane/biome` | `./presets/base.json` | Default: recommended rules + React domain, warns on unused code/console. |
|
|
445
|
+
| `lintlane/biome/strict` | `./presets/strict.json` | Base rules raised to errors (unused code, `any`, non-null assertions, console, exhaustive deps). |
|
|
446
|
+
| `lintlane/biome/next` | `./presets/next.json` | Base preset plus the Next.js lint domain. |
|
|
447
|
+
|
|
448
|
+
Presets intentionally don't set `files.includes` — setting it in your own
|
|
449
|
+
`biome.json` would _replace_ lintlane's, not merge with it. For Next.js apps,
|
|
450
|
+
add your own ignores:
|
|
451
|
+
|
|
452
|
+
```json
|
|
453
|
+
{
|
|
454
|
+
"extends": ["lintlane/biome/next"],
|
|
455
|
+
"files": { "includes": ["**", "!**/.next", "!**/out", "!**/next-env.d.ts"] }
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
To migrate an existing config into Biome first:
|
|
460
|
+
|
|
461
|
+
```sh
|
|
462
|
+
bunx biome migrate eslint --write
|
|
463
|
+
bunx biome migrate prettier --write
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## Manual setup (without the CLI)
|
|
467
|
+
|
|
468
|
+
**Install and configure**
|
|
469
|
+
|
|
470
|
+
```sh
|
|
471
|
+
bun add -d -E @biomejs/biome lintlane
|
|
472
|
+
npm install --save-dev --save-exact @biomejs/biome lintlane
|
|
473
|
+
pnpm add --save-dev --save-exact @biomejs/biome lintlane
|
|
474
|
+
yarn add --dev --exact @biomejs/biome lintlane
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
Create `biome.json`, extending the preset you want:
|
|
478
|
+
|
|
479
|
+
```json
|
|
480
|
+
{ "extends": ["lintlane/biome"] }
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
(`lintlane/biome/strict` or `lintlane/biome/next` for the others.)
|
|
484
|
+
Add scripts:
|
|
485
|
+
|
|
486
|
+
```json
|
|
487
|
+
"check": "biome check .",
|
|
488
|
+
"check:fix": "biome check --write ."
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
**Git hooks**
|
|
492
|
+
|
|
493
|
+
```sh
|
|
494
|
+
bun add -d husky
|
|
495
|
+
bunx husky init
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
Put these in `.husky/`:
|
|
499
|
+
|
|
500
|
+
`.husky/pre-commit`
|
|
501
|
+
|
|
502
|
+
```sh
|
|
503
|
+
./node_modules/.bin/biome check --write --staged --no-errors-on-unmatched --files-ignore-unknown=true
|
|
504
|
+
git update-index --again
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
`.husky/commit-msg`
|
|
508
|
+
|
|
509
|
+
```sh
|
|
510
|
+
[ -f node_modules/lintlane/bin/commit-msg.mjs ] || exit 0
|
|
511
|
+
node node_modules/lintlane/bin/commit-msg.mjs "$1"
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
`.husky/prepare-commit-msg`
|
|
515
|
+
|
|
516
|
+
```sh
|
|
517
|
+
[ -f node_modules/lintlane/bin/prepare-commit-msg.mjs ] || exit 0
|
|
518
|
+
node node_modules/lintlane/bin/prepare-commit-msg.mjs "$1" "$2"
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
`.husky/pre-push`
|
|
522
|
+
|
|
523
|
+
```sh
|
|
524
|
+
[ -f node_modules/lintlane/bin/pre-push-check.mjs ] || exit 0
|
|
525
|
+
node node_modules/lintlane/bin/pre-push-check.mjs "$1" "$2"
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
Commits with errors Biome can't fix are blocked until you resolve them.
|
|
529
|
+
|
|
530
|
+
## Troubleshooting
|
|
531
|
+
|
|
532
|
+
**`bunx lintlane …` downloads the package each time, or says "command not found".**
|
|
533
|
+
Outside a project that has it installed, `bunx` fetches `lintlane` from npm.
|
|
534
|
+
Run `bunx lintlane init` in the project first (or install `lintlane` as a dev
|
|
535
|
+
dependency), after which `bunx lintlane …` uses the local copy.
|
|
536
|
+
|
|
537
|
+
**Hooks don't run.** Run your package manager's install (the `prepare` script
|
|
538
|
+
runs husky), or run `node_modules/.bin/husky` once. Check
|
|
539
|
+
`git config core.hooksPath` prints `.husky/_`.
|
|
540
|
+
|
|
541
|
+
**The guided prompt doesn't appear on `git commit`.** It's skipped when `CI` or
|
|
542
|
+
`LINTLANE_NO_PROMPT` is set, when you pass `-m`/`-F` or amend, when there's no
|
|
543
|
+
terminal (GUI clients, some editors) and on systems without `/dev/tty`. Run
|
|
544
|
+
`bunx lintlane commit` for the same steps. The message is validated regardless.
|
|
545
|
+
|
|
546
|
+
**A commit was rejected and I lost my message.** Use
|
|
547
|
+
`bunx lintlane commit --retry` if you committed through `lintlane commit`.
|
|
548
|
+
|
|
549
|
+
**The pre-commit hook blocks my commit.** Biome found an error it can't fix.
|
|
550
|
+
Run `bunx lintlane check` to see it, or open `bunx lintlane ui`. Fix it and
|
|
551
|
+
commit again.
|
|
552
|
+
|
|
553
|
+
**Push blocked: "commit message(s) don't follow Conventional Commits".** Reword
|
|
554
|
+
the listed commits with `git rebase -i` (or `git commit --amend` for the latest),
|
|
555
|
+
then push again.
|
|
556
|
+
|
|
557
|
+
**`init` says a file already exists.** That's expected; `init` never overwrites.
|
|
558
|
+
Delete the file and re-run `init` if you want lintlane's version.
|
|
559
|
+
|
|
560
|
+
**The dashboard shows "Unauthorized" / 403.** Open the exact URL printed when
|
|
561
|
+
`lintlane ui` started; it contains a one-time token.
|
|
562
|
+
|
|
563
|
+
**Biome seems slow on a big project.** Add ignores for build output in your
|
|
564
|
+
`biome.json` (for example `dist`, `.next`, `build`, `coverage`) so Biome doesn't
|
|
565
|
+
scan them.
|
|
566
|
+
|
|
567
|
+
## Reference
|
|
568
|
+
|
|
569
|
+
**Environment variables**
|
|
570
|
+
|
|
571
|
+
| Variable | Effect |
|
|
572
|
+
| -------------------- | --------------------------------------------------------------------------------- |
|
|
573
|
+
| `LINTLANE_NO_PROMPT` | Set to any value to skip the guided prompt on `git commit`. |
|
|
574
|
+
| `CI` | When set, the guided prompt is skipped. The CI tab sets it for the steps it runs. |
|
|
575
|
+
| `NO_COLOR` | Turns off colors in the prompt. |
|
|
576
|
+
|
|
577
|
+
**Exit codes**
|
|
578
|
+
|
|
579
|
+
| Command | Codes |
|
|
580
|
+
| -------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
581
|
+
| `check`, `check:fix`, `ci` | Biome's exit code. |
|
|
582
|
+
| `commit` | `0` committed (or dry run), `1` cancelled, git's own exit code if the commit failed, `2` bad flags. |
|
|
583
|
+
| `check-commit` | `0` valid, `1` rejected, `2` usage or git error. |
|
|
584
|
+
| `ui` | Runs until you stop it. |
|
|
585
|
+
|
|
586
|
+
**Files lintlane may create or use**
|
|
587
|
+
|
|
588
|
+
| Path | What |
|
|
589
|
+
| ------------------------------------------------------------------- | ---------------------------------------------- |
|
|
590
|
+
| `biome.json` | Biome config extending a preset. |
|
|
591
|
+
| `.husky/pre-commit`, `commit-msg`, `prepare-commit-msg`, `pre-push` | Git hooks. |
|
|
592
|
+
| `.github/workflows/biome.yml` | CI workflow. |
|
|
593
|
+
| `.git/lintlane-commit-msg` | Your last message, kept after a failed commit. |
|
|
594
|
+
|
|
595
|
+
## Developing lintlane
|
|
596
|
+
|
|
597
|
+
To try a local build in a test app before publishing:
|
|
598
|
+
|
|
599
|
+
```sh
|
|
600
|
+
# In the lintlane repo:
|
|
601
|
+
npm pack --pack-destination /tmp/lintlane-pack # builds lintlane-<version>.tgz
|
|
602
|
+
|
|
603
|
+
# In a throwaway app (a git repo with a package.json):
|
|
604
|
+
bun add --dev --exact @biomejs/biome husky /tmp/lintlane-pack/lintlane-<version>.tgz
|
|
605
|
+
node_modules/.bin/lintlane init --skip-install # the package isn't on npm yet
|
|
606
|
+
node_modules/.bin/husky
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
If you rebuild without changing the version, Bun may reuse its cached tarball:
|
|
610
|
+
run `bun pm cache rm`, delete `node_modules/lintlane`, and reinstall (or
|
|
611
|
+
bump the version first). `npm pack --dry-run` lists what would be published.
|
|
612
|
+
|
|
613
|
+
## License
|
|
614
|
+
|
|
615
|
+
MIT
|