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.
Files changed (30) hide show
  1. package/dist/cli.js +50 -71
  2. package/package.json +1 -1
  3. package/templates/hooks/README.md +1 -13
  4. package/templates/hooks/cbp-test-coverage-gate.sh +8 -0
  5. package/templates/hooks/cbp-test-hooks.sh +0 -42
  6. package/templates/hooks/hooks.json +0 -9
  7. package/templates/skills/cbp-checkpoint-start/SKILL.md +2 -2
  8. package/templates/skills/cbp-session-start/SKILL.md +1 -1
  9. package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/SKILL.md +1 -1
  10. package/templates/skills/cbp-setup-eslint/SKILL.md +199 -0
  11. package/templates/skills/cbp-setup-eslint/reference/base.md +82 -0
  12. package/templates/skills/cbp-setup-eslint/reference/cli.md +56 -0
  13. package/templates/skills/cbp-setup-eslint/reference/e2e.md +68 -0
  14. package/templates/skills/cbp-setup-eslint/reference/jest.md +59 -0
  15. package/templates/skills/cbp-setup-eslint/reference/nestjs.md +69 -0
  16. package/templates/skills/cbp-setup-eslint/reference/nextjs.md +63 -0
  17. package/templates/skills/cbp-setup-eslint/reference/node.md +74 -0
  18. package/templates/skills/cbp-setup-eslint/reference/react-native.md +60 -0
  19. package/templates/skills/cbp-setup-eslint/reference/react.md +82 -0
  20. package/templates/skills/cbp-setup-eslint/reference/tailwind.md +64 -0
  21. package/templates/skills/cbp-setup-eslint/reference/testing-react.md +57 -0
  22. package/templates/skills/cbp-setup-eslint/reference/vitest.md +62 -0
  23. package/templates/skills/cbp-task-complete/SKILL.md +1 -3
  24. package/templates/skills/cbp-task-start/SKILL.md +3 -3
  25. package/templates/hooks/cbp-mcp-worktree-inject.sh +0 -76
  26. /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/maestro.md +0 -0
  27. /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/playwright.md +0 -0
  28. /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/tauri.md +0 -0
  29. /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/vscode.md +0 -0
  30. /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