{"owner":"harlan-zw","repo":"unlighthouse","hasSkills":true,"totalSkillsCount":7,"totalTokensCount":4237,"categories":["plugin-manifest","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["packages/cli/README.md","packages/client/README.md","packages/core/README.md","packages/server/README.md","packages/unlighthouse-ci/README.md","packages/unlighthouse/README.md","packages/unlighthouse/skills/unlighthouse/SKILL.md"],"skills":{"packages/cli/README.md":"# @unlighthouse/cli\n\nThe command-line interface and CI integration for [Unlighthouse](https://github.com/harlan-zw/unlighthouse), enabling automated website scanning in development and deployment workflows.\n\n## Installation\n\n```bash\n# Use directly with npx\nnpx unlighthouse --site https://example.com\n\n# Or install globally\nnpm install -g @unlighthouse/cli\n```\n\n## Usage\n\n### Basic Scanning\n\n```bash\n# Scan a website\nunlighthouse --site https://example.com\n\n# Enable debug mode\nunlighthouse --site https://example.com --debug\n\n# Mobile device simulation\nunlighthouse --site https://example.com --mobile\n```\n\n### Advanced Options\n\n```bash\n# Multiple samples with throttling\nunlighthouse --site https://example.com --samples 3 --throttle\n\n# Custom URLs and exclusions\nunlighthouse --site https://example.com --urls /home,/about,/contact --exclude-urls '/admin/**'\n\n# With custom configuration\nunlighthouse --site https://example.com --config-file ./my-config.ts\n```\n\n### CI Integration\n\n```bash\n# CI mode with exit codes for failed audits\nunlighthouse-ci --site https://example.com --budget 75\n```\n\n## Configuration\n\nCreate `unlighthouse.config.ts` in your project root:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  debug: true,\n  scanner: {\n    device: 'desktop',\n    throttle: false,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility'],\n  }\n})\n```\n\n## Documentation\n\n- [CLI Integration Guide](https://unlighthouse.dev/integrations/cli.html)\n- [CI Integration Guide](https://unlighthouse.dev/integrations/ci.html)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/client/README.md":"# @unlighthouse/client\n\nThe Vue-based user interface for [Unlighthouse](https://github.com/harlan-zw/unlighthouse), providing an interactive dashboard to view and analyze Lighthouse scan results.\n\n## Features\n\n- Interactive dashboard with performance metrics\n- Real-time scan progress tracking\n- Detailed Lighthouse reports per page\n- Performance charts and visualizations\n- Export capabilities\n\n## Development\n\n```bash\n# Install dependencies\npnpm install\n\n# Start development server\npnpm dev\n\n# Build for production\npnpm build\n```\n\n## Documentation\n\n- [Integration Guide](https://unlighthouse.dev/integrations/)\n- [API Reference](https://unlighthouse.dev/api/index.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/core/README.md":"# @unlighthouse/core\n\nThe core engine of [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that handles website scanning, Lighthouse execution, and report generation.\n\n## Usage\n\n### Basic Usage\n\n```ts\nimport { createUnlighthouse } from '@unlighthouse/core'\n\nconst unlighthouse = await createUnlighthouse({\n  site: 'https://example.com',\n  debug: true,\n  scanner: {\n    device: 'desktop',\n  }\n})\n\nawait unlighthouse.start()\n```\n\n### With Custom Provider\n\n```ts\nimport { createUnlighthouse } from '@unlighthouse/core'\n\nconst unlighthouse = await createUnlighthouse(\n  { /* user config */ },\n  {\n    name: 'custom',\n    routeDefinitions: () => generateRouteDefinitions(),\n  }\n)\n```\n\n### Hooks\n\n```ts\nimport { useUnlighthouse } from '@unlighthouse/core'\n\nconst { hooks } = useUnlighthouse()\n\nhooks.hook('task-complete', (path, response) => {\n  console.log('Task completed for:', path)\n})\n```\n\n## API\n\n- `createUnlighthouse(userConfig, provider?)` - Initialize Unlighthouse\n- `useUnlighthouse()` - Access the global Unlighthouse context\n- `generateClient(options)` - Generate static client files\n\n## Documentation\n\n- [API Reference](https://unlighthouse.dev/api/index.html)\n- [Configuration Guide](https://unlighthouse.dev/guide/config.html)\n- [Puppeteer Configuration](https://unlighthouse.dev/guide/puppeteer.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/server/README.md":"# @unlighthouse/server\n\nThe server package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that provides the web server and API endpoints for the scanning interface.\n\n## Usage\n\n```ts\nimport { createServer } from '@unlighthouse/server'\n\nconst { server, app } = await createServer()\n// server is an instance of listhen, app is an instance of h3\nawait unlighthouse.setServerContext({ url: server.url, server: server.server, app })\nawait unlighthouse.start()\n```\n\n## Documentation\n\n- [API Reference](https://unlighthouse.dev/api/index.html)\n- [Configuration Guide](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/unlighthouse-ci/README.md":"# unlighthouse-ci\n\nDedicated CI package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that provides continuous integration capabilities with budget enforcement and exit codes.\n\n## Installation\n\n```bash\n# Use directly with npx\nnpx unlighthouse-ci --site https://example.com\n\n# Or install globally\nnpm install -g unlighthouse-ci\n```\n\n## Usage\n\n### Basic CI Scanning\n\n```bash\n# Run CI scan with default budget (75)\nunlighthouse-ci --site https://example.com\n\n# Custom performance budget\nunlighthouse-ci --site https://example.com --budget 85\n\n# Desktop scanning with custom output\nunlighthouse-ci --site https://example.com --desktop --output-path ./lighthouse-reports\n```\n\n### GitHub Actions Integration\n\n```yaml\nname: Lighthouse CI\non: [push, pull_request]\njobs:\n  lighthouse:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run Lighthouse CI\n        run: npx unlighthouse-ci --site ${{ secrets.SITE_URL }} --budget 80\n```\n\n### Features\n\n- Performance budget enforcement with configurable thresholds\n- Exit codes for CI/CD pipeline integration\n- Static report generation for hosting\n- Comprehensive logging and debugging\n- Support for custom Lighthouse configurations\n\n## Configuration\n\nCreate `unlighthouse.config.ts` for advanced CI configuration:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  ci: {\n    budget: 80,\n    buildStatic: true,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility', 'seo'],\n  }\n})\n```\n\n## Documentation\n\n- [CI Integration Guide](https://unlighthouse.dev/integrations/ci.html)\n- [GitHub Actions Example](https://unlighthouse.dev/integrations/ci.html#github-actions)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/unlighthouse/README.md":"# unlighthouse\n\nThe main package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) - scan your entire website with Google Lighthouse. This is a convenience package that includes the core functionality and CLI tools.\n\n## Quick Start\n\n```bash\n# Scan your website instantly\nnpx unlighthouse --site https://example.com\n\n# CI mode with performance budgets\nnpx unlighthouse-ci --site https://example.com --budget 80\n```\n\n## What's Included\n\nThis package includes:\n- `@unlighthouse/core` - Core scanning engine\n- `@unlighthouse/cli` - Command-line interface\n- `@unlighthouse/client` - Web interface for results\n- Two binaries: `unlighthouse` and `unlighthouse-ci`\n\n## Installation\n\n```bash\n# Global installation\nnpm install -g unlighthouse\n\n# Project dependency\nnpm install unlighthouse --save-dev\n```\n\n## Usage\n\n### Interactive CLI\n\n```bash\n# Basic scan\nunlighthouse --site https://example.com\n\n# With debugging and custom device\nunlighthouse --site https://example.com --debug --desktop\n\n# Custom configuration\nunlighthouse --config-file unlighthouse.config.ts\n```\n\n### Programmatic Usage\n\n```ts\nimport { createUnlighthouse } from 'unlighthouse'\n\nconst unlighthouse = await createUnlighthouse({\n  site: 'https://example.com',\n  debug: true\n})\n\nawait unlighthouse.start()\n```\n\n### CI Integration\n\n```bash\n# Enforce performance budgets in CI\nunlighthouse-ci --site https://example.com --budget 85\n```\n\n## Configuration\n\nCreate `unlighthouse.config.ts`:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  scanner: {\n    device: 'desktop',\n    throttle: false,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility'],\n  }\n})\n```\n\n## Documentation\n\n- [Getting Started Guide](https://unlighthouse.dev/guide/)\n- [CLI Integration](https://unlighthouse.dev/integrations/cli.html)\n- [CI Integration](https://unlighthouse.dev/integrations/ci.html)\n- [API Reference](https://unlighthouse.dev/api/)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/unlighthouse/skills/unlighthouse/SKILL.md":"---\nname: unlighthouse\ndescription: Run Google Lighthouse on every page of a site with the unlighthouse CLI, and fail CI on low scores with unlighthouse-ci. Use when a task mentions unlighthouse, unlighthouse-ci, site-wide Lighthouse scans, performance budgets in CI, unlighthouse.config.ts, defineUnlighthouseConfig, scanner.exclude, dynamic sampling, the authenticate hook, or a scan that never exits, skips pages, or refuses to clear its output folder.\nlicense: MIT\ncompatibility: \"Requires Node.js >=22.18.0.\"\n---\n\n# unlighthouse\n\nTested on Node 24 against the `unlighthouse` release that ships this Skill (requires Node `>=22.18.0`).\nThe package finds the URLs of a site and runs Lighthouse on each one in parallel Chrome instances.\nIt ships two binaries: `unlighthouse` opens a live dashboard, and `unlighthouse-ci` exits with a status code. Docs: https://unlighthouse.dev\n\n## Setup\n\n```bash\nnpx unlighthouse-ci --site https://example.com --budget 80\n```\n\n- Install `unlighthouse` for both binaries. `@unlighthouse/cli` ships only `unlighthouse-ci`.\n- Do not install `puppeteer`. `puppeteer-cluster` already depends on it.\n- Chrome: the package uses the system Chrome. If there is none, it downloads Chrome to `~/.unlighthouse`. As root, it adds `--no-sandbox` itself.\n- Add `.unlighthouse` to `.gitignore`.\n- `@unlighthouse/nuxt`, `@unlighthouse/vite`, and `@unlighthouse/webpack` are deprecated. Run the CLI against the dev server URL instead.\n- The config file is `unlighthouse.config.ts` in the current directory. A CLI flag you pass wins over the config file. A flag you leave out keeps the config value.\n\n## Pick the binary\n\n- **`unlighthouse-ci`** scans, writes reports, and exits. Exit code 1 means a budget failed, or no route was left to scan. Use it in scripts, CI, and Agent runs.\n- **`unlighthouse`** starts a dashboard server (port 5678 by default), opens a browser, and keeps running after the scan. It never exits by itself.\n\n## Automatic behaviour\n\n- **URL discovery:** `urls` if set, else robots.txt, then sitemap.xml, then a crawler that follows links from the home page. Robots.txt `Disallow` lines become excludes.\n- **`--urls` or `urls`** turns off robots.txt, sitemap, crawler, and sampling. The paths are relative to `site`.\n- **A `site` with a path**, such as `https://example.com/docs`, turns off sitemap, robots.txt, and sampling.\n- **A sitemap with 50 or more URLs** turns off the crawler, except on `localhost`.\n- **Dynamic sampling** scans at most 8 random URLs per route group, such as `/blog/*`. Turn it off with `--disable-dynamic-sampling`.\n- **`scanner.maxRoutes`** (200) stops the queue. It logs a warning and exits 0.\n- **HTML inspection skips JavaScript.** If the home page has no links, the crawler turns JavaScript on and retries. For an SPA, pass `--enable-javascript`.\n- **Device** is mobile. Pass `--desktop` for desktop.\n- **Throttling** is simulated for a remote site and off for a local one (`localhost`, `127.0.0.1`). An explicit `scanner.throttle` or `--throttle` wins.\n- **Redirects:** if `site` redirects to another host, such as http to https or apex to www, the scan uses the redirect target.\n\n## Common tasks\n\nPer category budgets, reporters, and scope in one config:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://staging.example.com',\n  scanner: {\n    exclude: ['/admin/**', '/api/**'],\n    include: ['/', /^\\/blog\\//, '/docs/**'], // keep '/' so the crawler can start\n  },\n  ci: {\n    budget: { 'performance': 70, 'accessibility': 95, 'best-practices': 90, 'seo': 90 },\n    reporter: 'jsonExpanded',\n  },\n})\n```\n\n- Budgets use 0 to 100. Report scores use 0 to 1. A budget of 80 fails a score of 0.79.\n- Reporters: `json` (default), `jsonExpanded`, `csv`, `csvExpanded`, `lighthouseServer`. The file is `<outputPath>/ci-result.json` or `ci-result.csv`.\n- `lighthouseServer` needs `--lhci-host` and `--lhci-build-token`.\n\nStatic HTML report: pass `--build-static`, or set `ci.buildStatic: true`. It writes `index.html` to the root of `outputPath` (`.unlighthouse`). Upload that folder. It deletes the per page `lighthouse.json` files.\n\nAuthentication: the `authenticate` hook gets the Puppeteer `Page` as its first argument. It runs once. Its cookies reach every scanned page, including the Lighthouse run, and only the hosts they belong to.\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  auth: { username: 'admin', password: process.env.AUTH_PASS! },\n  hooks: {\n    async authenticate(page) {\n      await page.goto('https://example.com/login')\n      await page.type('input[name=\"email\"]', 'test@example.com')\n      await Promise.all([page.waitForNavigation(), page.click('button[type=\"submit\"]')])\n    },\n  },\n})\n```\n\nRead scores in a hook: `task-complete` fires once per task, so check `taskName`. `categories` is an array of `{ key, id, title, score }`.\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  hooks: {\n    'task-complete': (path, report, taskName) => {\n      if (taskName !== 'runLighthouseTask')\n        return\n      const performance = report.report?.categories.find(category => category.key === 'performance')\n      console.log(path, report.report?.score, performance?.score)\n    },\n  },\n})\n```\n\nProgrammatic scan: register `worker-finished` before `start()`. Without a provider, reports go to `.unlighthouse/<host>/<config hash>/`.\n\n```ts\nimport { createUnlighthouse } from 'unlighthouse'\n\nconst unlighthouse = await createUnlighthouse({ site: 'https://example.com', urls: ['/', '/about'] })\nunlighthouse.hooks.hook('worker-finished', async () => {\n  console.log(unlighthouse.worker.reports().map(r => [r.route.path, r.report?.score]))\n  await unlighthouse.worker.cluster.close()\n  process.exit(0)\n})\nawait unlighthouse.start()\n```\n\n## Traps\n\n- **`unlighthouse-ci` clears `outputPath` before it scans, and refuses a folder it did not create.** `--output-path .` exits 1 with `Refusing to clear ... it is not an unlighthouse output folder`. Point it at a new or empty folder. Unlighthouse marks its folders with a `.unlighthouse-output` file.\n- **String patterns are route patterns, not regex.** `--exclude-urls \"/blog/.*\"` excludes nothing. `*` matches one segment and `**` any depth, so use `/blog/**`, or a `RegExp` in the config.\n- **An `include` list that skips `/` stops a crawler scan.** The crawler starts from `/`, so nothing is queued and both binaries exit 1 with `No routes left to scan`. Add `'/'` to `include`, or use `--urls`.\n- **A hook that throws stops `unlighthouse-ci` with exit code 1.** Guard on `taskName` and optional fields.\n- **Dynamic sampling is random.** Two runs can scan different pages in one group. For stable CI results, pass `--urls` or turn sampling off.\n\n## Output\n\n- `unlighthouse-ci`: `.unlighthouse/ci-result.json` and `.unlighthouse/reports/<path>/lighthouse.json`.\n- `unlighthouse`: `.unlighthouse/<host>/<config hash>/`. A config change starts a new cache folder.\n\n## Config\n\n- `scanner.device` (`'mobile'`), `scanner.samples` (1, runs per page, averaged), `scanner.throttle` (on for remote sites, off for local ones).\n- `scanner.dynamicSampling` (8), `scanner.maxRoutes` (200), `scanner.crawler`, `scanner.sitemap`, `scanner.robotsTxt`.\n- `puppeteerClusterOptions.maxConcurrency` (half the CPU cores). Set 1 for stable performance scores.\n- `lighthouseOptions` passes through to Lighthouse. `onlyAudits` replaces `onlyCategories`.\n- `chrome.useSystem`, `chrome.downloadFallbackCacheDir`.\n- All options: https://unlighthouse.dev/api-doc/config\n\n## Debug\n\n- `--debug` logs the resolved config. A route that `include` or `exclude` drops logs `Skipping route based on include / exclude rules`.\n- \"Failed to queue routes for scanning\" means discovery found nothing. Check the `site` status and the robots.txt `Disallow` lines.\n- \"No routes left to scan\" means discovery found routes, and `include`, `exclude`, or robots.txt rules skipped all of them.\n"},"files":{"packages/cli/README.md":"# @unlighthouse/cli\n\nThe command-line interface and CI integration for [Unlighthouse](https://github.com/harlan-zw/unlighthouse), enabling automated website scanning in development and deployment workflows.\n\n## Installation\n\n```bash\n# Use directly with npx\nnpx unlighthouse --site https://example.com\n\n# Or install globally\nnpm install -g @unlighthouse/cli\n```\n\n## Usage\n\n### Basic Scanning\n\n```bash\n# Scan a website\nunlighthouse --site https://example.com\n\n# Enable debug mode\nunlighthouse --site https://example.com --debug\n\n# Mobile device simulation\nunlighthouse --site https://example.com --mobile\n```\n\n### Advanced Options\n\n```bash\n# Multiple samples with throttling\nunlighthouse --site https://example.com --samples 3 --throttle\n\n# Custom URLs and exclusions\nunlighthouse --site https://example.com --urls /home,/about,/contact --exclude-urls '/admin/**'\n\n# With custom configuration\nunlighthouse --site https://example.com --config-file ./my-config.ts\n```\n\n### CI Integration\n\n```bash\n# CI mode with exit codes for failed audits\nunlighthouse-ci --site https://example.com --budget 75\n```\n\n## Configuration\n\nCreate `unlighthouse.config.ts` in your project root:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  debug: true,\n  scanner: {\n    device: 'desktop',\n    throttle: false,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility'],\n  }\n})\n```\n\n## Documentation\n\n- [CLI Integration Guide](https://unlighthouse.dev/integrations/cli.html)\n- [CI Integration Guide](https://unlighthouse.dev/integrations/ci.html)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/client/README.md":"# @unlighthouse/client\n\nThe Vue-based user interface for [Unlighthouse](https://github.com/harlan-zw/unlighthouse), providing an interactive dashboard to view and analyze Lighthouse scan results.\n\n## Features\n\n- Interactive dashboard with performance metrics\n- Real-time scan progress tracking\n- Detailed Lighthouse reports per page\n- Performance charts and visualizations\n- Export capabilities\n\n## Development\n\n```bash\n# Install dependencies\npnpm install\n\n# Start development server\npnpm dev\n\n# Build for production\npnpm build\n```\n\n## Documentation\n\n- [Integration Guide](https://unlighthouse.dev/integrations/)\n- [API Reference](https://unlighthouse.dev/api/index.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/core/README.md":"# @unlighthouse/core\n\nThe core engine of [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that handles website scanning, Lighthouse execution, and report generation.\n\n## Usage\n\n### Basic Usage\n\n```ts\nimport { createUnlighthouse } from '@unlighthouse/core'\n\nconst unlighthouse = await createUnlighthouse({\n  site: 'https://example.com',\n  debug: true,\n  scanner: {\n    device: 'desktop',\n  }\n})\n\nawait unlighthouse.start()\n```\n\n### With Custom Provider\n\n```ts\nimport { createUnlighthouse } from '@unlighthouse/core'\n\nconst unlighthouse = await createUnlighthouse(\n  { /* user config */ },\n  {\n    name: 'custom',\n    routeDefinitions: () => generateRouteDefinitions(),\n  }\n)\n```\n\n### Hooks\n\n```ts\nimport { useUnlighthouse } from '@unlighthouse/core'\n\nconst { hooks } = useUnlighthouse()\n\nhooks.hook('task-complete', (path, response) => {\n  console.log('Task completed for:', path)\n})\n```\n\n## API\n\n- `createUnlighthouse(userConfig, provider?)` - Initialize Unlighthouse\n- `useUnlighthouse()` - Access the global Unlighthouse context\n- `generateClient(options)` - Generate static client files\n\n## Documentation\n\n- [API Reference](https://unlighthouse.dev/api/index.html)\n- [Configuration Guide](https://unlighthouse.dev/guide/config.html)\n- [Puppeteer Configuration](https://unlighthouse.dev/guide/puppeteer.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/server/README.md":"# @unlighthouse/server\n\nThe server package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that provides the web server and API endpoints for the scanning interface.\n\n## Usage\n\n```ts\nimport { createServer } from '@unlighthouse/server'\n\nconst { server, app } = await createServer()\n// server is an instance of listhen, app is an instance of h3\nawait unlighthouse.setServerContext({ url: server.url, server: server.server, app })\nawait unlighthouse.start()\n```\n\n## Documentation\n\n- [API Reference](https://unlighthouse.dev/api/index.html)\n- [Configuration Guide](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/unlighthouse-ci/README.md":"# unlighthouse-ci\n\nDedicated CI package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that provides continuous integration capabilities with budget enforcement and exit codes.\n\n## Installation\n\n```bash\n# Use directly with npx\nnpx unlighthouse-ci --site https://example.com\n\n# Or install globally\nnpm install -g unlighthouse-ci\n```\n\n## Usage\n\n### Basic CI Scanning\n\n```bash\n# Run CI scan with default budget (75)\nunlighthouse-ci --site https://example.com\n\n# Custom performance budget\nunlighthouse-ci --site https://example.com --budget 85\n\n# Desktop scanning with custom output\nunlighthouse-ci --site https://example.com --desktop --output-path ./lighthouse-reports\n```\n\n### GitHub Actions Integration\n\n```yaml\nname: Lighthouse CI\non: [push, pull_request]\njobs:\n  lighthouse:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run Lighthouse CI\n        run: npx unlighthouse-ci --site ${{ secrets.SITE_URL }} --budget 80\n```\n\n### Features\n\n- Performance budget enforcement with configurable thresholds\n- Exit codes for CI/CD pipeline integration\n- Static report generation for hosting\n- Comprehensive logging and debugging\n- Support for custom Lighthouse configurations\n\n## Configuration\n\nCreate `unlighthouse.config.ts` for advanced CI configuration:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  ci: {\n    budget: 80,\n    buildStatic: true,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility', 'seo'],\n  }\n})\n```\n\n## Documentation\n\n- [CI Integration Guide](https://unlighthouse.dev/integrations/ci.html)\n- [GitHub Actions Example](https://unlighthouse.dev/integrations/ci.html#github-actions)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/unlighthouse/README.md":"# unlighthouse\n\nThe main package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) - scan your entire website with Google Lighthouse. This is a convenience package that includes the core functionality and CLI tools.\n\n## Quick Start\n\n```bash\n# Scan your website instantly\nnpx unlighthouse --site https://example.com\n\n# CI mode with performance budgets\nnpx unlighthouse-ci --site https://example.com --budget 80\n```\n\n## What's Included\n\nThis package includes:\n- `@unlighthouse/core` - Core scanning engine\n- `@unlighthouse/cli` - Command-line interface\n- `@unlighthouse/client` - Web interface for results\n- Two binaries: `unlighthouse` and `unlighthouse-ci`\n\n## Installation\n\n```bash\n# Global installation\nnpm install -g unlighthouse\n\n# Project dependency\nnpm install unlighthouse --save-dev\n```\n\n## Usage\n\n### Interactive CLI\n\n```bash\n# Basic scan\nunlighthouse --site https://example.com\n\n# With debugging and custom device\nunlighthouse --site https://example.com --debug --desktop\n\n# Custom configuration\nunlighthouse --config-file unlighthouse.config.ts\n```\n\n### Programmatic Usage\n\n```ts\nimport { createUnlighthouse } from 'unlighthouse'\n\nconst unlighthouse = await createUnlighthouse({\n  site: 'https://example.com',\n  debug: true\n})\n\nawait unlighthouse.start()\n```\n\n### CI Integration\n\n```bash\n# Enforce performance budgets in CI\nunlighthouse-ci --site https://example.com --budget 85\n```\n\n## Configuration\n\nCreate `unlighthouse.config.ts`:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  scanner: {\n    device: 'desktop',\n    throttle: false,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility'],\n  }\n})\n```\n\n## Documentation\n\n- [Getting Started Guide](https://unlighthouse.dev/guide/)\n- [CLI Integration](https://unlighthouse.dev/integrations/cli.html)\n- [CI Integration](https://unlighthouse.dev/integrations/ci.html)\n- [API Reference](https://unlighthouse.dev/api/)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","packages/unlighthouse/skills/unlighthouse/SKILL.md":"---\nname: unlighthouse\ndescription: Run Google Lighthouse on every page of a site with the unlighthouse CLI, and fail CI on low scores with unlighthouse-ci. Use when a task mentions unlighthouse, unlighthouse-ci, site-wide Lighthouse scans, performance budgets in CI, unlighthouse.config.ts, defineUnlighthouseConfig, scanner.exclude, dynamic sampling, the authenticate hook, or a scan that never exits, skips pages, or refuses to clear its output folder.\nlicense: MIT\ncompatibility: \"Requires Node.js >=22.18.0.\"\n---\n\n# unlighthouse\n\nTested on Node 24 against the `unlighthouse` release that ships this Skill (requires Node `>=22.18.0`).\nThe package finds the URLs of a site and runs Lighthouse on each one in parallel Chrome instances.\nIt ships two binaries: `unlighthouse` opens a live dashboard, and `unlighthouse-ci` exits with a status code. Docs: https://unlighthouse.dev\n\n## Setup\n\n```bash\nnpx unlighthouse-ci --site https://example.com --budget 80\n```\n\n- Install `unlighthouse` for both binaries. `@unlighthouse/cli` ships only `unlighthouse-ci`.\n- Do not install `puppeteer`. `puppeteer-cluster` already depends on it.\n- Chrome: the package uses the system Chrome. If there is none, it downloads Chrome to `~/.unlighthouse`. As root, it adds `--no-sandbox` itself.\n- Add `.unlighthouse` to `.gitignore`.\n- `@unlighthouse/nuxt`, `@unlighthouse/vite`, and `@unlighthouse/webpack` are deprecated. Run the CLI against the dev server URL instead.\n- The config file is `unlighthouse.config.ts` in the current directory. A CLI flag you pass wins over the config file. A flag you leave out keeps the config value.\n\n## Pick the binary\n\n- **`unlighthouse-ci`** scans, writes reports, and exits. Exit code 1 means a budget failed, or no route was left to scan. Use it in scripts, CI, and Agent runs.\n- **`unlighthouse`** starts a dashboard server (port 5678 by default), opens a browser, and keeps running after the scan. It never exits by itself.\n\n## Automatic behaviour\n\n- **URL discovery:** `urls` if set, else robots.txt, then sitemap.xml, then a crawler that follows links from the home page. Robots.txt `Disallow` lines become excludes.\n- **`--urls` or `urls`** turns off robots.txt, sitemap, crawler, and sampling. The paths are relative to `site`.\n- **A `site` with a path**, such as `https://example.com/docs`, turns off sitemap, robots.txt, and sampling.\n- **A sitemap with 50 or more URLs** turns off the crawler, except on `localhost`.\n- **Dynamic sampling** scans at most 8 random URLs per route group, such as `/blog/*`. Turn it off with `--disable-dynamic-sampling`.\n- **`scanner.maxRoutes`** (200) stops the queue. It logs a warning and exits 0.\n- **HTML inspection skips JavaScript.** If the home page has no links, the crawler turns JavaScript on and retries. For an SPA, pass `--enable-javascript`.\n- **Device** is mobile. Pass `--desktop` for desktop.\n- **Throttling** is simulated for a remote site and off for a local one (`localhost`, `127.0.0.1`). An explicit `scanner.throttle` or `--throttle` wins.\n- **Redirects:** if `site` redirects to another host, such as http to https or apex to www, the scan uses the redirect target.\n\n## Common tasks\n\nPer category budgets, reporters, and scope in one config:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://staging.example.com',\n  scanner: {\n    exclude: ['/admin/**', '/api/**'],\n    include: ['/', /^\\/blog\\//, '/docs/**'], // keep '/' so the crawler can start\n  },\n  ci: {\n    budget: { 'performance': 70, 'accessibility': 95, 'best-practices': 90, 'seo': 90 },\n    reporter: 'jsonExpanded',\n  },\n})\n```\n\n- Budgets use 0 to 100. Report scores use 0 to 1. A budget of 80 fails a score of 0.79.\n- Reporters: `json` (default), `jsonExpanded`, `csv`, `csvExpanded`, `lighthouseServer`. The file is `<outputPath>/ci-result.json` or `ci-result.csv`.\n- `lighthouseServer` needs `--lhci-host` and `--lhci-build-token`.\n\nStatic HTML report: pass `--build-static`, or set `ci.buildStatic: true`. It writes `index.html` to the root of `outputPath` (`.unlighthouse`). Upload that folder. It deletes the per page `lighthouse.json` files.\n\nAuthentication: the `authenticate` hook gets the Puppeteer `Page` as its first argument. It runs once. Its cookies reach every scanned page, including the Lighthouse run, and only the hosts they belong to.\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  auth: { username: 'admin', password: process.env.AUTH_PASS! },\n  hooks: {\n    async authenticate(page) {\n      await page.goto('https://example.com/login')\n      await page.type('input[name=\"email\"]', 'test@example.com')\n      await Promise.all([page.waitForNavigation(), page.click('button[type=\"submit\"]')])\n    },\n  },\n})\n```\n\nRead scores in a hook: `task-complete` fires once per task, so check `taskName`. `categories` is an array of `{ key, id, title, score }`.\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  hooks: {\n    'task-complete': (path, report, taskName) => {\n      if (taskName !== 'runLighthouseTask')\n        return\n      const performance = report.report?.categories.find(category => category.key === 'performance')\n      console.log(path, report.report?.score, performance?.score)\n    },\n  },\n})\n```\n\nProgrammatic scan: register `worker-finished` before `start()`. Without a provider, reports go to `.unlighthouse/<host>/<config hash>/`.\n\n```ts\nimport { createUnlighthouse } from 'unlighthouse'\n\nconst unlighthouse = await createUnlighthouse({ site: 'https://example.com', urls: ['/', '/about'] })\nunlighthouse.hooks.hook('worker-finished', async () => {\n  console.log(unlighthouse.worker.reports().map(r => [r.route.path, r.report?.score]))\n  await unlighthouse.worker.cluster.close()\n  process.exit(0)\n})\nawait unlighthouse.start()\n```\n\n## Traps\n\n- **`unlighthouse-ci` clears `outputPath` before it scans, and refuses a folder it did not create.** `--output-path .` exits 1 with `Refusing to clear ... it is not an unlighthouse output folder`. Point it at a new or empty folder. Unlighthouse marks its folders with a `.unlighthouse-output` file.\n- **String patterns are route patterns, not regex.** `--exclude-urls \"/blog/.*\"` excludes nothing. `*` matches one segment and `**` any depth, so use `/blog/**`, or a `RegExp` in the config.\n- **An `include` list that skips `/` stops a crawler scan.** The crawler starts from `/`, so nothing is queued and both binaries exit 1 with `No routes left to scan`. Add `'/'` to `include`, or use `--urls`.\n- **A hook that throws stops `unlighthouse-ci` with exit code 1.** Guard on `taskName` and optional fields.\n- **Dynamic sampling is random.** Two runs can scan different pages in one group. For stable CI results, pass `--urls` or turn sampling off.\n\n## Output\n\n- `unlighthouse-ci`: `.unlighthouse/ci-result.json` and `.unlighthouse/reports/<path>/lighthouse.json`.\n- `unlighthouse`: `.unlighthouse/<host>/<config hash>/`. A config change starts a new cache folder.\n\n## Config\n\n- `scanner.device` (`'mobile'`), `scanner.samples` (1, runs per page, averaged), `scanner.throttle` (on for remote sites, off for local ones).\n- `scanner.dynamicSampling` (8), `scanner.maxRoutes` (200), `scanner.crawler`, `scanner.sitemap`, `scanner.robotsTxt`.\n- `puppeteerClusterOptions.maxConcurrency` (half the CPU cores). Set 1 for stable performance scores.\n- `lighthouseOptions` passes through to Lighthouse. `onlyAudits` replaces `onlyCategories`.\n- `chrome.useSystem`, `chrome.downloadFallbackCacheDir`.\n- All options: https://unlighthouse.dev/api-doc/config\n\n## Debug\n\n- `--debug` logs the resolved config. A route that `include` or `exclude` drops logs `Skipping route based on include / exclude rules`.\n- \"Failed to queue routes for scanning\" means discovery found nothing. Check the `site` status and the robots.txt `Disallow` lines.\n- \"No routes left to scan\" means discovery found routes, and `include`, `exclude`, or robots.txt rules skipped all of them.\n"},"items":[{"name":"SKILL.md","path":"packages/unlighthouse/skills/unlighthouse/SKILL.md","rawUrl":"https://raw.githubusercontent.com/harlan-zw/unlighthouse/HEAD/packages/unlighthouse/skills/unlighthouse/SKILL.md","title":"unlighthouse","category":"anthropic-skill","format":"markdown","content":"---\nname: unlighthouse\ndescription: Run Google Lighthouse on every page of a site with the unlighthouse CLI, and fail CI on low scores with unlighthouse-ci. Use when a task mentions unlighthouse, unlighthouse-ci, site-wide Lighthouse scans, performance budgets in CI, unlighthouse.config.ts, defineUnlighthouseConfig, scanner.exclude, dynamic sampling, the authenticate hook, or a scan that never exits, skips pages, or refuses to clear its output folder.\nlicense: MIT\ncompatibility: \"Requires Node.js >=22.18.0.\"\n---\n\n# unlighthouse\n\nTested on Node 24 against the `unlighthouse` release that ships this Skill (requires Node `>=22.18.0`).\nThe package finds the URLs of a site and runs Lighthouse on each one in parallel Chrome instances.\nIt ships two binaries: `unlighthouse` opens a live dashboard, and `unlighthouse-ci` exits with a status code. Docs: https://unlighthouse.dev\n\n## Setup\n\n```bash\nnpx unlighthouse-ci --site https://example.com --budget 80\n```\n\n- Install `unlighthouse` for both binaries. `@unlighthouse/cli` ships only `unlighthouse-ci`.\n- Do not install `puppeteer`. `puppeteer-cluster` already depends on it.\n- Chrome: the package uses the system Chrome. If there is none, it downloads Chrome to `~/.unlighthouse`. As root, it adds `--no-sandbox` itself.\n- Add `.unlighthouse` to `.gitignore`.\n- `@unlighthouse/nuxt`, `@unlighthouse/vite`, and `@unlighthouse/webpack` are deprecated. Run the CLI against the dev server URL instead.\n- The config file is `unlighthouse.config.ts` in the current directory. A CLI flag you pass wins over the config file. A flag you leave out keeps the config value.\n\n## Pick the binary\n\n- **`unlighthouse-ci`** scans, writes reports, and exits. Exit code 1 means a budget failed, or no route was left to scan. Use it in scripts, CI, and Agent runs.\n- **`unlighthouse`** starts a dashboard server (port 5678 by default), opens a browser, and keeps running after the scan. It never exits by itself.\n\n## Automatic behaviour\n\n- **URL discovery:** `urls` if set, else robots.txt, then sitemap.xml, then a crawler that follows links from the home page. Robots.txt `Disallow` lines become excludes.\n- **`--urls` or `urls`** turns off robots.txt, sitemap, crawler, and sampling. The paths are relative to `site`.\n- **A `site` with a path**, such as `https://example.com/docs`, turns off sitemap, robots.txt, and sampling.\n- **A sitemap with 50 or more URLs** turns off the crawler, except on `localhost`.\n- **Dynamic sampling** scans at most 8 random URLs per route group, such as `/blog/*`. Turn it off with `--disable-dynamic-sampling`.\n- **`scanner.maxRoutes`** (200) stops the queue. It logs a warning and exits 0.\n- **HTML inspection skips JavaScript.** If the home page has no links, the crawler turns JavaScript on and retries. For an SPA, pass `--enable-javascript`.\n- **Device** is mobile. Pass `--desktop` for desktop.\n- **Throttling** is simulated for a remote site and off for a local one (`localhost`, `127.0.0.1`). An explicit `scanner.throttle` or `--throttle` wins.\n- **Redirects:** if `site` redirects to another host, such as http to https or apex to www, the scan uses the redirect target.\n\n## Common tasks\n\nPer category budgets, reporters, and scope in one config:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://staging.example.com',\n  scanner: {\n    exclude: ['/admin/**', '/api/**'],\n    include: ['/', /^\\/blog\\//, '/docs/**'], // keep '/' so the crawler can start\n  },\n  ci: {\n    budget: { 'performance': 70, 'accessibility': 95, 'best-practices': 90, 'seo': 90 },\n    reporter: 'jsonExpanded',\n  },\n})\n```\n\n- Budgets use 0 to 100. Report scores use 0 to 1. A budget of 80 fails a score of 0.79.\n- Reporters: `json` (default), `jsonExpanded`, `csv`, `csvExpanded`, `lighthouseServer`. The file is `<outputPath>/ci-result.json` or `ci-result.csv`.\n- `lighthouseServer` needs `--lhci-host` and `--lhci-build-token`.\n\nStatic HTML report: pass `--build-static`, or set `ci.buildStatic: true`. It writes `index.html` to the root of `outputPath` (`.unlighthouse`). Upload that folder. It deletes the per page `lighthouse.json` files.\n\nAuthentication: the `authenticate` hook gets the Puppeteer `Page` as its first argument. It runs once. Its cookies reach every scanned page, including the Lighthouse run, and only the hosts they belong to.\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  auth: { username: 'admin', password: process.env.AUTH_PASS! },\n  hooks: {\n    async authenticate(page) {\n      await page.goto('https://example.com/login')\n      await page.type('input[name=\"email\"]', 'test@example.com')\n      await Promise.all([page.waitForNavigation(), page.click('button[type=\"submit\"]')])\n    },\n  },\n})\n```\n\nRead scores in a hook: `task-complete` fires once per task, so check `taskName`. `categories` is an array of `{ key, id, title, score }`.\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  hooks: {\n    'task-complete': (path, report, taskName) => {\n      if (taskName !== 'runLighthouseTask')\n        return\n      const performance = report.report?.categories.find(category => category.key === 'performance')\n      console.log(path, report.report?.score, performance?.score)\n    },\n  },\n})\n```\n\nProgrammatic scan: register `worker-finished` before `start()`. Without a provider, reports go to `.unlighthouse/<host>/<config hash>/`.\n\n```ts\nimport { createUnlighthouse } from 'unlighthouse'\n\nconst unlighthouse = await createUnlighthouse({ site: 'https://example.com', urls: ['/', '/about'] })\nunlighthouse.hooks.hook('worker-finished', async () => {\n  console.log(unlighthouse.worker.reports().map(r => [r.route.path, r.report?.score]))\n  await unlighthouse.worker.cluster.close()\n  process.exit(0)\n})\nawait unlighthouse.start()\n```\n\n## Traps\n\n- **`unlighthouse-ci` clears `outputPath` before it scans, and refuses a folder it did not create.** `--output-path .` exits 1 with `Refusing to clear ... it is not an unlighthouse output folder`. Point it at a new or empty folder. Unlighthouse marks its folders with a `.unlighthouse-output` file.\n- **String patterns are route patterns, not regex.** `--exclude-urls \"/blog/.*\"` excludes nothing. `*` matches one segment and `**` any depth, so use `/blog/**`, or a `RegExp` in the config.\n- **An `include` list that skips `/` stops a crawler scan.** The crawler starts from `/`, so nothing is queued and both binaries exit 1 with `No routes left to scan`. Add `'/'` to `include`, or use `--urls`.\n- **A hook that throws stops `unlighthouse-ci` with exit code 1.** Guard on `taskName` and optional fields.\n- **Dynamic sampling is random.** Two runs can scan different pages in one group. For stable CI results, pass `--urls` or turn sampling off.\n\n## Output\n\n- `unlighthouse-ci`: `.unlighthouse/ci-result.json` and `.unlighthouse/reports/<path>/lighthouse.json`.\n- `unlighthouse`: `.unlighthouse/<host>/<config hash>/`. A config change starts a new cache folder.\n\n## Config\n\n- `scanner.device` (`'mobile'`), `scanner.samples` (1, runs per page, averaged), `scanner.throttle` (on for remote sites, off for local ones).\n- `scanner.dynamicSampling` (8), `scanner.maxRoutes` (200), `scanner.crawler`, `scanner.sitemap`, `scanner.robotsTxt`.\n- `puppeteerClusterOptions.maxConcurrency` (half the CPU cores). Set 1 for stable performance scores.\n- `lighthouseOptions` passes through to Lighthouse. `onlyAudits` replaces `onlyCategories`.\n- `chrome.useSystem`, `chrome.downloadFallbackCacheDir`.\n- All options: https://unlighthouse.dev/api-doc/config\n\n## Debug\n\n- `--debug` logs the resolved config. A route that `include` or `exclude` drops logs `Skipping route based on include / exclude rules`.\n- \"Failed to queue routes for scanning\" means discovery found nothing. Check the `site` status and the robots.txt `Disallow` lines.\n- \"No routes left to scan\" means discovery found routes, and `include`, `exclude`, or robots.txt rules skipped all of them.\n","frontmatter":{"name":"unlighthouse","description":"Run Google Lighthouse on every page of a site with the unlighthouse CLI, and fail CI on low scores with unlighthouse-ci. Use when a task mentions unlighthouse, unlighthouse-ci, site-wide Lighthouse scans, performance budgets in CI, unlighthouse.config.ts, defineUnlighthouseConfig, scanner.exclude, dynamic sampling, the authenticate hook, or a scan that never exits, skips pages, or refuses to clear its output folder.","license":"MIT","compatibility":"Requires Node.js >=22.18.0."},"isInternal":false,"tokens":2071,"sizeBytes":8083},{"name":"README.md","path":"packages/cli/README.md","rawUrl":"https://raw.githubusercontent.com/harlan-zw/unlighthouse/HEAD/packages/cli/README.md","title":"cli Documentation","category":"plugin-manifest","format":"markdown","content":"# @unlighthouse/cli\n\nThe command-line interface and CI integration for [Unlighthouse](https://github.com/harlan-zw/unlighthouse), enabling automated website scanning in development and deployment workflows.\n\n## Installation\n\n```bash\n# Use directly with npx\nnpx unlighthouse --site https://example.com\n\n# Or install globally\nnpm install -g @unlighthouse/cli\n```\n\n## Usage\n\n### Basic Scanning\n\n```bash\n# Scan a website\nunlighthouse --site https://example.com\n\n# Enable debug mode\nunlighthouse --site https://example.com --debug\n\n# Mobile device simulation\nunlighthouse --site https://example.com --mobile\n```\n\n### Advanced Options\n\n```bash\n# Multiple samples with throttling\nunlighthouse --site https://example.com --samples 3 --throttle\n\n# Custom URLs and exclusions\nunlighthouse --site https://example.com --urls /home,/about,/contact --exclude-urls '/admin/**'\n\n# With custom configuration\nunlighthouse --site https://example.com --config-file ./my-config.ts\n```\n\n### CI Integration\n\n```bash\n# CI mode with exit codes for failed audits\nunlighthouse-ci --site https://example.com --budget 75\n```\n\n## Configuration\n\nCreate `unlighthouse.config.ts` in your project root:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  debug: true,\n  scanner: {\n    device: 'desktop',\n    throttle: false,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility'],\n  }\n})\n```\n\n## Documentation\n\n- [CLI Integration Guide](https://unlighthouse.dev/integrations/cli.html)\n- [CI Integration Guide](https://unlighthouse.dev/integrations/ci.html)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","isInternal":false,"tokens":446,"sizeBytes":1802},{"name":"README.md","path":"packages/client/README.md","rawUrl":"https://raw.githubusercontent.com/harlan-zw/unlighthouse/HEAD/packages/client/README.md","title":"client Documentation","category":"plugin-manifest","format":"markdown","content":"# @unlighthouse/client\n\nThe Vue-based user interface for [Unlighthouse](https://github.com/harlan-zw/unlighthouse), providing an interactive dashboard to view and analyze Lighthouse scan results.\n\n## Features\n\n- Interactive dashboard with performance metrics\n- Real-time scan progress tracking\n- Detailed Lighthouse reports per page\n- Performance charts and visualizations\n- Export capabilities\n\n## Development\n\n```bash\n# Install dependencies\npnpm install\n\n# Start development server\npnpm dev\n\n# Build for production\npnpm build\n```\n\n## Documentation\n\n- [Integration Guide](https://unlighthouse.dev/integrations/)\n- [API Reference](https://unlighthouse.dev/api/index.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","isInternal":false,"tokens":175,"sizeBytes":759},{"name":"README.md","path":"packages/core/README.md","rawUrl":"https://raw.githubusercontent.com/harlan-zw/unlighthouse/HEAD/packages/core/README.md","title":"core Documentation","category":"plugin-manifest","format":"markdown","content":"# @unlighthouse/core\n\nThe core engine of [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that handles website scanning, Lighthouse execution, and report generation.\n\n## Usage\n\n### Basic Usage\n\n```ts\nimport { createUnlighthouse } from '@unlighthouse/core'\n\nconst unlighthouse = await createUnlighthouse({\n  site: 'https://example.com',\n  debug: true,\n  scanner: {\n    device: 'desktop',\n  }\n})\n\nawait unlighthouse.start()\n```\n\n### With Custom Provider\n\n```ts\nimport { createUnlighthouse } from '@unlighthouse/core'\n\nconst unlighthouse = await createUnlighthouse(\n  { /* user config */ },\n  {\n    name: 'custom',\n    routeDefinitions: () => generateRouteDefinitions(),\n  }\n)\n```\n\n### Hooks\n\n```ts\nimport { useUnlighthouse } from '@unlighthouse/core'\n\nconst { hooks } = useUnlighthouse()\n\nhooks.hook('task-complete', (path, response) => {\n  console.log('Task completed for:', path)\n})\n```\n\n## API\n\n- `createUnlighthouse(userConfig, provider?)` - Initialize Unlighthouse\n- `useUnlighthouse()` - Access the global Unlighthouse context\n- `generateClient(options)` - Generate static client files\n\n## Documentation\n\n- [API Reference](https://unlighthouse.dev/api/index.html)\n- [Configuration Guide](https://unlighthouse.dev/guide/config.html)\n- [Puppeteer Configuration](https://unlighthouse.dev/guide/puppeteer.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","isInternal":false,"tokens":360,"sizeBytes":1407},{"name":"README.md","path":"packages/server/README.md","rawUrl":"https://raw.githubusercontent.com/harlan-zw/unlighthouse/HEAD/packages/server/README.md","title":"server Documentation","category":"plugin-manifest","format":"markdown","content":"# @unlighthouse/server\n\nThe server package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that provides the web server and API endpoints for the scanning interface.\n\n## Usage\n\n```ts\nimport { createServer } from '@unlighthouse/server'\n\nconst { server, app } = await createServer()\n// server is an instance of listhen, app is an instance of h3\nawait unlighthouse.setServerContext({ url: server.url, server: server.server, app })\nawait unlighthouse.start()\n```\n\n## Documentation\n\n- [API Reference](https://unlighthouse.dev/api/index.html)\n- [Configuration Guide](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","isInternal":false,"tokens":176,"sizeBytes":706},{"name":"README.md","path":"packages/unlighthouse-ci/README.md","rawUrl":"https://raw.githubusercontent.com/harlan-zw/unlighthouse/HEAD/packages/unlighthouse-ci/README.md","title":"unlighthouse-ci Documentation","category":"plugin-manifest","format":"markdown","content":"# unlighthouse-ci\n\nDedicated CI package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that provides continuous integration capabilities with budget enforcement and exit codes.\n\n## Installation\n\n```bash\n# Use directly with npx\nnpx unlighthouse-ci --site https://example.com\n\n# Or install globally\nnpm install -g unlighthouse-ci\n```\n\n## Usage\n\n### Basic CI Scanning\n\n```bash\n# Run CI scan with default budget (75)\nunlighthouse-ci --site https://example.com\n\n# Custom performance budget\nunlighthouse-ci --site https://example.com --budget 85\n\n# Desktop scanning with custom output\nunlighthouse-ci --site https://example.com --desktop --output-path ./lighthouse-reports\n```\n\n### GitHub Actions Integration\n\n```yaml\nname: Lighthouse CI\non: [push, pull_request]\njobs:\n  lighthouse:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run Lighthouse CI\n        run: npx unlighthouse-ci --site ${{ secrets.SITE_URL }} --budget 80\n```\n\n### Features\n\n- Performance budget enforcement with configurable thresholds\n- Exit codes for CI/CD pipeline integration\n- Static report generation for hosting\n- Comprehensive logging and debugging\n- Support for custom Lighthouse configurations\n\n## Configuration\n\nCreate `unlighthouse.config.ts` for advanced CI configuration:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  ci: {\n    budget: 80,\n    buildStatic: true,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility', 'seo'],\n  }\n})\n```\n\n## Documentation\n\n- [CI Integration Guide](https://unlighthouse.dev/integrations/ci.html)\n- [GitHub Actions Example](https://unlighthouse.dev/integrations/ci.html#github-actions)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","isInternal":false,"tokens":471,"sizeBytes":1933},{"name":"README.md","path":"packages/unlighthouse/README.md","rawUrl":"https://raw.githubusercontent.com/harlan-zw/unlighthouse/HEAD/packages/unlighthouse/README.md","title":"unlighthouse Documentation","category":"plugin-manifest","format":"markdown","content":"# unlighthouse\n\nThe main package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) - scan your entire website with Google Lighthouse. This is a convenience package that includes the core functionality and CLI tools.\n\n## Quick Start\n\n```bash\n# Scan your website instantly\nnpx unlighthouse --site https://example.com\n\n# CI mode with performance budgets\nnpx unlighthouse-ci --site https://example.com --budget 80\n```\n\n## What's Included\n\nThis package includes:\n- `@unlighthouse/core` - Core scanning engine\n- `@unlighthouse/cli` - Command-line interface\n- `@unlighthouse/client` - Web interface for results\n- Two binaries: `unlighthouse` and `unlighthouse-ci`\n\n## Installation\n\n```bash\n# Global installation\nnpm install -g unlighthouse\n\n# Project dependency\nnpm install unlighthouse --save-dev\n```\n\n## Usage\n\n### Interactive CLI\n\n```bash\n# Basic scan\nunlighthouse --site https://example.com\n\n# With debugging and custom device\nunlighthouse --site https://example.com --debug --desktop\n\n# Custom configuration\nunlighthouse --config-file unlighthouse.config.ts\n```\n\n### Programmatic Usage\n\n```ts\nimport { createUnlighthouse } from 'unlighthouse'\n\nconst unlighthouse = await createUnlighthouse({\n  site: 'https://example.com',\n  debug: true\n})\n\nawait unlighthouse.start()\n```\n\n### CI Integration\n\n```bash\n# Enforce performance budgets in CI\nunlighthouse-ci --site https://example.com --budget 85\n```\n\n## Configuration\n\nCreate `unlighthouse.config.ts`:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  scanner: {\n    device: 'desktop',\n    throttle: false,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility'],\n  }\n})\n```\n\n## Documentation\n\n- [Getting Started Guide](https://unlighthouse.dev/guide/)\n- [CLI Integration](https://unlighthouse.dev/integrations/cli.html)\n- [CI Integration](https://unlighthouse.dev/integrations/ci.html)\n- [API Reference](https://unlighthouse.dev/api/)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n","isInternal":false,"tokens":538,"sizeBytes":2172}],"systemPromptSnippet":"<yakaai_skills repo=\"harlan-zw/unlighthouse\">\n<!-- File: packages/unlighthouse/skills/unlighthouse/SKILL.md (Tokens: ~2071 | Category: anthropic-skill) -->\n---\nname: unlighthouse\ndescription: Run Google Lighthouse on every page of a site with the unlighthouse CLI, and fail CI on low scores with unlighthouse-ci. Use when a task mentions unlighthouse, unlighthouse-ci, site-wide Lighthouse scans, performance budgets in CI, unlighthouse.config.ts, defineUnlighthouseConfig, scanner.exclude, dynamic sampling, the authenticate hook, or a scan that never exits, skips pages, or refuses to clear its output folder.\nlicense: MIT\ncompatibility: \"Requires Node.js >=22.18.0.\"\n---\n\n# unlighthouse\n\nTested on Node 24 against the `unlighthouse` release that ships this Skill (requires Node `>=22.18.0`).\nThe package finds the URLs of a site and runs Lighthouse on each one in parallel Chrome instances.\nIt ships two binaries: `unlighthouse` opens a live dashboard, and `unlighthouse-ci` exits with a status code. Docs: https://unlighthouse.dev\n\n## Setup\n\n```bash\nnpx unlighthouse-ci --site https://example.com --budget 80\n```\n\n- Install `unlighthouse` for both binaries. `@unlighthouse/cli` ships only `unlighthouse-ci`.\n- Do not install `puppeteer`. `puppeteer-cluster` already depends on it.\n- Chrome: the package uses the system Chrome. If there is none, it downloads Chrome to `~/.unlighthouse`. As root, it adds `--no-sandbox` itself.\n- Add `.unlighthouse` to `.gitignore`.\n- `@unlighthouse/nuxt`, `@unlighthouse/vite`, and `@unlighthouse/webpack` are deprecated. Run the CLI against the dev server URL instead.\n- The config file is `unlighthouse.config.ts` in the current directory. A CLI flag you pass wins over the config file. A flag you leave out keeps the config value.\n\n## Pick the binary\n\n- **`unlighthouse-ci`** scans, writes reports, and exits. Exit code 1 means a budget failed, or no route was left to scan. Use it in scripts, CI, and Agent runs.\n- **`unlighthouse`** starts a dashboard server (port 5678 by default), opens a browser, and keeps running after the scan. It never exits by itself.\n\n## Automatic behaviour\n\n- **URL discovery:** `urls` if set, else robots.txt, then sitemap.xml, then a crawler that follows links from the home page. Robots.txt `Disallow` lines become excludes.\n- **`--urls` or `urls`** turns off robots.txt, sitemap, crawler, and sampling. The paths are relative to `site`.\n- **A `site` with a path**, such as `https://example.com/docs`, turns off sitemap, robots.txt, and sampling.\n- **A sitemap with 50 or more URLs** turns off the crawler, except on `localhost`.\n- **Dynamic sampling** scans at most 8 random URLs per route group, such as `/blog/*`. Turn it off with `--disable-dynamic-sampling`.\n- **`scanner.maxRoutes`** (200) stops the queue. It logs a warning and exits 0.\n- **HTML inspection skips JavaScript.** If the home page has no links, the crawler turns JavaScript on and retries. For an SPA, pass `--enable-javascript`.\n- **Device** is mobile. Pass `--desktop` for desktop.\n- **Throttling** is simulated for a remote site and off for a local one (`localhost`, `127.0.0.1`). An explicit `scanner.throttle` or `--throttle` wins.\n- **Redirects:** if `site` redirects to another host, such as http to https or apex to www, the scan uses the redirect target.\n\n## Common tasks\n\nPer category budgets, reporters, and scope in one config:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://staging.example.com',\n  scanner: {\n    exclude: ['/admin/**', '/api/**'],\n    include: ['/', /^\\/blog\\//, '/docs/**'], // keep '/' so the crawler can start\n  },\n  ci: {\n    budget: { 'performance': 70, 'accessibility': 95, 'best-practices': 90, 'seo': 90 },\n    reporter: 'jsonExpanded',\n  },\n})\n```\n\n- Budgets use 0 to 100. Report scores use 0 to 1. A budget of 80 fails a score of 0.79.\n- Reporters: `json` (default), `jsonExpanded`, `csv`, `csvExpanded`, `lighthouseServer`. The file is `<outputPath>/ci-result.json` or `ci-result.csv`.\n- `lighthouseServer` needs `--lhci-host` and `--lhci-build-token`.\n\nStatic HTML report: pass `--build-static`, or set `ci.buildStatic: true`. It writes `index.html` to the root of `outputPath` (`.unlighthouse`). Upload that folder. It deletes the per page `lighthouse.json` files.\n\nAuthentication: the `authenticate` hook gets the Puppeteer `Page` as its first argument. It runs once. Its cookies reach every scanned page, including the Lighthouse run, and only the hosts they belong to.\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  auth: { username: 'admin', password: process.env.AUTH_PASS! },\n  hooks: {\n    async authenticate(page) {\n      await page.goto('https://example.com/login')\n      await page.type('input[name=\"email\"]', 'test@example.com')\n      await Promise.all([page.waitForNavigation(), page.click('button[type=\"submit\"]')])\n    },\n  },\n})\n```\n\nRead scores in a hook: `task-complete` fires once per task, so check `taskName`. `categories` is an array of `{ key, id, title, score }`.\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  hooks: {\n    'task-complete': (path, report, taskName) => {\n      if (taskName !== 'runLighthouseTask')\n        return\n      const performance = report.report?.categories.find(category => category.key === 'performance')\n      console.log(path, report.report?.score, performance?.score)\n    },\n  },\n})\n```\n\nProgrammatic scan: register `worker-finished` before `start()`. Without a provider, reports go to `.unlighthouse/<host>/<config hash>/`.\n\n```ts\nimport { createUnlighthouse } from 'unlighthouse'\n\nconst unlighthouse = await createUnlighthouse({ site: 'https://example.com', urls: ['/', '/about'] })\nunlighthouse.hooks.hook('worker-finished', async () => {\n  console.log(unlighthouse.worker.reports().map(r => [r.route.path, r.report?.score]))\n  await unlighthouse.worker.cluster.close()\n  process.exit(0)\n})\nawait unlighthouse.start()\n```\n\n## Traps\n\n- **`unlighthouse-ci` clears `outputPath` before it scans, and refuses a folder it did not create.** `--output-path .` exits 1 with `Refusing to clear ... it is not an unlighthouse output folder`. Point it at a new or empty folder. Unlighthouse marks its folders with a `.unlighthouse-output` file.\n- **String patterns are route patterns, not regex.** `--exclude-urls \"/blog/.*\"` excludes nothing. `*` matches one segment and `**` any depth, so use `/blog/**`, or a `RegExp` in the config.\n- **An `include` list that skips `/` stops a crawler scan.** The crawler starts from `/`, so nothing is queued and both binaries exit 1 with `No routes left to scan`. Add `'/'` to `include`, or use `--urls`.\n- **A hook that throws stops `unlighthouse-ci` with exit code 1.** Guard on `taskName` and optional fields.\n- **Dynamic sampling is random.** Two runs can scan different pages in one group. For stable CI results, pass `--urls` or turn sampling off.\n\n## Output\n\n- `unlighthouse-ci`: `.unlighthouse/ci-result.json` and `.unlighthouse/reports/<path>/lighthouse.json`.\n- `unlighthouse`: `.unlighthouse/<host>/<config hash>/`. A config change starts a new cache folder.\n\n## Config\n\n- `scanner.device` (`'mobile'`), `scanner.samples` (1, runs per page, averaged), `scanner.throttle` (on for remote sites, off for local ones).\n- `scanner.dynamicSampling` (8), `scanner.maxRoutes` (200), `scanner.crawler`, `scanner.sitemap`, `scanner.robotsTxt`.\n- `puppeteerClusterOptions.maxConcurrency` (half the CPU cores). Set 1 for stable performance scores.\n- `lighthouseOptions` passes through to Lighthouse. `onlyAudits` replaces `onlyCategories`.\n- `chrome.useSystem`, `chrome.downloadFallbackCacheDir`.\n- All options: https://unlighthouse.dev/api-doc/config\n\n## Debug\n\n- `--debug` logs the resolved config. A route that `include` or `exclude` drops logs `Skipping route based on include / exclude rules`.\n- \"Failed to queue routes for scanning\" means discovery found nothing. Check the `site` status and the robots.txt `Disallow` lines.\n- \"No routes left to scan\" means discovery found routes, and `include`, `exclude`, or robots.txt rules skipped all of them.\n\n<!-- File: packages/cli/README.md (Tokens: ~446 | Category: plugin-manifest) -->\n# @unlighthouse/cli\n\nThe command-line interface and CI integration for [Unlighthouse](https://github.com/harlan-zw/unlighthouse), enabling automated website scanning in development and deployment workflows.\n\n## Installation\n\n```bash\n# Use directly with npx\nnpx unlighthouse --site https://example.com\n\n# Or install globally\nnpm install -g @unlighthouse/cli\n```\n\n## Usage\n\n### Basic Scanning\n\n```bash\n# Scan a website\nunlighthouse --site https://example.com\n\n# Enable debug mode\nunlighthouse --site https://example.com --debug\n\n# Mobile device simulation\nunlighthouse --site https://example.com --mobile\n```\n\n### Advanced Options\n\n```bash\n# Multiple samples with throttling\nunlighthouse --site https://example.com --samples 3 --throttle\n\n# Custom URLs and exclusions\nunlighthouse --site https://example.com --urls /home,/about,/contact --exclude-urls '/admin/**'\n\n# With custom configuration\nunlighthouse --site https://example.com --config-file ./my-config.ts\n```\n\n### CI Integration\n\n```bash\n# CI mode with exit codes for failed audits\nunlighthouse-ci --site https://example.com --budget 75\n```\n\n## Configuration\n\nCreate `unlighthouse.config.ts` in your project root:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  debug: true,\n  scanner: {\n    device: 'desktop',\n    throttle: false,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility'],\n  }\n})\n```\n\n## Documentation\n\n- [CLI Integration Guide](https://unlighthouse.dev/integrations/cli.html)\n- [CI Integration Guide](https://unlighthouse.dev/integrations/ci.html)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n\n<!-- File: packages/client/README.md (Tokens: ~175 | Category: plugin-manifest) -->\n# @unlighthouse/client\n\nThe Vue-based user interface for [Unlighthouse](https://github.com/harlan-zw/unlighthouse), providing an interactive dashboard to view and analyze Lighthouse scan results.\n\n## Features\n\n- Interactive dashboard with performance metrics\n- Real-time scan progress tracking\n- Detailed Lighthouse reports per page\n- Performance charts and visualizations\n- Export capabilities\n\n## Development\n\n```bash\n# Install dependencies\npnpm install\n\n# Start development server\npnpm dev\n\n# Build for production\npnpm build\n```\n\n## Documentation\n\n- [Integration Guide](https://unlighthouse.dev/integrations/)\n- [API Reference](https://unlighthouse.dev/api/index.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n\n<!-- File: packages/core/README.md (Tokens: ~360 | Category: plugin-manifest) -->\n# @unlighthouse/core\n\nThe core engine of [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that handles website scanning, Lighthouse execution, and report generation.\n\n## Usage\n\n### Basic Usage\n\n```ts\nimport { createUnlighthouse } from '@unlighthouse/core'\n\nconst unlighthouse = await createUnlighthouse({\n  site: 'https://example.com',\n  debug: true,\n  scanner: {\n    device: 'desktop',\n  }\n})\n\nawait unlighthouse.start()\n```\n\n### With Custom Provider\n\n```ts\nimport { createUnlighthouse } from '@unlighthouse/core'\n\nconst unlighthouse = await createUnlighthouse(\n  { /* user config */ },\n  {\n    name: 'custom',\n    routeDefinitions: () => generateRouteDefinitions(),\n  }\n)\n```\n\n### Hooks\n\n```ts\nimport { useUnlighthouse } from '@unlighthouse/core'\n\nconst { hooks } = useUnlighthouse()\n\nhooks.hook('task-complete', (path, response) => {\n  console.log('Task completed for:', path)\n})\n```\n\n## API\n\n- `createUnlighthouse(userConfig, provider?)` - Initialize Unlighthouse\n- `useUnlighthouse()` - Access the global Unlighthouse context\n- `generateClient(options)` - Generate static client files\n\n## Documentation\n\n- [API Reference](https://unlighthouse.dev/api/index.html)\n- [Configuration Guide](https://unlighthouse.dev/guide/config.html)\n- [Puppeteer Configuration](https://unlighthouse.dev/guide/puppeteer.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n\n<!-- File: packages/server/README.md (Tokens: ~176 | Category: plugin-manifest) -->\n# @unlighthouse/server\n\nThe server package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that provides the web server and API endpoints for the scanning interface.\n\n## Usage\n\n```ts\nimport { createServer } from '@unlighthouse/server'\n\nconst { server, app } = await createServer()\n// server is an instance of listhen, app is an instance of h3\nawait unlighthouse.setServerContext({ url: server.url, server: server.server, app })\nawait unlighthouse.start()\n```\n\n## Documentation\n\n- [API Reference](https://unlighthouse.dev/api/index.html)\n- [Configuration Guide](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n\n<!-- File: packages/unlighthouse-ci/README.md (Tokens: ~471 | Category: plugin-manifest) -->\n# unlighthouse-ci\n\nDedicated CI package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) that provides continuous integration capabilities with budget enforcement and exit codes.\n\n## Installation\n\n```bash\n# Use directly with npx\nnpx unlighthouse-ci --site https://example.com\n\n# Or install globally\nnpm install -g unlighthouse-ci\n```\n\n## Usage\n\n### Basic CI Scanning\n\n```bash\n# Run CI scan with default budget (75)\nunlighthouse-ci --site https://example.com\n\n# Custom performance budget\nunlighthouse-ci --site https://example.com --budget 85\n\n# Desktop scanning with custom output\nunlighthouse-ci --site https://example.com --desktop --output-path ./lighthouse-reports\n```\n\n### GitHub Actions Integration\n\n```yaml\nname: Lighthouse CI\non: [push, pull_request]\njobs:\n  lighthouse:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run Lighthouse CI\n        run: npx unlighthouse-ci --site ${{ secrets.SITE_URL }} --budget 80\n```\n\n### Features\n\n- Performance budget enforcement with configurable thresholds\n- Exit codes for CI/CD pipeline integration\n- Static report generation for hosting\n- Comprehensive logging and debugging\n- Support for custom Lighthouse configurations\n\n## Configuration\n\nCreate `unlighthouse.config.ts` for advanced CI configuration:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  ci: {\n    budget: 80,\n    buildStatic: true,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility', 'seo'],\n  }\n})\n```\n\n## Documentation\n\n- [CI Integration Guide](https://unlighthouse.dev/integrations/ci.html)\n- [GitHub Actions Example](https://unlighthouse.dev/integrations/ci.html#github-actions)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n\n<!-- File: packages/unlighthouse/README.md (Tokens: ~538 | Category: plugin-manifest) -->\n# unlighthouse\n\nThe main package for [Unlighthouse](https://github.com/harlan-zw/unlighthouse) - scan your entire website with Google Lighthouse. This is a convenience package that includes the core functionality and CLI tools.\n\n## Quick Start\n\n```bash\n# Scan your website instantly\nnpx unlighthouse --site https://example.com\n\n# CI mode with performance budgets\nnpx unlighthouse-ci --site https://example.com --budget 80\n```\n\n## What's Included\n\nThis package includes:\n- `@unlighthouse/core` - Core scanning engine\n- `@unlighthouse/cli` - Command-line interface\n- `@unlighthouse/client` - Web interface for results\n- Two binaries: `unlighthouse` and `unlighthouse-ci`\n\n## Installation\n\n```bash\n# Global installation\nnpm install -g unlighthouse\n\n# Project dependency\nnpm install unlighthouse --save-dev\n```\n\n## Usage\n\n### Interactive CLI\n\n```bash\n# Basic scan\nunlighthouse --site https://example.com\n\n# With debugging and custom device\nunlighthouse --site https://example.com --debug --desktop\n\n# Custom configuration\nunlighthouse --config-file unlighthouse.config.ts\n```\n\n### Programmatic Usage\n\n```ts\nimport { createUnlighthouse } from 'unlighthouse'\n\nconst unlighthouse = await createUnlighthouse({\n  site: 'https://example.com',\n  debug: true\n})\n\nawait unlighthouse.start()\n```\n\n### CI Integration\n\n```bash\n# Enforce performance budgets in CI\nunlighthouse-ci --site https://example.com --budget 85\n```\n\n## Configuration\n\nCreate `unlighthouse.config.ts`:\n\n```ts\nimport { defineUnlighthouseConfig } from 'unlighthouse/config'\n\nexport default defineUnlighthouseConfig({\n  site: 'https://example.com',\n  scanner: {\n    device: 'desktop',\n    throttle: false,\n  },\n  lighthouseOptions: {\n    onlyCategories: ['performance', 'accessibility'],\n  }\n})\n```\n\n## Documentation\n\n- [Getting Started Guide](https://unlighthouse.dev/guide/)\n- [CLI Integration](https://unlighthouse.dev/integrations/cli.html)\n- [CI Integration](https://unlighthouse.dev/integrations/ci.html)\n- [API Reference](https://unlighthouse.dev/api/)\n- [Configuration Reference](https://unlighthouse.dev/guide/config.html)\n\n## License\n\nMIT License © 2021-PRESENT [Harlan Wilton](https://github.com/harlan-zw)\n</yakaai_skills>"}