{"owner":"sidorares","repo":"node-mysql2","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# MySQL2 — Agent Instructions\n\nYou are an expert Node.js developer contributing to MySQL2, a high-performance MySQL driver focused on compatibility.\n\n## Project\n\n- Minimum compatibility: **Node 14**, whatever the `engines` field in `package.json` declares.\n- Core: `/lib`, exposed through `index.js` (callback) and `promise.js` (promise-based).\n- Types: `/typings` (`.d.ts` files), exposed through `index.d.ts` (callback) and `promise.d.ts` (promise-based).\n- Documentation: `website/docs/` (Docusaurus).\n- Tests:\n  - Unit: `test/unit`, parallel.\n  - Integration: `test/integration`, parallel, alongside the unit tests.\n  - Global: `test/global`, sequential, for tests that change MySQL Server global state and need careful cleanup.\n\n---\n\n## Skills\n\n- Use the [`/lagune` skill](.claude/skills/lagune/SKILL.md) whenever you build or change code, so it improves safety by default. When it is not available, install it from its manifest with `npx -y lagune@latest pull`.\n- Read the [code review skill](.github/skills/code-review/SKILL.md) before reviewing a pull request, a diff, or a branch.\n- Use the [`/types` skill](.claude/skills/types/SKILL.md) when working on `/typings` or fixing a type error in a test.\n\n---\n\n## Comments\n\nNever add an obvious comment nor narrate a statement: code that needs a comment to be understood is usually poorly implemented, and comment length measures how bad the code underneath it is.\n\nWhen code feels like it needs an explanation, improve the implementation instead: clear names, decoupled functions with a defined scope, and proper abstractions.\n\n---\n\n## Tests\n\n**Read `test/common.test.mts` before writing any test.** It provides the shared helpers for creating connections, pools, clusters, and servers, and for reading the test configuration.\n\nThe test runner is **Poku** ([docs](https://poku.io/docs), [repo](https://github.com/wellwelwel/poku)). Test files use `.mts` (ESM TypeScript) and support top-level `await`.\n\nAssertions, utilities, and test structure come from Poku:\n\n```ts\nimport { describe, it, assert, skip, sleep, strict } from 'poku';\n```\n\n- `skip` skips the entire test file and reports it, for cases like a Deno-only test or a specific Node version.\n- `sleep` waits for a given duration: `await sleep(100)`.\n\n| File                      | Description                                                         |\n| ------------------------- | ------------------------------------------------------------------- |\n| `test/common.test.mts`    | Shared helpers                                                      |\n| `poku.config.js`          | Poku config: parallel/sequential suites, timeouts, test directories |\n| `test/docker-compose.yml` | Local environment with MySQL, Node, Deno, Bun, and coverage         |\n\n```sh\nnpm run typecheck\nnpm run lint:fix\nFILTER=test/unit/my-test.mts npx poku    # run a single file through Poku\nnpx tsx test/unit/my-test.mts            # run a single file directly\n```\n\n### Connection scope and resource cleanup\n\nNever close the connection in the same scope as an assertion that may fail. When the assertion throws, `end()` is never reached and the process hangs indefinitely.\n\nOpen and close the connection in an outer scope:\n\n```ts\n// ❌ Wrong: end() sits in the same scope as the assertion\nawait describe('test', async () => {\n  await it('should do something', async () => {\n    const connection = await createConnection(); // same for pool or cluster connections\n    assert(false);\n    await connection.end(); // never reached\n  });\n  // process hangs\n});\n\n// ❌ Wrong: try-finally is a workaround, not a fix\nawait describe('test', async () => {\n  await it('should do something', async () => {\n    const connection = await createConnection();\n    try {\n      assert(false);\n    } finally {\n      await connection.end();\n    }\n  });\n  // process hangs\n});\n\n// ✅ Correct: end() in an outer scope\nawait describe('test', async () => {\n  const connection = await createConnection();\n\n  it('should do something', () => {\n    assert(false); // fails in its own scope\n  });\n\n  await connection.end(); // always reached\n});\n```\n\n- Every teardown method and every connection type is affected: `close`, `end`, `destroy`, `release`, on `Connection`, `Pool`, `PoolCluster`, and the rest.\n- Use nested or dedicated `describe` blocks to isolate each connection.\n- Callbacks fail the same way, with the teardown buried in a nested callback that a failing assertion prevents from ever running.\n\nPrefer `await conn.promise().end()` instead of wrapping callbacks in `new Promise`:\n\n```ts\n// ❌ Avoid\nawait new Promise<void>((resolve) => pool.end(() => resolve()));\n\n// ✅ Prefer\nawait pool.promise().end();\n```\n\n### Avoid timer-dependent tests\n\nNever wait on an internal timer, such as idle connection cleanup, with `setTimeout` or `sleep`. Execution timing in CI is unpredictable and the test turns flaky. Call the internal method directly, or assert the state synchronously right after the action. When the timer behavior itself is what needs coverage, isolate it so no assertion depends on wall-clock timing.\n\n### `async`/`await`\n\nPoku treats `async`/`await` just like standard JavaScript, so `describe`, `it`, and `test` are awaited **only** when the callback is asynchronous.\n\n**Asynchronous:**\n\n```ts\nawait describe('test', async () => {\n  const connection = createConnection().promise();\n\n  await it('should do something', async () => {\n    const result = await connection.query('SELECT 1');\n\n    assert(result);\n  });\n\n  await connection.end();\n});\n```\n\n**Synchronous:**\n\n```ts\ndescribe('test', () => {\n  it('should do something', () => {\n    strict.equal(1 + 1, 2);\n  });\n});\n```\n\n### Prefer promise-based API\n\nNew tests prefer the promise-based API through `.promise()`. Callbacks stay for events, streams, anything the promise API does not cover, and features that genuinely need coverage in both modes.\n\n> A recommendation, not a strict rule.\n\n```ts\nconst connection = createConnection({/* ... */}).promise();\nconst pool = createPool({/* ... */}).promise();\n\nconst cluster = createPoolCluster({/* ... */});\ncluster.add('node1', {/* ... */});\nconst clusterConnection = await cluster.promise().getConnection();\n```\n\n### TypeScript in tests\n\nNever use `as unknown as` or `any` in test files.\n\nWhen reaching for an internal that the public typings do not expose, use exactly:\n\n```ts\n// @ts-expect-error: internal access\n```\n\nWhen a type in `typings/` is wrong or missing and the contribution has no relation to that type, use exactly:\n\n```ts\n// @ts-expect-error: TODO: implement typings\n```\n\nIf the type error **is** related to the contribution, fix the type in `typings/` instead of suppressing it.\n\n---\n\n## Cursor Cloud specific instructions\n\nMySQL2 is a **library**, not a long-running app. Development means installing the Node dependencies, starting MySQL for the integration tests, then running lint, typecheck, and tests against the driver.\n\n### Services\n\n| Service                          | Required?          | Notes                                                         |\n| -------------------------------- | ------------------ | ------------------------------------------------------------- |\n| **Node.js** (14 or later, CI 22) | Yes                | `npm ci` at repo root                                         |\n| **MySQL**                        | Yes for full tests | Integration and global tests need a `test` database           |\n| **Docker**                       | Recommended        | Runs MySQL the same way as CI                                 |\n| **Docusaurus** (`website/`)      | Optional           | `cd website && npm ci && npm start`, on http://localhost:3000 |\n\n### MySQL via Docker\n\nDocker is installed on the VM, but the daemon may need a manual start when systemd is not active:\n\n```sh\nsudo dockerd > /tmp/dockerd.log 2>&1 &\n```\n\nStart MySQL, which creates the `test` database with an empty root password:\n\n```sh\nsudo docker compose -f test/docker-compose.yml up -d mysql\nnode tools/wait-up.js\n```\n\nUse `sudo docker` when the socket permission error appears. CI pins **MySQL 8.3** (`mysql:8.3`), while `test/docker-compose.yml` uses `mysql:lts`, currently 9.x. For full CI parity, run:\n\n```sh\nsudo docker run -d --name mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=1 -e MYSQL_DATABASE=test -p 3306:3306 mysql:8.3\n```\n\nWithout `CI=1`, tests use an empty root password, matching docker-compose. With `CI=1`, set `MYSQL_PASSWORD=root`.\n\n### Commands\n\nSee `package.json` and `Contributing.md` for the full set.\n\n| Task        | Command                                            |\n| ----------- | -------------------------------------------------- |\n| Lint        | `npm run lint`                                     |\n| Typecheck   | `npm run typecheck`                                |\n| Tests       | `npm test` (or `FILTER=path/to/test.mts npx poku`) |\n| Build check | `npm run test:build`                               |\n| Website     | `cd website && npm ci && npm test`                 |\n\n`test/global` runs sequentially and needs elevated MySQL privileges. Poku skips those files when `hasPrivileges()` fails, so a green local run does not prove they were exercised.\n"},"files":{"CLAUDE.md":"# MySQL2 — Agent Instructions\n\nYou are an expert Node.js developer contributing to MySQL2, a high-performance MySQL driver focused on compatibility.\n\n## Project\n\n- Minimum compatibility: **Node 14**, whatever the `engines` field in `package.json` declares.\n- Core: `/lib`, exposed through `index.js` (callback) and `promise.js` (promise-based).\n- Types: `/typings` (`.d.ts` files), exposed through `index.d.ts` (callback) and `promise.d.ts` (promise-based).\n- Documentation: `website/docs/` (Docusaurus).\n- Tests:\n  - Unit: `test/unit`, parallel.\n  - Integration: `test/integration`, parallel, alongside the unit tests.\n  - Global: `test/global`, sequential, for tests that change MySQL Server global state and need careful cleanup.\n\n---\n\n## Skills\n\n- Use the [`/lagune` skill](.claude/skills/lagune/SKILL.md) whenever you build or change code, so it improves safety by default. When it is not available, install it from its manifest with `npx -y lagune@latest pull`.\n- Read the [code review skill](.github/skills/code-review/SKILL.md) before reviewing a pull request, a diff, or a branch.\n- Use the [`/types` skill](.claude/skills/types/SKILL.md) when working on `/typings` or fixing a type error in a test.\n\n---\n\n## Comments\n\nNever add an obvious comment nor narrate a statement: code that needs a comment to be understood is usually poorly implemented, and comment length measures how bad the code underneath it is.\n\nWhen code feels like it needs an explanation, improve the implementation instead: clear names, decoupled functions with a defined scope, and proper abstractions.\n\n---\n\n## Tests\n\n**Read `test/common.test.mts` before writing any test.** It provides the shared helpers for creating connections, pools, clusters, and servers, and for reading the test configuration.\n\nThe test runner is **Poku** ([docs](https://poku.io/docs), [repo](https://github.com/wellwelwel/poku)). Test files use `.mts` (ESM TypeScript) and support top-level `await`.\n\nAssertions, utilities, and test structure come from Poku:\n\n```ts\nimport { describe, it, assert, skip, sleep, strict } from 'poku';\n```\n\n- `skip` skips the entire test file and reports it, for cases like a Deno-only test or a specific Node version.\n- `sleep` waits for a given duration: `await sleep(100)`.\n\n| File                      | Description                                                         |\n| ------------------------- | ------------------------------------------------------------------- |\n| `test/common.test.mts`    | Shared helpers                                                      |\n| `poku.config.js`          | Poku config: parallel/sequential suites, timeouts, test directories |\n| `test/docker-compose.yml` | Local environment with MySQL, Node, Deno, Bun, and coverage         |\n\n```sh\nnpm run typecheck\nnpm run lint:fix\nFILTER=test/unit/my-test.mts npx poku    # run a single file through Poku\nnpx tsx test/unit/my-test.mts            # run a single file directly\n```\n\n### Connection scope and resource cleanup\n\nNever close the connection in the same scope as an assertion that may fail. When the assertion throws, `end()` is never reached and the process hangs indefinitely.\n\nOpen and close the connection in an outer scope:\n\n```ts\n// ❌ Wrong: end() sits in the same scope as the assertion\nawait describe('test', async () => {\n  await it('should do something', async () => {\n    const connection = await createConnection(); // same for pool or cluster connections\n    assert(false);\n    await connection.end(); // never reached\n  });\n  // process hangs\n});\n\n// ❌ Wrong: try-finally is a workaround, not a fix\nawait describe('test', async () => {\n  await it('should do something', async () => {\n    const connection = await createConnection();\n    try {\n      assert(false);\n    } finally {\n      await connection.end();\n    }\n  });\n  // process hangs\n});\n\n// ✅ Correct: end() in an outer scope\nawait describe('test', async () => {\n  const connection = await createConnection();\n\n  it('should do something', () => {\n    assert(false); // fails in its own scope\n  });\n\n  await connection.end(); // always reached\n});\n```\n\n- Every teardown method and every connection type is affected: `close`, `end`, `destroy`, `release`, on `Connection`, `Pool`, `PoolCluster`, and the rest.\n- Use nested or dedicated `describe` blocks to isolate each connection.\n- Callbacks fail the same way, with the teardown buried in a nested callback that a failing assertion prevents from ever running.\n\nPrefer `await conn.promise().end()` instead of wrapping callbacks in `new Promise`:\n\n```ts\n// ❌ Avoid\nawait new Promise<void>((resolve) => pool.end(() => resolve()));\n\n// ✅ Prefer\nawait pool.promise().end();\n```\n\n### Avoid timer-dependent tests\n\nNever wait on an internal timer, such as idle connection cleanup, with `setTimeout` or `sleep`. Execution timing in CI is unpredictable and the test turns flaky. Call the internal method directly, or assert the state synchronously right after the action. When the timer behavior itself is what needs coverage, isolate it so no assertion depends on wall-clock timing.\n\n### `async`/`await`\n\nPoku treats `async`/`await` just like standard JavaScript, so `describe`, `it`, and `test` are awaited **only** when the callback is asynchronous.\n\n**Asynchronous:**\n\n```ts\nawait describe('test', async () => {\n  const connection = createConnection().promise();\n\n  await it('should do something', async () => {\n    const result = await connection.query('SELECT 1');\n\n    assert(result);\n  });\n\n  await connection.end();\n});\n```\n\n**Synchronous:**\n\n```ts\ndescribe('test', () => {\n  it('should do something', () => {\n    strict.equal(1 + 1, 2);\n  });\n});\n```\n\n### Prefer promise-based API\n\nNew tests prefer the promise-based API through `.promise()`. Callbacks stay for events, streams, anything the promise API does not cover, and features that genuinely need coverage in both modes.\n\n> A recommendation, not a strict rule.\n\n```ts\nconst connection = createConnection({/* ... */}).promise();\nconst pool = createPool({/* ... */}).promise();\n\nconst cluster = createPoolCluster({/* ... */});\ncluster.add('node1', {/* ... */});\nconst clusterConnection = await cluster.promise().getConnection();\n```\n\n### TypeScript in tests\n\nNever use `as unknown as` or `any` in test files.\n\nWhen reaching for an internal that the public typings do not expose, use exactly:\n\n```ts\n// @ts-expect-error: internal access\n```\n\nWhen a type in `typings/` is wrong or missing and the contribution has no relation to that type, use exactly:\n\n```ts\n// @ts-expect-error: TODO: implement typings\n```\n\nIf the type error **is** related to the contribution, fix the type in `typings/` instead of suppressing it.\n\n---\n\n## Cursor Cloud specific instructions\n\nMySQL2 is a **library**, not a long-running app. Development means installing the Node dependencies, starting MySQL for the integration tests, then running lint, typecheck, and tests against the driver.\n\n### Services\n\n| Service                          | Required?          | Notes                                                         |\n| -------------------------------- | ------------------ | ------------------------------------------------------------- |\n| **Node.js** (14 or later, CI 22) | Yes                | `npm ci` at repo root                                         |\n| **MySQL**                        | Yes for full tests | Integration and global tests need a `test` database           |\n| **Docker**                       | Recommended        | Runs MySQL the same way as CI                                 |\n| **Docusaurus** (`website/`)      | Optional           | `cd website && npm ci && npm start`, on http://localhost:3000 |\n\n### MySQL via Docker\n\nDocker is installed on the VM, but the daemon may need a manual start when systemd is not active:\n\n```sh\nsudo dockerd > /tmp/dockerd.log 2>&1 &\n```\n\nStart MySQL, which creates the `test` database with an empty root password:\n\n```sh\nsudo docker compose -f test/docker-compose.yml up -d mysql\nnode tools/wait-up.js\n```\n\nUse `sudo docker` when the socket permission error appears. CI pins **MySQL 8.3** (`mysql:8.3`), while `test/docker-compose.yml` uses `mysql:lts`, currently 9.x. For full CI parity, run:\n\n```sh\nsudo docker run -d --name mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=1 -e MYSQL_DATABASE=test -p 3306:3306 mysql:8.3\n```\n\nWithout `CI=1`, tests use an empty root password, matching docker-compose. With `CI=1`, set `MYSQL_PASSWORD=root`.\n\n### Commands\n\nSee `package.json` and `Contributing.md` for the full set.\n\n| Task        | Command                                            |\n| ----------- | -------------------------------------------------- |\n| Lint        | `npm run lint`                                     |\n| Typecheck   | `npm run typecheck`                                |\n| Tests       | `npm test` (or `FILTER=path/to/test.mts npx poku`) |\n| Build check | `npm run test:build`                               |\n| Website     | `cd website && npm ci && npm test`                 |\n\n`test/global` runs sequentially and needs elevated MySQL privileges. Poku skips those files when `hasPrivileges()` fails, so a green local run does not prove they were exercised.\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# MySQL2 — Agent Instructions\n\nYou are an expert Node.js developer contributing to MySQL2, a high-performance MySQL driver focused on compatibility.\n\n## Project\n\n- Minimum compatibility: **Node 14**, whatever the `engines` field in `package.json` declares.\n- Core: `/lib`, exposed through `index.js` (callback) and `promise.js` (promise-based).\n- Types: `/typings` (`.d.ts` files), exposed through `index.d.ts` (callback) and `promise.d.ts` (promise-based).\n- Documentation: `website/docs/` (Docusaurus).\n- Tests:\n  - Unit: `test/unit`, parallel.\n  - Integration: `test/integration`, parallel, alongside the unit tests.\n  - Global: `test/global`, sequential, for tests that change MySQL Server global state and need careful cleanup.\n\n---\n\n## Skills\n\n- Use the [`/lagune` skill](.claude/skills/lagune/SKILL.md) whenever you build or change code, so it improves safety by default. When it is not available, install it from its manifest with `npx -y lagune@latest pull`.\n- Read the [code review skill](.github/skills/code-review/SKILL.md) before reviewing a pull request, a diff, or a branch.\n- Use the [`/types` skill](.claude/skills/types/SKILL.md) when working on `/typings` or fixing a type error in a test.\n\n---\n\n## Comments\n\nNever add an obvious comment nor narrate a statement: code that needs a comment to be understood is usually poorly implemented, and comment length measures how bad the code underneath it is.\n\nWhen code feels like it needs an explanation, improve the implementation instead: clear names, decoupled functions with a defined scope, and proper abstractions.\n\n---\n\n## Tests\n\n**Read `test/common.test.mts` before writing any test.** It provides the shared helpers for creating connections, pools, clusters, and servers, and for reading the test configuration.\n\nThe test runner is **Poku** ([docs](https://poku.io/docs), [repo](https://github.com/wellwelwel/poku)). Test files use `.mts` (ESM TypeScript) and support top-level `await`.\n\nAssertions, utilities, and test structure come from Poku:\n\n```ts\nimport { describe, it, assert, skip, sleep, strict } from 'poku';\n```\n\n- `skip` skips the entire test file and reports it, for cases like a Deno-only test or a specific Node version.\n- `sleep` waits for a given duration: `await sleep(100)`.\n\n| File                      | Description                                                         |\n| ------------------------- | ------------------------------------------------------------------- |\n| `test/common.test.mts`    | Shared helpers                                                      |\n| `poku.config.js`          | Poku config: parallel/sequential suites, timeouts, test directories |\n| `test/docker-compose.yml` | Local environment with MySQL, Node, Deno, Bun, and coverage         |\n\n```sh\nnpm run typecheck\nnpm run lint:fix\nFILTER=test/unit/my-test.mts npx poku    # run a single file through Poku\nnpx tsx test/unit/my-test.mts            # run a single file directly\n```\n\n### Connection scope and resource cleanup\n\nNever close the connection in the same scope as an assertion that may fail. When the assertion throws, `end()` is never reached and the process hangs indefinitely.\n\nOpen and close the connection in an outer scope:\n\n```ts\n// ❌ Wrong: end() sits in the same scope as the assertion\nawait describe('test', async () => {\n  await it('should do something', async () => {\n    const connection = await createConnection(); // same for pool or cluster connections\n    assert(false);\n    await connection.end(); // never reached\n  });\n  // process hangs\n});\n\n// ❌ Wrong: try-finally is a workaround, not a fix\nawait describe('test', async () => {\n  await it('should do something', async () => {\n    const connection = await createConnection();\n    try {\n      assert(false);\n    } finally {\n      await connection.end();\n    }\n  });\n  // process hangs\n});\n\n// ✅ Correct: end() in an outer scope\nawait describe('test', async () => {\n  const connection = await createConnection();\n\n  it('should do something', () => {\n    assert(false); // fails in its own scope\n  });\n\n  await connection.end(); // always reached\n});\n```\n\n- Every teardown method and every connection type is affected: `close`, `end`, `destroy`, `release`, on `Connection`, `Pool`, `PoolCluster`, and the rest.\n- Use nested or dedicated `describe` blocks to isolate each connection.\n- Callbacks fail the same way, with the teardown buried in a nested callback that a failing assertion prevents from ever running.\n\nPrefer `await conn.promise().end()` instead of wrapping callbacks in `new Promise`:\n\n```ts\n// ❌ Avoid\nawait new Promise<void>((resolve) => pool.end(() => resolve()));\n\n// ✅ Prefer\nawait pool.promise().end();\n```\n\n### Avoid timer-dependent tests\n\nNever wait on an internal timer, such as idle connection cleanup, with `setTimeout` or `sleep`. Execution timing in CI is unpredictable and the test turns flaky. Call the internal method directly, or assert the state synchronously right after the action. When the timer behavior itself is what needs coverage, isolate it so no assertion depends on wall-clock timing.\n\n### `async`/`await`\n\nPoku treats `async`/`await` just like standard JavaScript, so `describe`, `it`, and `test` are awaited **only** when the callback is asynchronous.\n\n**Asynchronous:**\n\n```ts\nawait describe('test', async () => {\n  const connection = createConnection().promise();\n\n  await it('should do something', async () => {\n    const result = await connection.query('SELECT 1');\n\n    assert(result);\n  });\n\n  await connection.end();\n});\n```\n\n**Synchronous:**\n\n```ts\ndescribe('test', () => {\n  it('should do something', () => {\n    strict.equal(1 + 1, 2);\n  });\n});\n```\n\n### Prefer promise-based API\n\nNew tests prefer the promise-based API through `.promise()`. Callbacks stay for events, streams, anything the promise API does not cover, and features that genuinely need coverage in both modes.\n\n> A recommendation, not a strict rule.\n\n```ts\nconst connection = createConnection({/* ... */}).promise();\nconst pool = createPool({/* ... */}).promise();\n\nconst cluster = createPoolCluster({/* ... */});\ncluster.add('node1', {/* ... */});\nconst clusterConnection = await cluster.promise().getConnection();\n```\n\n### TypeScript in tests\n\nNever use `as unknown as` or `any` in test files.\n\nWhen reaching for an internal that the public typings do not expose, use exactly:\n\n```ts\n// @ts-expect-error: internal access\n```\n\nWhen a type in `typings/` is wrong or missing and the contribution has no relation to that type, use exactly:\n\n```ts\n// @ts-expect-error: TODO: implement typings\n```\n\nIf the type error **is** related to the contribution, fix the type in `typings/` instead of suppressing it.\n\n---\n\n## Cursor Cloud specific instructions\n\nMySQL2 is a **library**, not a long-running app. Development means installing the Node dependencies, starting MySQL for the integration tests, then running lint, typecheck, and tests against the driver.\n\n### Services\n\n| Service                          | Required?          | Notes                                                         |\n| -------------------------------- | ------------------ | ------------------------------------------------------------- |\n| **Node.js** (14 or later, CI 22) | Yes                | `npm ci` at repo root                                         |\n| **MySQL**                        | Yes for full tests | Integration and global tests need a `test` database           |\n| **Docker**                       | Recommended        | Runs MySQL the same way as CI                                 |\n| **Docusaurus** (`website/`)      | Optional           | `cd website && npm ci && npm start`, on http://localhost:3000 |\n\n### MySQL via Docker\n\nDocker is installed on the VM, but the daemon may need a manual start when systemd is not active:\n\n```sh\nsudo dockerd > /tmp/dockerd.log 2>&1 &\n```\n\nStart MySQL, which creates the `test` database with an empty root password:\n\n```sh\nsudo docker compose -f test/docker-compose.yml up -d mysql\nnode tools/wait-up.js\n```\n\nUse `sudo docker` when the socket permission error appears. CI pins **MySQL 8.3** (`mysql:8.3`), while `test/docker-compose.yml` uses `mysql:lts`, currently 9.x. For full CI parity, run:\n\n```sh\nsudo docker run -d --name mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=1 -e MYSQL_DATABASE=test -p 3306:3306 mysql:8.3\n```\n\nWithout `CI=1`, tests use an empty root password, matching docker-compose. With `CI=1`, set `MYSQL_PASSWORD=root`.\n\n### Commands\n\nSee `package.json` and `Contributing.md` for the full set.\n\n| Task        | Command                                            |\n| ----------- | -------------------------------------------------- |\n| Lint        | `npm run lint`                                     |\n| Typecheck   | `npm run typecheck`                                |\n| Tests       | `npm test` (or `FILTER=path/to/test.mts npx poku`) |\n| Build check | `npm run test:build`                               |\n| Website     | `cd website && npm ci && npm test`                 |\n\n`test/global` runs sequentially and needs elevated MySQL privileges. Poku skips those files when `hasPrivileges()` fails, so a green local run does not prove they were exercised.\n","category":"root","tokens":2294}]}