lintlane 3.0.1 → 4.0.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 +204 -632
- package/bin/check-commit.mjs +54 -137
- package/bin/{ci.mjs → checks.mjs} +104 -35
- package/bin/cli.mjs +226 -69
- package/bin/commit-cli.mjs +36 -122
- package/bin/doctor.mjs +328 -0
- package/bin/hook.mjs +156 -0
- package/bin/proc.mjs +20 -1
- package/bin/project.mjs +100 -4
- package/bin/ui-server.mjs +77 -10
- package/package.json +18 -5
- package/presets/commitizen.cjs +4 -0
- package/presets/commitlint.mjs +47 -0
- package/templates/commit-msg +2 -2
- package/templates/pre-commit +2 -5
- package/templates/pre-push +2 -2
- package/templates/prepare-commit-msg +2 -2
- package/ui/index.html +210 -44
- package/bin/commit-config.mjs +0 -24
- package/bin/commit-lint.mjs +0 -143
- package/bin/commit-msg.mjs +0 -18
- package/bin/commit-prompt.mjs +0 -110
- package/bin/pre-commit.mjs +0 -55
- package/bin/pre-push-check.mjs +0 -48
- package/bin/prepare-commit-msg.mjs +0 -46
- package/bin/staged.mjs +0 -333
package/README.md
CHANGED
|
@@ -1,387 +1,154 @@
|
|
|
1
1
|
# lintlane
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- `lintlane ui`: a local dashboard with a Lint tab (errors and fixes as a
|
|
17
|
-
diff) and a CI tab (lint, typecheck, build and tests run locally).
|
|
3
|
+
A code-quality workflow for JavaScript, React and Next.js projects. lintlane
|
|
4
|
+
**orchestrates proven tools instead of reimplementing them**: one command wires
|
|
5
|
+
them together, one config drives the checks everywhere, and a local dashboard
|
|
6
|
+
shows what your CI will say before you push.
|
|
7
|
+
|
|
8
|
+
| Job | Tool |
|
|
9
|
+
| ------------------------------------ | --------------------------------------------------------- |
|
|
10
|
+
| Formatting and linting | [Biome](https://biomejs.dev) |
|
|
11
|
+
| Staged files (partial staging safe) | [lint-staged](https://github.com/lint-staged/lint-staged) |
|
|
12
|
+
| Git hooks | [Husky](https://typicode.github.io/husky) |
|
|
13
|
+
| Guided Conventional Commits | [Commitizen](https://commitizen.github.io/cz-cli/) |
|
|
14
|
+
| Commit message validation | [commitlint](https://commitlint.js.org) |
|
|
15
|
+
| Setup, checks, CI, doctor, dashboard | **lintlane** |
|
|
18
16
|
|
|
19
17
|
## Contents
|
|
20
18
|
|
|
21
19
|
- [Quick start](#quick-start)
|
|
22
|
-
- [Commands at a glance](#commands-at-a-glance)
|
|
23
20
|
- [Requirements](#requirements)
|
|
24
|
-
- [
|
|
25
|
-
- [
|
|
26
|
-
- [
|
|
27
|
-
- [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- [Settings](#settings)
|
|
32
|
-
- [Skipping a check](#skipping-a-check)
|
|
33
|
-
- [Dashboard (`ui`)](#dashboard-ui)
|
|
21
|
+
- [Commands](#commands)
|
|
22
|
+
- [`init`](#init--one-time-setup)
|
|
23
|
+
- [Checks: one config for CLI, dashboard and CI](#checks-one-config-for-cli-dashboard-and-ci)
|
|
24
|
+
- [Git hooks](#git-hooks)
|
|
25
|
+
- [Commits](#commits)
|
|
26
|
+
- [`doctor`](#doctor)
|
|
27
|
+
- [Dashboard](#dashboard-ui)
|
|
34
28
|
- [Presets](#presets)
|
|
35
|
-
- [
|
|
36
|
-
- [Limitations](#limitations)
|
|
29
|
+
- [Migrating from lintlane 3.x](#migrating-from-lintlane-3x)
|
|
37
30
|
- [Troubleshooting](#troubleshooting)
|
|
38
|
-
- [
|
|
31
|
+
- [Security](#security)
|
|
32
|
+
- [Limitations](#limitations)
|
|
39
33
|
- [Developing lintlane](#developing-lintlane)
|
|
40
34
|
|
|
41
35
|
## Quick start
|
|
42
36
|
|
|
43
37
|
```sh
|
|
44
|
-
#
|
|
38
|
+
# In a git repository with a package.json. Preview first, if you like:
|
|
39
|
+
npx lintlane init --dry-run
|
|
45
40
|
npx lintlane init
|
|
46
41
|
|
|
47
|
-
|
|
48
|
-
npx lintlane
|
|
49
|
-
npx lintlane
|
|
50
|
-
|
|
51
|
-
# 3. Open the dashboard to review issues and run your CI checks locally:
|
|
52
|
-
npx lintlane ui
|
|
42
|
+
npx lintlane doctor # verify the setup
|
|
43
|
+
npx lintlane run # Biome + typecheck + build + tests, like CI
|
|
44
|
+
npx lintlane ui # the dashboard
|
|
53
45
|
```
|
|
54
46
|
|
|
55
|
-
From then on, `git commit` is guided and checked, and every push is checked
|
|
56
|
-
before it leaves your machine.
|
|
57
|
-
|
|
58
|
-
> Use your package manager's runner for that first command: `npx lintlane init`,
|
|
59
|
-
> `pnpm dlx lintlane init`, `yarn dlx lintlane init` or `bunx lintlane init`. It
|
|
60
|
-
> runs on Node.js, so you don't need Bun. After `init`, lintlane is installed in
|
|
61
|
-
> your project and `npx lintlane …` (or `pnpm exec lintlane …`, `yarn lintlane …`,
|
|
62
|
-
> `bunx lintlane …`) runs your local copy without touching the network.
|
|
63
|
-
|
|
64
|
-
## Commands at a glance
|
|
65
|
-
|
|
66
|
-
| Command | What it does |
|
|
67
|
-
| ----------------------------------------------- | --------------------------------------------------------------- |
|
|
68
|
-
| `lintlane init [flags]` | One-time setup: installs, writes config, scripts, hooks and CI. |
|
|
69
|
-
| `lintlane check [paths]` | Run `biome check` (lint + format), no changes. |
|
|
70
|
-
| `lintlane check:fix [paths]` | Run `biome check --write`: apply safe fixes. |
|
|
71
|
-
| `lintlane ci [paths]` | Run `biome ci --reporter=github` (what CI runs). |
|
|
72
|
-
| `lintlane commit [flags] [-- <git args>]` | Guided Conventional Commit (alias `c`). |
|
|
73
|
-
| `lintlane check-commit [flags]` | Validate commit messages (a message, a file or a git range). |
|
|
74
|
-
| `lintlane ui [flags]` | Open the local dashboard (Lint + CI tabs). |
|
|
75
|
-
| `lintlane -h` / `commit -h` / `check-commit -h` | Show help. |
|
|
76
|
-
|
|
77
|
-
Every command except `init` runs from the project root. Examples below use
|
|
78
|
-
`npx lintlane …`; once lintlane is installed, `pnpm exec lintlane …`,
|
|
79
|
-
`yarn lintlane …`, `bunx lintlane …` and `node_modules/.bin/lintlane …` work too.
|
|
80
|
-
|
|
81
47
|
## Requirements
|
|
82
48
|
|
|
83
|
-
- **Node.js 22 or newer.**
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
-
|
|
88
|
-
|
|
89
|
-
- **Biome 2.2 up to (not including) 3.** It's a peer dependency; `init` installs it.
|
|
90
|
-
- **Git**, for the hooks and the commit workflow.
|
|
91
|
-
- **macOS or Linux** for the guided prompt on a plain `git commit` (it reads the
|
|
92
|
-
terminal through `/dev/tty`). Elsewhere that prompt is skipped; messages are
|
|
93
|
-
still validated, and `lintlane commit` still works. Windows isn't tested yet.
|
|
94
|
-
|
|
95
|
-
## `init` — one-time project setup
|
|
96
|
-
|
|
97
|
-
```sh
|
|
98
|
-
npx lintlane init
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
`init` installs `@biomejs/biome`, `lintlane` and (unless `--no-hooks`)
|
|
102
|
-
`husky`, then writes:
|
|
103
|
-
|
|
104
|
-
| File / change | Purpose |
|
|
105
|
-
| ----------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
106
|
-
| `biome.json` | Extends the preset. If one exists, it only tells you what to add. |
|
|
107
|
-
| `package.json` scripts | `check`, `check:fix`, and `prepare` (runs husky). |
|
|
108
|
-
| `.husky/pre-commit` | Biome on the staged files, auto-fixing what it can (safely: see [the pre-commit hook](#the-pre-commit-hook)). |
|
|
109
|
-
| `.husky/commit-msg` | Rejects messages that aren't Conventional Commits. |
|
|
110
|
-
| `.husky/prepare-commit-msg` | Guided prompt when you run a plain `git commit`. |
|
|
111
|
-
| `.husky/pre-push` | Checks every commit about to be pushed. |
|
|
112
|
-
| `.github/workflows/biome.yml` | `biome ci`, plus a commit-message check on pull requests. |
|
|
113
|
-
|
|
114
|
-
### Flags
|
|
115
|
-
|
|
116
|
-
| Flag | Effect |
|
|
117
|
-
| ------------------ | ----------------------------------------------------------------------- |
|
|
118
|
-
| `--preset <name>` | `base`, `strict` or `next`; overrides auto-detection. |
|
|
119
|
-
| `--no-hooks` | Skip husky and every git hook (also leaves the commit check out of CI). |
|
|
120
|
-
| `--no-commit-lint` | Keep the pre-commit hook; skip the commit-message hooks and CI check. |
|
|
121
|
-
| `--no-ci` | Skip the GitHub Actions workflow. |
|
|
122
|
-
| `--skip-install` | Print the install command instead of running it. |
|
|
123
|
-
| `-h`, `--help` | Show usage. |
|
|
124
|
-
|
|
125
|
-
```sh
|
|
126
|
-
npx lintlane init # everything, preset auto-detected
|
|
127
|
-
npx lintlane init --preset strict # force a preset
|
|
128
|
-
npx lintlane init --no-commit-lint # lint hook only, no commit rules
|
|
129
|
-
npx lintlane init --no-hooks --no-ci # just biome.json and scripts
|
|
130
|
-
npx lintlane init --skip-install # you install packages yourself
|
|
131
|
-
npx lintlane init --preset next --no-ci
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### Preset auto-detection
|
|
135
|
-
|
|
136
|
-
Without `--preset`, `init` reads your `package.json` dependencies:
|
|
137
|
-
|
|
138
|
-
| Found in dependencies | Preset used |
|
|
139
|
-
| ------------------------------------------------- | ----------- |
|
|
140
|
-
| `next` | `next` |
|
|
141
|
-
| `@tanstack/react-start`, `@tanstack/start` | `base` |
|
|
142
|
-
| `@react-router/dev` (React Router framework mode) | `base` |
|
|
143
|
-
| `@remix-run/react`, `@remix-run/node` | `base` |
|
|
144
|
-
| `react` (no framework above) | `base` |
|
|
145
|
-
| none of the above | `base` |
|
|
146
|
-
|
|
147
|
-
Only Next.js has its own Biome lint domain, so it's the only framework that
|
|
148
|
-
changes which preset is used. `init` says what it detected either way.
|
|
149
|
-
`strict` is never auto-selected; pass `--preset strict` when you want it.
|
|
150
|
-
|
|
151
|
-
### Package manager detection
|
|
152
|
-
|
|
153
|
-
`init` picks the package manager in this order, and tells you which signal it used:
|
|
154
|
-
|
|
155
|
-
1. the `packageManager` field in `package.json` (for example `pnpm@9.1.0`);
|
|
156
|
-
2. a lockfile: `bun.lock` / `bun.lockb`, `package-lock.json` / `npm-shrinkwrap.json`,
|
|
157
|
-
`pnpm-lock.yaml` or `yarn.lock`;
|
|
158
|
-
3. the tool you launched lintlane with (`npx`, `pnpm dlx`, `yarn dlx`, `bunx`);
|
|
159
|
-
4. otherwise **npm**, which ships with Node.js.
|
|
160
|
-
|
|
161
|
-
It then uses that package manager's install command (exact dev dependencies) and
|
|
162
|
-
writes matching setup steps into the CI workflow. If the package manager isn't
|
|
163
|
-
installed, `init` stops with a clear message before writing anything; you can
|
|
164
|
-
re-run with `--skip-install` and install the packages yourself.
|
|
165
|
-
|
|
166
|
-
| Package manager | Install command `init` runs |
|
|
167
|
-
| --------------- | ------------------------------------------------ |
|
|
168
|
-
| npm | `npm install --save-dev --save-exact <packages>` |
|
|
169
|
-
| pnpm | `pnpm add --save-dev --save-exact <packages>` |
|
|
170
|
-
| Yarn | `yarn add --dev --exact <packages>` |
|
|
171
|
-
| Bun | `bun add --dev --exact <packages>` |
|
|
172
|
-
|
|
173
|
-
### Safe to re-run
|
|
174
|
-
|
|
175
|
-
`init` never overwrites an existing `biome.json`/`biome.jsonc`, script, hook or
|
|
176
|
-
workflow file; it prints a `!` warning for whatever already exists and writes
|
|
177
|
-
only what's missing. That makes it the way to **upgrade**: update the package,
|
|
178
|
-
then run `init` again to pick up hooks added in newer versions.
|
|
179
|
-
|
|
180
|
-
One exception, for safety: an untouched copy of the **old pre-commit hook**
|
|
181
|
-
(the one that ended with `git update-index --again`, written by lintlane up to
|
|
182
|
-
2.5.1) is replaced with the current one, because the old hook could stage changes
|
|
183
|
-
you hadn't staged. If you edited that hook yourself, `init` leaves it alone and
|
|
184
|
-
warns you to replace it.
|
|
185
|
-
|
|
186
|
-
## `check`, `check:fix`, `ci` — run Biome
|
|
187
|
-
|
|
188
|
-
These wrap the Biome binary installed in your project, so you never need
|
|
189
|
-
Biome's own flags:
|
|
190
|
-
|
|
191
|
-
```sh
|
|
192
|
-
npx lintlane check # biome check . (read-only)
|
|
193
|
-
npx lintlane check:fix # biome check --write . (applies safe fixes)
|
|
194
|
-
npx lintlane ci # biome ci --reporter=github . (CI-formatted output)
|
|
49
|
+
- **Node.js 22 or newer.** Any package manager: npm, pnpm, Yarn or Bun
|
|
50
|
+
(`npx`, `pnpm dlx`, `yarn dlx`, `bunx`). `init` detects which one you use.
|
|
51
|
+
- **Biome 2.2 up to (not including) 3**, a peer dependency that `init` installs.
|
|
52
|
+
- **Git**.
|
|
53
|
+
- macOS or Linux for the guided prompt on a plain `git commit` (it reads the
|
|
54
|
+
terminal through `/dev/tty`). Windows is untested; see [Limitations](#limitations).
|
|
195
55
|
|
|
196
|
-
|
|
197
|
-
npx lintlane check:fix src/components/Button.tsx
|
|
198
|
-
npx lintlane ci src/ tests/
|
|
199
|
-
```
|
|
56
|
+
## Commands
|
|
200
57
|
|
|
201
|
-
|
|
202
|
-
|
|
58
|
+
| Command | What it does |
|
|
59
|
+
| --------------------------- | ----------------------------------------------------------------------------------------- |
|
|
60
|
+
| `init [--dry-run]` | Install and configure everything. Safe to re-run; never overwrites your config. |
|
|
61
|
+
| `doctor [--json]` | Diagnose the setup. Read-only. Exit code 1 only if something is broken. |
|
|
62
|
+
| `run [checks…]` | Run the project's checks in order (`--list`, `--keep-going`). |
|
|
63
|
+
| `check`, `check:fix`, `ci` | Run `biome check`, `biome check --write`, `biome ci`. |
|
|
64
|
+
| `commit` (`c`) | Guided Conventional Commit, run by Commitizen. Git flags go after `--`. |
|
|
65
|
+
| `check-commit` | Validate messages with commitlint: `--message`, `--commit-msg-file`, `--rev-range`, `-d`. |
|
|
66
|
+
| `ui [--port n] [--no-open]` | The local dashboard. |
|
|
203
67
|
|
|
204
|
-
`init`
|
|
205
|
-
call `biome` directly, so `npm run check` (or `pnpm`/`yarn`/`bun run check`)
|
|
206
|
-
works without lintlane's own command:
|
|
68
|
+
## `init` — one-time setup
|
|
207
69
|
|
|
208
70
|
```sh
|
|
209
|
-
|
|
210
|
-
npm run check:fix
|
|
71
|
+
npx lintlane init [--dry-run] [--preset base|strict|next] [--no-hooks] [--no-commit-lint] [--no-ci] [--skip-install]
|
|
211
72
|
```
|
|
212
73
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
`biome check --write` on the files you staged and puts the result back into your
|
|
217
|
-
commit. It is built so that **it can never stage, discard or rewrite anything you
|
|
218
|
-
didn't stage**:
|
|
219
|
-
|
|
220
|
-
- Only the staged files are touched. Unstaged edits to other files and untracked
|
|
221
|
-
files are never read, formatted or staged.
|
|
222
|
-
- A **partially staged** file (you staged some hunks and kept editing) is handled
|
|
223
|
-
correctly: Biome sees exactly the staged content, the fix is written to the
|
|
224
|
-
index, and Biome's changes are merged back into your working copy with a
|
|
225
|
-
three-way merge, so your unstaged edits survive byte for byte. If your unstaged
|
|
226
|
-
edit overlaps a formatting change, your working copy is left exactly as you
|
|
227
|
-
wrote it (the staged content is still formatted), and you get a notice.
|
|
228
|
-
- Nothing is ever staged with `git add`, `git add -A` or `git update-index --again`.
|
|
229
|
-
Fixed content goes into the index entry of each staged path only.
|
|
230
|
-
- If Biome reports an error it can't fix, the commit is blocked **and every file is
|
|
231
|
-
put back exactly as it was**: the index, the working tree and HEAD are
|
|
232
|
-
unchanged. It is all-or-nothing, so a fixable file isn't modified when another
|
|
233
|
-
staged file fails.
|
|
234
|
-
- Deleted and renamed files, file names with spaces, non-ASCII characters or a
|
|
235
|
-
leading dash, executable bits, symlinks, files Biome ignores and file types it
|
|
236
|
-
doesn't know are all handled.
|
|
237
|
-
- Ctrl+C or a termination signal during the run restores your working files
|
|
238
|
-
before exiting. Your working copy of a partially staged file is saved under
|
|
239
|
-
`.git/lintlane-backup` while the hook runs.
|
|
240
|
-
|
|
241
|
-
If the hook is killed in a way that can't be caught (`kill -9`, a power cut), the
|
|
242
|
-
next commit stops with a message instead of continuing, and you recover with:
|
|
74
|
+
It installs `@biomejs/biome`, `lintlane` and (with hooks) `husky` as exact dev
|
|
75
|
+
dependencies — only those that are missing, so a Biome or Husky version you
|
|
76
|
+
already pin is never bumped — then adds only what is missing:
|
|
243
77
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
78
|
+
- `biome.json` extending the detected preset (Next.js → `next`; React, TanStack
|
|
79
|
+
Start, React Router, Remix → `base`; `strict` only when you ask).
|
|
80
|
+
- `check`, `check:fix` and `prepare` scripts.
|
|
81
|
+
- a `lint-staged` entry in `package.json` that runs Biome on staged files.
|
|
82
|
+
- `commitlint.config.mjs` and `config.commitizen` in `package.json`.
|
|
83
|
+
- `.husky/pre-commit`, `commit-msg`, `prepare-commit-msg`, `pre-push`.
|
|
84
|
+
- `.github/workflows/biome.yml`, generated from your [checks](#checks-one-config-for-cli-dashboard-and-ci).
|
|
247
85
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
86
|
+
**`--dry-run`** prints every action (including the install command) and changes
|
|
87
|
+
nothing. **Re-running** is safe: whatever exists is reported and left alone. An
|
|
88
|
+
untouched hook from an older lintlane is upgraded; an edited one is never
|
|
89
|
+
rewritten, only reported. Existing lint-staged, commitlint and Commitizen
|
|
90
|
+
configuration is kept as it is.
|
|
252
91
|
|
|
253
|
-
|
|
92
|
+
The package manager comes from the `packageManager` field, then a lockfile, then
|
|
93
|
+
the tool that launched lintlane, then npm.
|
|
254
94
|
|
|
255
|
-
|
|
256
|
-
(`type(scope): subject`), which keeps history readable and works with changelog
|
|
257
|
-
and release tooling. The `commit` and `check-commit` commands and flags follow
|
|
258
|
-
[Commitizen](https://commitizen-tools.github.io/commitizen/) where they overlap
|
|
259
|
-
(`check-commit` is Commitizen's `cz check`; it isn't called `check` because
|
|
260
|
-
`lintlane check` runs Biome).
|
|
95
|
+
## Checks: one config for CLI, dashboard and CI
|
|
261
96
|
|
|
262
|
-
|
|
97
|
+
`lintlane run`, the dashboard's CI tab and the generated workflow all read the
|
|
98
|
+
same list, detected from `package.json`:
|
|
263
99
|
|
|
264
|
-
|
|
265
|
-
|
|
100
|
+
| id | Runs |
|
|
101
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
102
|
+
| `install` | Frozen-lockfile install (off by default locally) |
|
|
103
|
+
| `biome` | `biome ci .` |
|
|
104
|
+
| `typecheck` | script `typecheck`, `type-check`, `check-types` or `tsc`; else `tsc --noEmit` locally when a `tsconfig.json` exists |
|
|
105
|
+
| `build` | script `build` |
|
|
106
|
+
| `test` | script `test` (npm's placeholder is ignored) |
|
|
266
107
|
|
|
267
|
-
|
|
108
|
+
Tune it in `package.json`:
|
|
268
109
|
|
|
269
|
-
|
|
270
|
-
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"lintlane": {
|
|
113
|
+
"checks": { "build": false, "test": "test:unit" }
|
|
114
|
+
}
|
|
115
|
+
}
|
|
271
116
|
```
|
|
272
117
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
- A breaking change is marked with `!` (`feat(api)!: …`) plus a
|
|
278
|
-
`BREAKING CHANGE:` footer.
|
|
279
|
-
- Messages starting with `Merge`, `Revert`, `Pull request`, `fixup!`,
|
|
280
|
-
`squash!` or `amend!` are left alone.
|
|
281
|
-
|
|
282
|
-
### `commit` — guided Conventional Commit
|
|
118
|
+
`false` turns a check off everywhere, a string names the script to run, `true`
|
|
119
|
+
keeps the detected one. Unknown ids or missing scripts are reported by `doctor`
|
|
120
|
+
and the dashboard instead of failing silently. Only script names come from
|
|
121
|
+
config, never command lines.
|
|
283
122
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
npx lintlane commit # alias: npx lintlane c
|
|
287
|
-
```
|
|
123
|
+
The workflow is written once by `init`; after changing checks, `lintlane doctor`
|
|
124
|
+
tells you which CI steps are missing.
|
|
288
125
|
|
|
289
|
-
|
|
290
|
-
confirm** — then runs `git commit` with the result, so your pre-commit and
|
|
291
|
-
commit-msg hooks still run. It refuses if nothing is staged. Ctrl+C at any
|
|
292
|
-
step cancels with no commit made. Invalid answers (an empty subject, a trailing
|
|
293
|
-
period, an over-long header) are explained and asked again.
|
|
294
|
-
|
|
295
|
-
| Flag | Effect |
|
|
296
|
-
| -------------------------------- | -------------------------------------------------------------------- |
|
|
297
|
-
| `--dry-run` | Show the message without committing. |
|
|
298
|
-
| `--write-message-to-file <file>` | Write the message to a file (combine with `--dry-run`). |
|
|
299
|
-
| `--retry` | Reuse your last message after a failed commit, without asking again. |
|
|
300
|
-
| `--no-retry` | Always ask, even if `retryAfterFailure` is set. |
|
|
301
|
-
| `-l`, `--message-length-limit` | Maximum header length (`0` = no limit). |
|
|
302
|
-
| `-h`, `--help` | Show help for this command. |
|
|
303
|
-
| `-- <git args>` | Everything after `--` is passed to `git commit`. |
|
|
126
|
+
## Git hooks
|
|
304
127
|
|
|
305
|
-
|
|
306
|
-
npx lintlane commit # ask, then commit the staged changes
|
|
307
|
-
npx lintlane commit -- -a # stage all tracked changes, then commit
|
|
308
|
-
npx lintlane commit -- -a -S # …and sign the commit
|
|
309
|
-
npx lintlane commit -- -s # add a Signed-off-by line
|
|
310
|
-
npx lintlane commit -- -n # skip git hooks
|
|
311
|
-
npx lintlane commit --dry-run # just print the message
|
|
312
|
-
npx lintlane commit --dry-run --write-message-to-file msg.txt
|
|
313
|
-
npx lintlane commit -l 72 # stricter header limit for this commit
|
|
314
|
-
```
|
|
128
|
+
Hooks are Husky scripts that call `lintlane hook <name>`, which runs the real tool:
|
|
315
129
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
`
|
|
130
|
+
| Hook | Does |
|
|
131
|
+
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
132
|
+
| `pre-commit` | **lint-staged** runs `biome check --write` on staged files. Partially staged files keep their unstaged edits; nothing you didn't stage is committed. A lint error blocks the commit and changes nothing. |
|
|
133
|
+
| `commit-msg` | **commitlint** validates the message. |
|
|
134
|
+
| `prepare-commit-msg` | A plain `git commit` opens the **Commitizen** prompt (skipped for `-m`, merges, amends, CI, no terminal, `LINTLANE_NO_PROMPT=1`). |
|
|
135
|
+
| `pre-push` | **commitlint** checks every commit being pushed, catching `--no-verify` and GUI clients. |
|
|
321
136
|
|
|
322
|
-
|
|
137
|
+
Customize staged-file processing in the `lint-staged` key of `package.json` (or
|
|
138
|
+
any lint-staged config file). Bypass once with `git commit --no-verify`.
|
|
323
139
|
|
|
324
|
-
|
|
140
|
+
## Commits
|
|
325
141
|
|
|
326
142
|
```sh
|
|
327
|
-
npx lintlane
|
|
328
|
-
|
|
329
|
-
npx lintlane check-commit --
|
|
330
|
-
npx lintlane check-commit --rev-range origin/main..HEAD
|
|
331
|
-
npx lintlane check-commit -d # shorthand for <default branch>..HEAD
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
| Flag | Effect |
|
|
335
|
-
| ------------------------------ | ----------------------------------------------------- |
|
|
336
|
-
| `--message <msg>` | Check this message (or pipe one in on stdin). |
|
|
337
|
-
| `--commit-msg-file <path>` | Check the message in a file. |
|
|
338
|
-
| `--rev-range <range>` | Check every commit in a git range, e.g. `main..HEAD`. |
|
|
339
|
-
| `-d`, `--use-default-range` | Same as `--rev-range <default branch>..HEAD`. |
|
|
340
|
-
| `--allow-abort` | Accept an empty message. |
|
|
341
|
-
| `--allowed-prefixes <prefix>` | Skip messages starting with this (repeatable). |
|
|
342
|
-
| `-l`, `--message-length-limit` | Maximum header length (`0` = no limit). |
|
|
343
|
-
|
|
344
|
-
Exit codes: `0` everything passed, `1` a message was rejected, `2` a usage or
|
|
345
|
-
git error. For a range, the output lists each bad commit with its hash and why.
|
|
346
|
-
|
|
347
|
-
### Hooks: how a bad commit gets caught
|
|
348
|
-
|
|
349
|
-
Four layers, so a mistake is stopped somewhere:
|
|
350
|
-
|
|
351
|
-
| Layer | Catches |
|
|
352
|
-
| -------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
353
|
-
| `prepare-commit-msg` | A plain `git commit` (no `-m`): walks you through the steps instead of opening an empty editor. |
|
|
354
|
-
| `commit-msg` | `git commit -m "test"`: rejects a message in the wrong format, and says why. |
|
|
355
|
-
| `pre-push` | Commits that skipped the hooks (`--no-verify`, GUI clients, a fresh clone): checks every commit about to be pushed. |
|
|
356
|
-
| CI (pull requests) | Anything that still got through: checks the commits in the PR. |
|
|
357
|
-
|
|
358
|
-
```text
|
|
359
|
-
$ git commit -m "test"
|
|
360
|
-
|
|
361
|
-
✘ Commit message rejected
|
|
362
|
-
|
|
363
|
-
• The header must look like "type(scope): subject", e.g. "feat(auth): add login form".
|
|
364
|
-
|
|
365
|
-
Format: type(scope): subject
|
|
366
|
-
Example: feat(auth): add login form
|
|
367
|
-
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
143
|
+
npx lintlane commit # guided prompt
|
|
144
|
+
npx lintlane commit -- -S # extra args go to git commit
|
|
145
|
+
npx lintlane check-commit --message "feat: add login"
|
|
146
|
+
npx lintlane check-commit --rev-range origin/main..HEAD
|
|
368
147
|
```
|
|
369
148
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
message is validated again afterwards. `git commit --amend`, `-m` and `-F`
|
|
374
|
-
skip the prompt but not the validation.
|
|
375
|
-
- The prompt steps aside in CI, when `LINTLANE_NO_PROMPT` is set, and
|
|
376
|
-
whenever there's no terminal (editors and GUI clients that commit for you).
|
|
377
|
-
- Hooks run only once git hooks are installed. `init` does this, and teammates
|
|
378
|
-
get them from `install` through the `prepare` script (`husky`).
|
|
379
|
-
- The pre-push hook checks the commits being pushed (for a new branch: those
|
|
380
|
-
not already on the remote). Tag pushes and branch deletions are ignored.
|
|
381
|
-
|
|
382
|
-
### Settings
|
|
383
|
-
|
|
384
|
-
Optional, in your `package.json`:
|
|
149
|
+
Rules come from `commitlint.config.mjs`, which by default is
|
|
150
|
+
`export { default } from "lintlane/commitlint"`: Conventional Commits, plus the
|
|
151
|
+
optional block below. Replace the file with your own config any time.
|
|
385
152
|
|
|
386
153
|
```json
|
|
387
154
|
{
|
|
@@ -389,119 +156,52 @@ Optional, in your `package.json`:
|
|
|
389
156
|
"commit": {
|
|
390
157
|
"types": ["feat", "fix", "chore"],
|
|
391
158
|
"messageLengthLimit": 72,
|
|
392
|
-
"allowedPrefixes": ["WIP"]
|
|
393
|
-
"retryAfterFailure": true
|
|
159
|
+
"allowedPrefixes": ["WIP"]
|
|
394
160
|
}
|
|
395
161
|
}
|
|
396
162
|
}
|
|
397
163
|
```
|
|
398
164
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
### Skipping a check
|
|
410
|
-
|
|
411
|
-
| To skip… | Do this |
|
|
412
|
-
| ------------------------- | ----------------------------------------------------------------------- |
|
|
413
|
-
| The commit hooks, once | `git commit --no-verify` (the pre-push hook and CI still check it). |
|
|
414
|
-
| The pre-push check, once | `git push --no-verify` (CI still checks pull requests). |
|
|
415
|
-
| Only the guided prompt | Set `LINTLANE_NO_PROMPT=1`. |
|
|
416
|
-
| Commit rules for everyone | Re-run `init --no-commit-lint` on a fresh project, or delete the hooks. |
|
|
417
|
-
|
|
418
|
-
### Adding the CI step to an existing workflow
|
|
419
|
-
|
|
420
|
-
`init` adds the commit-message check only to newly generated workflows. To add
|
|
421
|
-
it to one you already have:
|
|
422
|
-
|
|
423
|
-
```yaml
|
|
424
|
-
- uses: actions/checkout@v4
|
|
425
|
-
with:
|
|
426
|
-
fetch-depth: 0
|
|
427
|
-
# …after your install step:
|
|
428
|
-
- name: Check commit messages
|
|
429
|
-
if: github.event_name == 'pull_request'
|
|
430
|
-
run: node node_modules/lintlane/bin/check-commit.mjs --rev-range origin/${{ github.base_ref }}..HEAD
|
|
165
|
+
The guided prompt is Commitizen's standard `cz-conventional-changelog`
|
|
166
|
+
(`config.commitizen.path = "lintlane/presets/commitizen.cjs"`); configure it like
|
|
167
|
+
any Commitizen adapter.
|
|
168
|
+
|
|
169
|
+
## `doctor`
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
npx lintlane doctor # human-readable, with a fix for every problem
|
|
173
|
+
npx lintlane doctor --json # { ok, version, findings: [{ id, status, message, fix? }] }
|
|
431
174
|
```
|
|
432
175
|
|
|
176
|
+
It checks Node, `package.json`, git, the package manager, Biome (and whether it
|
|
177
|
+
is installed in the project, where lint-staged looks for it), lintlane, the
|
|
178
|
+
bundled tools, Husky and `core.hooksPath`, every hook (current, upgradable,
|
|
179
|
+
broken, not executable), lint-staged/commitlint/Commitizen config, your
|
|
180
|
+
`lintlane.checks`, and whether the CI workflow runs your checks. Statuses:
|
|
181
|
+
`pass`, `warn` (missing or out of date), `fail` (broken). It never changes anything.
|
|
182
|
+
|
|
433
183
|
## Dashboard (`ui`)
|
|
434
184
|
|
|
435
|
-
`lintlane ui`
|
|
436
|
-
would fail before you push:
|
|
185
|
+
`npx lintlane ui` serves a dashboard on `127.0.0.1` and opens it.
|
|
437
186
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
187
|
+
- **Lint tab:** Biome diagnostics by file, the proposed fix as a diff, apply
|
|
188
|
+
fixes per file or all at once. Errors from Biome (can't start, invalid output)
|
|
189
|
+
are shown with the underlying message; a second check can't start while one runs.
|
|
190
|
+
- **CI tab:** the same checks as `lintlane run` with live output, per-step status
|
|
191
|
+
and timing, Stop (kills the whole process tree) and stop-on-first-failure.
|
|
192
|
+
Configuration problems and `doctor` failures appear above the table.
|
|
193
|
+
|
|
194
|
+
### Security
|
|
443
195
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
your
|
|
453
|
-
|
|
454
|
-
### Lint tab
|
|
455
|
-
|
|
456
|
-
Runs `biome check` and shows the result:
|
|
457
|
-
|
|
458
|
-
- **Summary cards:** errors, warnings, files with issues, check time.
|
|
459
|
-
- **File table:** each file's worst level, issue count, and whether Biome can fix
|
|
460
|
-
it. Rows with errors are tinted. Search by file name, message or rule, and
|
|
461
|
-
filter by All / Errors / Warnings.
|
|
462
|
-
- **Detail panel:** click a file to see each issue (rule, line and column) and
|
|
463
|
-
the proposed fix as a red/green diff, like `git diff`. Use ↑/↓ (or `j`/`k`) to
|
|
464
|
-
move between files and `Esc` to close.
|
|
465
|
-
- **Apply fix** writes the fix for one file; **Apply all fixes** applies them to
|
|
466
|
-
every listed file in one batch. Nothing is written until you click, and the
|
|
467
|
-
page re-checks afterwards.
|
|
468
|
-
|
|
469
|
-
Only Biome's _safe_ fixes are applied (the same ones as `check:fix`). Issues
|
|
470
|
-
with no automatic fix are labelled "Manual". The page lists the first 200 files
|
|
471
|
-
with issues; if there are more, a notice says so and "Apply all fixes" only
|
|
472
|
-
touches the files shown — click it again after the re-check to continue.
|
|
473
|
-
|
|
474
|
-
### CI tab
|
|
475
|
-
|
|
476
|
-
Runs the checks your CI would run, locally. The steps are detected from your
|
|
477
|
-
project:
|
|
478
|
-
|
|
479
|
-
| Step | Runs | On by default |
|
|
480
|
-
| ------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------- |
|
|
481
|
-
| Install (frozen lockfile) | `bun install --frozen-lockfile`, `npm ci`, or the `pnpm`/`yarn` equivalent | No |
|
|
482
|
-
| Biome CI (lint + format) | `biome ci .` — the same check the generated GitHub workflow runs | Yes |
|
|
483
|
-
| Typecheck | your `typecheck` script (or `type-check`, `check-types`, `tsc`), else `tsc --noEmit` if there's a `tsconfig.json` | Yes |
|
|
484
|
-
| Build | your `build` script | Yes |
|
|
485
|
-
| Tests | your `test` script (skipped if it's npm's "no test specified" placeholder) | Yes |
|
|
486
|
-
|
|
487
|
-
Tick the steps you want, then **Run CI**. Steps run in order with `CI=true`,
|
|
488
|
-
and their output streams into the panel as they run. **Stop on first failure**
|
|
489
|
-
(on by default, like real CI) skips the remaining steps after one fails. At the
|
|
490
|
-
end a banner says either "All N steps passed — safe to push" or "CI would
|
|
491
|
-
fail", naming the first failing step. **Stop** cancels the run and kills the
|
|
492
|
-
running process.
|
|
493
|
-
|
|
494
|
-
This is a script-based simulation, not a replica of your workflow: it runs the
|
|
495
|
-
commands above, not the steps in `.github/workflows/*.yml`, and it doesn't
|
|
496
|
-
reproduce CI's environment variables, secrets or Node version. A pass here is a
|
|
497
|
-
strong signal, not a guarantee.
|
|
498
|
-
|
|
499
|
-
### Safety
|
|
500
|
-
|
|
501
|
-
The server listens on `127.0.0.1` only. Every request needs a random token that
|
|
502
|
-
is part of the URL printed at startup — opening the dashboard without it gives a
|
|
503
|
-
403. The page only sends step ids and file paths; the server decides which
|
|
504
|
-
commands run and refuses paths outside the project.
|
|
196
|
+
- Listens on loopback only, on a URL carrying a random per-run token; API calls
|
|
197
|
+
need the token in a header (compared in constant time).
|
|
198
|
+
- The `Host` header must be `127.0.0.1:<port>` or `localhost:<port>`, which
|
|
199
|
+
blocks DNS-rebinding attacks from web pages.
|
|
200
|
+
- The page is served with a Content-Security-Policy (per-response script nonce,
|
|
201
|
+
`default-src 'none'`, `frame-ancestors 'none'`), `nosniff` and `no-referrer`.
|
|
202
|
+
- The browser sends step ids and file paths, never commands. Paths are resolved
|
|
203
|
+
inside the project and anything outside is refused.
|
|
204
|
+
- Only the checks you configured run, with your project's own scripts.
|
|
505
205
|
|
|
506
206
|
## Presets
|
|
507
207
|
|
|
@@ -529,212 +229,84 @@ npx biome migrate eslint --write
|
|
|
529
229
|
npx biome migrate prettier --write
|
|
530
230
|
```
|
|
531
231
|
|
|
532
|
-
##
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
```sh
|
|
560
|
-
npm install --save-dev husky # or: pnpm add -D husky / yarn add -D husky / bun add -d husky
|
|
561
|
-
npx husky init
|
|
562
|
-
```
|
|
563
|
-
|
|
564
|
-
Put these in `.husky/`:
|
|
565
|
-
|
|
566
|
-
`.husky/pre-commit`
|
|
567
|
-
|
|
568
|
-
```sh
|
|
569
|
-
if [ -f node_modules/lintlane/bin/pre-commit.mjs ]; then
|
|
570
|
-
node node_modules/lintlane/bin/pre-commit.mjs
|
|
571
|
-
else
|
|
572
|
-
echo "lintlane: node_modules/lintlane not found; skipping staged-file checks. Run your package manager's install." >&2
|
|
573
|
-
fi
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
Don't write your own `biome check --write --staged` followed by `git add` or
|
|
577
|
-
`git update-index --again`: that stages unstaged edits in partially staged files.
|
|
578
|
-
|
|
579
|
-
`.husky/commit-msg`
|
|
580
|
-
|
|
581
|
-
```sh
|
|
582
|
-
[ -f node_modules/lintlane/bin/commit-msg.mjs ] || exit 0
|
|
583
|
-
node node_modules/lintlane/bin/commit-msg.mjs "$1"
|
|
584
|
-
```
|
|
585
|
-
|
|
586
|
-
`.husky/prepare-commit-msg`
|
|
587
|
-
|
|
588
|
-
```sh
|
|
589
|
-
[ -f node_modules/lintlane/bin/prepare-commit-msg.mjs ] || exit 0
|
|
590
|
-
node node_modules/lintlane/bin/prepare-commit-msg.mjs "$1" "$2"
|
|
591
|
-
```
|
|
592
|
-
|
|
593
|
-
`.husky/pre-push`
|
|
594
|
-
|
|
595
|
-
```sh
|
|
596
|
-
[ -f node_modules/lintlane/bin/pre-push-check.mjs ] || exit 0
|
|
597
|
-
node node_modules/lintlane/bin/pre-push-check.mjs "$1" "$2"
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
Commits with errors Biome can't fix are blocked until you resolve them.
|
|
601
|
-
|
|
602
|
-
## Limitations
|
|
603
|
-
|
|
604
|
-
- **Windows is untested.** Subprocesses are started through `.cmd` shims there, but
|
|
605
|
-
none of it has been run on Windows. The guided prompt on `git commit` needs
|
|
606
|
-
`/dev/tty` and is skipped on Windows (`lintlane commit` works).
|
|
607
|
-
- **Yarn:** command generation is covered by tests, but a real Yarn install isn't
|
|
608
|
-
part of the automated end-to-end run here, so Yarn is the least exercised.
|
|
609
|
-
- **Line-ending and content filters.** The pre-commit hook compares your working
|
|
610
|
-
files with the raw staged content. If `core.autocrlf`, `.gitattributes` eol rules
|
|
611
|
-
or a filter makes them differ byte for byte, the file is treated as partially
|
|
612
|
-
staged: it's formatted in the index and your working copy is left as it was.
|
|
613
|
-
- **Merges.** During a merge commit, the hook also checks the files the merge staged.
|
|
614
|
-
- **Monorepos.** The hook runs from the repository root and uses the repository's
|
|
615
|
-
`node_modules`; a `package.json` in a subfolder isn't supported yet.
|
|
616
|
-
- **Concurrent edits.** If you save a file in your editor _while_ the hook is
|
|
617
|
-
running, that file is left as saved and the hook says so.
|
|
232
|
+
## Migrating from lintlane 3.x
|
|
233
|
+
|
|
234
|
+
lintlane 4 replaces its own staged-file and commit code with the tools above.
|
|
235
|
+
|
|
236
|
+
1. Upgrade: `npm install -D lintlane@4` (or your package manager's equivalent).
|
|
237
|
+
2. Run `npx lintlane init --dry-run`, then `npx lintlane init`. Untouched 3.x
|
|
238
|
+
hooks are upgraded; a hook you edited is left alone and reported.
|
|
239
|
+
3. Run `npx lintlane doctor`.
|
|
240
|
+
|
|
241
|
+
**Breaking changes**
|
|
242
|
+
|
|
243
|
+
- `lintlane` now has runtime dependencies (lint-staged, commitlint, Commitizen).
|
|
244
|
+
- `bin/pre-commit.mjs`, `commit-msg.mjs`, `prepare-commit-msg.mjs`,
|
|
245
|
+
`pre-push-check.mjs` are gone. Hooks that call them do nothing, which `doctor`
|
|
246
|
+
reports as a failure. `pre-commit.mjs --restore` is gone too: lint-staged
|
|
247
|
+
keeps its own backup stash.
|
|
248
|
+
- `lintlane commit` is Commitizen. `--write-message-to-file` and `-l` are gone;
|
|
249
|
+
`--dry-run`, `--retry`, `-a`, `-S` work as in Commitizen, `-- <git args>` as before.
|
|
250
|
+
- `check-commit`: `--allow-abort`, `--allowed-prefixes` and `-l` are gone; set
|
|
251
|
+
`lintlane.commit.allowedPrefixes` / `messageLengthLimit` or edit the commitlint config.
|
|
252
|
+
- Commit settings `retryAfterFailure` is gone (use `lintlane commit --retry`).
|
|
253
|
+
Custom `types` still apply to commitlint but no longer to the prompt; configure
|
|
254
|
+
the prompt through Commitizen.
|
|
255
|
+
- The CI workflow now runs every detected check (typecheck, tests, build), not
|
|
256
|
+
only Biome, and the commit check calls `lintlane check-commit`. Existing
|
|
257
|
+
workflows are not rewritten; turn checks off with `lintlane.checks`.
|
|
258
|
+
- Messages are formatted by commitlint, so wording of rejections changed.
|
|
618
259
|
|
|
619
260
|
## Troubleshooting
|
|
620
261
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
**A commit was rejected and I lost my message.** Use
|
|
637
|
-
`npx lintlane commit --retry` if you committed through `lintlane commit`.
|
|
638
|
-
|
|
639
|
-
**The pre-commit hook blocks my commit.** Biome found an error it can't fix.
|
|
640
|
-
Run `npx lintlane check` to see it, or open `npx lintlane ui`. Fix it and
|
|
641
|
-
commit again. Your files were left exactly as they were.
|
|
642
|
-
|
|
643
|
-
**"An earlier lintlane run was interrupted".** The hook was killed before it could
|
|
644
|
-
put your working files back. Run
|
|
645
|
-
`node node_modules/lintlane/bin/pre-commit.mjs --restore`, then commit again.
|
|
646
|
-
|
|
647
|
-
**My unstaged edit was reformatted / not reformatted.** The hook only formats what
|
|
648
|
-
you staged. When it formats a partially staged file it merges those changes into
|
|
649
|
-
your working copy without touching your unstaged edit. If your edit overlaps the
|
|
650
|
-
formatting change, your file is left exactly as you wrote it. Stage the file
|
|
651
|
-
fully, or run `npx lintlane check:fix`, to format it.
|
|
652
|
-
|
|
653
|
-
**`npx lintlane init` fails with "pnpm was not found" (or yarn, bun).** The project
|
|
654
|
-
says it uses that package manager (a lockfile or `packageManager`) but it isn't
|
|
655
|
-
installed. Install it, or run `npx lintlane init --skip-install` and install
|
|
656
|
-
`@biomejs/biome`, `lintlane` and `husky` yourself.
|
|
657
|
-
|
|
658
|
-
**Push blocked: "commit message(s) don't follow Conventional Commits".** Reword
|
|
659
|
-
the listed commits with `git rebase -i` (or `git commit --amend` for the latest),
|
|
660
|
-
then push again.
|
|
262
|
+
Start with `npx lintlane doctor`; each problem comes with a fix.
|
|
263
|
+
|
|
264
|
+
| Symptom | Likely cause / fix |
|
|
265
|
+
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
266
|
+
| Hooks don't run | `core.hooksPath` isn't `.husky/_`. Run your package manager's `husky` (via `install`, which runs `prepare`). |
|
|
267
|
+
| "lintlane: node_modules/lintlane not found" | Dependencies aren't installed. Run your package manager's install. |
|
|
268
|
+
| `biome: command not found` in pre-commit | Biome isn't a dependency of the project. Install `@biomejs/biome`. |
|
|
269
|
+
| lint-staged: "no configuration found" | Add a `lint-staged` key (run `init`). |
|
|
270
|
+
| commitlint: "Please add rules" | Missing `commitlint.config.mjs` (run `init`). |
|
|
271
|
+
| `lintlane commit` says no adapter configured | Add `config.commitizen.path` (run `init`). |
|
|
272
|
+
| No prompt on `git commit` | Expected for `-m`, merges, amends, CI, GUI clients, Windows. Use `lintlane commit`. |
|
|
273
|
+
| Old hook silently does nothing | It calls a 3.x file that no longer exists. `init` upgrades untouched ones; see [Migrating](#migrating-from-lintlane-3x). |
|
|
274
|
+
| Dashboard says Forbidden | Open the exact URL printed by `lintlane ui` (it includes the token). |
|
|
275
|
+
| CI doesn't run a check | The workflow predates the check. Add the step, or disable the check under `lintlane.checks`. |
|
|
661
276
|
|
|
662
|
-
|
|
663
|
-
Delete the file and re-run `init` if you want lintlane's version.
|
|
664
|
-
|
|
665
|
-
**The dashboard shows "Unauthorized" / 403.** Open the exact URL printed when
|
|
666
|
-
`lintlane ui` started; it contains a one-time token.
|
|
667
|
-
|
|
668
|
-
**Biome seems slow on a big project.** Add ignores for build output in your
|
|
669
|
-
`biome.json` (for example `dist`, `.next`, `build`, `coverage`) so Biome doesn't
|
|
670
|
-
scan them.
|
|
671
|
-
|
|
672
|
-
## Reference
|
|
673
|
-
|
|
674
|
-
**Environment variables**
|
|
675
|
-
|
|
676
|
-
| Variable | Effect |
|
|
677
|
-
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
678
|
-
| `LINTLANE_NO_PROMPT` | Set to any value to skip the guided prompt on `git commit`. |
|
|
679
|
-
| `CI` | When set, the guided prompt is skipped. The CI tab sets it for the steps it runs. |
|
|
680
|
-
| `NO_COLOR` | Turns off colors in the prompt. |
|
|
681
|
-
| `LINTLANE_INSTALL_SPEC` | What `init` installs instead of `lintlane@<version>` (a tarball or folder), for testing a local build. |
|
|
682
|
-
|
|
683
|
-
**Exit codes**
|
|
684
|
-
|
|
685
|
-
| Command | Codes |
|
|
686
|
-
| -------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
687
|
-
| `check`, `check:fix`, `ci` | Biome's exit code. |
|
|
688
|
-
| `commit` | `0` committed (or dry run), `1` cancelled, git's own exit code if the commit failed, `2` bad flags. |
|
|
689
|
-
| `check-commit` | `0` valid, `1` rejected, `2` usage or git error. |
|
|
690
|
-
| `ui` | Runs until you stop it. |
|
|
691
|
-
|
|
692
|
-
**Files lintlane may create or use**
|
|
277
|
+
## Limitations
|
|
693
278
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
| `.git/lintlane-backup/` | Your working copies, only while the pre-commit hook runs (or after it was killed). |
|
|
279
|
+
- Windows isn't tested. The CLI avoids Unix-only APIs, but the guided prompt on
|
|
280
|
+
`git commit` is skipped there and CI here runs on Ubuntu and macOS only.
|
|
281
|
+
- The generated workflow targets GitHub Actions.
|
|
282
|
+
- The guided prompt uses the standard Conventional Commits adapter.
|
|
283
|
+
- lint-staged and commitlint behavior, including their config discovery, is theirs;
|
|
284
|
+
see their docs for advanced setups (monorepos, per-folder configs).
|
|
701
285
|
|
|
702
286
|
## Developing lintlane
|
|
703
287
|
|
|
704
|
-
Requires Node.js 22 or newer.
|
|
705
|
-
dependency is Biome.
|
|
288
|
+
Requires Node.js 22 or newer.
|
|
706
289
|
|
|
707
290
|
```sh
|
|
708
|
-
npm test # unit + integration tests (about
|
|
709
|
-
npm run test:e2e # real npm / pnpm / bun installs
|
|
291
|
+
npm test # unit + integration tests (about 40 seconds, no network)
|
|
292
|
+
npm run test:e2e # real npm / pnpm / yarn / bun installs (needs network)
|
|
710
293
|
npm run check # lint and format this repository
|
|
294
|
+
npm run verify:release [npm|pnpm|yarn|bun] # pack, install in a fresh project, init, doctor, real commits
|
|
711
295
|
```
|
|
712
296
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
|
716
|
-
|
|
|
717
|
-
| `test/
|
|
718
|
-
| `test/
|
|
719
|
-
| `test/
|
|
720
|
-
| `test/ui.test.mjs` |
|
|
721
|
-
| `test/e2e.test.mjs` | **Real** package managers
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
# In the lintlane repo:
|
|
727
|
-
npm pack --pack-destination /tmp/lintlane-pack # builds lintlane-<version>.tgz
|
|
728
|
-
|
|
729
|
-
# In a throwaway app (a git repo with a package.json), from its directory:
|
|
730
|
-
LINTLANE_INSTALL_SPEC=/tmp/lintlane-pack/lintlane-<version>.tgz \
|
|
731
|
-
npx --package=/tmp/lintlane-pack/lintlane-<version>.tgz lintlane init
|
|
732
|
-
```
|
|
733
|
-
|
|
734
|
-
`init` then installs your tarball, Biome and husky with the app's package manager
|
|
735
|
-
and does everything a real run does. `npm pack --dry-run` lists what would be
|
|
736
|
-
published. If you rebuild without changing the version, a package manager may
|
|
737
|
-
reuse its cached tarball: bump the version, or clear the cache and reinstall.
|
|
297
|
+
| File | What it covers |
|
|
298
|
+
| -------------------------------- | ------------------------------------------------------------------------------------------- |
|
|
299
|
+
| `test/hooks.test.mjs` | Real git: pre-commit (partial staging, failures), commit-msg, prepare-commit-msg, pre-push. |
|
|
300
|
+
| `test/setup.test.mjs` | `init --dry-run`, idempotency, upgrades from 3.x hooks, `doctor`. |
|
|
301
|
+
| `test/checks.test.mjs` | The shared checks list, generated CI, `lintlane run`. |
|
|
302
|
+
| `test/cli.test.mjs` | Running on Node without Bun, packaging, `init`. Package managers are **mocked** here. |
|
|
303
|
+
| `test/package-managers.test.mjs` | Package-manager detection and command generation (pure). |
|
|
304
|
+
| `test/ui.test.mjs` | Dashboard: auth, Host/CSP hardening, every API route, Stop. |
|
|
305
|
+
| `test/e2e.test.mjs` | **Real** package managers and the packed tarball. Needs `LINTLANE_E2E=1`. |
|
|
306
|
+
|
|
307
|
+
CI (`.github/workflows/ci.yml`) runs the tests on Ubuntu and macOS with Node 22
|
|
308
|
+
and 24, and `verify:release` for each package manager. To try a local build,
|
|
309
|
+
set `LINTLANE_INSTALL_SPEC` to a tarball from `npm pack` when running `init`.
|
|
738
310
|
|
|
739
311
|
## License
|
|
740
312
|
|