[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71KCYWT09M17HJTH66W49AS":3,"skill-same:01M71KCYWT09M17HJTH66W49AS":85},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":46,"linkOnly":47,"markdownContent":48,"markdownBody":49,"frontMatter":50,"refName":62,"commitSha":63,"skillDirectory":64,"forksCount":65,"repositoryHtmlUrl":66,"repositoryHomepageUrl":67,"ownerHtmlUrl":68,"ownerBlogUrl":69,"ownerDescription":70,"updatedAt":71,"install":72,"resources":84},"01M71KCYWT09M17HJTH66W49AS","browse",null,"Playwright-powered browser automation and E2E testing for SolanaOS Hub. Covers test configuration, agent-driven test generation (planner\u002Fgenerator\u002Fhealer), NanoHub route testing, Convex API validation, wallet flow testing, IPFS Hub verification, and CI\u002FCD integration. Use when asked about E2E tests, browser automation, Playwright setup, NanoHub testing, visual regression, or Hub route verification.","clawdsolana\u002FOpenClawd","clawdsolana","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F279036008?v=4","01M71JTVF9FNGKE2SVJRPTQM31","OpenClawd","01M71JTVGCKWBSS8ZYC1HYWVA5",2,"MIT","https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fskills\u002Fbrowse\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[5,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"regression","solanaos","when","for","CI\u002FCD","ipfs","visual regression","route","Wallet","node","testing","api","flow","ci","verification","browser","e2e tests","windows","browser automation","2026-11-10 10:12:30",false,"---\nname: browse\ndescription: \"Playwright-powered browser automation and E2E testing for SolanaOS Hub. Covers test configuration, agent-driven test generation (planner\u002Fgenerator\u002Fhealer), NanoHub route testing, Convex API validation, wallet flow testing, IPFS Hub verification, and CI\u002FCD integration. Use when asked about E2E tests, browser automation, Playwright setup, NanoHub testing, visual regression, or Hub route verification.\"\nversion: 1.0.0\nmetadata: {\"solanaos\":{\"emoji\":\"🎭\",\"requires\":{\"bins\":[\"node\",\"npx\",\"bun\"]},\"os\":[\"darwin\",\"linux\",\"windows\"]}}\n---\n\n# Browse — Playwright E2E Testing for SolanaOS Hub\n\nBrowser automation and end-to-end testing skill for the SolanaOS NanoHub, powered by Playwright.\n\n## Quick Start\n\n```bash\n# Install Playwright browsers\nnpx playwright install chromium\n\n# Run E2E tests\nbun run test:e2e\n\n# Run with UI mode\nnpx playwright test --ui\n\n# Generate tests interactively\nnpx playwright codegen https:\u002F\u002Fseeker.solanaos.net\n```\n\n## NanoHub Test Configuration\n\nThe NanoHub uses a dual config setup:\n\n### Playwright Config (`playwright.config.ts`)\n\nBrowser-based E2E tests against the built frontend.\n\n```typescript\nimport { defineConfig, devices } from '@playwright\u002Ftest'\n\nexport default defineConfig({\n  testDir: '.\u002Fe2e',\n  testMatch: \u002F.*\\.pw\\.test\\.ts\u002F,\n  timeout: 60_000,\n  expect: { timeout: 10_000 },\n  fullyParallel: true,\n  retries: process.env.CI ? 2 : 0,\n  use: {\n    baseURL: process.env.PLAYWRIGHT_BASE_URL || 'http:\u002F\u002F127.0.0.1:4173',\n    trace: 'retain-on-failure',\n  },\n  webServer: {\n    command: 'bun run preview -- --host 127.0.0.1 --port 4173',\n    url: 'http:\u002F\u002F127.0.0.1:4173',\n    reuseExistingServer: !process.env.CI,\n  },\n  projects: [\n    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },\n  ],\n})\n```\n\n### Vitest E2E Config (`vitest.e2e.config.ts`)\n\nNode-based E2E tests for CLI and API validation (no browser needed).\n\n```bash\nbun vitest run -c vitest.e2e.config.ts\n```\n\n## NanoHub Routes to Test\n\n| Route | Auth | What to verify |\n|-------|------|----------------|\n| `\u002F` | No | Landing page renders, navigation works |\n| `\u002Flaunch` | No | Boot sequence animation, CTA links |\n| `\u002Fmobile` | No | Seeker mobile walkthrough renders |\n| `\u002Fskills` | No | Skill cards load from Convex |\n| `\u002Fsouls` | No | Soul cards load from Convex |\n| `\u002Fipfs` | No | IPFS Hub page renders, wallet input works |\n| `\u002Fagents` | No | Agent directory loads public agents |\n| `\u002Fdashboard` | Yes | Wallet connect, agent factory, pairing |\n| `\u002Fupload` | Yes | Skill publish flow with file upload |\n| `\u002Fsettings` | Yes | User preferences, agent config |\n| `\u002Fmining` | No | BitAxe fleet dashboard renders |\n| `\u002Fstrategy` | No | Strategy builder loads |\n| `\u002Fcreate` | Yes | Skill creator wizard |\n| `\u002Fauth\u002Fcallback` | No | GitHub OAuth redirect handling |\n\n## Writing Hub Tests\n\n### Public Route Test\n\n```typescript\nimport { test, expect } from '@playwright\u002Ftest'\n\ntest('IPFS Hub page loads', async ({ page }) => {\n  await page.goto('\u002Fipfs')\n  await expect(page.locator('h1')).toContainText('Private IPFS')\n  await expect(page.locator('.gallery-stat-card')).toHaveCount(4)\n})\n\ntest('agent directory shows cards', async ({ page }) => {\n  await page.goto('\u002Fagents')\n  await expect(page.locator('h1')).toContainText('Registered')\n  \u002F\u002F Wait for Convex query\n  await page.waitForSelector('.agent-card', { timeout: 10_000 })\n})\n\ntest('skill search works', async ({ page }) => {\n  await page.goto('\u002Fskills')\n  await page.locator('input[type=\"search\"]').fill('solanaos')\n  await page.waitForSelector('.skill-card')\n  await expect(page.locator('.skill-card')).toHaveCount.greaterThan(0)\n})\n```\n\n### Authenticated Route Test\n\n```typescript\nimport { test, expect } from '@playwright\u002Ftest'\n\n\u002F\u002F Use storage state from auth setup\ntest.use({ storageState: 'e2e\u002F.auth\u002Fuser.json' })\n\ntest('dashboard loads for authenticated user', async ({ page }) => {\n  await page.goto('\u002Fdashboard')\n  await expect(page.locator('.dashboard-section')).toBeVisible()\n})\n```\n\n### Convex API Test (Vitest, no browser)\n\n```typescript\nimport { describe, expect, it } from 'vitest'\n\nconst CONVEX_URL = process.env.CONVEX_URL || 'https:\u002F\u002Fartful-frog-940.convex.cloud'\n\ndescribe('Convex IPFS API', () => {\n  it('GET \u002Fapi\u002Fv1\u002Fipfs\u002Ffiles returns array', async () => {\n    const res = await fetch(\n      `${CONVEX_URL}\u002Fapi\u002Fv1\u002Fipfs\u002Ffiles?wallet=test`,\n      { headers: { Accept: 'application\u002Fjson' } }\n    )\n    expect(res.ok).toBe(true)\n    const data = await res.json()\n    expect(data).toHaveProperty('files')\n    expect(Array.isArray(data.files)).toBe(true)\n  })\n\n  it('GET \u002Fapi\u002Fv1\u002Fipfs\u002Fstats returns stats object', async () => {\n    const res = await fetch(\n      `${CONVEX_URL}\u002Fapi\u002Fv1\u002Fipfs\u002Fstats?wallet=test`,\n      { headers: { Accept: 'application\u002Fjson' } }\n    )\n    expect(res.ok).toBe(true)\n    const data = await res.json()\n    expect(data.stats).toHaveProperty('totalFiles')\n  })\n})\n```\n\n## Playwright Agents (AI-Driven Testing)\n\nPlaywright includes three built-in AI test agents.\n\n### Setup\n\n```bash\nnpx playwright init-agents --loop=vscode\n```\n\n### Planner\n\nExplores the app and produces a Markdown test plan.\n\n```\nInput: \"Generate a test plan for the IPFS Hub upload and recall flow\"\nOutput: specs\u002Fipfs-hub.md\n```\n\nThe planner needs a **seed test** that sets up the environment:\n\n```typescript\n\u002F\u002F tests\u002Fseed.spec.ts\nimport { test } from '@playwright\u002Ftest'\n\ntest('seed', async ({ page }) => {\n  await page.goto('\u002F')\n})\n```\n\n### Generator\n\nTransforms Markdown plans into executable Playwright test files.\n\n```\nInput: specs\u002Fipfs-hub.md\nOutput: tests\u002Fipfs-hub\u002Fupload-file.spec.ts\n```\n\n### Healer\n\nAutomatically repairs failing tests by:\n1. Replaying failing steps\n2. Inspecting current UI for equivalent elements\n3. Patching locators, waits, or data\n4. Re-running until pass or skip\n\n```\nInput: \"Heal tests\u002Fipfs-hub\u002Fupload-file.spec.ts\"\nOutput: Passing test (or skipped with reason)\n```\n\n## Configuration Reference\n\n### Top-Level Options\n\n| Option | Description |\n|--------|-------------|\n| `testDir` | Directory with test files |\n| `testMatch` | Glob\u002Fregex for test file matching |\n| `testIgnore` | Glob\u002Fregex for files to skip |\n| `timeout` | Per-test timeout (default: 30s) |\n| `retries` | Retry count for flaky tests |\n| `workers` | Parallel worker count |\n| `fullyParallel` | Run all tests in parallel |\n| `forbidOnly` | Fail if `test.only` found (CI) |\n| `reporter` | Output format: `list`, `html`, `json`, `dot` |\n| `outputDir` | Artifacts directory (screenshots, videos, traces) |\n| `globalSetup` | Path to setup script (runs before all tests) |\n| `globalTeardown` | Path to teardown script (runs after all tests) |\n| `webServer` | Auto-start dev server before tests |\n\n### `use` Options\n\n| Option | Description |\n|--------|-------------|\n| `baseURL` | Base URL for `page.goto('\u002F')` |\n| `storageState` | Pre-populated auth state |\n| `trace` | Trace capture: `off`, `on`, `retain-on-failure`, `on-first-retry` |\n| `screenshot` | Screenshot capture: `off`, `on`, `only-on-failure` |\n| `video` | Video recording: `off`, `on`, `retain-on-failure` |\n| `headless` | Run without browser UI (default: true) |\n| `viewport` | Browser viewport size |\n| `locale` | User locale emulation |\n| `colorScheme` | `light` or `dark` mode |\n| `geolocation` | GPS coordinate emulation |\n| `permissions` | Browser permission grants |\n| `offline` | Simulate offline mode |\n| `proxy` | HTTP proxy settings |\n| `extraHTTPHeaders` | Headers sent with every request |\n| `actionTimeout` | Timeout per action (click, fill, etc.) |\n| `testIdAttribute` | Custom test ID attribute |\n\n### Annotations\n\n```typescript\n\u002F\u002F Skip a test\ntest.skip('not ready', async ({ page }) => {})\n\n\u002F\u002F Mark as expected failure\ntest.fail('known bug', async ({ page }) => {})\n\n\u002F\u002F Mark as slow (3x timeout)\ntest.slow()\n\n\u002F\u002F Tag for filtering\ntest('login @smoke', async ({ page }) => {})\ntest('checkout', { tag: ['@e2e', '@slow'] }, async ({ page }) => {})\n\n\u002F\u002F Run tagged tests\n\u002F\u002F npx playwright test --grep @smoke\n\u002F\u002F npx playwright test --grep-invert @slow\n```\n\n## CLI Commands\n\n```bash\n# Run all tests\nnpx playwright test\n\n# Run specific file\nnpx playwright test e2e\u002Fipfs-hub.pw.test.ts\n\n# Run by title match\nnpx playwright test -g \"IPFS Hub\"\n\n# Run with browser visible\nnpx playwright test --headed\n\n# Debug mode (inspector + slow)\nnpx playwright test --debug\n\n# Interactive UI mode\nnpx playwright test --ui\n\n# Generate test code interactively\nnpx playwright codegen https:\u002F\u002Fseeker.solanaos.net\n\n# View last test report\nnpx playwright show-report\n\n# View trace file\nnpx playwright show-trace test-results\u002Ftrace.zip\n\n# Only re-run failures\nnpx playwright test --last-failed\n\n# Shard across CI workers\nnpx playwright test --shard=1\u002F3\n```\n\n## CI Integration\n\n```yaml\n# .github\u002Fworkflows\u002Fe2e.yml\nname: E2E Tests\non: [push, pull_request]\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: oven-sh\u002Fsetup-bun@v2\n      - run: bun install\n      - run: npx playwright install --with-deps chromium\n      - run: bun run build\n      - run: npx playwright test\n      - uses: actions\u002Fupload-artifact@v4\n        if: failure()\n        with:\n          name: playwright-report\n          path: playwright-report\u002F\n```\n\n## NanoHub E2E Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `PLAYWRIGHT_BASE_URL` | Override base URL (skip local server) |\n| `PLAYWRIGHT_PORT` | Override preview server port (default: 4173) |\n| `CLAWHUB_E2E_TOKEN` | API token for authenticated CLI tests |\n| `CLAWDHUB_E2E_TOKEN` | Alias for above |\n| `CLAWHUB_REGISTRY` | Registry URL override |\n| `CLAWHUB_SITE` | Site URL override |\n| `CI` | Enables retries, single worker, forbidOnly |\n","# Browse — Playwright E2E Testing for SolanaOS Hub\n\nBrowser automation and end-to-end testing skill for the SolanaOS NanoHub, powered by Playwright.\n\n## Quick Start\n\n```bash\n# Install Playwright browsers\nnpx playwright install chromium\n\n# Run E2E tests\nbun run test:e2e\n\n# Run with UI mode\nnpx playwright test --ui\n\n# Generate tests interactively\nnpx playwright codegen https:\u002F\u002Fseeker.solanaos.net\n```\n\n## NanoHub Test Configuration\n\nThe NanoHub uses a dual config setup:\n\n### Playwright Config (`playwright.config.ts`)\n\nBrowser-based E2E tests against the built frontend.\n\n```typescript\nimport { defineConfig, devices } from '@playwright\u002Ftest'\n\nexport default defineConfig({\n  testDir: '.\u002Fe2e',\n  testMatch: \u002F.*\\.pw\\.test\\.ts\u002F,\n  timeout: 60_000,\n  expect: { timeout: 10_000 },\n  fullyParallel: true,\n  retries: process.env.CI ? 2 : 0,\n  use: {\n    baseURL: process.env.PLAYWRIGHT_BASE_URL || 'http:\u002F\u002F127.0.0.1:4173',\n    trace: 'retain-on-failure',\n  },\n  webServer: {\n    command: 'bun run preview -- --host 127.0.0.1 --port 4173',\n    url: 'http:\u002F\u002F127.0.0.1:4173',\n    reuseExistingServer: !process.env.CI,\n  },\n  projects: [\n    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },\n  ],\n})\n```\n\n### Vitest E2E Config (`vitest.e2e.config.ts`)\n\nNode-based E2E tests for CLI and API validation (no browser needed).\n\n```bash\nbun vitest run -c vitest.e2e.config.ts\n```\n\n## NanoHub Routes to Test\n\n| Route | Auth | What to verify |\n|-------|------|----------------|\n| `\u002F` | No | Landing page renders, navigation works |\n| `\u002Flaunch` | No | Boot sequence animation, CTA links |\n| `\u002Fmobile` | No | Seeker mobile walkthrough renders |\n| `\u002Fskills` | No | Skill cards load from Convex |\n| `\u002Fsouls` | No | Soul cards load from Convex |\n| `\u002Fipfs` | No | IPFS Hub page renders, wallet input works |\n| `\u002Fagents` | No | Agent directory loads public agents |\n| `\u002Fdashboard` | Yes | Wallet connect, agent factory, pairing |\n| `\u002Fupload` | Yes | Skill publish flow with file upload |\n| `\u002Fsettings` | Yes | User preferences, agent config |\n| `\u002Fmining` | No | BitAxe fleet dashboard renders |\n| `\u002Fstrategy` | No | Strategy builder loads |\n| `\u002Fcreate` | Yes | Skill creator wizard |\n| `\u002Fauth\u002Fcallback` | No | GitHub OAuth redirect handling |\n\n## Writing Hub Tests\n\n### Public Route Test\n\n```typescript\nimport { test, expect } from '@playwright\u002Ftest'\n\ntest('IPFS Hub page loads', async ({ page }) => {\n  await page.goto('\u002Fipfs')\n  await expect(page.locator('h1')).toContainText('Private IPFS')\n  await expect(page.locator('.gallery-stat-card')).toHaveCount(4)\n})\n\ntest('agent directory shows cards', async ({ page }) => {\n  await page.goto('\u002Fagents')\n  await expect(page.locator('h1')).toContainText('Registered')\n  \u002F\u002F Wait for Convex query\n  await page.waitForSelector('.agent-card', { timeout: 10_000 })\n})\n\ntest('skill search works', async ({ page }) => {\n  await page.goto('\u002Fskills')\n  await page.locator('input[type=\"search\"]').fill('solanaos')\n  await page.waitForSelector('.skill-card')\n  await expect(page.locator('.skill-card')).toHaveCount.greaterThan(0)\n})\n```\n\n### Authenticated Route Test\n\n```typescript\nimport { test, expect } from '@playwright\u002Ftest'\n\n\u002F\u002F Use storage state from auth setup\ntest.use({ storageState: 'e2e\u002F.auth\u002Fuser.json' })\n\ntest('dashboard loads for authenticated user', async ({ page }) => {\n  await page.goto('\u002Fdashboard')\n  await expect(page.locator('.dashboard-section')).toBeVisible()\n})\n```\n\n### Convex API Test (Vitest, no browser)\n\n```typescript\nimport { describe, expect, it } from 'vitest'\n\nconst CONVEX_URL = process.env.CONVEX_URL || 'https:\u002F\u002Fartful-frog-940.convex.cloud'\n\ndescribe('Convex IPFS API', () => {\n  it('GET \u002Fapi\u002Fv1\u002Fipfs\u002Ffiles returns array', async () => {\n    const res = await fetch(\n      `${CONVEX_URL}\u002Fapi\u002Fv1\u002Fipfs\u002Ffiles?wallet=test`,\n      { headers: { Accept: 'application\u002Fjson' } }\n    )\n    expect(res.ok).toBe(true)\n    const data = await res.json()\n    expect(data).toHaveProperty('files')\n    expect(Array.isArray(data.files)).toBe(true)\n  })\n\n  it('GET \u002Fapi\u002Fv1\u002Fipfs\u002Fstats returns stats object', async () => {\n    const res = await fetch(\n      `${CONVEX_URL}\u002Fapi\u002Fv1\u002Fipfs\u002Fstats?wallet=test`,\n      { headers: { Accept: 'application\u002Fjson' } }\n    )\n    expect(res.ok).toBe(true)\n    const data = await res.json()\n    expect(data.stats).toHaveProperty('totalFiles')\n  })\n})\n```\n\n## Playwright Agents (AI-Driven Testing)\n\nPlaywright includes three built-in AI test agents.\n\n### Setup\n\n```bash\nnpx playwright init-agents --loop=vscode\n```\n\n### Planner\n\nExplores the app and produces a Markdown test plan.\n\n```\nInput: \"Generate a test plan for the IPFS Hub upload and recall flow\"\nOutput: specs\u002Fipfs-hub.md\n```\n\nThe planner needs a **seed test** that sets up the environment:\n\n```typescript\n\u002F\u002F tests\u002Fseed.spec.ts\nimport { test } from '@playwright\u002Ftest'\n\ntest('seed', async ({ page }) => {\n  await page.goto('\u002F')\n})\n```\n\n### Generator\n\nTransforms Markdown plans into executable Playwright test files.\n\n```\nInput: specs\u002Fipfs-hub.md\nOutput: tests\u002Fipfs-hub\u002Fupload-file.spec.ts\n```\n\n### Healer\n\nAutomatically repairs failing tests by:\n1. Replaying failing steps\n2. Inspecting current UI for equivalent elements\n3. Patching locators, waits, or data\n4. Re-running until pass or skip\n\n```\nInput: \"Heal tests\u002Fipfs-hub\u002Fupload-file.spec.ts\"\nOutput: Passing test (or skipped with reason)\n```\n\n## Configuration Reference\n\n### Top-Level Options\n\n| Option | Description |\n|--------|-------------|\n| `testDir` | Directory with test files |\n| `testMatch` | Glob\u002Fregex for test file matching |\n| `testIgnore` | Glob\u002Fregex for files to skip |\n| `timeout` | Per-test timeout (default: 30s) |\n| `retries` | Retry count for flaky tests |\n| `workers` | Parallel worker count |\n| `fullyParallel` | Run all tests in parallel |\n| `forbidOnly` | Fail if `test.only` found (CI) |\n| `reporter` | Output format: `list`, `html`, `json`, `dot` |\n| `outputDir` | Artifacts directory (screenshots, videos, traces) |\n| `globalSetup` | Path to setup script (runs before all tests) |\n| `globalTeardown` | Path to teardown script (runs after all tests) |\n| `webServer` | Auto-start dev server before tests |\n\n### `use` Options\n\n| Option | Description |\n|--------|-------------|\n| `baseURL` | Base URL for `page.goto('\u002F')` |\n| `storageState` | Pre-populated auth state |\n| `trace` | Trace capture: `off`, `on`, `retain-on-failure`, `on-first-retry` |\n| `screenshot` | Screenshot capture: `off`, `on`, `only-on-failure` |\n| `video` | Video recording: `off`, `on`, `retain-on-failure` |\n| `headless` | Run without browser UI (default: true) |\n| `viewport` | Browser viewport size |\n| `locale` | User locale emulation |\n| `colorScheme` | `light` or `dark` mode |\n| `geolocation` | GPS coordinate emulation |\n| `permissions` | Browser permission grants |\n| `offline` | Simulate offline mode |\n| `proxy` | HTTP proxy settings |\n| `extraHTTPHeaders` | Headers sent with every request |\n| `actionTimeout` | Timeout per action (click, fill, etc.) |\n| `testIdAttribute` | Custom test ID attribute |\n\n### Annotations\n\n```typescript\n\u002F\u002F Skip a test\ntest.skip('not ready', async ({ page }) => {})\n\n\u002F\u002F Mark as expected failure\ntest.fail('known bug', async ({ page }) => {})\n\n\u002F\u002F Mark as slow (3x timeout)\ntest.slow()\n\n\u002F\u002F Tag for filtering\ntest('login @smoke', async ({ page }) => {})\ntest('checkout', { tag: ['@e2e', '@slow'] }, async ({ page }) => {})\n\n\u002F\u002F Run tagged tests\n\u002F\u002F npx playwright test --grep @smoke\n\u002F\u002F npx playwright test --grep-invert @slow\n```\n\n## CLI Commands\n\n```bash\n# Run all tests\nnpx playwright test\n\n# Run specific file\nnpx playwright test e2e\u002Fipfs-hub.pw.test.ts\n\n# Run by title match\nnpx playwright test -g \"IPFS Hub\"\n\n# Run with browser visible\nnpx playwright test --headed\n\n# Debug mode (inspector + slow)\nnpx playwright test --debug\n\n# Interactive UI mode\nnpx playwright test --ui\n\n# Generate test code interactively\nnpx playwright codegen https:\u002F\u002Fseeker.solanaos.net\n\n# View last test report\nnpx playwright show-report\n\n# View trace file\nnpx playwright show-trace test-results\u002Ftrace.zip\n\n# Only re-run failures\nnpx playwright test --last-failed\n\n# Shard across CI workers\nnpx playwright test --shard=1\u002F3\n```\n\n## CI Integration\n\n```yaml\n# .github\u002Fworkflows\u002Fe2e.yml\nname: E2E Tests\non: [push, pull_request]\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: oven-sh\u002Fsetup-bun@v2\n      - run: bun install\n      - run: npx playwright install --with-deps chromium\n      - run: bun run build\n      - run: npx playwright test\n      - uses: actions\u002Fupload-artifact@v4\n        if: failure()\n        with:\n          name: playwright-report\n          path: playwright-report\u002F\n```\n\n## NanoHub E2E Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `PLAYWRIGHT_BASE_URL` | Override base URL (skip local server) |\n| `PLAYWRIGHT_PORT` | Override preview server port (default: 4173) |\n| `CLAWHUB_E2E_TOKEN` | API token for authenticated CLI tests |\n| `CLAWDHUB_E2E_TOKEN` | Alias for above |\n| `CLAWHUB_REGISTRY` | Registry URL override |\n| `CLAWHUB_SITE` | Site URL override |\n| `CI` | Enables retries, single worker, forbidOnly |\n",{"name":5,"version":51,"metadata":52,"description":7},"1.0.0",{"solanaos":53},{"os":54,"emoji":57,"requires":58},[55,56,44],"darwin","linux","🎭",{"bins":59},[36,60,61],"npx","bun","main","6b4a291df75c639681e93b4b5b812126443fd6ed","skills\u002Fbrowse",3,"https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd","https:\u002F\u002Fsolanaclawd.com\u002Fopenclawd","https:\u002F\u002Fgithub.com\u002Fclawdsolana","https:\u002F\u002Fmusebook.trade","Welcome to Open Clawd. The future of Ai on and off chain. Bringing webMCP to web 3 using X402, A2A, MPP and so much more!","2026-08-01 09:30:51",{"source":8,"skillName":5,"commands":73,"prompt":82,"zipAvailable":83},[74,76,79],{"tool":60,"command":75},"npx skills add clawdsolana\u002FOpenClawd --skill browse",{"tool":77,"command":78},"bunx","bunx skills add clawdsolana\u002FOpenClawd --skill browse",{"tool":80,"command":81},"pnpm","pnpm dlx skills add clawdsolana\u002FOpenClawd --skill browse","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fskills\u002Fbrowse\u002FSKILL.md",true,[],[86,112,136,162,172,196],{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":93,"publishedAt":111},"01M71KRBD0W01EAXJ8YM4M1SJ2","solana-dev","End-to-end Solana development playbook (Jan 2026). Prefer Solana Foundation framework-kit (@solana\u002Fclient + @solana\u002Freact-hooks) for React\u002FNext.js UI. Prefer @solana\u002Fkit for all new client\u002FRPC\u002Ftransaction code. When legacy dependencies require web3.js, isolate it behind @solana\u002Fweb3-compat (or @solana\u002Fweb3.js as a true legacy fallback). Covers wallet-standard-first connection (incl. ConnectorKit), Anchor\u002FPinocchio programs, Codama-based client generation, LiteSVM\u002FMollusk\u002FSurfpool testing, and security checklists.","https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Fsolana-dev\u002FSKILL.md",[92],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[94,95,96,35,97,37,98,99,100,29,101,102,103,104,105,106,107,108,109,110],"solana dev","dev","solana","end","hooks","kit","new","web3","code","react","next","2026","playbook","security","ui","fallback","framework","2026-11-10 10:56:23",{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":119,"publishedAt":111},"01M71KR8QPESSY61SVE8ZTFNVT","xurl","A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.","https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fskills\u002Fxurl\u002FSKILL.md",[118],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[114,120,121,122,123,124,125,29,126,38,127,128,129,130,131,132,30,133,134,135],"posts","Media","x api","search","send","tap","you","cli","read","install","cli tool","endpoint","brew","manage","tool","twitter",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":143,"publishedAt":111},"01M71KR6FSXV88YDKWP7NBY3SH","wurk-integration","WURK API integration for monetizing agents with x402 payments on Solana\u002FBase - create social jobs, custom challenges, and agent help tasks","https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fskills\u002Fwurk-integration\u002FSKILL.md",[142],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[144,145,146,147,148,149,150,151,38,152,153,154,155,156,157,158,30,159,160,161],"wurk","wurk integration","integration","x402","social","payments","tasks","team","create","social-jobs","command","agent-help","custom-jobs","clawd","safe","api integration","custom","true",{"skillNo":163,"name":164,"nameZh":6,"description":165,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":166,"categories":167,"keywords":168,"publishedAt":111},"01M71KR4HCX41BPAK9GP7RPRRP","workflows","Manage application workflows including configuration, restart, and removal.","https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fskills\u002Fworkflows\u002FSKILL.md",[],[164,133,169,170,171],"configuration","application","restart",{"skillNo":173,"name":174,"nameZh":6,"description":175,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":176,"categories":177,"keywords":178,"publishedAt":111},"01M71KR1VM0F5GPEQDNG5J7A0H","web-search","Search the web, fetch content, extract branding profiles, and capture screenshots from URLs. Use for real-time information, API documentation, current events, design matching, and visual reference.","https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fskills\u002Fweb-search\u002FSKILL.md",[],[179,123,180,181,182,30,183,184,185,186,187,188,189,38,190,191,192,193,194,195],"web search","web","fetch","api documentation","real-time","time","profiles","design","use","information","visual","documentation","branding","matching","reference","capture","content",{"skillNo":197,"name":198,"nameZh":6,"description":199,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":200,"categories":201,"keywords":202,"publishedAt":111},"01M71KQZN5MR1JFQHG5GWXYAHS","weather","Get current weather and forecasts via wttr.in or Open-Meteo. Use when: user asks about weather, temperature, or forecasts for any location. NOT for: historical weather data, severe weather alerts, or detailed meteorological analysis. No API key needed.","https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fskills\u002Fweather\u002FSKILL.md",[],[198,203,30,204,187,29,205,38,206,207,208,209,210,211,212,213,214,215],"get","open","analysis","alerts","temperature","curl","via","help","about","https","location","data","user"]