codebyplan 1.12.0 → 1.13.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/dist/cli.js +50 -71
- package/package.json +1 -1
- package/templates/hooks/README.md +1 -13
- package/templates/hooks/cbp-test-coverage-gate.sh +8 -0
- package/templates/hooks/cbp-test-hooks.sh +0 -42
- package/templates/hooks/hooks.json +0 -9
- package/templates/skills/cbp-checkpoint-start/SKILL.md +2 -2
- package/templates/skills/cbp-session-start/SKILL.md +1 -1
- package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/SKILL.md +1 -1
- package/templates/skills/cbp-setup-eslint/SKILL.md +199 -0
- package/templates/skills/cbp-setup-eslint/reference/base.md +82 -0
- package/templates/skills/cbp-setup-eslint/reference/cli.md +56 -0
- package/templates/skills/cbp-setup-eslint/reference/e2e.md +68 -0
- package/templates/skills/cbp-setup-eslint/reference/jest.md +59 -0
- package/templates/skills/cbp-setup-eslint/reference/nestjs.md +69 -0
- package/templates/skills/cbp-setup-eslint/reference/nextjs.md +63 -0
- package/templates/skills/cbp-setup-eslint/reference/node.md +74 -0
- package/templates/skills/cbp-setup-eslint/reference/react-native.md +60 -0
- package/templates/skills/cbp-setup-eslint/reference/react.md +82 -0
- package/templates/skills/cbp-setup-eslint/reference/tailwind.md +64 -0
- package/templates/skills/cbp-setup-eslint/reference/testing-react.md +57 -0
- package/templates/skills/cbp-setup-eslint/reference/vitest.md +62 -0
- package/templates/skills/cbp-task-complete/SKILL.md +1 -3
- package/templates/skills/cbp-task-start/SKILL.md +3 -3
- package/templates/hooks/cbp-mcp-worktree-inject.sh +0 -76
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/maestro.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/playwright.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/tauri.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/vscode.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/xcuitest.md +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# base — TypeScript foundation (ESLint v10 flat config)
|
|
2
|
+
|
|
3
|
+
The foundation every TypeScript app shares: ESLint flat config, type-checked
|
|
4
|
+
`typescript-eslint` rules, security scanning, and Prettier. Maps to the CBP **`base`** DB
|
|
5
|
+
preset (`tech_match.requires: ["TypeScript"]`).
|
|
6
|
+
|
|
7
|
+
> **Verified 2026-05-31.** ESLint is on **v10** — flat config (`eslint.config.mjs`) is the
|
|
8
|
+
> only native format (legacy `.eslintrc*` was removed). `defineConfig` from `eslint/config`
|
|
9
|
+
> is the canonical wrapper for every stack below.
|
|
10
|
+
|
|
11
|
+
## Packages
|
|
12
|
+
|
|
13
|
+
| Package | Latest | Purpose |
|
|
14
|
+
| ------- | ------ | ------- |
|
|
15
|
+
| `eslint` | `10.4.1` | the linter (flat config only) |
|
|
16
|
+
| `@eslint/js` | `10.0.1` | `js.configs.recommended` |
|
|
17
|
+
| `typescript-eslint` | `8.60.0` | unified parser + plugin + presets |
|
|
18
|
+
| `eslint-config-prettier` | `10.x` | turns off formatting rules (subpath `/flat`) |
|
|
19
|
+
| `eslint-plugin-security` | `^3` | OWASP-style heuristics |
|
|
20
|
+
| `eslint-plugin-no-secrets` | `^2.1` | high-entropy string detection |
|
|
21
|
+
| `globals` | `17.6.0` | env global definitions |
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pnpm add -D eslint @eslint/js typescript-eslint eslint-config-prettier \
|
|
25
|
+
eslint-plugin-security eslint-plugin-no-secrets globals
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Flat config
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
// eslint.config.mjs
|
|
32
|
+
import { defineConfig } from "eslint/config";
|
|
33
|
+
import js from "@eslint/js";
|
|
34
|
+
import tseslint from "typescript-eslint";
|
|
35
|
+
import security from "eslint-plugin-security";
|
|
36
|
+
import noSecrets from "eslint-plugin-no-secrets";
|
|
37
|
+
import prettier from "eslint-config-prettier/flat";
|
|
38
|
+
|
|
39
|
+
export default defineConfig([
|
|
40
|
+
js.configs.recommended,
|
|
41
|
+
...tseslint.configs.recommendedTypeChecked, // type-aware: no-floating-promises, etc.
|
|
42
|
+
security.configs.recommended,
|
|
43
|
+
{ plugins: { "no-secrets": noSecrets }, rules: { "no-secrets/no-secrets": ["warn", { tolerance: 4.5 }] } },
|
|
44
|
+
{
|
|
45
|
+
languageOptions: {
|
|
46
|
+
parserOptions: {
|
|
47
|
+
projectService: true, // current type-info mechanism
|
|
48
|
+
tsconfigRootDir: import.meta.dirname,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{ rules: { "security/detect-object-injection": "off" } }, // famously noisy
|
|
53
|
+
prettier, // MUST be last
|
|
54
|
+
]);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Gotchas
|
|
58
|
+
|
|
59
|
+
- **`recommended` vs `recommendedTypeChecked`.** The type-checked preset is what enables the
|
|
60
|
+
genuinely valuable rules (`no-floating-promises`, `no-misused-promises`, `no-unsafe-*`) but
|
|
61
|
+
needs type info and is **much slower** — scope it to `**/*.ts`/`**/*.tsx` and disable on JS
|
|
62
|
+
config files with `tseslint.configs.disableTypeChecked`.
|
|
63
|
+
- **`projectService: true`** replaces the old `project: "./tsconfig.json"`. It auto-finds the
|
|
64
|
+
nearest `tsconfig.json` per file and lints out-of-project files (like `eslint.config.mjs`)
|
|
65
|
+
without a `tsconfig.eslint.json`. Always pair it with `tsconfigRootDir: import.meta.dirname`.
|
|
66
|
+
- **`tseslint.config()` is deprecated** in favour of core `defineConfig` from `eslint/config`
|
|
67
|
+
(a near-exact clone). The `tseslint.configs.*` presets are unchanged.
|
|
68
|
+
- **Prettier last.** `eslint-config-prettier/flat` must come after every rule-defining config
|
|
69
|
+
so it can switch off conflicting stylistic rules.
|
|
70
|
+
|
|
71
|
+
## CBP preset divergence
|
|
72
|
+
|
|
73
|
+
CBP's `base` DB preset currently pins `eslint: ^9.0.0` / `typescript-eslint: ^8.0.0` and
|
|
74
|
+
keeps several `@typescript-eslint/no-unsafe-*` rules at `warn`. The setup above reflects the
|
|
75
|
+
**latest** (`eslint@10`); both are flat-config and interoperate. Bumping the preset to v10 is
|
|
76
|
+
out of scope for the skill (no DB/preset changes) — adopt v10 per-repo when you regenerate.
|
|
77
|
+
|
|
78
|
+
## Official docs
|
|
79
|
+
|
|
80
|
+
- Configuration files: https://eslint.org/docs/latest/use/configure/configuration-files
|
|
81
|
+
- Typed linting: https://typescript-eslint.io/getting-started/typed-linting/
|
|
82
|
+
- `projectService`: https://typescript-eslint.io/blog/project-service/
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# cli — Node CLI tool overrides
|
|
2
|
+
|
|
3
|
+
For Node CLI packages with a `bin` (the CBP `codebyplan` package). Layers a small **override
|
|
4
|
+
block** on top of [base](base.md) + [node](node.md). Maps to the CBP **`cli`** DB preset
|
|
5
|
+
(`tech_match.requires_capabilities: ["cli-bin"]`).
|
|
6
|
+
|
|
7
|
+
> **Verified 2026-05-31.** There is no "CLI" ESLint plugin — the convention is a scoped
|
|
8
|
+
> rule-override block.
|
|
9
|
+
|
|
10
|
+
## What it does
|
|
11
|
+
|
|
12
|
+
A CLI legitimately (a) talks to the user via `console`, and (b) operates on user-supplied
|
|
13
|
+
filesystem paths and dynamic keys — so the `eslint-plugin-security` heuristics that flag those
|
|
14
|
+
produce noise, not findings. Relax them, **scoped narrowly** to the CLI surface.
|
|
15
|
+
|
|
16
|
+
## Flat config (override block)
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
// eslint.config.mjs — appended after base + node + security configs
|
|
20
|
+
export default [
|
|
21
|
+
// ...base, node, security.configs.recommended, etc.
|
|
22
|
+
{
|
|
23
|
+
files: ["bin/**/*.{js,ts,mjs}", "src/cli/**/*.{js,ts}"],
|
|
24
|
+
rules: {
|
|
25
|
+
"no-console": "off", // console output IS the CLI's UI
|
|
26
|
+
|
|
27
|
+
// CLIs operate on user paths and dynamic keys by design:
|
|
28
|
+
"security/detect-non-literal-fs-filename": "off",
|
|
29
|
+
"security/detect-object-injection": "off",
|
|
30
|
+
|
|
31
|
+
// optional, if eslint-plugin-n is in use (CLIs call process.exit):
|
|
32
|
+
// "n/no-process-exit": "off",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Gotchas
|
|
39
|
+
|
|
40
|
+
- **Scope via `files`** — do NOT disable these repo-wide; the same rules are valuable in
|
|
41
|
+
server/library code.
|
|
42
|
+
- The two `security/*` lines require `eslint-plugin-security` to be installed and registered
|
|
43
|
+
(otherwise ESLint errors "rule not found"). If the project has no security plugin, only the
|
|
44
|
+
`no-console: "off"` line applies.
|
|
45
|
+
|
|
46
|
+
## CBP preset divergence
|
|
47
|
+
|
|
48
|
+
The CBP `cli` preset matches the rule set above exactly (`no-console`,
|
|
49
|
+
`security/detect-non-literal-fs-filename`, `security/detect-object-injection` all off) and is
|
|
50
|
+
capability-gated on `cli-bin`. The repo's own `packages/codebyplan-package/eslint.config.mjs`
|
|
51
|
+
already applies this. No divergence — this doc just documents the convention.
|
|
52
|
+
|
|
53
|
+
## Official docs
|
|
54
|
+
|
|
55
|
+
- Convention (no upstream doc); rules: https://eslint.org/docs/latest/rules/no-console and
|
|
56
|
+
https://github.com/eslint-community/eslint-plugin-security
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# e2e — Playwright / WebdriverIO / Mocha test rules
|
|
2
|
+
|
|
3
|
+
For end-to-end specs. Three runners appear across CBP repos: **Playwright** (web), **WebdriverIO**
|
|
4
|
+
(Tauri desktop), and **Mocha** (the framework WDIO drives). Each is a **directory-scoped**
|
|
5
|
+
override. Playwright maps to the CBP **`testing-e2e`** preset
|
|
6
|
+
(`tech_match.requires: ["Playwright"]`); WebdriverIO + Mocha are **gap stacks — no preset**.
|
|
7
|
+
|
|
8
|
+
> **Verified 2026-05-31.** Version traps: Playwright is **2.10.4** (not the 0.15.x search
|
|
9
|
+
> sometimes returns); Mocha 11.x uses **`configs.recommended`** — NOT `configs.flat.recommended`.
|
|
10
|
+
|
|
11
|
+
## Packages
|
|
12
|
+
|
|
13
|
+
| Package | Latest | Flat key |
|
|
14
|
+
| ------- | ------ | -------- |
|
|
15
|
+
| `eslint-plugin-playwright` | `2.10.4` | `configs['flat/recommended']` |
|
|
16
|
+
| `eslint-plugin-wdio` | `9.27.2` | `configs['flat/recommended']` |
|
|
17
|
+
| `eslint-plugin-mocha` | `11.3.0` | `configs.recommended` (NOT `.flat`) |
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add -D eslint-plugin-playwright # web
|
|
21
|
+
pnpm add -D eslint-plugin-wdio eslint-plugin-mocha # Tauri / WebdriverIO desktop
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Flat config
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
// eslint.config.mjs
|
|
28
|
+
import playwright from "eslint-plugin-playwright";
|
|
29
|
+
// desktop: import { configs as wdioConfigs } from "eslint-plugin-wdio";
|
|
30
|
+
// desktop: import mocha from "eslint-plugin-mocha";
|
|
31
|
+
|
|
32
|
+
export default [
|
|
33
|
+
// Playwright — scope to the web e2e dir
|
|
34
|
+
{
|
|
35
|
+
...playwright.configs["flat/recommended"],
|
|
36
|
+
files: ["e2e/**", "**/*.e2e.{ts,js}"],
|
|
37
|
+
rules: { ...playwright.configs["flat/recommended"].rules, "no-console": "off" },
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
// WebdriverIO + Mocha (Tauri desktop) — scope to the wdio spec dir
|
|
41
|
+
// { ...wdioConfigs["flat/recommended"], files: ["test/**", "e2e/**"] },
|
|
42
|
+
// { ...mocha.configs.recommended, files: ["test/**/*.{ts,js}"] },
|
|
43
|
+
];
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Gotchas
|
|
47
|
+
|
|
48
|
+
- **Scope every e2e override via `files`** — Playwright/WDIO/Mocha rules false-positive on
|
|
49
|
+
unit tests, and Testing-Library rules false-positive on e2e specs.
|
|
50
|
+
- **Mocha 11.x = `mocha.configs.recommended`** — `mocha.configs.flat.recommended` is
|
|
51
|
+
`undefined` in 11.x (it only exists on the unreleased 12.x main branch) and crashes config
|
|
52
|
+
load. Don't copy a `.flat.recommended` example.
|
|
53
|
+
- **WebdriverIO**: `eslint-plugin-wdio@9` requires ESLint 9+; when `typescript-eslint` is
|
|
54
|
+
present its recommended config auto-swaps `wdio/await-expect` → `wdio/no-floating-promise`.
|
|
55
|
+
- The CBP web app keeps Playwright specs in `e2e/**` with a Vitest sibling override for
|
|
56
|
+
`e2e/**/__tests__/**` — mirror that split if you co-locate unit tests under `e2e/`.
|
|
57
|
+
|
|
58
|
+
## CBP preset divergence
|
|
59
|
+
|
|
60
|
+
CBP's `testing-e2e` preset covers **Playwright only** (`eslint-plugin-playwright: ^2.0.0`,
|
|
61
|
+
`no-console: off`). There is **no** preset for WebdriverIO or Mocha — the Tauri desktop e2e
|
|
62
|
+
config is manual. The skill does not add presets for the gap runners.
|
|
63
|
+
|
|
64
|
+
## Official docs
|
|
65
|
+
|
|
66
|
+
- Playwright: https://github.com/mskelton/eslint-plugin-playwright
|
|
67
|
+
- WebdriverIO: https://github.com/webdriverio/webdriverio/tree/main/packages/eslint-plugin-wdio
|
|
68
|
+
- Mocha: https://github.com/lo1tuma/eslint-plugin-mocha
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# jest — Jest test-file rules
|
|
2
|
+
|
|
3
|
+
For apps that test with Jest (CBP `apps/backend` NestJS specs, `livebyplan` Expo). **Gap
|
|
4
|
+
stack — no CBP DB preset** (the `testing` preset is Vitest-only). Layers a test-scoped
|
|
5
|
+
override on top of [base](base.md).
|
|
6
|
+
|
|
7
|
+
> **Verified 2026-05-31.** `eslint-plugin-jest` uses the **bracketed** flat-config keys
|
|
8
|
+
> `configs['flat/recommended']` / `['flat/style']` (the un-prefixed keys are legacy eslintrc).
|
|
9
|
+
|
|
10
|
+
## Packages
|
|
11
|
+
|
|
12
|
+
| Package | Latest | Purpose |
|
|
13
|
+
| ------- | ------ | ------- |
|
|
14
|
+
| `eslint-plugin-jest` | `29.15.2` | Jest rules |
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add -D eslint-plugin-jest
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Peers: `eslint ^8.57 || ^9 || ^10`, `@typescript-eslint/eslint-plugin ^8`, `jest`.
|
|
21
|
+
|
|
22
|
+
## Flat config
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
// eslint.config.mjs
|
|
26
|
+
import jest from "eslint-plugin-jest";
|
|
27
|
+
|
|
28
|
+
export default [
|
|
29
|
+
{
|
|
30
|
+
files: ["**/*.{test,spec}.{ts,tsx,js,jsx}", "**/__tests__/**/*.{ts,tsx,js,jsx}"],
|
|
31
|
+
...jest.configs["flat/recommended"],
|
|
32
|
+
rules: {
|
|
33
|
+
...jest.configs["flat/recommended"].rules,
|
|
34
|
+
...jest.configs["flat/style"].rules, // optional stylistic rules
|
|
35
|
+
// type-aware: hand the unbound-method check to the jest-aware version
|
|
36
|
+
"@typescript-eslint/unbound-method": "off",
|
|
37
|
+
"jest/unbound-method": "error",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Gotchas
|
|
44
|
+
|
|
45
|
+
- Keys are **`configs['flat/recommended']`** / **`['flat/style']`** (bracketed) — the
|
|
46
|
+
unprefixed `configs.recommended` is the legacy eslintrc preset.
|
|
47
|
+
- **`jest/unbound-method`** extends `@typescript-eslint/unbound-method`; turn the base rule
|
|
48
|
+
off on test files and enable the jest version (needs `@typescript-eslint/parser` + type
|
|
49
|
+
info). Type-aware jest rules safely no-op when type info is absent.
|
|
50
|
+
- Avoid pinning `flat/all` long-term — it enables every rule and can break on minor releases.
|
|
51
|
+
|
|
52
|
+
## CBP preset divergence
|
|
53
|
+
|
|
54
|
+
There is **no** CBP `testing-jest` preset. NestJS/Expo Jest specs are currently linted only by
|
|
55
|
+
the base rules. Add the override above per-repo; the skill does not add a preset.
|
|
56
|
+
|
|
57
|
+
## Official docs
|
|
58
|
+
|
|
59
|
+
- eslint-plugin-jest: https://github.com/jest-community/eslint-plugin-jest
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# nestjs — NestJS back-end flat config
|
|
2
|
+
|
|
3
|
+
For NestJS apps (the CBP `apps/backend`). **Gap stack — no CBP DB preset.** Use this doc to
|
|
4
|
+
hand-author `eslint.config.mjs`; the `base` + `node` presets cover most of it, but the
|
|
5
|
+
official Nest starter has a specific shape worth matching.
|
|
6
|
+
|
|
7
|
+
> **Verified 2026-05-31.** There is **no first-party NestJS ESLint plugin** — the official
|
|
8
|
+
> `nest new` starter uses plain type-checked `typescript-eslint` + Prettier.
|
|
9
|
+
|
|
10
|
+
## Packages
|
|
11
|
+
|
|
12
|
+
| Package | Latest | Purpose |
|
|
13
|
+
| ------- | ------ | ------- |
|
|
14
|
+
| `typescript-eslint` | `8.60.0` | parser + type-checked preset |
|
|
15
|
+
| `@eslint/js` | `10.0.1` | `eslint.configs.recommended` |
|
|
16
|
+
| `eslint-plugin-prettier` | `^5` | `/recommended` subpath |
|
|
17
|
+
| `globals` | `17.6.0` | `globals.node`, `globals.jest` |
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add -D typescript-eslint @eslint/js eslint-plugin-prettier eslint-config-prettier globals
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Flat config (official `nest new` starter, verbatim)
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
// @ts-check
|
|
27
|
+
import eslint from "@eslint/js";
|
|
28
|
+
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
|
|
29
|
+
import globals from "globals";
|
|
30
|
+
import tseslint from "typescript-eslint";
|
|
31
|
+
|
|
32
|
+
export default tseslint.config(
|
|
33
|
+
{ ignores: ["eslint.config.mjs"] },
|
|
34
|
+
eslint.configs.recommended,
|
|
35
|
+
...tseslint.configs.recommendedTypeChecked,
|
|
36
|
+
eslintPluginPrettierRecommended,
|
|
37
|
+
{
|
|
38
|
+
languageOptions: {
|
|
39
|
+
globals: { ...globals.node, ...globals.jest },
|
|
40
|
+
sourceType: "commonjs", // "module" for an ESM Nest app
|
|
41
|
+
parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname },
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
rules: {
|
|
46
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
47
|
+
"@typescript-eslint/no-floating-promises": "warn",
|
|
48
|
+
"@typescript-eslint/no-unsafe-argument": "warn",
|
|
49
|
+
"prettier/prettier": ["error", { endOfLine: "auto" }],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Gotchas
|
|
56
|
+
|
|
57
|
+
- Nest relaxes three type-checked rules (`no-explicit-any` off; `no-floating-promises` and
|
|
58
|
+
`no-unsafe-argument` to `warn`) because its DI/decorator patterns trip them. Keep these.
|
|
59
|
+
- `{ ignores: ["eslint.config.mjs"] }` keeps type-aware linting off the config file itself.
|
|
60
|
+
- `sourceType: "commonjs"` matches Nest's default CJS build — flip to `"module"` for ESM.
|
|
61
|
+
- The starter still uses `tseslint.config(...)`; you may swap it for `defineConfig` from
|
|
62
|
+
`eslint/config` (deprecation note in [base.md](base.md)) — the presets are identical.
|
|
63
|
+
- Optional community add-on: `@darraghor/eslint-plugin-nestjs-typed` adds
|
|
64
|
+
decorator/Swagger/DTO-aware rules. Not part of the official starter.
|
|
65
|
+
- Nest tests use **Jest** — add the [jest.md](jest.md) override scoped to `**/*.spec.ts`.
|
|
66
|
+
|
|
67
|
+
## Official docs
|
|
68
|
+
|
|
69
|
+
- Starter config: https://github.com/nestjs/typescript-starter/blob/master/eslint.config.mjs
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# nextjs — Next.js (App Router) flat config
|
|
2
|
+
|
|
3
|
+
For Next.js apps. Layers on top of [base](base.md). Maps to the CBP **`nextjs`** DB preset
|
|
4
|
+
(`tech_match.requires: ["Next.js"]`, `requires_capabilities: ["jsx"]`).
|
|
5
|
+
|
|
6
|
+
> **Verified 2026-05-31.** As of **Next.js 16**, `eslint-config-next` ships **native flat
|
|
7
|
+
> config**, `next lint` is **removed** (run `eslint .` directly), and the `eslint` key in
|
|
8
|
+
> `next.config.js` is gone. No `FlatCompat` shim is needed.
|
|
9
|
+
|
|
10
|
+
## Packages
|
|
11
|
+
|
|
12
|
+
| Package | Latest | Purpose |
|
|
13
|
+
| ------- | ------ | ------- |
|
|
14
|
+
| `eslint-config-next` | `16.2.6` | bundles `@next/eslint-plugin-next` + react/react-hooks/import |
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add -D eslint-config-next
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Flat config
|
|
21
|
+
|
|
22
|
+
`eslint-config-next` exposes spreadable **array** subpath exports:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
// eslint.config.mjs
|
|
26
|
+
import { defineConfig, globalIgnores } from "eslint/config";
|
|
27
|
+
import nextVitals from "eslint-config-next/core-web-vitals";
|
|
28
|
+
import nextTs from "eslint-config-next/typescript";
|
|
29
|
+
|
|
30
|
+
export default defineConfig([
|
|
31
|
+
...nextVitals, // base + Core-Web-Vitals rules promoted warn→error
|
|
32
|
+
...nextTs, // typescript-eslint rules (based on @typescript-eslint/recommended)
|
|
33
|
+
globalIgnores([".next/**", "out/**", "build/**", "next-env.d.ts"]),
|
|
34
|
+
]);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Subpath exports:
|
|
38
|
+
- `eslint-config-next` — base (Next + react + react-hooks recommended).
|
|
39
|
+
- `eslint-config-next/core-web-vitals` — base + CWV rules at error (**recommended default**).
|
|
40
|
+
- `eslint-config-next/typescript` — adds typescript-eslint rules; spread alongside a base.
|
|
41
|
+
|
|
42
|
+
## Gotchas
|
|
43
|
+
|
|
44
|
+
- **`globalIgnores([...])` is required** when you spread the config — re-assert the default
|
|
45
|
+
ignores (`.next/`, etc.) per the official docs example.
|
|
46
|
+
- **Monorepo**: point the plugin at the app with `settings: { next: { rootDir: "apps/web" } }`
|
|
47
|
+
(path, glob, or array).
|
|
48
|
+
- **Prettier**: add `import prettier from "eslint-config-prettier/flat"` last.
|
|
49
|
+
- `next lint` removal landed in Next 16.0.0 — old `.eslintrc.json` configs should migrate to
|
|
50
|
+
`eslint.config.mjs` (a codemod exists).
|
|
51
|
+
|
|
52
|
+
## CBP preset divergence
|
|
53
|
+
|
|
54
|
+
CBP's `nextjs` preset pins `eslint-config-next: ^15.0.0` and registers
|
|
55
|
+
`eslint-plugin-react-compiler` explicitly (see [react.md](react.md) — that plugin is now
|
|
56
|
+
**superseded**). The repo's own `apps/web/eslint.config.mjs` already uses the
|
|
57
|
+
`createRequire` + `eslint-config-next/core-web-vitals` + `eslint-config-next/typescript`
|
|
58
|
+
pattern. Adopt the native spread form above when regenerating; presets are not changed by
|
|
59
|
+
this skill.
|
|
60
|
+
|
|
61
|
+
## Official docs
|
|
62
|
+
|
|
63
|
+
- ESLint config: https://nextjs.org/docs/app/api-reference/config/eslint
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# node — Node/TypeScript service (Hono, Express, plain Node) flat config
|
|
2
|
+
|
|
3
|
+
For Node back-end services and server-side packages (the CBP MCP server uses Hono; any
|
|
4
|
+
`node-server` capability). Layers on [base](base.md). Maps to the CBP **`node`** DB preset
|
|
5
|
+
(`tech_match.requires: ["Node.js"]`, `requires_capabilities: ["node-server"]`).
|
|
6
|
+
|
|
7
|
+
> **Verified 2026-05-31.** The valuable async-safety rules (`no-floating-promises`,
|
|
8
|
+
> `no-misused-promises`) are **typescript-eslint** rules that need type info — they come from
|
|
9
|
+
> `recommendedTypeChecked`, not from a node plugin.
|
|
10
|
+
|
|
11
|
+
## Packages
|
|
12
|
+
|
|
13
|
+
| Package | Latest | Purpose |
|
|
14
|
+
| ------- | ------ | ------- |
|
|
15
|
+
| `globals` | `17.6.0` | `globals.node` |
|
|
16
|
+
| `typescript-eslint` | `8.60.0` | type-aware promise rules |
|
|
17
|
+
| `eslint-plugin-n` | `18.0.1` | **optional** — unsupported-Node-API / import / engines checks |
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add -D globals typescript-eslint
|
|
21
|
+
# optional (libraries / dual ESM-CJS packages):
|
|
22
|
+
pnpm add -D eslint-plugin-n
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Flat config
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
// eslint.config.mjs
|
|
29
|
+
import { defineConfig } from "eslint/config";
|
|
30
|
+
import js from "@eslint/js";
|
|
31
|
+
import tseslint from "typescript-eslint";
|
|
32
|
+
import globals from "globals";
|
|
33
|
+
// optional: import n from "eslint-plugin-n";
|
|
34
|
+
|
|
35
|
+
export default defineConfig([
|
|
36
|
+
js.configs.recommended,
|
|
37
|
+
...tseslint.configs.recommendedTypeChecked, // enables the promise rules below
|
|
38
|
+
{
|
|
39
|
+
files: ["**/*.{ts,mts,cts}"],
|
|
40
|
+
languageOptions: {
|
|
41
|
+
globals: globals.node,
|
|
42
|
+
sourceType: "module", // "commonjs" for a CJS service
|
|
43
|
+
parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname },
|
|
44
|
+
},
|
|
45
|
+
rules: {
|
|
46
|
+
"@typescript-eslint/no-floating-promises": "error",
|
|
47
|
+
"@typescript-eslint/no-misused-promises": "error",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
// optional eslint-plugin-n:
|
|
51
|
+
// { files: ["**/*.{ts,mts,cts}"], plugins: { n }, extends: ["n/recommended-module"] },
|
|
52
|
+
]);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Gotchas
|
|
56
|
+
|
|
57
|
+
- **`eslint-plugin-n` is optional.** For a pure internal TS service you can skip it — its main
|
|
58
|
+
value is catching unsupported Node APIs, missing imports, and `package.json#engines` issues
|
|
59
|
+
in **libraries** and dual ESM/CJS packages. Pick the right preset: `n/recommended-module`
|
|
60
|
+
(ESM), `n/recommended-script` (CJS), `n/recommended` (mixed).
|
|
61
|
+
- The promise rules **require** a type-checked config + `projectService` — they silently do
|
|
62
|
+
nothing without type info.
|
|
63
|
+
- A CJS service uses `sourceType: "commonjs"`; an ESM service uses `"module"`.
|
|
64
|
+
|
|
65
|
+
## CBP preset divergence
|
|
66
|
+
|
|
67
|
+
CBP's `node` preset ships only the two `@typescript-eslint` promise rules at `error` (no
|
|
68
|
+
`eslint-plugin-n`). The repo's MCP server / CLI configs follow this minimal shape. Add
|
|
69
|
+
`eslint-plugin-n` per-repo if you publish a library; the skill does not modify the preset.
|
|
70
|
+
|
|
71
|
+
## Official docs
|
|
72
|
+
|
|
73
|
+
- eslint-plugin-n: https://github.com/eslint-community/eslint-plugin-n
|
|
74
|
+
- no-floating-promises: https://typescript-eslint.io/rules/no-floating-promises/
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# react-native — React Native / Expo flat config
|
|
2
|
+
|
|
3
|
+
For Expo / React Native apps (the CBP `livebyplan` mobile app). **Gap stack — no CBP DB
|
|
4
|
+
preset.** Use Expo's official lint config.
|
|
5
|
+
|
|
6
|
+
> **Verified 2026-05-31.** `eslint-config-expo` is the official config and ships **flat config
|
|
7
|
+
> by default from Expo SDK 53** onward (SDK 52 and earlier use legacy `.eslintrc`).
|
|
8
|
+
|
|
9
|
+
## Packages
|
|
10
|
+
|
|
11
|
+
| Package | Latest | Purpose |
|
|
12
|
+
| ------- | ------ | ------- |
|
|
13
|
+
| `eslint-config-expo` | `56.0.4` | Expo's flat config (`/flat` subpath) |
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx expo lint # installs eslint + eslint-config-expo and scaffolds eslint.config.js
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`eslint-config-expo` bundles `eslint-plugin-expo`, `eslint-plugin-react`,
|
|
20
|
+
`eslint-plugin-react-hooks`, `eslint-plugin-import`, and `@typescript-eslint/*`. It does **not**
|
|
21
|
+
bundle `eslint-plugin-react-native` (that's a separate optional add-on, `@5.0.0`).
|
|
22
|
+
|
|
23
|
+
## Flat config
|
|
24
|
+
|
|
25
|
+
Expo's template is **CommonJS `eslint.config.js`** (not `.mjs`):
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
// eslint.config.js
|
|
29
|
+
const { defineConfig } = require("eslint/config");
|
|
30
|
+
const expoConfig = require("eslint-config-expo/flat");
|
|
31
|
+
const eslintPluginPrettierRecommended = require("eslint-plugin-prettier/recommended");
|
|
32
|
+
|
|
33
|
+
module.exports = defineConfig([
|
|
34
|
+
expoConfig,
|
|
35
|
+
eslintPluginPrettierRecommended,
|
|
36
|
+
{ ignores: ["dist/*"] },
|
|
37
|
+
]);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Minimal form (no Prettier): just `expoConfig` in the array.
|
|
41
|
+
|
|
42
|
+
## Gotchas
|
|
43
|
+
|
|
44
|
+
- RN platform support comes from RN global variables + platform file extensions
|
|
45
|
+
(`.android.ts`, `.ios.ts`, `.web.ts`) and `eslint-plugin-expo` — **not** from
|
|
46
|
+
`eslint-plugin-react-native`. Add `eslint-plugin-react-native@5.0.0` manually only if you
|
|
47
|
+
want RN-specific rules (`no-inline-styles`, `no-unused-styles`).
|
|
48
|
+
- Run linting with `npx expo lint` (it wires the config the first time).
|
|
49
|
+
- Expo apps test with **Jest** — add the [jest.md](jest.md) override.
|
|
50
|
+
|
|
51
|
+
## CBP preset divergence
|
|
52
|
+
|
|
53
|
+
There is **no** CBP `react-native`/`expo` DB preset, and the `react` preset `excludes`
|
|
54
|
+
nothing for RN but is browser-globals oriented. Use `eslint-config-expo/flat` directly; the
|
|
55
|
+
skill does not add a preset for this stack.
|
|
56
|
+
|
|
57
|
+
## Official docs
|
|
58
|
+
|
|
59
|
+
- Using ESLint in Expo: https://docs.expo.dev/guides/using-eslint/
|
|
60
|
+
- eslint-config-expo: https://github.com/expo/expo/tree/main/packages/eslint-config-expo
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# react — standalone React (Vite, Tauri) flat config
|
|
2
|
+
|
|
3
|
+
For React apps that are **not** Next.js (Vite SPA, Tauri desktop webview). Layers on
|
|
4
|
+
[base](base.md). Maps to the CBP **`react`** DB preset
|
|
5
|
+
(`tech_match.requires: ["React"]`, `excludes: ["Next.js"]`, `requires_capabilities: ["jsx"]`).
|
|
6
|
+
|
|
7
|
+
> **Verified 2026-05-31.** **Do NOT install `eslint-plugin-react-compiler`** — it is
|
|
8
|
+
> superseded. React Compiler v1.0 (Oct 2025) merged the compiler lint rules into
|
|
9
|
+
> **`eslint-plugin-react-hooks@7`** under `configs.flat["recommended-latest"]`.
|
|
10
|
+
|
|
11
|
+
## Packages
|
|
12
|
+
|
|
13
|
+
| Package | Latest | Purpose |
|
|
14
|
+
| ------- | ------ | ------- |
|
|
15
|
+
| `eslint-plugin-react` | `7.37.5` | React rules + JSX parsing (`configs.flat.*`) |
|
|
16
|
+
| `eslint-plugin-react-hooks` | `7.1.1` | hooks rules **+ bundled React Compiler rules** |
|
|
17
|
+
| `eslint-plugin-jsx-a11y` | `6.10.2` | accessibility (`flatConfigs.*` — note plural) |
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add -D eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y globals
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Flat config
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
// eslint.config.mjs
|
|
27
|
+
import { defineConfig } from "eslint/config";
|
|
28
|
+
import react from "eslint-plugin-react";
|
|
29
|
+
import reactHooks from "eslint-plugin-react-hooks";
|
|
30
|
+
import jsxA11y from "eslint-plugin-jsx-a11y";
|
|
31
|
+
import globals from "globals";
|
|
32
|
+
|
|
33
|
+
export default defineConfig([
|
|
34
|
+
react.configs.flat.recommended, // namespaced react/, enables JSX parsing
|
|
35
|
+
react.configs.flat["jsx-runtime"], // React 17+ automatic JSX transform
|
|
36
|
+
reactHooks.configs.flat["recommended-latest"], // hooks + React Compiler rules
|
|
37
|
+
jsxA11y.flatConfigs.strict, // or flatConfigs.recommended
|
|
38
|
+
{
|
|
39
|
+
files: ["**/*.{js,jsx,ts,tsx}"],
|
|
40
|
+
languageOptions: { globals: globals.browser },
|
|
41
|
+
settings: { react: { version: "detect" } },
|
|
42
|
+
},
|
|
43
|
+
]);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Gotchas
|
|
47
|
+
|
|
48
|
+
- **`eslint-plugin-react` flat configs do not set `files` or globals** — add your own
|
|
49
|
+
`files`/`globals.browser`/`settings.react.version` object (shown above) or you'll get the
|
|
50
|
+
"React version not specified" warning and no JSX globals.
|
|
51
|
+
- **`eslint-plugin-react-hooks` v7 keys** live under `configs.flat.*`:
|
|
52
|
+
`recommended` (standard hooks) vs `recommended-latest` (hooks **+ compiler** rules — use
|
|
53
|
+
this for React 19 + the compiler).
|
|
54
|
+
- **`jsx-a11y` uses `flatConfigs` (plural)** — `jsxA11y.flatConfigs.strict`, a different
|
|
55
|
+
namespace from react's `configs.flat`.
|
|
56
|
+
|
|
57
|
+
## Storybook (bonus)
|
|
58
|
+
|
|
59
|
+
If the app uses Storybook, add `eslint-plugin-storybook@10.4.1`:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
import storybook from "eslint-plugin-storybook";
|
|
63
|
+
// ...spread into the array:
|
|
64
|
+
...storybook.configs["flat/recommended"],
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The standalone plugin repo was archived (2025-11); it now lives in the Storybook monorepo but
|
|
68
|
+
the npm name `eslint-plugin-storybook` is unchanged.
|
|
69
|
+
|
|
70
|
+
## CBP preset divergence
|
|
71
|
+
|
|
72
|
+
CBP's `react` preset still depends on `eslint-plugin-react-compiler: ^19.0.0` and registers
|
|
73
|
+
`react-compiler/react-compiler`. The latest guidance removes that plugin and relies on
|
|
74
|
+
`eslint-plugin-react-hooks@7`'s `recommended-latest`. Adopt that when regenerating; the skill
|
|
75
|
+
does not modify the preset.
|
|
76
|
+
|
|
77
|
+
## Official docs
|
|
78
|
+
|
|
79
|
+
- eslint-plugin-react: https://github.com/jsx-eslint/eslint-plugin-react
|
|
80
|
+
- react-hooks: https://react.dev/reference/eslint-plugin-react-hooks
|
|
81
|
+
- React Compiler v1.0: https://react.dev/blog/2025/10/07/react-compiler-1
|
|
82
|
+
- jsx-a11y: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
|