{"owner":"hyperdxio","repo":"hyperdx","hasSkills":true,"totalSkillsCount":46,"totalTokensCount":24805,"categories":["mcp-config","project-spec","subagent-persona","command-prompt","cursor-rule","anthropic-skill","root-instruction","plugin-manifest"],"hasMcp":true,"mcpConfig":{"mcpServers":{"playwright-test":{"command":"npx","args":["playwright","run-test-mcp-server"]}}},"found":[".cursor/mcp.json","agent_docs/architecture.md",".claude/agents/playwright-test-healer.md",".opencode/commands/do-linear.md",".claude/agents/playwright-test-planner.md",".opencode/commands/plan-linear.md",".claude/agents/playwright-test-generator.md",".cursor/rules/playwright.mdc",".claude/skills/refactor-component/SKILL.md",".claude/skills/playwright/SKILL.md","AGENTS.md","packages/otel-collector/builder-config.yaml","packages/otel-collector/CHANGELOG.md","packages/otel-collector/package.json","packages/otel-collector/README.md","packages/common-utils/CHANGELOG.md","packages/common-utils/package.json","packages/common-utils/README.md","packages/common-utils/tsconfig.json","packages/cli/AGENTS.md","packages/cli/CHANGELOG.md","packages/cli/CONTRIBUTING.md","packages/cli/package.json","packages/cli/README.md","packages/cli/tsconfig.json","packages/app/CHANGELOG.md","packages/app/package.json","packages/app/tsconfig.build.json","packages/app/tsconfig.json","packages/api/.spectral.yaml","packages/api/CHANGELOG.md","packages/api/nodemon.json","packages/api/openapi.json","packages/api/package.json","packages/api/tsconfig.build.json","packages/api/tsconfig.json","packages/app/public/pyodide/pyodide-lock.json","packages/app/src/dashboardTemplates/dotnet-runtime.json","packages/app/src/dashboardTemplates/go-runtime.json","packages/app/src/dashboardTemplates/jvm-runtime-metrics.json","packages/app/src/dashboardTemplates/nodejs-runtime.json","packages/app/src/dashboardTemplates/python-runtime.json","packages/app/tests/e2e/README.md","packages/api/docs/auto_provision/AUTO_PROVISION.md","packages/api/src/opamp/README.md","packages/app/tests/e2e/fixtures/e2e-fixtures.json"],"skills":{".cursor/mcp.json":"{\n  \"mcpServers\": {\n    \"playwright-test\": {\n      \"command\": \"npx\",\n      \"args\": [\"playwright\", \"run-test-mcp-server\"]\n    }\n  }\n}\n","agent_docs/architecture.md":"# HyperDX Architecture\n\n## Core Services\n\n- **HyperDX UI (`packages/app`)**: Next.js frontend serving the user interface\n- **HyperDX API (`packages/api`)**: Node.js/Express backend handling queries and business logic\n- **OpenTelemetry Collector**: Receives and processes telemetry data\n- **ClickHouse**: Primary data store for all telemetry (logs, metrics, traces)\n- **MongoDB**: Metadata storage (users, dashboards, alerts, saved searches)\n\n## Data Flow\n\n1. Applications send telemetry via OpenTelemetry → OTel Collector\n2. OTel Collector processes and forwards data → ClickHouse\n3. Users interact with UI → API queries ClickHouse\n4. Configuration/metadata stored in MongoDB\n\n## Key MongoDB Models\n\nAll models follow consistent patterns with:\n- Team-based multi-tenancy (most entities belong to a `team`)\n- ObjectId references between related entities\n- Timestamps for audit trails\n- Zod schema validation\n\n**Key Models** (see `packages/api/src/models/`):\n- `Team`: Multi-tenant organization unit\n- `User`: Team members with authentication\n- `Source`: ClickHouse data source configuration\n- `Connection`: Database connection settings\n- `SavedSearch`: Saved queries and filters\n- `Dashboard`: Custom dashboard configurations\n- `Alert`: Monitoring alerts with thresholds\n\n## Frontend Architecture\n\n- **Pages**: `packages/app/pages/` (Next.js routing)\n- **Components**: `packages/app/src/` (reusable components)\n- **API communication**: Custom hooks wrapping TanStack Query\n- **State**: See tech_stack.md for state management details\n\n## Backend Architecture\n\nThe API package (`packages/api`) hosts several distinct applications, each with\nits own routing, authentication, and rate limiting:\n\n### Internal API (`src/routers/api/`)\n\nThe primary API consumed by the web frontend (`packages/app`). Uses session-based\nauthentication (Passport.js). Follows a standard layered structure:\n\n- **Routers**: `src/routers/api/` - Domain-specific API routes\n- **Controllers**: `src/controllers/` - Business logic separated from routes\n- **Middleware**: `src/middleware/` - Authentication, CORS, error handling\n- **Services**: `src/services/` - Reusable business logic (e.g., `agentService`)\n\n### External API v2 (`src/routers/external-api/v2/`)\n\nPublic REST API for programmatic access. Authenticated via Personal API Access\nKey (`validateUserAccessKey` middleware), rate-limited to 100 req/min.\n\n- **Routes**: `alerts.ts`, `charts.ts`, `dashboards.ts`, `sources.ts`,\n  `webhooks.ts`\n- **OpenAPI spec**: `packages/api/openapi.json` (auto-generated via\n  `yarn docgen`, linted via `yarn lint:openapi` using Spectral)\n- **Tests**: `src/routers/external-api/__tests__/`\n\nWhen adding or modifying external API endpoints, run `yarn docgen` to regenerate\nthe OpenAPI spec and `yarn lint:openapi` to validate it.\n\n`scripts/ci/check-openapi-sync.sh` (run by `make ci-lint` and by CI) fails if the\ncommitted spec is stale. `swaggerOptions` in `src/utils/swagger.ts` is also an\ninput, and the spec is in `.prettierignore` because docgen owns its formatting.\n\n### MCP Server (`src/mcp/`)\n\n[Model Context Protocol](https://modelcontextprotocol.io/) server that lets AI\nassistants query observability data and manage dashboards. Exposed as a stateless\nStreamable HTTP endpoint at `/api/mcp`, authenticated via Personal API Access\nKey, rate-limited to 600 req/min.\n\n- **Entry**: `app.ts` (Express middleware), `mcpServer.ts` (server factory)\n- **Tools**: `tools/alerts/`, `tools/dashboards/`, `tools/query/`,\n  `tools/savedSearches/` - each directory contains tool definitions and handlers\n- **Prompts**: `prompts/dashboards/` - context prompts for AI assistants\n- **Tests**: `src/mcp/__tests__/` (alerts, dashboards, query, savedSearches,\n  tracing)\n- **Dev/debug**: `yarn dev:mcp` launches the MCP Inspector for interactive\n  testing\n- **Response size**: each tool call records the UTF-8 bytes it returns\n  (`mcp.tool.response.size_bytes` span attribute,\n  `hyperdx.mcp.tool.response.size_bytes` histogram)\n\nSee `MCP.md` in the repo root for user-facing setup instructions.\n\n### OpAMP Server (`src/opamp/`)\n\nHTTP-based [OpAMP](https://github.com/open-telemetry/opamp-spec) server that\nserves configurations to supervised OpenTelemetry Collectors. The supervisor\npings `/v1/opamp` with status, and the server returns updated config when needed.\n\n- **Entry**: `app.ts` (Express sub-app)\n- **Controller**: `controllers/opampController.ts` - config derivation logic\n- **Service**: `services/agentService.ts` - agent management\n- **Model**: `models/agent.ts` - agent state persistence\n- **Proto**: `proto/` - Protocol Buffer definitions for OpAMP and anyvalue\n\nConfig is derived from the team document with the ingestion API key.\n\n### Background Tasks (`src/tasks/`)\n\nCron-driven tasks that run outside the request/response cycle. In development,\ntasks run via `yarn dev-task`; in production, they are triggered externally.\n\n- `checkAlerts/` - Alert evaluation (runs every minute in dev)\n- `provisionDashboards/` - Dashboard provisioning from config files\n- `usageStats.ts` - Usage statistics collection\n- `pingPongTask.ts` - Health check task\n- `metrics.ts` - Task execution metrics (duration, success/failure counters)\n\nNote: Background tasks do **not** run in Vercel preview deployments (see\n`agent_docs/development.md` for details).\n\n## Data & Query Patterns\n\n### ClickHouse Integration\n- **Query building**: Use `common-utils` for safe query construction\n- **Schema flexibility**: Support for various telemetry schemas via `Source` configuration\n\n### MongoDB Patterns\n- **Multi-tenancy**: All queries filtered by team context\n- **Relationships**: Use ObjectId references with proper population\n- **Indexing**: Strategic indexes for query performance\n- **Migrations**: Versioned migrations for schema changes (see `packages/api/migrations/`)\n\n## Security Requirements\n\n- **Server-side validation**: Always validate and sanitize on the backend\n- **Team isolation**: All data access must filter by team context\n- **API authentication**: Use authentication middleware on protected routes\n- **Secrets**: Never commit secrets; use `.env` files\n\n",".claude/agents/playwright-test-healer.md":"---\nname: playwright-test-healer\ndescription: Use this agent when you need to debug and fix failing Playwright tests\ntools: Glob, Grep, Read, LS, Edit, MultiEdit, Write, mcp__playwright-test__browser_console_messages, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_generate_locator, mcp__playwright-test__browser_network_requests, mcp__playwright-test__browser_snapshot, mcp__playwright-test__test_debug, mcp__playwright-test__test_list, mcp__playwright-test__test_run\nmodel: sonnet\ncolor: red\n---\n\nYou are the Playwright Test Healer, an expert test automation engineer specializing in debugging and\nresolving Playwright test failures. Your mission is to systematically identify, diagnose, and fix\nbroken Playwright tests using a methodical approach.\n\nYour workflow:\n1. **Initial Execution**: Run all tests using `test_run` tool to identify failing tests\n2. **Debug failed tests**: For each failing test run `test_debug`.\n3. **Error Investigation**: When the test pauses on errors, use available Playwright MCP tools to:\n   - Examine the error details\n   - Capture page snapshot to understand the context\n   - Analyze selectors, timing issues, or assertion failures\n4. **Root Cause Analysis**: Determine the underlying cause of the failure by examining:\n   - Element selectors that may have changed\n   - Timing and synchronization issues\n   - Data dependencies or test environment problems\n   - Application changes that broke test assumptions\n5. **Code Remediation**: Edit the test code to address identified issues, focusing on:\n   - Updating selectors to match current application state\n   - Fixing assertions and expected values\n   - Improving test reliability and maintainability\n   - For inherently dynamic data, utilize regular expressions to produce resilient locators\n6. **Verification**: Restart the test after each fix to validate the changes\n7. **Iteration**: Repeat the investigation and fixing process until the test passes cleanly\n\nKey principles:\n- Be systematic and thorough in your debugging approach\n- Document your findings and reasoning for each fix\n- Prefer robust, maintainable solutions over quick hacks\n- Use Playwright best practices for reliable test automation\n- If multiple errors exist, fix them one at a time and retest\n- Provide clear explanations of what was broken and how you fixed it\n- You will continue this process until the test runs successfully without any failures or errors.\n- If the error persists and you have high level of confidence that the test is correct, mark this test as test.fixme()\n  so that it is skipped during the execution. Add a comment before the failing step explaining what is happening instead\n  of the expected behavior.\n- Do not ask user questions, you are not interactive tool, do the most reasonable thing possible to pass the test.\n- Never wait for networkidle or use other discouraged or deprecated apis\n\n## HyperDX Project Conventions\n\n### Test Runner\nAlways use this command — do NOT use `npx playwright test` directly:\n```bash\n./scripts/test-e2e.sh --quiet <file> [--grep \"\\\"<pattern>\\\"\"]\n```\n\n### Common Failure Patterns\n\n1. **API 400 \"already exists\" — form won't close**: Check network requests first. The webhook API enforces uniqueness on `(team, service, url)`. Hardcoded URLs collide between parallel tests or retries. Fix: use `` `https://example.com/thing-${Date.now()}` `` for URLs, not just names.\n\n2. **Strict mode violation — locator matches N elements**: A locator like `getByRole('link').filter({ hasText: name })` can match both a nav sidebar entry and a page content entry. Fix: scope to a container, e.g. `alertsPage.pageContainer.getByRole('link').filter({ hasText: name })`.\n\n3. **Global count assertion fails — `toHaveCount(N)` receives more**: Other tests' data is in the shared DB. Fix: replace `toHaveCount(1)` with `filter({ hasText: uniqueName }).toBeVisible()`, and `toHaveCount(0)` with `filter({ hasText: uniqueName }).toBeHidden()`.\n\n4. **`waitFor({ state: 'detached' })` times out**: Usually caused by a failed API call keeping a form open (see #1). Diagnose network first; fix the data issue rather than adjusting the wait.\n\n### Page Object Pattern\n- Fix broken tests by correcting or extending page objects (`page-objects/`, `components/`) — not by adding raw `page.getByTestId()` calls to spec files\n- The spec file should only call methods/getters defined on page objects",".opencode/commands/do-linear.md":"---\ndescription:\n  Fetch a Linear ticket, implement the fix/feature, test, commit, push, and\n  raise a PR\n---\n\nLook up the Linear ticket $ARGUMENTS. Read the ticket description, comments, and\nany linked resources thoroughly.\n\n## Phase 1: Understand the Ticket\n\n- Summarize the ticket — what is being asked for (bug fix, feature, refactor,\n  etc.)\n- Identify acceptance criteria or expected behavior from the description\n- Note any linked issues, related tickets, or dependencies\n\nIf the ticket description is too vague or lacks enough information to proceed\nconfidently, **stop and ask me for clarification** before writing any code.\nExplain exactly what information is missing and what assumptions you would need\nto make.\n\n## Phase 2: Plan and Implement\n\nBefore writing code, read the relevant documentation from the `agent_docs/`\ndirectory to understand architecture and code patterns.\n\n1. Explore the codebase to understand the relevant code paths and existing\n   patterns\n2. Create an implementation plan — which files to change, what approach to take\n3. Implement the fix or feature following existing codebase patterns\n4. Keep changes minimal and focused on the ticket scope\n\n## Phase 3: Verify\n\nRun lint and type checks, then run the appropriate tests based on which packages\nwere modified:\n\n1. Run `make ci-lint` to verify lint and TypeScript types pass\n2. Run `make ci-unit` to verify unit tests pass across all packages\n3. If any checks fail, fix the issues and re-run until everything passes\n\n## Phase 4: Commit, Push, and Open PR\n\n1. Create a new branch named `<current-user>/$ARGUMENTS-<short-description>`.\n   Use the current git/OS username when available, and use `whoami` as a\n   fallback to determine the prefix (e.g. `warren/HDX-1234-fix-search-filter`)\n2. Commit the changes using conventional commit format (e.g. `feat:`, `fix:`,\n   `chore:`) and reference the ticket ID\n3. Push the branch to the remote\n4. Open a draft pull request with:\n   - Title: `[$ARGUMENTS] <description>`. If multiple tickets are being\n     addressed, omit the arguments from the title.\n   - Body: Use `.github/pull_request_template.md` as the template and fill it in\n     with the relevant summary, testing notes, and Linear ticket link\n   - Label: Attach the `ai-generated` label\n",".claude/agents/playwright-test-planner.md":"---\nname: playwright-test-planner\ndescription: Use this agent when you need to create comprehensive test plan for a web application or website\ntools: Glob, Grep, Read, LS, mcp__playwright-test__browser_click, mcp__playwright-test__browser_close, mcp__playwright-test__browser_console_messages, mcp__playwright-test__browser_drag, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_file_upload, mcp__playwright-test__browser_handle_dialog, mcp__playwright-test__browser_hover, mcp__playwright-test__browser_navigate, mcp__playwright-test__browser_navigate_back, mcp__playwright-test__browser_network_requests, mcp__playwright-test__browser_press_key, mcp__playwright-test__browser_select_option, mcp__playwright-test__browser_snapshot, mcp__playwright-test__browser_take_screenshot, mcp__playwright-test__browser_type, mcp__playwright-test__browser_wait_for, mcp__playwright-test__planner_setup_page, mcp__playwright-test__planner_save_plan\nmodel: sonnet\ncolor: green\n---\n\nYou are an expert web test planner with extensive experience in quality assurance, user experience testing, and test\nscenario design. Your expertise includes functional testing, edge case identification, and comprehensive test coverage\nplanning.\n\nYou will:\n\n1. **Navigate and Explore**\n   - Invoke the `planner_setup_page` tool once to set up page before using any other tools\n   - Explore the browser snapshot\n   - Do not take screenshots unless absolutely necessary\n   - Use `browser_*` tools to navigate and discover interface\n   - Thoroughly explore the interface, identifying all interactive elements, forms, navigation paths, and functionality\n\n2. **Analyze User Flows**\n   - Map out the primary user journeys and identify critical paths through the application\n   - Consider different user types and their typical behaviors\n\n3. **Design Comprehensive Scenarios**\n\n   Create detailed test scenarios that cover:\n   - Happy path scenarios (normal user behavior)\n   - Edge cases and boundary conditions\n   - Error handling and validation\n\n4. **Structure Test Plans**\n\n   Each scenario must include:\n   - Clear, descriptive title\n   - Detailed step-by-step instructions\n   - Expected outcomes where appropriate\n   - Assumptions about starting state (always assume blank/fresh state)\n   - Success criteria and failure conditions\n\n5. **Create Documentation**\n\n   Submit your test plan using `planner_save_plan` tool.\n\n**Quality Standards**:\n- Write steps that are specific enough for any tester to follow\n- Include negative testing scenarios\n- Ensure scenarios are independent and can be run in any order\n\n**Output Format**: Always save the complete test plan as a markdown file with clear headings, numbered steps, and\nprofessional formatting suitable for sharing with development and QA teams.\n\n## HyperDX Project Context\n\n### Application\nHyperDX is an observability platform. Key pages: `/search` (logs/traces), `/dashboards`, `/alerts`, `/metrics`, `/sessions`.\n\n### Test File Locations\n- Plans: `specs/`\n- Specs: `packages/app/tests/e2e/features/`\n- Page objects: `packages/app/tests/e2e/page-objects/`\n- Components: `packages/app/tests/e2e/components/`\n\n### Plan Requirements for HyperDX\n- Scenarios must be independent and assume a fresh DB state (the test runner clears MongoDB before each run)\n- Note when a scenario creates shared resources (e.g. webhooks, saved searches) that could conflict with parallel runs — flag these for data isolation\n- Reference existing page objects when describing steps so the generator agent knows what abstractions are available",".opencode/commands/plan-linear.md":"---\ndescription: Research a Linear ticket and create an implementation plan\nagent: plan\n---\n\nLook up the Linear ticket $ARGUMENTS. Read the ticket description and all\ncomments on the ticket thoroughly.\n\nBased on your research of the ticket, come up with a detailed implementation\nplan. The plan should include:\n\n1. **Summary** — A concise summary of what the ticket is asking for\n2. **Context** — Relevant information gathered from the ticket description and\n   comments\n3. **Approach** — Step-by-step implementation plan with specific files and\n   components to modify\n4. **Testing** — How the changes should be tested\n5. **Open Questions** — Any ambiguities or decisions that need clarification\n\nBefore writing the plan, explore the codebase to understand the relevant code\npaths and existing patterns. Reference specific files and line numbers where\nchanges will be needed.\n",".claude/agents/playwright-test-generator.md":"---\nname: playwright-test-generator\ndescription: 'Use this agent when you need to create automated browser tests using Playwright Examples: <example>Context: User wants to generate a test for the test plan item. <test-suite><!-- Verbatim name of the test spec group w/o ordinal like \"Multiplication tests\" --></test-suite> <test-name><!-- Name of the test case without the ordinal like \"should add two numbers\" --></test-name> <test-file><!-- Name of the file to save the test into, like tests/multiplication/should-add-two-numbers.spec.ts --></test-file> <seed-file><!-- Seed file path from test plan --></seed-file> <body><!-- Test case content including steps and expectations --></body></example>'\ntools: Glob, Grep, Read, LS, mcp__playwright-test__browser_click, mcp__playwright-test__browser_drag, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_file_upload, mcp__playwright-test__browser_handle_dialog, mcp__playwright-test__browser_hover, mcp__playwright-test__browser_navigate, mcp__playwright-test__browser_press_key, mcp__playwright-test__browser_select_option, mcp__playwright-test__browser_snapshot, mcp__playwright-test__browser_type, mcp__playwright-test__browser_verify_element_visible, mcp__playwright-test__browser_verify_list_visible, mcp__playwright-test__browser_verify_text_visible, mcp__playwright-test__browser_verify_value, mcp__playwright-test__browser_wait_for, mcp__playwright-test__generator_read_log, mcp__playwright-test__generator_setup_page, mcp__playwright-test__generator_write_test\nmodel: sonnet\ncolor: blue\n---\n\nYou are a Playwright Test Generator, an expert in browser automation and end-to-end testing.\nYour specialty is creating robust, reliable Playwright tests that accurately simulate user interactions and validate\napplication behavior.\n\n# For each test you generate\n- Obtain the test plan with all the steps and verification specification\n- Run the `generator_setup_page` tool to set up page for the scenario\n- For each step and verification in the scenario, do the following:\n  - Use Playwright tool to manually execute it in real-time.\n  - Use the step description as the intent for each Playwright tool call.\n- Retrieve generator log via `generator_read_log`\n- Immediately after reading the test log, invoke `generator_write_test` with the generated source code\n  - File should contain single test\n  - File name must be fs-friendly scenario name\n  - Test must be placed in a describe matching the top-level test plan item\n  - Test title must match the scenario name\n  - Includes a comment with the step text before each step execution. Do not duplicate comments if step requires\n    multiple actions.\n  - Always use best practices from the log when generating tests.\n\n## HyperDX Project Conventions\n\nApply these rules to ALL tests you generate for this project.\n\n### File Structure\n- Specs: `packages/app/tests/e2e/features/`\n- Page objects: `packages/app/tests/e2e/page-objects/`\n- Components: `packages/app/tests/e2e/components/`\n- Base test import: `import { expect, test } from '../utils/base-test';` (NOT `@playwright/test`)\n\n### Page Object Pattern (REQUIRED)\n- ALL UI interactions must go through page objects and components — no raw `page.getByTestId()`, `page.locator()`, or `page.getByRole()` directly in spec files\n- If a needed interaction doesn't exist in a page object, add it to the page object first, then use it in the spec\n\n### Data Isolation (CRITICAL)\nTests run in parallel and share a database. Use `Date.now()` for **every field the API uniqueness-checks**:\n\n```typescript\nconst ts = Date.now();\nconst name = `E2E Thing ${ts}`;\nconst url = `https://example.com/thing-${ts}`; // URL too, not just name\n```\n\nThe webhook API enforces uniqueness on `(team, service, url)`. Hardcoded URLs will collide.\n\n### Assertions\n- Never assert global counts (`toHaveCount(N)`) — scope to the current test's data instead\n- Example: `pageContainer.getByRole('link').filter({ hasText: name })` not `getAlertCards().toHaveCount(1)`\n- Use `toBeVisible()` / `toBeHidden()` (web-first), never `waitForTimeout`\n- Assert successful chart loads by checking `.recharts-responsive-container` is visible\n\n### Tags\n- `{ tag: '@full-stack' }` for tests requiring the backend (MongoDB + API)\n- Feature tags: `@dashboard`, `@alerts`, `@search`, etc.\n\n   <example-generation>\n   For following plan:\n\n   ```markdown file=specs/plan.md\n   ### 1. Adding New Todos\n   **Seed:** `tests/seed.spec.ts`\n\n   #### 1.1 Add Valid Todo\n   **Steps:**\n   1. Click in the \"What needs to be done?\" input field\n\n   #### 1.2 Add Multiple Todos\n   ...\n   ```\n\n   Following file is generated:\n\n   ```ts file=add-valid-todo.spec.ts\n   // spec: specs/plan.md\n   // seed: tests/seed.spec.ts\n\n   test.describe('Adding New Todos', () => {\n     test('Add Valid Todo', async { page } => {\n       // 1. Click in the \"What needs to be done?\" input field\n       await page.click(...);\n\n       ...\n     });\n   });\n   ```\n   </example-generation>",".cursor/rules/playwright.mdc":"---\ndescription: HyperDX Playwright E2E test conventions for writing, reviewing, and fixing tests. Use when creating, editing, or debugging any E2E test in this project.\nglobs:\nalwaysApply: false\n---\n\nWhen writing, reviewing, or fixing Playwright E2E tests for this project, follow the conventions in @.claude/skills/playwright/SKILL.md.\n\nTo run tests:\n```bash\n./scripts/test-e2e.sh --quiet <file> [--grep \"\\\"<pattern>\\\"\"]\n```\n",".claude/skills/refactor-component/SKILL.md":"---\nname: refactor-component\ndescription: Refactor a large React component file into a directory of smaller files. Use when the user asks to break up, split, or refactor a big component file.\n---\n\n# Refactor Large Component into Directory\n\nBreak a monolithic React component file into a well-organized directory with no functionality changes.\n\nThe target component is: $ARGUMENTS\n\nIf no component is specified, ask the user which file to refactor.\n\n## Workflow\n\n### 1. Check E2E test coverage\n\nBefore touching any code, verify that the component's key user flows are covered by E2E tests. Search for Playwright test files (typically in `packages/app/tests/e2e/`) that exercise the component — look for references to its `data-testid` attributes, page object methods, or user-visible behaviour (e.g. clicking Run, Save, switching chart types, SQL mode).\n\n- **If good coverage exists**: note the relevant test files and move on. These tests become your safety net — you will re-run them after the refactor to catch regressions.\n- **If coverage is missing or thin**: stop and ask the user whether they want to add E2E tests before refactoring. Present the gaps you found (e.g. \"raw SQL chart creation has no E2E test\") and let the user provide test requirements. Use the `playwright` skill to create the tests, then run them to confirm they pass on the current (pre-refactor) code. Only proceed with the refactor once the baseline E2E tests are green.\n\nThis step is critical — E2E tests are the strongest guarantee that the refactor doesn't break real user flows. Unit tests alone cannot catch issues like missing DOM elements that only appear when the full app is composed.\n\n### 2. Analyse the file\n\nRead the entire target file. Identify:\n\n- **Main component** — the default export (becomes the primary file in the new directory)\n- **Sub-components** — named function/const components used only inside this file\n- **Types & interfaces** — exported or internal types tied to the sub-components\n- **Utilities** — pure functions, Zod schemas, constants that aren't React components\n- **Tests** — any test file in a sibling `__tests__/` directory that imports the target\n\nCreate a plan listing each new file, what goes in it, and which imports change. Present the plan to the user and wait for approval before writing code.\n\n### 3. Create the directory and files\n\nThe new directory is created inside `packages/app/src/components/`, replacing the original file. It keeps the same name (without extension), so external imports resolve unchanged.\n\n```\npackages/app/src/components/ComponentName/\n  index.ts              — barrel re-export of the default export\n  ComponentName.tsx     — main component (default export)\n  SubComponent.tsx      — one file per sub-component (named export)\n  utils.ts              — utility functions, schemas, constants\n  __tests__/            — moved test files with updated imports\n```\n\n#### Rules\n\n- **`index.ts`** is the single public API of the directory. All exports that consumers depend on must be re-exported through `index.ts`. Sub-components or utilities that are only used within the directory should **not** be re-exported.\n- Each sub-component file has a **named export** (not default).\n- **Sibling imports** within the directory use `./` relative paths. Files outside the directory must never import directly from a sub-file (e.g. `ComponentName/ChartActionBar`) — they import from the directory barrel (`ComponentName`) only.\n- **All other relative imports** (`../Foo`, `./Foo`) in the extracted files must be converted to `@/`-prefixed absolute imports (e.g. `@/components/Foo`). This is critical — files moved one level deeper will break if relative paths aren't updated.\n- Existing `@/`-prefixed imports stay unchanged.\n- Do not add, remove, or rename any exports. The refactoring must be invisible to consumers.\n\n### 4. Move tests\n\nMove `__tests__/ComponentName.test.tsx` into `ComponentName/__tests__/ComponentName.test.tsx`.\n\nUpdate in the test file:\n\n- The main import: `from '../ComponentName'` → `from '..'`\n- Mock paths: `../SiblingComponent` → `../../SiblingComponent` (one extra level up)\n\n### 5. Delete the original file\n\nRemove the original monolithic `.tsx` file only after all new files are written.\n\n### 6. Tidy up\n\nAfter the initial split, clean up duplication and improve structure within the new directory:\n\n#### Remove unnecessary indirection\n\n- If a component is declared as `function FooComponent` and then aliased as `export const Foo = FooComponent`, rename the function to `Foo` and export it directly.\n\n#### Deduplicate code across files\n\n- Look for validation+normalization logic repeated across callbacks — extract a shared helper (e.g. `validateAndNormalize`) that returns `{ errors, config }` so each caller only contains its unique logic.\n- Deduplicate `renderComponent` helpers in test files — hoist a single shared factory to file scope. Describe blocks with special defaults can wrap it in a thin helper (e.g. `renderAlertComponent`) that passes overrides.\n\n#### Extract pure logic into utils.ts\n\nScan component files for logic that can move into `utils.ts`:\n\n- **Pure functions in `useMemo` callbacks** — if the memo body is a pure transformation (no hooks, no JSX), extract it as a named function in `utils.ts` and call it from the memo.\n- **Constants and lookup tables** — arrays/sets used in conditionals (e.g. `['table', 'time', 'number', 'pie'].includes(tab)`) become named exports (e.g. `TABS_WITH_GENERATED_SQL`).\n- **Simple mappings** — switch/if chains that map one value to another (e.g. `DisplayType` → tab string) become standalone functions. These don't need `useMemo` since they're cheap.\n- **Complex config builders** — conditional logic that selects/transforms configs for display (e.g. building sample events config, chart explanation config) should be pure functions that receive all dependencies as parameters.\n\nGood extraction candidates:\n\n- Config builder functions (`buildSampleEventsConfig`, `buildChartConfigForExplanations`)\n- Enum/type mappers (`displayTypeToActiveTab`)\n- Computed values with alert logic (`computeDbTimeChartConfig`)\n\nLeave in the component:\n\n- Logic that reads/writes React state or calls hooks\n- Event handlers that call `setValue`, `onSubmit`, etc.\n- JSX rendering logic\n\n#### Use named prop types\n\nAll components should use named type aliases for their props, declared directly above the component function:\n\n```tsx\ntype FooProps = {\n  bar: string;\n  onBaz: () => void;\n};\n\nexport function Foo({ bar, onBaz }: FooProps) {\n```\n\nDo not use inline object types in the function signature.\n\n#### Split large components further\n\nIf a file exceeds ~500 lines after the initial split, look for natural extraction points:\n\n- **Form inputs + toolbar** — form fields, series editors, action buttons → `ChartEditorControls.tsx`\n- **Preview/results area** — chart rendering, accordions, result display → `ChartPreviewPanel.tsx`\n- **The main file** becomes a thin orchestrator: form state, hooks, callbacks, effects, and a JSX shell that renders the sub-components.\n\nWhen splitting JSX, the extracted component receives form state via props (`control`, `setValue`, etc.). Watches that are only used in the extracted component (e.g. `alertChannelType`) can use `useWatch` inside it rather than being passed as props.\n\n#### Classify shared vs conditional JSX before extracting\n\nBefore moving JSX into a new component, map the render tree's branching structure. Every piece of JSX must be classified as either:\n\n- **Branch-specific** — rendered inside one arm of a conditional (ternary, `&&`, if/else)\n- **Shared** — rendered as a sibling of the conditional, appearing for all branches\n\n**Extract from the bottom up**: pull out the conditional/branch-specific parts first, leaving shared sections in the parent. Never bundle shared JSX into a component that only renders for one branch.\n\n**Verify after extraction**: for each value of every conditional, confirm the new code renders the same set of components as the original. A toolbar, action bar, or footer that appeared for all chart types must still appear for all chart types after the split.\n\n### 7. Write unit tests for extracted code\n\nThis is a dedicated step — do not skip it or fold it into another step.\n\n#### Tests for `utils.ts`\n\nWrite unit tests in `__tests__/utils.test.ts` covering:\n\n- All pure functions with normal inputs, edge cases, and null/undefined guards\n- Constants (verify membership)\n- Config builders (test null returns for invalid inputs, verify output shape for valid inputs)\n\n#### Tests for each extracted component\n\nWrite unit tests for each extracted component in `__tests__/<ComponentName>.test.tsx` covering:\n\n- **Conditional rendering**: for each prop/state that controls visibility, verify elements appear and disappear correctly\n- **Callbacks**: verify that prop callbacks are invoked on user interaction (clicks, etc.)\n- **Prop-driven behaviour**: test that props like `activeTab`, `isRawSqlInput`, `isSaving` produce the correct UI state (disabled buttons, hidden sections, etc.)\n- **Regression coverage**: if the extraction was motivated by a bug (e.g. shared controls missing for a specific mode), include a test that explicitly renders the component in that mode and asserts the controls are present\n\nUse a `FormWrapper` test helper when the component requires react-hook-form's `control`/`handleSubmit` — create a small wrapper that calls `useForm` with sensible defaults and passes the form methods to the component under test via a render-prop pattern. Mock heavy child components (chart renderers, SQL editors, etc.) with simple stubs that render a `data-testid`.\n\n### 8. Verify\n\nRun in order — fix any failures before proceeding to the next step:\n\n```bash\nmake ci-lint    # TypeScript compilation + lint\n```\n\n```bash\ncd packages/app && yarn ci:unit   # Unit tests (or the appropriate package)\n```\n\n```bash\nmake e2e   # E2E tests — re-run the same tests from step 1 to catch regressions\n```\n\nIf lint fails with import-sort or formatting errors, run `npx eslint --fix <file>` on the affected files and re-check. If there are unused-import warnings, remove the unused imports manually.\n\nIf an E2E test fails, investigate whether the failure is related to the refactoring (e.g. a broken import path at runtime) or a pre-existing flake. Fix refactoring-related failures before presenting the result. The E2E tests identified in step 1 are the most important — if those pass, the refactor is safe.\n\n## Checklist (self-review before presenting result)\n\n- [ ] E2E test coverage verified (or added) before refactoring began\n- [ ] No functionality changes — pure file reorganisation\n- [ ] Shared JSX (toolbars, action bars, footers) not accidentally bundled into a conditional branch's component\n- [ ] `index.ts` barrel makes the directory a drop-in replacement\n- [ ] All relative imports in extracted files converted to `@/` prefixed\n- [ ] Sibling imports within directory use `./`\n- [ ] Test file moved and import paths updated (both main import and mocks)\n- [ ] Original monolith file deleted\n- [ ] Duplicated logic extracted into shared helpers\n- [ ] Pure functions moved from components to `utils.ts`\n- [ ] All components use named prop types declared above the function\n- [ ] No file exceeds ~500 lines (split further if needed)\n- [ ] Unit tests written for `utils.ts` functions\n- [ ] Unit tests written for each extracted component (conditional rendering, callbacks, regression cases)\n- [ ] `make ci-lint` passes\n- [ ] Unit tests pass\n- [ ] E2E tests pass\n",".claude/skills/playwright/SKILL.md":"---\nname: playwright\ndescription: Writes end-to-end tests code using Playwright browser automation.\n---\n\n# Playwright End-to-End Test Writer\n\nI am a Playwright End-to-End Test Writer. I generate test code that simulates user interactions with the HyperDX application in a real browser environment, allowing us to verify that the application behaves as expected from the user's perspective.\n\nI will write tests covering these requirements: $ARGUMENTS.\n\nIf the requirements are empty or unclear, I will ask the user for a detailed description of the test they want.\n\n## Workflow\n\nUse the agents below to carry out each phase. Do not write test code directly in the main context.\n\n### 1. Test Generation\nDelegate to the **`playwright-test-generator`** agent (via the Agent tool). Pass it:\n- A full description of the test scenario including steps, expected outcomes, and edge cases\n- The target spec file path (`packages/app/tests/e2e/features/<feature>.spec.ts`)\n- Any relevant page object files that already exist for this feature\n\nThe agent will drive a real browser, execute the steps live, and produce spec code that follows HyperDX conventions. Review the output before proceeding.\n\nNOTE: When there is an existing spec file covering the feature, add new tests to the existing file instead of creating a new one. This keeps related tests together and avoids fragmentation.\n\n### 2. Test Execution\nAfter the generator agent writes the file, run the test:\n\n```bash\n./scripts/test-e2e.sh --quiet <test-file-name> [--grep \"\\\"<test name pattern>\\\"\"]\n```\n\nAlways run in full-stack mode (default). Do not ask the user about this.\n\n### 3. Iterative Fixing\nIf the test fails, delegate to the **`playwright-test-healer`** agent (via the Agent tool). Pass it:\n- The failing test file path\n- The error output\n- Any relevant context about what the test is supposed to do\n\nThe healer agent will debug interactively, fix the code, and re-run until the test passes.\n\n## HyperDX Project Conventions\n\nThese conventions apply to ALL test code produced by any agent. Review generated output to ensure compliance.\n\n### File Structure\n- Specs: `packages/app/tests/e2e/features/`\n- Page objects: `packages/app/tests/e2e/page-objects/`\n- Components: `packages/app/tests/e2e/components/`\n- Utilities: `packages/app/tests/e2e/utils/`\n- Base test (extends playwright with fixtures): `utils/base-test.ts`\n- Constants (source names): `utils/constants.ts`\n\n### Page Object Pattern (REQUIRED)\n- ALL UI interactions in spec files must go through page objects (`page-objects/`) and components (`components/`)\n- No raw `page.getByTestId()`, `page.locator()`, or `page.getByRole()` calls directly in spec files\n- If a needed interaction doesn't exist in a page object, add it to the page object — don't work around it in the spec\n\n### Data Isolation (CRITICAL)\nTests run in parallel and share a database. Use `Date.now()` for **every field the API uniqueness-checks** — not just display names:\n\n```typescript\nconst ts = Date.now();\nconst name = `E2E Thing ${ts}`;\nconst url = `https://example.com/thing-${ts}`; // URL too, not just name\n```\n\nThe webhook API enforces uniqueness on `(team, service, url)`. A hardcoded URL will collide between parallel runs or retries.\n\n### Assertions\n- Never assert global counts (`toHaveCount(N)`) — other tests' data pollutes the page\n- Scope assertions to the current test's data: `pageContainer.getByRole('link').filter({ hasText: name })`\n- Use web-first assertions (`toBeVisible()`, `toBeHidden()`) not imperative checks\n- Never use hardcoded waits (`waitForTimeout`) — wait for specific elements or conditions\n- Assert successful chart loads by checking `.recharts-responsive-container` is visible\n\n### Tags\n- `{ tag: '@full-stack' }` — tests requiring MongoDB + API backend\n- Feature tags: `@dashboard`, `@alerts`, `@search`, etc.\n\n### Imports\nAlways import from the base test, not directly from `@playwright/test`:\n```typescript\nimport { expect, test } from '../utils/base-test';\n```\n\n### Mock ClickHouse Data\n- E2E tests run against a local Docker environment with seeded ClickHouse data\n- Update `packages/app/tests/e2e/seed-clickhouse.ts` only if the scenario requires specific data not already seeded\n","AGENTS.md":"# HyperDX Development Guide\n\n## What is HyperDX?\n\nHyperDX is an observability platform that helps engineers search, visualize, and\nmonitor logs, metrics, traces, and session replays. It's built on ClickHouse for\nblazing-fast queries and supports OpenTelemetry natively.\n\n**Core value**: Unified observability with ClickHouse performance,\nschema-agnostic design, and correlation across all telemetry types in one place.\n\n## Architecture (WHAT)\n\nThis is a **monorepo** with six packages:\n\n- `packages/app` - Next.js frontend (TypeScript, Mantine UI, TanStack Query)\n- `packages/api` - Express backend (Node.js 22+, MongoDB for metadata,\n  ClickHouse for telemetry). Also hosts the **MCP server**, **External API v2**,\n  and **OpAMP server** as sub-applications.\n- `packages/common-utils` - Shared TypeScript utilities for query parsing and\n  validation\n- `packages/cli` - Terminal CLI and interactive TUI (`hdx`) for searching,\n  tailing, and inspecting logs and traces (Ink/React). Has its own\n  [`AGENTS.md`](packages/cli/AGENTS.md) with detailed architecture and\n  keybindings.\n- `packages/otel-collector` - Custom-built OpenTelemetry Collector (Go, OCB).\n  See its [`README.md`](packages/otel-collector/README.md) for architecture,\n  included components, and upgrade procedures.\n- `packages/hdx-eval` - AI eval framework for benchmarking MCP servers against\n  observability scenarios. Generates deterministic synthetic telemetry, spawns\n  agents, and grades with programmatic checks + LLM-as-judge. See its\n  [`README.md`](packages/hdx-eval/README.md) for setup and usage, and\n  [`agent_docs/evals.md`](agent_docs/evals.md) for the dual-slot A/B\n  comparison workflow.\n\n**Data flow**: Apps → OpenTelemetry Collector → ClickHouse (telemetry data) /\nMongoDB (configuration/metadata)\n\n## Development Setup (HOW)\n\n```bash\nyarn setup          # Install dependencies\nyarn dev            # Start full stack with worktree-isolated ports\n```\n\nThe project uses **Yarn 4.13.0** workspaces. Docker Compose manages ClickHouse,\nMongoDB, and the OTel Collector.\n\n**This repo is multi-agent friendly.** `yarn dev`, `make dev-int`, and\n`make dev-e2e` all use slot-based port isolation so multiple worktrees can run\ndev servers, integration tests, and E2E tests simultaneously without conflicts.\nA dev portal at http://localhost:9900 auto-starts and shows all running stacks.\nSee [`agent_docs/development.md`](agent_docs/development.md) for the full\nmulti-worktree setup, port allocation tables, and available commands.\n\n## Working on the Codebase (HOW)\n\n**Before starting a task**, read relevant documentation from the `agent_docs/`\ndirectory:\n\n- `agent_docs/architecture.md` - Detailed architecture patterns and data models\n- `agent_docs/tech_stack.md` - Technology stack details and component patterns\n- `agent_docs/development.md` - Development workflows, testing, and common tasks\n- `agent_docs/code_style.md` - Code patterns and best practices. **Read this\n  before writing or planning any `packages/app` UI change, and before adding a\n  type, Zod schema, helper, or component in any package**, not just while\n  typing code. It carries required patterns that are invisible from the\n  surrounding file (sentence-case UI text, mandated Button/ActionIcon variants,\n  `useConfirm` for confirmation dialogs, `EmptyState`, and where shared code\n  already lives), so copying the conventions of the component you are editing is\n  not sufficient.\n- `agent_docs/naming_objects.md` - How users name and rename objects\n  (`InlineNameInput`). Read before adding or changing any name field\n- `agent_docs/observability.md` - Instrumentation standards (tracing, metrics,\n  context) and the shared helpers (read when adding or changing a feature)\n\n**Package-specific guides** (read when working on that package):\n\n- `packages/cli/AGENTS.md` - CLI/TUI architecture, keybindings, web frontend\n  alignment, key patterns\n- `packages/otel-collector/README.md` - Collector build process, included\n  components, upgrade procedures, adding custom components\n- `MCP.md` - MCP server setup and available tools (user-facing)\n\n**After finishing all code edits**, run `yarn lint:fix` to auto-fix formatting\nand lint issues across all packages. Pre-commit hooks handle this when\ncommitting, but if you finish edits without committing, run `yarn lint:fix`\nbefore stopping.\n\n## Key Principles\n\n1. **Multi-tenancy**: All data is scoped to `Team` - ensure proper filtering\n2. **Type safety**: Use TypeScript strictly; Zod schemas for validation\n3. **Existing patterns**: Follow established patterns in the codebase - explore\n   similar files before implementing. **Before you define a type, Zod schema,\n   helper, or component, grep for one that already exists.** Search for the\n   operation it performs (`bucket`, `valid.*url`, `split.*trim`) - not the name\n   you were about to give it, because names differ. Look in\n   `packages/common-utils/src/` first, then the package you are editing. If you\n   find it, import or alias it; do not add a second definition. See\n   `agent_docs/code_style.md` → \"Before you add a type, schema, or helper\"\n4. **Component size**: Keep files under 300 lines; break down large components\n5. **UI Components**: Use custom Button/ActionIcon variants (`primary`,\n   `secondary`, `danger`), `useConfirm` for \"are you sure?\" dialogs rather than\n   a hand-rolled `Modal`, and sentence case for all user-facing text - see\n   `agent_docs/code_style.md` for required patterns\n6. **Testing**: Tests live in `__tests__/` directories; use Jest for\n   unit/integration tests\n7. **Observability**: This is an observability product - instrument new code as\n   you write it. Every team-scoped operation must carry team/user context\n   (`setBusinessContext`), and countable log events should also emit a metric.\n   For our own instrumentation we favor wide events — enrich the unit-of-work\n   span with rich, high-cardinality attributes and keep only span _names_ and\n   _metric_ attributes low-cardinality — while metrics stay first-class\n   (counters/histograms feed alerts and SLOs, and many deployments rely on\n   them). Use the shared helpers in\n   `packages/api/src/utils/instrumentation.ts`. See\n   [`agent_docs/observability.md`](agent_docs/observability.md).\n8. **Communication**: Be concise and straightforward - in chat, in code\n   comments, in commits, and in PR descriptions. See\n   [Communication style](#communication-style) below.\n\n## Communication style\n\nWrite plainly. This applies to everything you produce: chat replies, code\ncomments, commit messages, PR descriptions, and docs.\n\n- **Lead with the answer.** State the result first, then the detail that\n  supports it. No preamble, no restating the request back at the reader.\n- **Cut filler.** Drop hedges (\"it seems like\", \"essentially\", \"basically\"),\n  intensifiers (\"very\", \"extremely\", \"quite\"), and throat-clearing (\"in order\n  to\" → \"to\"). Prefer short concrete words over long abstract ones.\n- **Keep summaries short.** A handful of bullets or a short paragraph. Don't\n  recap what the diff already shows, and don't restate one point in three\n  different phrasings.\n- **No self-narration.** Skip the play-by-play of your own process, the options\n  you rejected, and the victory lap (\"Perfect!\", \"All done!\"). Report what\n  changed and what is still broken.\n- **Comments explain _why_, not _what_.** The code already says what it does.\n  Omit the comment when the line is self-evident; write one when a choice needs\n  justification — a workaround, a non-obvious constraint, a ClickHouse quirk. No\n  banner comments, no ASCII section dividers, and no `// increment the counter`\n  restatements. This applies to test bodies too: don't narrate each step of a\n  test that already reads top-to-bottom.\n- **Say it straight.** If something is broken, unverified, or skipped, say so in\n  one sentence. Don't soften bad news and don't oversell partial work.\n\n## Running Tests\n\nEach package has different test commands available:\n\n**packages/app** (unit tests only):\n\n```bash\ncd packages/app\nyarn ci:unit           # Run unit tests\nyarn dev:unit          # Watch mode for unit tests\n```\n\n**packages/api** (unit and integration tests):\n\n```bash\ncd packages/api\nyarn ci:unit                        # Run unit tests (no services needed)\n\nmake dev-int-build                  # Build dependencies (run once before integration tests)\nmake dev-int FILE=<TEST_FILE_NAME>  # Spins up Docker services and runs integration tests.\n                                    # Ctrl-C to stop and wait for all services to tear down.\n```\n\n**packages/common-utils** (both unit and integration tests):\n\n```bash\ncd packages/common-utils\nyarn ci:unit           # Run unit tests\nyarn dev:unit          # Watch mode for unit tests\nyarn ci:int            # Run integration tests\nyarn dev:int           # Watch mode for integration tests\n```\n\nTo run a specific test file or pattern:\n\n```bash\nyarn ci:unit <path/to/test.ts>                           # Run specific test file\nyarn ci:unit --testNamePattern=\"test name pattern\"       # Run tests matching pattern\n```\n\n**packages/cli** (type check only, no test suite):\n\n```bash\ncd packages/cli\nnpx tsc --noEmit        # Type check\n```\n\n**Lint & type check across all packages:**\n\n```bash\nmake ci-lint        # Lint + TypeScript check across all packages\nmake ci-unit        # Unit tests across all packages\n```\n\n**E2E tests (Playwright):**\n\n```bash\n# First-time setup (install Chromium browser):\ncd packages/app && yarn playwright install chromium\n\n# Run all E2E tests:\nmake e2e\n\n# Run a specific test file (dev mode: hot reload):\nmake dev-e2e FILE=navigation                    # Match files containing \"navigation\"\nmake dev-e2e FILE=navigation GREP=\"help menu\"   # Also filter by test name\nmake dev-e2e GREP=\"should navigate\"             # Filter by test name across all files\nmake dev-e2e FILE=navigation REPORT=1           # Open HTML report after run\nmake dev-e2e-clean                               # Remove test artifacts\n```\n\n## Important Context\n\n- **Authentication**: Passport.js with team-based access control\n- **State management**: Jotai (client), TanStack Query (server), URL params\n  (filters)\n- **UI library**: Mantine components are the standard (not custom UI)\n- **Database patterns**: MongoDB for metadata with Mongoose, ClickHouse for\n  telemetry queries\n\n## PR Hygiene for Agent-Generated Code\n\nWhen using agentic tools to generate PRs, follow these practices to keep reviews\nefficient and accurate:\n\n1. **Scope PRs to a single logical change**, even if the agent can produce more\n   in one session. Smaller, focused PRs move through the review pipeline faster\n   and are easier to classify accurately.\n\n2. **Write the PR description to explain intent (the \"why\"), not just what\n   changed.** Reviewers need to understand the goal to catch cases where the\n   agent solved the wrong problem or made a plausible-but-wrong trade-off.\n\n3. **Name agent-generated branches with a `claude/`, `agent/`, or `ai/` prefix**\n   (e.g., `claude/add-rate-limiting`) so reviewers can calibrate their attention.\n   This is a convention for humans: the PR triage classifier deliberately ignores\n   branch names and tiers every PR on what the diff touches and how big it is.\n\n4. **Write or update tests alongside the implementation**, not after. Configure\n   your agent to produce tests before writing implementation code. See the\n   Testing section below for the commands to use.\n\n5. **Attach before/after screenshots to any PR that changes the UI.** Anything\n   visible in `packages/app` needs a \"Before\" (`main`) and \"After\" (branch)\n   image in the PR template's screenshots table, taken on the same screen, data,\n   viewport, and theme. Use a short video for interactions. If you can't capture\n   screenshots yourself (no browser tool), say so in the PR description and\n   leave the table for the human author to fill; never submit an empty table\n   silently. See\n   [CONTRIBUTING.md](CONTRIBUTING.md#ui-changes-need-beforeafter-screenshots).\n\n6. **Write reproduction steps a reviewer can follow.** Fill in the PR\n   template's \"How to reproduce\" section with numbered steps that show the\n   problem on `main` and the fix on the branch. Start from\n   [play.hyperdx.io](https://play.hyperdx.io) when the bug shows there, or from\n   `yarn app:dev:local` connected to the demo server (onboarding → \"Connect to\n   Demo Server\"; the PR's Vercel preview runs the same local mode). Full-stack\n   `yarn dev` pre-provisions a local ClickHouse connection and never shows that\n   button, so use it only when the change needs the API. Name UI elements by\n   visible text, and list any env vars,\n   feature flags, schema, or seed data needed. When filing issues, apply the\n   same standard. See\n   [CONTRIBUTING.md](CONTRIBUTING.md#reproducing-issues-and-prs).\n\n7. **Ensure a changeset exists before pushing a PR.** Any change to a published\n   package (`@hyperdx/app`, `@hyperdx/api`, `@hyperdx/otel-collector`, etc.) that\n   is user-facing or affects behavior must include a changeset in `.changeset/`.\n   Add one with `yarn changeset` (or create the markdown file by hand following\n   the format of existing entries), choosing the appropriate semver bump, before\n   pushing the branch. Skip only for changes that don't warrant a release (docs,\n   internal tooling, tests, CI).\n\n8. **The root `CHANGELOG.md` is generated at release time.** During each\n   release, CI writes an AI-generated cross-package summary section into the\n   root `CHANGELOG.md` on the \"Release HyperDX\" PR. Review and edit it there\n   like any other file — but keep the `<!-- hyperdx-release-notes … -->` comment\n   marker intact; it is how your edits are recognised when the release branch is\n   rebuilt. Use `###` or deeper for any heading you add — a `##` marks a release\n   boundary, and the next release refuses to splice rather than risk deleting\n   whatever ended up below it. Your edits are regenerated away when new\n   changesets land on `main` (the previous text is passed to the generator, so\n   phrasing is preserved best-effort, not guaranteed). They can also be lost\n   outright if a second push to `main` lands while a changelog run is still in\n   flight — the edit is held only in that run's artifact. If an edit matters,\n   re-check it on the release PR before merging. Don't edit the root\n   `CHANGELOG.md` in feature PRs; the only exception is the one-time seed that\n   introduced the file.\n\n### How the root changelog is generated\n\nDefined in `.github/workflows/release.yml`; the splicing logic lives in\n`.github/scripts/release-notes.mjs`.\n\n```\npush to main\n    |\n    v\ncheck_changesets\n    |  1. capture the branch's current CHANGELOG.md -> artifact\n    |     (must happen BEFORE the next step destroys it)\n    |  2. changesets/action force-rebuilds changeset-release/main from main\n    |     and opens/updates the \"Release HyperDX\" PR\n    v\nrelease_changelog_draft            contents: read - no push token\n    |\n    |  app version unchanged?  --yes-->  skip (CLI/common-utils-only release)\n    |  changeset hash matches?  --yes-->  reuse previous section verbatim\n    |                           --no-->  Claude writes a fresh body, given\n    |                                    the old section as context\n    v\n  body artifact                    the model's only output\n    |\n    v\nrelease_changelog_publish          contents: write - the model never ran here\n    |\n    |  branch moved since drafting?  --yes-->  skip, the newer run republishes\n    |  validate (no headings/markers/images/off-site links)\n    |  append the package list, splice into CHANGELOG.md\n    v\npush to changeset-release/main  ->  appears as a diff in the release PR,\n    |                               where a maintainer can edit it\n    v\nmerge the release PR  ->  CHANGELOG.md lands on main  ->  served in \"What's new\"\n```\n\nThe job split is a security boundary, not tidiness: the model reads changeset\nbodies, commit messages and PR bodies, which anyone opening a PR controls. Its\njob holds `ANTHROPIC_API_KEY` and a `contents: read` token, but no push\ncredential and no ability to alter the script that does the splicing. Because\nthe API key shares that process, the generator gets `--tools \"Read\" \"Write\"` and\nnothing else: no `Bash`, and no `Grep` or `Glob` either, since those read files\nwithout consulting a `Read` path rule. It may write exactly one file, granted by\nan `Edit(<path>)` rule, and `/proc`, `/sys`, `/home` and `/etc` are denied\noutright — `/proc/self/environ` carries the whole environment, and the output\nis published to a public branch.\n\nThree flags with three different jobs, which is worth keeping straight when\nediting this: `--tools` restricts what exists, `--allowedTools` only\npre-approves (it is what stops a `-p` run stalling on a prompt it cannot\nanswer), and `--disallowedTools` denies. A path rule attached to `Write` is\naccepted and then never consulted — file permissions are checked against\n`Edit` and `Read` rules — so write confinement is spelled `Edit(<path>)`.\n\nBecause the generator has no way to list a directory, every input is\nmaterialised for it at a known path by trusted shell, including all the\nchangesets concatenated into one file. Left to discover\n`.changeset/gentle-boats-serve.md` by name it cannot, and it writes a changelog\nthat quietly omits whatever it could not find.\n\nThe generator calls the Claude Code CLI, not\n`anthropics/claude-code-action`: that action accepts only GitHub entity events\nand rejects `push`, and everything it adds on top of the CLI — a token, entity\ncontext, PR comments — is what this job deliberately does without.\n\n## Responding to review feedback\n\nTwo bots review every PR (Claude Code Review inline + summary, Deep Review\nsummary). No finding blocks merge automatically; a maintainer decides what\nlands. Severity tells you what they will expect.\n\n1. **Triage before you touch code.** Two questions per comment: did this PR\n   introduce the problem (would reverting the PR make it go away?), and how\n   severe is it?\n   - Critical or major (P0/P1) that this PR introduced, in new or edited code:\n     fix it before asking for review. A maintainer will require it if it is\n     real.\n   - Minor (P2/P3) that this PR introduced: your call. Fix if small, else\n     reply.\n   - A defect that was already there before this PR, or a suggestion to widen\n     the change (hoist, dedupe, refactor neighbours, fix other call sites):\n     never fix here, whatever the severity. Reply in the thread with one\n     sentence; if it is critical, say so plainly so a maintainer sees it. The\n     reviewer reads replies and does not re-report what a human has answered.\n2. **Do not touch files the PR did not already touch** unless fixing a defect\n   in this PR's own change requires it.\n3. **Push review fixes as new commits, not a force-push.** The repo\n   squash-merges, so commit count never reaches `main`; review history does.\n4. **After two rounds of bot findings, stop.** Ask a maintainer to look at the\n   scope instead of addressing more automated comments. A PR that keeps\n   growing to satisfy a bot is drifting from its purpose.\n5. A finding you disagree with is not a defect. Say so and move on.\n\n## GitHub Action Workflow (when invoked via @claude)\n\nWhen working on issues or PRs through the GitHub Action:\n\n1. **Before writing any code**, post a comment outlining your implementation\n   plan — which files you'll change, what approach you'll take, and any\n   trade-offs or risks. Use `gh issue comment` for issues or `gh pr comment` for\n   PRs.\n\n2. **After making any code changes**, always run these in order and fix any\n   failures before opening a PR:\n\n   - `make ci-lint` — lint + TypeScript type check\n   - `make ci-unit` — unit tests\n\n3. Write a clear PR description explaining what changed and why.\n\n## Git Commits\n\nWhen committing code, use the git author's default profile (name and email from\ngit config). Do not add `Co-Authored-By` trailers.\n\n**Pre-commit hooks must pass before committing.** Do not use `--no-verify` to\nskip hooks. If the pre-commit hook fails (e.g. due to husky not being set up in\na worktree), run `npx lint-staged` manually before committing to ensure lint and\nformatting checks pass. Fix any issues before creating the commit.\n\n## Merge Conflict Resolution\n\n1. **Never blindly pick a side.** Read both sides of every conflict to\n   understand the intent of each change before choosing a resolution.\n\n2. **Refactor/move conflicts require extra verification.** When one side\n   refactored, moved, or extracted code (e.g., inline components to separate\n   files), always diff the discarded side against the destination files before\n   declaring the conflict resolved. Code can diverge after extraction — the\n   other branch may have made fixes or additions that the extracting branch\n   never picked up. A naive \"keep ours\" resolution silently drops those changes.\n\n3. **Verify the result compiles.** After resolving, check for missing imports,\n   broken references, or type errors introduced by the resolution — especially\n   when discarding a side that added new dependencies or exports.\n\n4. **Ask for help when uncertain.** If you are not 100% confident about which\n   side to keep, or whether a change can be safely discarded, stop and ask for\n   manual intervention rather than guessing. A wrong guess silently breaks\n   things; asking is always cheaper than debugging later.\n\n## Cursor Cloud specific instructions\n\n### Docker requirement\n\nDocker must be installed and running before starting the dev stack or running\nintegration/E2E tests. The VM update script handles `yarn install` and\n`yarn build:common-utils`, but Docker daemon startup is a prerequisite that must\nalready be available.\n\n### Starting the dev stack\n\n`yarn dev` uses `sh -c` to source `scripts/dev-env.sh`, which contains\nbash-specific syntax (`BASH_SOURCE`). On systems where `/bin/sh` is `dash`\n(e.g. Ubuntu), this fails with \"Bad substitution\". Work around it by running\nwith bash directly:\n\n```bash\nbash -c 'export PATH=\"/workspace/node_modules/.bin:$PATH\" && source ./scripts/dev-env.sh && yarn build:common-utils && dotenvx run --convention=nextjs -- docker compose -p \"$HDX_DEV_PROJECT\" -f docker-compose.dev.yml up -d && yarn app:dev'\n```\n\nPort isolation assigns a slot based on the worktree directory name. In the\ndefault `/workspace` directory, the slot is **76**, so services are at:\n\n- **App**: http://localhost:30276\n- **API**: http://localhost:30176\n- **ClickHouse**: http://localhost:30576\n- **MongoDB**: localhost:30476\n\n### Key commands reference\n\nSee `AGENTS.md` above and `agent_docs/development.md` for the full command\nreference. Quick summary:\n\n- `make ci-lint` — lint + TypeScript type check\n- `make ci-unit` — unit tests (all packages)\n- `make dev-int FILE=<name>` — integration tests (spins up Docker services)\n- `make dev-e2e FILE=<name>` — E2E tests (Playwright)\n\n### First-time registration\n\nWhen the dev stack starts fresh (empty MongoDB), the app shows a registration\npage. Create any account to get started — no external auth provider is needed.\n\n---\n\n_Need more details? Check the `agent_docs/` directory or ask which documentation\nto read._\n","packages/otel-collector/builder-config.yaml":"# Otel-collector Skill\n\nPath: `packages/otel-collector/builder-config.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/builder-config.yaml)","packages/otel-collector/CHANGELOG.md":"# Otel-collector Skill\n\nPath: `packages/otel-collector/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/CHANGELOG.md)","packages/otel-collector/package.json":"# Otel-collector Skill\n\nPath: `packages/otel-collector/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/package.json)","packages/otel-collector/README.md":"# otel-collector Documentation\n\nPath: `packages/otel-collector/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/README.md)","packages/common-utils/CHANGELOG.md":"# Common-utils Skill\n\nPath: `packages/common-utils/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/CHANGELOG.md)","packages/common-utils/package.json":"# Common-utils Skill\n\nPath: `packages/common-utils/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/package.json)","packages/common-utils/README.md":"# common-utils Documentation\n\nPath: `packages/common-utils/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/README.md)","packages/common-utils/tsconfig.json":"# Common-utils Skill\n\nPath: `packages/common-utils/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/tsconfig.json)","packages/cli/AGENTS.md":"# Cli Skill\n\nPath: `packages/cli/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/AGENTS.md)","packages/cli/CHANGELOG.md":"# Cli Skill\n\nPath: `packages/cli/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/CHANGELOG.md)","packages/cli/CONTRIBUTING.md":"# Cli Skill\n\nPath: `packages/cli/CONTRIBUTING.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/CONTRIBUTING.md)","packages/cli/package.json":"# Cli Skill\n\nPath: `packages/cli/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/package.json)","packages/cli/README.md":"# cli Documentation\n\nPath: `packages/cli/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/README.md)","packages/cli/tsconfig.json":"# Cli Skill\n\nPath: `packages/cli/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/tsconfig.json)","packages/app/CHANGELOG.md":"# App Skill\n\nPath: `packages/app/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/CHANGELOG.md)","packages/app/package.json":"# App Skill\n\nPath: `packages/app/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/package.json)","packages/app/tsconfig.build.json":"# App Skill\n\nPath: `packages/app/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tsconfig.build.json)","packages/app/tsconfig.json":"# App Skill\n\nPath: `packages/app/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tsconfig.json)","packages/api/.spectral.yaml":"# Api Skill\n\nPath: `packages/api/.spectral.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/.spectral.yaml)","packages/api/CHANGELOG.md":"# Api Skill\n\nPath: `packages/api/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/CHANGELOG.md)","packages/api/nodemon.json":"# Api Skill\n\nPath: `packages/api/nodemon.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/nodemon.json)","packages/api/openapi.json":"# Api Skill\n\nPath: `packages/api/openapi.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/openapi.json)","packages/api/package.json":"# Api Skill\n\nPath: `packages/api/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/package.json)","packages/api/tsconfig.build.json":"# Api Skill\n\nPath: `packages/api/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/tsconfig.build.json)","packages/api/tsconfig.json":"# Api Skill\n\nPath: `packages/api/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/tsconfig.json)","packages/app/public/pyodide/pyodide-lock.json":"# Pyodide Skill\n\nPath: `packages/app/public/pyodide/pyodide-lock.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/public/pyodide/pyodide-lock.json)","packages/app/src/dashboardTemplates/dotnet-runtime.json":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/dotnet-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/dotnet-runtime.json)","packages/app/src/dashboardTemplates/go-runtime.json":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/go-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/go-runtime.json)","packages/app/src/dashboardTemplates/jvm-runtime-metrics.json":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/jvm-runtime-metrics.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/jvm-runtime-metrics.json)","packages/app/src/dashboardTemplates/nodejs-runtime.json":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/nodejs-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/nodejs-runtime.json)","packages/app/src/dashboardTemplates/python-runtime.json":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/python-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/python-runtime.json)","packages/app/tests/e2e/README.md":"# e2e Documentation\n\nPath: `packages/app/tests/e2e/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tests/e2e/README.md)","packages/api/docs/auto_provision/AUTO_PROVISION.md":"# Auto_provision Skill\n\nPath: `packages/api/docs/auto_provision/AUTO_PROVISION.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/docs/auto_provision/AUTO_PROVISION.md)","packages/api/src/opamp/README.md":"# opamp Documentation\n\nPath: `packages/api/src/opamp/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/src/opamp/README.md)","packages/app/tests/e2e/fixtures/e2e-fixtures.json":"# Fixtures Skill\n\nPath: `packages/app/tests/e2e/fixtures/e2e-fixtures.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tests/e2e/fixtures/e2e-fixtures.json)"},"files":{".cursor/mcp.json":"{\n  \"mcpServers\": {\n    \"playwright-test\": {\n      \"command\": \"npx\",\n      \"args\": [\"playwright\", \"run-test-mcp-server\"]\n    }\n  }\n}\n","agent_docs/architecture.md":"# HyperDX Architecture\n\n## Core Services\n\n- **HyperDX UI (`packages/app`)**: Next.js frontend serving the user interface\n- **HyperDX API (`packages/api`)**: Node.js/Express backend handling queries and business logic\n- **OpenTelemetry Collector**: Receives and processes telemetry data\n- **ClickHouse**: Primary data store for all telemetry (logs, metrics, traces)\n- **MongoDB**: Metadata storage (users, dashboards, alerts, saved searches)\n\n## Data Flow\n\n1. Applications send telemetry via OpenTelemetry → OTel Collector\n2. OTel Collector processes and forwards data → ClickHouse\n3. Users interact with UI → API queries ClickHouse\n4. Configuration/metadata stored in MongoDB\n\n## Key MongoDB Models\n\nAll models follow consistent patterns with:\n- Team-based multi-tenancy (most entities belong to a `team`)\n- ObjectId references between related entities\n- Timestamps for audit trails\n- Zod schema validation\n\n**Key Models** (see `packages/api/src/models/`):\n- `Team`: Multi-tenant organization unit\n- `User`: Team members with authentication\n- `Source`: ClickHouse data source configuration\n- `Connection`: Database connection settings\n- `SavedSearch`: Saved queries and filters\n- `Dashboard`: Custom dashboard configurations\n- `Alert`: Monitoring alerts with thresholds\n\n## Frontend Architecture\n\n- **Pages**: `packages/app/pages/` (Next.js routing)\n- **Components**: `packages/app/src/` (reusable components)\n- **API communication**: Custom hooks wrapping TanStack Query\n- **State**: See tech_stack.md for state management details\n\n## Backend Architecture\n\nThe API package (`packages/api`) hosts several distinct applications, each with\nits own routing, authentication, and rate limiting:\n\n### Internal API (`src/routers/api/`)\n\nThe primary API consumed by the web frontend (`packages/app`). Uses session-based\nauthentication (Passport.js). Follows a standard layered structure:\n\n- **Routers**: `src/routers/api/` - Domain-specific API routes\n- **Controllers**: `src/controllers/` - Business logic separated from routes\n- **Middleware**: `src/middleware/` - Authentication, CORS, error handling\n- **Services**: `src/services/` - Reusable business logic (e.g., `agentService`)\n\n### External API v2 (`src/routers/external-api/v2/`)\n\nPublic REST API for programmatic access. Authenticated via Personal API Access\nKey (`validateUserAccessKey` middleware), rate-limited to 100 req/min.\n\n- **Routes**: `alerts.ts`, `charts.ts`, `dashboards.ts`, `sources.ts`,\n  `webhooks.ts`\n- **OpenAPI spec**: `packages/api/openapi.json` (auto-generated via\n  `yarn docgen`, linted via `yarn lint:openapi` using Spectral)\n- **Tests**: `src/routers/external-api/__tests__/`\n\nWhen adding or modifying external API endpoints, run `yarn docgen` to regenerate\nthe OpenAPI spec and `yarn lint:openapi` to validate it.\n\n`scripts/ci/check-openapi-sync.sh` (run by `make ci-lint` and by CI) fails if the\ncommitted spec is stale. `swaggerOptions` in `src/utils/swagger.ts` is also an\ninput, and the spec is in `.prettierignore` because docgen owns its formatting.\n\n### MCP Server (`src/mcp/`)\n\n[Model Context Protocol](https://modelcontextprotocol.io/) server that lets AI\nassistants query observability data and manage dashboards. Exposed as a stateless\nStreamable HTTP endpoint at `/api/mcp`, authenticated via Personal API Access\nKey, rate-limited to 600 req/min.\n\n- **Entry**: `app.ts` (Express middleware), `mcpServer.ts` (server factory)\n- **Tools**: `tools/alerts/`, `tools/dashboards/`, `tools/query/`,\n  `tools/savedSearches/` - each directory contains tool definitions and handlers\n- **Prompts**: `prompts/dashboards/` - context prompts for AI assistants\n- **Tests**: `src/mcp/__tests__/` (alerts, dashboards, query, savedSearches,\n  tracing)\n- **Dev/debug**: `yarn dev:mcp` launches the MCP Inspector for interactive\n  testing\n- **Response size**: each tool call records the UTF-8 bytes it returns\n  (`mcp.tool.response.size_bytes` span attribute,\n  `hyperdx.mcp.tool.response.size_bytes` histogram)\n\nSee `MCP.md` in the repo root for user-facing setup instructions.\n\n### OpAMP Server (`src/opamp/`)\n\nHTTP-based [OpAMP](https://github.com/open-telemetry/opamp-spec) server that\nserves configurations to supervised OpenTelemetry Collectors. The supervisor\npings `/v1/opamp` with status, and the server returns updated config when needed.\n\n- **Entry**: `app.ts` (Express sub-app)\n- **Controller**: `controllers/opampController.ts` - config derivation logic\n- **Service**: `services/agentService.ts` - agent management\n- **Model**: `models/agent.ts` - agent state persistence\n- **Proto**: `proto/` - Protocol Buffer definitions for OpAMP and anyvalue\n\nConfig is derived from the team document with the ingestion API key.\n\n### Background Tasks (`src/tasks/`)\n\nCron-driven tasks that run outside the request/response cycle. In development,\ntasks run via `yarn dev-task`; in production, they are triggered externally.\n\n- `checkAlerts/` - Alert evaluation (runs every minute in dev)\n- `provisionDashboards/` - Dashboard provisioning from config files\n- `usageStats.ts` - Usage statistics collection\n- `pingPongTask.ts` - Health check task\n- `metrics.ts` - Task execution metrics (duration, success/failure counters)\n\nNote: Background tasks do **not** run in Vercel preview deployments (see\n`agent_docs/development.md` for details).\n\n## Data & Query Patterns\n\n### ClickHouse Integration\n- **Query building**: Use `common-utils` for safe query construction\n- **Schema flexibility**: Support for various telemetry schemas via `Source` configuration\n\n### MongoDB Patterns\n- **Multi-tenancy**: All queries filtered by team context\n- **Relationships**: Use ObjectId references with proper population\n- **Indexing**: Strategic indexes for query performance\n- **Migrations**: Versioned migrations for schema changes (see `packages/api/migrations/`)\n\n## Security Requirements\n\n- **Server-side validation**: Always validate and sanitize on the backend\n- **Team isolation**: All data access must filter by team context\n- **API authentication**: Use authentication middleware on protected routes\n- **Secrets**: Never commit secrets; use `.env` files\n\n",".claude/agents/playwright-test-healer.md":"---\nname: playwright-test-healer\ndescription: Use this agent when you need to debug and fix failing Playwright tests\ntools: Glob, Grep, Read, LS, Edit, MultiEdit, Write, mcp__playwright-test__browser_console_messages, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_generate_locator, mcp__playwright-test__browser_network_requests, mcp__playwright-test__browser_snapshot, mcp__playwright-test__test_debug, mcp__playwright-test__test_list, mcp__playwright-test__test_run\nmodel: sonnet\ncolor: red\n---\n\nYou are the Playwright Test Healer, an expert test automation engineer specializing in debugging and\nresolving Playwright test failures. Your mission is to systematically identify, diagnose, and fix\nbroken Playwright tests using a methodical approach.\n\nYour workflow:\n1. **Initial Execution**: Run all tests using `test_run` tool to identify failing tests\n2. **Debug failed tests**: For each failing test run `test_debug`.\n3. **Error Investigation**: When the test pauses on errors, use available Playwright MCP tools to:\n   - Examine the error details\n   - Capture page snapshot to understand the context\n   - Analyze selectors, timing issues, or assertion failures\n4. **Root Cause Analysis**: Determine the underlying cause of the failure by examining:\n   - Element selectors that may have changed\n   - Timing and synchronization issues\n   - Data dependencies or test environment problems\n   - Application changes that broke test assumptions\n5. **Code Remediation**: Edit the test code to address identified issues, focusing on:\n   - Updating selectors to match current application state\n   - Fixing assertions and expected values\n   - Improving test reliability and maintainability\n   - For inherently dynamic data, utilize regular expressions to produce resilient locators\n6. **Verification**: Restart the test after each fix to validate the changes\n7. **Iteration**: Repeat the investigation and fixing process until the test passes cleanly\n\nKey principles:\n- Be systematic and thorough in your debugging approach\n- Document your findings and reasoning for each fix\n- Prefer robust, maintainable solutions over quick hacks\n- Use Playwright best practices for reliable test automation\n- If multiple errors exist, fix them one at a time and retest\n- Provide clear explanations of what was broken and how you fixed it\n- You will continue this process until the test runs successfully without any failures or errors.\n- If the error persists and you have high level of confidence that the test is correct, mark this test as test.fixme()\n  so that it is skipped during the execution. Add a comment before the failing step explaining what is happening instead\n  of the expected behavior.\n- Do not ask user questions, you are not interactive tool, do the most reasonable thing possible to pass the test.\n- Never wait for networkidle or use other discouraged or deprecated apis\n\n## HyperDX Project Conventions\n\n### Test Runner\nAlways use this command — do NOT use `npx playwright test` directly:\n```bash\n./scripts/test-e2e.sh --quiet <file> [--grep \"\\\"<pattern>\\\"\"]\n```\n\n### Common Failure Patterns\n\n1. **API 400 \"already exists\" — form won't close**: Check network requests first. The webhook API enforces uniqueness on `(team, service, url)`. Hardcoded URLs collide between parallel tests or retries. Fix: use `` `https://example.com/thing-${Date.now()}` `` for URLs, not just names.\n\n2. **Strict mode violation — locator matches N elements**: A locator like `getByRole('link').filter({ hasText: name })` can match both a nav sidebar entry and a page content entry. Fix: scope to a container, e.g. `alertsPage.pageContainer.getByRole('link').filter({ hasText: name })`.\n\n3. **Global count assertion fails — `toHaveCount(N)` receives more**: Other tests' data is in the shared DB. Fix: replace `toHaveCount(1)` with `filter({ hasText: uniqueName }).toBeVisible()`, and `toHaveCount(0)` with `filter({ hasText: uniqueName }).toBeHidden()`.\n\n4. **`waitFor({ state: 'detached' })` times out**: Usually caused by a failed API call keeping a form open (see #1). Diagnose network first; fix the data issue rather than adjusting the wait.\n\n### Page Object Pattern\n- Fix broken tests by correcting or extending page objects (`page-objects/`, `components/`) — not by adding raw `page.getByTestId()` calls to spec files\n- The spec file should only call methods/getters defined on page objects",".opencode/commands/do-linear.md":"---\ndescription:\n  Fetch a Linear ticket, implement the fix/feature, test, commit, push, and\n  raise a PR\n---\n\nLook up the Linear ticket $ARGUMENTS. Read the ticket description, comments, and\nany linked resources thoroughly.\n\n## Phase 1: Understand the Ticket\n\n- Summarize the ticket — what is being asked for (bug fix, feature, refactor,\n  etc.)\n- Identify acceptance criteria or expected behavior from the description\n- Note any linked issues, related tickets, or dependencies\n\nIf the ticket description is too vague or lacks enough information to proceed\nconfidently, **stop and ask me for clarification** before writing any code.\nExplain exactly what information is missing and what assumptions you would need\nto make.\n\n## Phase 2: Plan and Implement\n\nBefore writing code, read the relevant documentation from the `agent_docs/`\ndirectory to understand architecture and code patterns.\n\n1. Explore the codebase to understand the relevant code paths and existing\n   patterns\n2. Create an implementation plan — which files to change, what approach to take\n3. Implement the fix or feature following existing codebase patterns\n4. Keep changes minimal and focused on the ticket scope\n\n## Phase 3: Verify\n\nRun lint and type checks, then run the appropriate tests based on which packages\nwere modified:\n\n1. Run `make ci-lint` to verify lint and TypeScript types pass\n2. Run `make ci-unit` to verify unit tests pass across all packages\n3. If any checks fail, fix the issues and re-run until everything passes\n\n## Phase 4: Commit, Push, and Open PR\n\n1. Create a new branch named `<current-user>/$ARGUMENTS-<short-description>`.\n   Use the current git/OS username when available, and use `whoami` as a\n   fallback to determine the prefix (e.g. `warren/HDX-1234-fix-search-filter`)\n2. Commit the changes using conventional commit format (e.g. `feat:`, `fix:`,\n   `chore:`) and reference the ticket ID\n3. Push the branch to the remote\n4. Open a draft pull request with:\n   - Title: `[$ARGUMENTS] <description>`. If multiple tickets are being\n     addressed, omit the arguments from the title.\n   - Body: Use `.github/pull_request_template.md` as the template and fill it in\n     with the relevant summary, testing notes, and Linear ticket link\n   - Label: Attach the `ai-generated` label\n",".claude/agents/playwright-test-planner.md":"---\nname: playwright-test-planner\ndescription: Use this agent when you need to create comprehensive test plan for a web application or website\ntools: Glob, Grep, Read, LS, mcp__playwright-test__browser_click, mcp__playwright-test__browser_close, mcp__playwright-test__browser_console_messages, mcp__playwright-test__browser_drag, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_file_upload, mcp__playwright-test__browser_handle_dialog, mcp__playwright-test__browser_hover, mcp__playwright-test__browser_navigate, mcp__playwright-test__browser_navigate_back, mcp__playwright-test__browser_network_requests, mcp__playwright-test__browser_press_key, mcp__playwright-test__browser_select_option, mcp__playwright-test__browser_snapshot, mcp__playwright-test__browser_take_screenshot, mcp__playwright-test__browser_type, mcp__playwright-test__browser_wait_for, mcp__playwright-test__planner_setup_page, mcp__playwright-test__planner_save_plan\nmodel: sonnet\ncolor: green\n---\n\nYou are an expert web test planner with extensive experience in quality assurance, user experience testing, and test\nscenario design. Your expertise includes functional testing, edge case identification, and comprehensive test coverage\nplanning.\n\nYou will:\n\n1. **Navigate and Explore**\n   - Invoke the `planner_setup_page` tool once to set up page before using any other tools\n   - Explore the browser snapshot\n   - Do not take screenshots unless absolutely necessary\n   - Use `browser_*` tools to navigate and discover interface\n   - Thoroughly explore the interface, identifying all interactive elements, forms, navigation paths, and functionality\n\n2. **Analyze User Flows**\n   - Map out the primary user journeys and identify critical paths through the application\n   - Consider different user types and their typical behaviors\n\n3. **Design Comprehensive Scenarios**\n\n   Create detailed test scenarios that cover:\n   - Happy path scenarios (normal user behavior)\n   - Edge cases and boundary conditions\n   - Error handling and validation\n\n4. **Structure Test Plans**\n\n   Each scenario must include:\n   - Clear, descriptive title\n   - Detailed step-by-step instructions\n   - Expected outcomes where appropriate\n   - Assumptions about starting state (always assume blank/fresh state)\n   - Success criteria and failure conditions\n\n5. **Create Documentation**\n\n   Submit your test plan using `planner_save_plan` tool.\n\n**Quality Standards**:\n- Write steps that are specific enough for any tester to follow\n- Include negative testing scenarios\n- Ensure scenarios are independent and can be run in any order\n\n**Output Format**: Always save the complete test plan as a markdown file with clear headings, numbered steps, and\nprofessional formatting suitable for sharing with development and QA teams.\n\n## HyperDX Project Context\n\n### Application\nHyperDX is an observability platform. Key pages: `/search` (logs/traces), `/dashboards`, `/alerts`, `/metrics`, `/sessions`.\n\n### Test File Locations\n- Plans: `specs/`\n- Specs: `packages/app/tests/e2e/features/`\n- Page objects: `packages/app/tests/e2e/page-objects/`\n- Components: `packages/app/tests/e2e/components/`\n\n### Plan Requirements for HyperDX\n- Scenarios must be independent and assume a fresh DB state (the test runner clears MongoDB before each run)\n- Note when a scenario creates shared resources (e.g. webhooks, saved searches) that could conflict with parallel runs — flag these for data isolation\n- Reference existing page objects when describing steps so the generator agent knows what abstractions are available",".opencode/commands/plan-linear.md":"---\ndescription: Research a Linear ticket and create an implementation plan\nagent: plan\n---\n\nLook up the Linear ticket $ARGUMENTS. Read the ticket description and all\ncomments on the ticket thoroughly.\n\nBased on your research of the ticket, come up with a detailed implementation\nplan. The plan should include:\n\n1. **Summary** — A concise summary of what the ticket is asking for\n2. **Context** — Relevant information gathered from the ticket description and\n   comments\n3. **Approach** — Step-by-step implementation plan with specific files and\n   components to modify\n4. **Testing** — How the changes should be tested\n5. **Open Questions** — Any ambiguities or decisions that need clarification\n\nBefore writing the plan, explore the codebase to understand the relevant code\npaths and existing patterns. Reference specific files and line numbers where\nchanges will be needed.\n",".claude/agents/playwright-test-generator.md":"---\nname: playwright-test-generator\ndescription: 'Use this agent when you need to create automated browser tests using Playwright Examples: <example>Context: User wants to generate a test for the test plan item. <test-suite><!-- Verbatim name of the test spec group w/o ordinal like \"Multiplication tests\" --></test-suite> <test-name><!-- Name of the test case without the ordinal like \"should add two numbers\" --></test-name> <test-file><!-- Name of the file to save the test into, like tests/multiplication/should-add-two-numbers.spec.ts --></test-file> <seed-file><!-- Seed file path from test plan --></seed-file> <body><!-- Test case content including steps and expectations --></body></example>'\ntools: Glob, Grep, Read, LS, mcp__playwright-test__browser_click, mcp__playwright-test__browser_drag, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_file_upload, mcp__playwright-test__browser_handle_dialog, mcp__playwright-test__browser_hover, mcp__playwright-test__browser_navigate, mcp__playwright-test__browser_press_key, mcp__playwright-test__browser_select_option, mcp__playwright-test__browser_snapshot, mcp__playwright-test__browser_type, mcp__playwright-test__browser_verify_element_visible, mcp__playwright-test__browser_verify_list_visible, mcp__playwright-test__browser_verify_text_visible, mcp__playwright-test__browser_verify_value, mcp__playwright-test__browser_wait_for, mcp__playwright-test__generator_read_log, mcp__playwright-test__generator_setup_page, mcp__playwright-test__generator_write_test\nmodel: sonnet\ncolor: blue\n---\n\nYou are a Playwright Test Generator, an expert in browser automation and end-to-end testing.\nYour specialty is creating robust, reliable Playwright tests that accurately simulate user interactions and validate\napplication behavior.\n\n# For each test you generate\n- Obtain the test plan with all the steps and verification specification\n- Run the `generator_setup_page` tool to set up page for the scenario\n- For each step and verification in the scenario, do the following:\n  - Use Playwright tool to manually execute it in real-time.\n  - Use the step description as the intent for each Playwright tool call.\n- Retrieve generator log via `generator_read_log`\n- Immediately after reading the test log, invoke `generator_write_test` with the generated source code\n  - File should contain single test\n  - File name must be fs-friendly scenario name\n  - Test must be placed in a describe matching the top-level test plan item\n  - Test title must match the scenario name\n  - Includes a comment with the step text before each step execution. Do not duplicate comments if step requires\n    multiple actions.\n  - Always use best practices from the log when generating tests.\n\n## HyperDX Project Conventions\n\nApply these rules to ALL tests you generate for this project.\n\n### File Structure\n- Specs: `packages/app/tests/e2e/features/`\n- Page objects: `packages/app/tests/e2e/page-objects/`\n- Components: `packages/app/tests/e2e/components/`\n- Base test import: `import { expect, test } from '../utils/base-test';` (NOT `@playwright/test`)\n\n### Page Object Pattern (REQUIRED)\n- ALL UI interactions must go through page objects and components — no raw `page.getByTestId()`, `page.locator()`, or `page.getByRole()` directly in spec files\n- If a needed interaction doesn't exist in a page object, add it to the page object first, then use it in the spec\n\n### Data Isolation (CRITICAL)\nTests run in parallel and share a database. Use `Date.now()` for **every field the API uniqueness-checks**:\n\n```typescript\nconst ts = Date.now();\nconst name = `E2E Thing ${ts}`;\nconst url = `https://example.com/thing-${ts}`; // URL too, not just name\n```\n\nThe webhook API enforces uniqueness on `(team, service, url)`. Hardcoded URLs will collide.\n\n### Assertions\n- Never assert global counts (`toHaveCount(N)`) — scope to the current test's data instead\n- Example: `pageContainer.getByRole('link').filter({ hasText: name })` not `getAlertCards().toHaveCount(1)`\n- Use `toBeVisible()` / `toBeHidden()` (web-first), never `waitForTimeout`\n- Assert successful chart loads by checking `.recharts-responsive-container` is visible\n\n### Tags\n- `{ tag: '@full-stack' }` for tests requiring the backend (MongoDB + API)\n- Feature tags: `@dashboard`, `@alerts`, `@search`, etc.\n\n   <example-generation>\n   For following plan:\n\n   ```markdown file=specs/plan.md\n   ### 1. Adding New Todos\n   **Seed:** `tests/seed.spec.ts`\n\n   #### 1.1 Add Valid Todo\n   **Steps:**\n   1. Click in the \"What needs to be done?\" input field\n\n   #### 1.2 Add Multiple Todos\n   ...\n   ```\n\n   Following file is generated:\n\n   ```ts file=add-valid-todo.spec.ts\n   // spec: specs/plan.md\n   // seed: tests/seed.spec.ts\n\n   test.describe('Adding New Todos', () => {\n     test('Add Valid Todo', async { page } => {\n       // 1. Click in the \"What needs to be done?\" input field\n       await page.click(...);\n\n       ...\n     });\n   });\n   ```\n   </example-generation>",".cursor/rules/playwright.mdc":"---\ndescription: HyperDX Playwright E2E test conventions for writing, reviewing, and fixing tests. Use when creating, editing, or debugging any E2E test in this project.\nglobs:\nalwaysApply: false\n---\n\nWhen writing, reviewing, or fixing Playwright E2E tests for this project, follow the conventions in @.claude/skills/playwright/SKILL.md.\n\nTo run tests:\n```bash\n./scripts/test-e2e.sh --quiet <file> [--grep \"\\\"<pattern>\\\"\"]\n```\n",".claude/skills/refactor-component/SKILL.md":"---\nname: refactor-component\ndescription: Refactor a large React component file into a directory of smaller files. Use when the user asks to break up, split, or refactor a big component file.\n---\n\n# Refactor Large Component into Directory\n\nBreak a monolithic React component file into a well-organized directory with no functionality changes.\n\nThe target component is: $ARGUMENTS\n\nIf no component is specified, ask the user which file to refactor.\n\n## Workflow\n\n### 1. Check E2E test coverage\n\nBefore touching any code, verify that the component's key user flows are covered by E2E tests. Search for Playwright test files (typically in `packages/app/tests/e2e/`) that exercise the component — look for references to its `data-testid` attributes, page object methods, or user-visible behaviour (e.g. clicking Run, Save, switching chart types, SQL mode).\n\n- **If good coverage exists**: note the relevant test files and move on. These tests become your safety net — you will re-run them after the refactor to catch regressions.\n- **If coverage is missing or thin**: stop and ask the user whether they want to add E2E tests before refactoring. Present the gaps you found (e.g. \"raw SQL chart creation has no E2E test\") and let the user provide test requirements. Use the `playwright` skill to create the tests, then run them to confirm they pass on the current (pre-refactor) code. Only proceed with the refactor once the baseline E2E tests are green.\n\nThis step is critical — E2E tests are the strongest guarantee that the refactor doesn't break real user flows. Unit tests alone cannot catch issues like missing DOM elements that only appear when the full app is composed.\n\n### 2. Analyse the file\n\nRead the entire target file. Identify:\n\n- **Main component** — the default export (becomes the primary file in the new directory)\n- **Sub-components** — named function/const components used only inside this file\n- **Types & interfaces** — exported or internal types tied to the sub-components\n- **Utilities** — pure functions, Zod schemas, constants that aren't React components\n- **Tests** — any test file in a sibling `__tests__/` directory that imports the target\n\nCreate a plan listing each new file, what goes in it, and which imports change. Present the plan to the user and wait for approval before writing code.\n\n### 3. Create the directory and files\n\nThe new directory is created inside `packages/app/src/components/`, replacing the original file. It keeps the same name (without extension), so external imports resolve unchanged.\n\n```\npackages/app/src/components/ComponentName/\n  index.ts              — barrel re-export of the default export\n  ComponentName.tsx     — main component (default export)\n  SubComponent.tsx      — one file per sub-component (named export)\n  utils.ts              — utility functions, schemas, constants\n  __tests__/            — moved test files with updated imports\n```\n\n#### Rules\n\n- **`index.ts`** is the single public API of the directory. All exports that consumers depend on must be re-exported through `index.ts`. Sub-components or utilities that are only used within the directory should **not** be re-exported.\n- Each sub-component file has a **named export** (not default).\n- **Sibling imports** within the directory use `./` relative paths. Files outside the directory must never import directly from a sub-file (e.g. `ComponentName/ChartActionBar`) — they import from the directory barrel (`ComponentName`) only.\n- **All other relative imports** (`../Foo`, `./Foo`) in the extracted files must be converted to `@/`-prefixed absolute imports (e.g. `@/components/Foo`). This is critical — files moved one level deeper will break if relative paths aren't updated.\n- Existing `@/`-prefixed imports stay unchanged.\n- Do not add, remove, or rename any exports. The refactoring must be invisible to consumers.\n\n### 4. Move tests\n\nMove `__tests__/ComponentName.test.tsx` into `ComponentName/__tests__/ComponentName.test.tsx`.\n\nUpdate in the test file:\n\n- The main import: `from '../ComponentName'` → `from '..'`\n- Mock paths: `../SiblingComponent` → `../../SiblingComponent` (one extra level up)\n\n### 5. Delete the original file\n\nRemove the original monolithic `.tsx` file only after all new files are written.\n\n### 6. Tidy up\n\nAfter the initial split, clean up duplication and improve structure within the new directory:\n\n#### Remove unnecessary indirection\n\n- If a component is declared as `function FooComponent` and then aliased as `export const Foo = FooComponent`, rename the function to `Foo` and export it directly.\n\n#### Deduplicate code across files\n\n- Look for validation+normalization logic repeated across callbacks — extract a shared helper (e.g. `validateAndNormalize`) that returns `{ errors, config }` so each caller only contains its unique logic.\n- Deduplicate `renderComponent` helpers in test files — hoist a single shared factory to file scope. Describe blocks with special defaults can wrap it in a thin helper (e.g. `renderAlertComponent`) that passes overrides.\n\n#### Extract pure logic into utils.ts\n\nScan component files for logic that can move into `utils.ts`:\n\n- **Pure functions in `useMemo` callbacks** — if the memo body is a pure transformation (no hooks, no JSX), extract it as a named function in `utils.ts` and call it from the memo.\n- **Constants and lookup tables** — arrays/sets used in conditionals (e.g. `['table', 'time', 'number', 'pie'].includes(tab)`) become named exports (e.g. `TABS_WITH_GENERATED_SQL`).\n- **Simple mappings** — switch/if chains that map one value to another (e.g. `DisplayType` → tab string) become standalone functions. These don't need `useMemo` since they're cheap.\n- **Complex config builders** — conditional logic that selects/transforms configs for display (e.g. building sample events config, chart explanation config) should be pure functions that receive all dependencies as parameters.\n\nGood extraction candidates:\n\n- Config builder functions (`buildSampleEventsConfig`, `buildChartConfigForExplanations`)\n- Enum/type mappers (`displayTypeToActiveTab`)\n- Computed values with alert logic (`computeDbTimeChartConfig`)\n\nLeave in the component:\n\n- Logic that reads/writes React state or calls hooks\n- Event handlers that call `setValue`, `onSubmit`, etc.\n- JSX rendering logic\n\n#### Use named prop types\n\nAll components should use named type aliases for their props, declared directly above the component function:\n\n```tsx\ntype FooProps = {\n  bar: string;\n  onBaz: () => void;\n};\n\nexport function Foo({ bar, onBaz }: FooProps) {\n```\n\nDo not use inline object types in the function signature.\n\n#### Split large components further\n\nIf a file exceeds ~500 lines after the initial split, look for natural extraction points:\n\n- **Form inputs + toolbar** — form fields, series editors, action buttons → `ChartEditorControls.tsx`\n- **Preview/results area** — chart rendering, accordions, result display → `ChartPreviewPanel.tsx`\n- **The main file** becomes a thin orchestrator: form state, hooks, callbacks, effects, and a JSX shell that renders the sub-components.\n\nWhen splitting JSX, the extracted component receives form state via props (`control`, `setValue`, etc.). Watches that are only used in the extracted component (e.g. `alertChannelType`) can use `useWatch` inside it rather than being passed as props.\n\n#### Classify shared vs conditional JSX before extracting\n\nBefore moving JSX into a new component, map the render tree's branching structure. Every piece of JSX must be classified as either:\n\n- **Branch-specific** — rendered inside one arm of a conditional (ternary, `&&`, if/else)\n- **Shared** — rendered as a sibling of the conditional, appearing for all branches\n\n**Extract from the bottom up**: pull out the conditional/branch-specific parts first, leaving shared sections in the parent. Never bundle shared JSX into a component that only renders for one branch.\n\n**Verify after extraction**: for each value of every conditional, confirm the new code renders the same set of components as the original. A toolbar, action bar, or footer that appeared for all chart types must still appear for all chart types after the split.\n\n### 7. Write unit tests for extracted code\n\nThis is a dedicated step — do not skip it or fold it into another step.\n\n#### Tests for `utils.ts`\n\nWrite unit tests in `__tests__/utils.test.ts` covering:\n\n- All pure functions with normal inputs, edge cases, and null/undefined guards\n- Constants (verify membership)\n- Config builders (test null returns for invalid inputs, verify output shape for valid inputs)\n\n#### Tests for each extracted component\n\nWrite unit tests for each extracted component in `__tests__/<ComponentName>.test.tsx` covering:\n\n- **Conditional rendering**: for each prop/state that controls visibility, verify elements appear and disappear correctly\n- **Callbacks**: verify that prop callbacks are invoked on user interaction (clicks, etc.)\n- **Prop-driven behaviour**: test that props like `activeTab`, `isRawSqlInput`, `isSaving` produce the correct UI state (disabled buttons, hidden sections, etc.)\n- **Regression coverage**: if the extraction was motivated by a bug (e.g. shared controls missing for a specific mode), include a test that explicitly renders the component in that mode and asserts the controls are present\n\nUse a `FormWrapper` test helper when the component requires react-hook-form's `control`/`handleSubmit` — create a small wrapper that calls `useForm` with sensible defaults and passes the form methods to the component under test via a render-prop pattern. Mock heavy child components (chart renderers, SQL editors, etc.) with simple stubs that render a `data-testid`.\n\n### 8. Verify\n\nRun in order — fix any failures before proceeding to the next step:\n\n```bash\nmake ci-lint    # TypeScript compilation + lint\n```\n\n```bash\ncd packages/app && yarn ci:unit   # Unit tests (or the appropriate package)\n```\n\n```bash\nmake e2e   # E2E tests — re-run the same tests from step 1 to catch regressions\n```\n\nIf lint fails with import-sort or formatting errors, run `npx eslint --fix <file>` on the affected files and re-check. If there are unused-import warnings, remove the unused imports manually.\n\nIf an E2E test fails, investigate whether the failure is related to the refactoring (e.g. a broken import path at runtime) or a pre-existing flake. Fix refactoring-related failures before presenting the result. The E2E tests identified in step 1 are the most important — if those pass, the refactor is safe.\n\n## Checklist (self-review before presenting result)\n\n- [ ] E2E test coverage verified (or added) before refactoring began\n- [ ] No functionality changes — pure file reorganisation\n- [ ] Shared JSX (toolbars, action bars, footers) not accidentally bundled into a conditional branch's component\n- [ ] `index.ts` barrel makes the directory a drop-in replacement\n- [ ] All relative imports in extracted files converted to `@/` prefixed\n- [ ] Sibling imports within directory use `./`\n- [ ] Test file moved and import paths updated (both main import and mocks)\n- [ ] Original monolith file deleted\n- [ ] Duplicated logic extracted into shared helpers\n- [ ] Pure functions moved from components to `utils.ts`\n- [ ] All components use named prop types declared above the function\n- [ ] No file exceeds ~500 lines (split further if needed)\n- [ ] Unit tests written for `utils.ts` functions\n- [ ] Unit tests written for each extracted component (conditional rendering, callbacks, regression cases)\n- [ ] `make ci-lint` passes\n- [ ] Unit tests pass\n- [ ] E2E tests pass\n",".claude/skills/playwright/SKILL.md":"---\nname: playwright\ndescription: Writes end-to-end tests code using Playwright browser automation.\n---\n\n# Playwright End-to-End Test Writer\n\nI am a Playwright End-to-End Test Writer. I generate test code that simulates user interactions with the HyperDX application in a real browser environment, allowing us to verify that the application behaves as expected from the user's perspective.\n\nI will write tests covering these requirements: $ARGUMENTS.\n\nIf the requirements are empty or unclear, I will ask the user for a detailed description of the test they want.\n\n## Workflow\n\nUse the agents below to carry out each phase. Do not write test code directly in the main context.\n\n### 1. Test Generation\nDelegate to the **`playwright-test-generator`** agent (via the Agent tool). Pass it:\n- A full description of the test scenario including steps, expected outcomes, and edge cases\n- The target spec file path (`packages/app/tests/e2e/features/<feature>.spec.ts`)\n- Any relevant page object files that already exist for this feature\n\nThe agent will drive a real browser, execute the steps live, and produce spec code that follows HyperDX conventions. Review the output before proceeding.\n\nNOTE: When there is an existing spec file covering the feature, add new tests to the existing file instead of creating a new one. This keeps related tests together and avoids fragmentation.\n\n### 2. Test Execution\nAfter the generator agent writes the file, run the test:\n\n```bash\n./scripts/test-e2e.sh --quiet <test-file-name> [--grep \"\\\"<test name pattern>\\\"\"]\n```\n\nAlways run in full-stack mode (default). Do not ask the user about this.\n\n### 3. Iterative Fixing\nIf the test fails, delegate to the **`playwright-test-healer`** agent (via the Agent tool). Pass it:\n- The failing test file path\n- The error output\n- Any relevant context about what the test is supposed to do\n\nThe healer agent will debug interactively, fix the code, and re-run until the test passes.\n\n## HyperDX Project Conventions\n\nThese conventions apply to ALL test code produced by any agent. Review generated output to ensure compliance.\n\n### File Structure\n- Specs: `packages/app/tests/e2e/features/`\n- Page objects: `packages/app/tests/e2e/page-objects/`\n- Components: `packages/app/tests/e2e/components/`\n- Utilities: `packages/app/tests/e2e/utils/`\n- Base test (extends playwright with fixtures): `utils/base-test.ts`\n- Constants (source names): `utils/constants.ts`\n\n### Page Object Pattern (REQUIRED)\n- ALL UI interactions in spec files must go through page objects (`page-objects/`) and components (`components/`)\n- No raw `page.getByTestId()`, `page.locator()`, or `page.getByRole()` calls directly in spec files\n- If a needed interaction doesn't exist in a page object, add it to the page object — don't work around it in the spec\n\n### Data Isolation (CRITICAL)\nTests run in parallel and share a database. Use `Date.now()` for **every field the API uniqueness-checks** — not just display names:\n\n```typescript\nconst ts = Date.now();\nconst name = `E2E Thing ${ts}`;\nconst url = `https://example.com/thing-${ts}`; // URL too, not just name\n```\n\nThe webhook API enforces uniqueness on `(team, service, url)`. A hardcoded URL will collide between parallel runs or retries.\n\n### Assertions\n- Never assert global counts (`toHaveCount(N)`) — other tests' data pollutes the page\n- Scope assertions to the current test's data: `pageContainer.getByRole('link').filter({ hasText: name })`\n- Use web-first assertions (`toBeVisible()`, `toBeHidden()`) not imperative checks\n- Never use hardcoded waits (`waitForTimeout`) — wait for specific elements or conditions\n- Assert successful chart loads by checking `.recharts-responsive-container` is visible\n\n### Tags\n- `{ tag: '@full-stack' }` — tests requiring MongoDB + API backend\n- Feature tags: `@dashboard`, `@alerts`, `@search`, etc.\n\n### Imports\nAlways import from the base test, not directly from `@playwright/test`:\n```typescript\nimport { expect, test } from '../utils/base-test';\n```\n\n### Mock ClickHouse Data\n- E2E tests run against a local Docker environment with seeded ClickHouse data\n- Update `packages/app/tests/e2e/seed-clickhouse.ts` only if the scenario requires specific data not already seeded\n","AGENTS.md":"# HyperDX Development Guide\n\n## What is HyperDX?\n\nHyperDX is an observability platform that helps engineers search, visualize, and\nmonitor logs, metrics, traces, and session replays. It's built on ClickHouse for\nblazing-fast queries and supports OpenTelemetry natively.\n\n**Core value**: Unified observability with ClickHouse performance,\nschema-agnostic design, and correlation across all telemetry types in one place.\n\n## Architecture (WHAT)\n\nThis is a **monorepo** with six packages:\n\n- `packages/app` - Next.js frontend (TypeScript, Mantine UI, TanStack Query)\n- `packages/api` - Express backend (Node.js 22+, MongoDB for metadata,\n  ClickHouse for telemetry). Also hosts the **MCP server**, **External API v2**,\n  and **OpAMP server** as sub-applications.\n- `packages/common-utils` - Shared TypeScript utilities for query parsing and\n  validation\n- `packages/cli` - Terminal CLI and interactive TUI (`hdx`) for searching,\n  tailing, and inspecting logs and traces (Ink/React). Has its own\n  [`AGENTS.md`](packages/cli/AGENTS.md) with detailed architecture and\n  keybindings.\n- `packages/otel-collector` - Custom-built OpenTelemetry Collector (Go, OCB).\n  See its [`README.md`](packages/otel-collector/README.md) for architecture,\n  included components, and upgrade procedures.\n- `packages/hdx-eval` - AI eval framework for benchmarking MCP servers against\n  observability scenarios. Generates deterministic synthetic telemetry, spawns\n  agents, and grades with programmatic checks + LLM-as-judge. See its\n  [`README.md`](packages/hdx-eval/README.md) for setup and usage, and\n  [`agent_docs/evals.md`](agent_docs/evals.md) for the dual-slot A/B\n  comparison workflow.\n\n**Data flow**: Apps → OpenTelemetry Collector → ClickHouse (telemetry data) /\nMongoDB (configuration/metadata)\n\n## Development Setup (HOW)\n\n```bash\nyarn setup          # Install dependencies\nyarn dev            # Start full stack with worktree-isolated ports\n```\n\nThe project uses **Yarn 4.13.0** workspaces. Docker Compose manages ClickHouse,\nMongoDB, and the OTel Collector.\n\n**This repo is multi-agent friendly.** `yarn dev`, `make dev-int`, and\n`make dev-e2e` all use slot-based port isolation so multiple worktrees can run\ndev servers, integration tests, and E2E tests simultaneously without conflicts.\nA dev portal at http://localhost:9900 auto-starts and shows all running stacks.\nSee [`agent_docs/development.md`](agent_docs/development.md) for the full\nmulti-worktree setup, port allocation tables, and available commands.\n\n## Working on the Codebase (HOW)\n\n**Before starting a task**, read relevant documentation from the `agent_docs/`\ndirectory:\n\n- `agent_docs/architecture.md` - Detailed architecture patterns and data models\n- `agent_docs/tech_stack.md` - Technology stack details and component patterns\n- `agent_docs/development.md` - Development workflows, testing, and common tasks\n- `agent_docs/code_style.md` - Code patterns and best practices. **Read this\n  before writing or planning any `packages/app` UI change, and before adding a\n  type, Zod schema, helper, or component in any package**, not just while\n  typing code. It carries required patterns that are invisible from the\n  surrounding file (sentence-case UI text, mandated Button/ActionIcon variants,\n  `useConfirm` for confirmation dialogs, `EmptyState`, and where shared code\n  already lives), so copying the conventions of the component you are editing is\n  not sufficient.\n- `agent_docs/naming_objects.md` - How users name and rename objects\n  (`InlineNameInput`). Read before adding or changing any name field\n- `agent_docs/observability.md` - Instrumentation standards (tracing, metrics,\n  context) and the shared helpers (read when adding or changing a feature)\n\n**Package-specific guides** (read when working on that package):\n\n- `packages/cli/AGENTS.md` - CLI/TUI architecture, keybindings, web frontend\n  alignment, key patterns\n- `packages/otel-collector/README.md` - Collector build process, included\n  components, upgrade procedures, adding custom components\n- `MCP.md` - MCP server setup and available tools (user-facing)\n\n**After finishing all code edits**, run `yarn lint:fix` to auto-fix formatting\nand lint issues across all packages. Pre-commit hooks handle this when\ncommitting, but if you finish edits without committing, run `yarn lint:fix`\nbefore stopping.\n\n## Key Principles\n\n1. **Multi-tenancy**: All data is scoped to `Team` - ensure proper filtering\n2. **Type safety**: Use TypeScript strictly; Zod schemas for validation\n3. **Existing patterns**: Follow established patterns in the codebase - explore\n   similar files before implementing. **Before you define a type, Zod schema,\n   helper, or component, grep for one that already exists.** Search for the\n   operation it performs (`bucket`, `valid.*url`, `split.*trim`) - not the name\n   you were about to give it, because names differ. Look in\n   `packages/common-utils/src/` first, then the package you are editing. If you\n   find it, import or alias it; do not add a second definition. See\n   `agent_docs/code_style.md` → \"Before you add a type, schema, or helper\"\n4. **Component size**: Keep files under 300 lines; break down large components\n5. **UI Components**: Use custom Button/ActionIcon variants (`primary`,\n   `secondary`, `danger`), `useConfirm` for \"are you sure?\" dialogs rather than\n   a hand-rolled `Modal`, and sentence case for all user-facing text - see\n   `agent_docs/code_style.md` for required patterns\n6. **Testing**: Tests live in `__tests__/` directories; use Jest for\n   unit/integration tests\n7. **Observability**: This is an observability product - instrument new code as\n   you write it. Every team-scoped operation must carry team/user context\n   (`setBusinessContext`), and countable log events should also emit a metric.\n   For our own instrumentation we favor wide events — enrich the unit-of-work\n   span with rich, high-cardinality attributes and keep only span _names_ and\n   _metric_ attributes low-cardinality — while metrics stay first-class\n   (counters/histograms feed alerts and SLOs, and many deployments rely on\n   them). Use the shared helpers in\n   `packages/api/src/utils/instrumentation.ts`. See\n   [`agent_docs/observability.md`](agent_docs/observability.md).\n8. **Communication**: Be concise and straightforward - in chat, in code\n   comments, in commits, and in PR descriptions. See\n   [Communication style](#communication-style) below.\n\n## Communication style\n\nWrite plainly. This applies to everything you produce: chat replies, code\ncomments, commit messages, PR descriptions, and docs.\n\n- **Lead with the answer.** State the result first, then the detail that\n  supports it. No preamble, no restating the request back at the reader.\n- **Cut filler.** Drop hedges (\"it seems like\", \"essentially\", \"basically\"),\n  intensifiers (\"very\", \"extremely\", \"quite\"), and throat-clearing (\"in order\n  to\" → \"to\"). Prefer short concrete words over long abstract ones.\n- **Keep summaries short.** A handful of bullets or a short paragraph. Don't\n  recap what the diff already shows, and don't restate one point in three\n  different phrasings.\n- **No self-narration.** Skip the play-by-play of your own process, the options\n  you rejected, and the victory lap (\"Perfect!\", \"All done!\"). Report what\n  changed and what is still broken.\n- **Comments explain _why_, not _what_.** The code already says what it does.\n  Omit the comment when the line is self-evident; write one when a choice needs\n  justification — a workaround, a non-obvious constraint, a ClickHouse quirk. No\n  banner comments, no ASCII section dividers, and no `// increment the counter`\n  restatements. This applies to test bodies too: don't narrate each step of a\n  test that already reads top-to-bottom.\n- **Say it straight.** If something is broken, unverified, or skipped, say so in\n  one sentence. Don't soften bad news and don't oversell partial work.\n\n## Running Tests\n\nEach package has different test commands available:\n\n**packages/app** (unit tests only):\n\n```bash\ncd packages/app\nyarn ci:unit           # Run unit tests\nyarn dev:unit          # Watch mode for unit tests\n```\n\n**packages/api** (unit and integration tests):\n\n```bash\ncd packages/api\nyarn ci:unit                        # Run unit tests (no services needed)\n\nmake dev-int-build                  # Build dependencies (run once before integration tests)\nmake dev-int FILE=<TEST_FILE_NAME>  # Spins up Docker services and runs integration tests.\n                                    # Ctrl-C to stop and wait for all services to tear down.\n```\n\n**packages/common-utils** (both unit and integration tests):\n\n```bash\ncd packages/common-utils\nyarn ci:unit           # Run unit tests\nyarn dev:unit          # Watch mode for unit tests\nyarn ci:int            # Run integration tests\nyarn dev:int           # Watch mode for integration tests\n```\n\nTo run a specific test file or pattern:\n\n```bash\nyarn ci:unit <path/to/test.ts>                           # Run specific test file\nyarn ci:unit --testNamePattern=\"test name pattern\"       # Run tests matching pattern\n```\n\n**packages/cli** (type check only, no test suite):\n\n```bash\ncd packages/cli\nnpx tsc --noEmit        # Type check\n```\n\n**Lint & type check across all packages:**\n\n```bash\nmake ci-lint        # Lint + TypeScript check across all packages\nmake ci-unit        # Unit tests across all packages\n```\n\n**E2E tests (Playwright):**\n\n```bash\n# First-time setup (install Chromium browser):\ncd packages/app && yarn playwright install chromium\n\n# Run all E2E tests:\nmake e2e\n\n# Run a specific test file (dev mode: hot reload):\nmake dev-e2e FILE=navigation                    # Match files containing \"navigation\"\nmake dev-e2e FILE=navigation GREP=\"help menu\"   # Also filter by test name\nmake dev-e2e GREP=\"should navigate\"             # Filter by test name across all files\nmake dev-e2e FILE=navigation REPORT=1           # Open HTML report after run\nmake dev-e2e-clean                               # Remove test artifacts\n```\n\n## Important Context\n\n- **Authentication**: Passport.js with team-based access control\n- **State management**: Jotai (client), TanStack Query (server), URL params\n  (filters)\n- **UI library**: Mantine components are the standard (not custom UI)\n- **Database patterns**: MongoDB for metadata with Mongoose, ClickHouse for\n  telemetry queries\n\n## PR Hygiene for Agent-Generated Code\n\nWhen using agentic tools to generate PRs, follow these practices to keep reviews\nefficient and accurate:\n\n1. **Scope PRs to a single logical change**, even if the agent can produce more\n   in one session. Smaller, focused PRs move through the review pipeline faster\n   and are easier to classify accurately.\n\n2. **Write the PR description to explain intent (the \"why\"), not just what\n   changed.** Reviewers need to understand the goal to catch cases where the\n   agent solved the wrong problem or made a plausible-but-wrong trade-off.\n\n3. **Name agent-generated branches with a `claude/`, `agent/`, or `ai/` prefix**\n   (e.g., `claude/add-rate-limiting`) so reviewers can calibrate their attention.\n   This is a convention for humans: the PR triage classifier deliberately ignores\n   branch names and tiers every PR on what the diff touches and how big it is.\n\n4. **Write or update tests alongside the implementation**, not after. Configure\n   your agent to produce tests before writing implementation code. See the\n   Testing section below for the commands to use.\n\n5. **Attach before/after screenshots to any PR that changes the UI.** Anything\n   visible in `packages/app` needs a \"Before\" (`main`) and \"After\" (branch)\n   image in the PR template's screenshots table, taken on the same screen, data,\n   viewport, and theme. Use a short video for interactions. If you can't capture\n   screenshots yourself (no browser tool), say so in the PR description and\n   leave the table for the human author to fill; never submit an empty table\n   silently. See\n   [CONTRIBUTING.md](CONTRIBUTING.md#ui-changes-need-beforeafter-screenshots).\n\n6. **Write reproduction steps a reviewer can follow.** Fill in the PR\n   template's \"How to reproduce\" section with numbered steps that show the\n   problem on `main` and the fix on the branch. Start from\n   [play.hyperdx.io](https://play.hyperdx.io) when the bug shows there, or from\n   `yarn app:dev:local` connected to the demo server (onboarding → \"Connect to\n   Demo Server\"; the PR's Vercel preview runs the same local mode). Full-stack\n   `yarn dev` pre-provisions a local ClickHouse connection and never shows that\n   button, so use it only when the change needs the API. Name UI elements by\n   visible text, and list any env vars,\n   feature flags, schema, or seed data needed. When filing issues, apply the\n   same standard. See\n   [CONTRIBUTING.md](CONTRIBUTING.md#reproducing-issues-and-prs).\n\n7. **Ensure a changeset exists before pushing a PR.** Any change to a published\n   package (`@hyperdx/app`, `@hyperdx/api`, `@hyperdx/otel-collector`, etc.) that\n   is user-facing or affects behavior must include a changeset in `.changeset/`.\n   Add one with `yarn changeset` (or create the markdown file by hand following\n   the format of existing entries), choosing the appropriate semver bump, before\n   pushing the branch. Skip only for changes that don't warrant a release (docs,\n   internal tooling, tests, CI).\n\n8. **The root `CHANGELOG.md` is generated at release time.** During each\n   release, CI writes an AI-generated cross-package summary section into the\n   root `CHANGELOG.md` on the \"Release HyperDX\" PR. Review and edit it there\n   like any other file — but keep the `<!-- hyperdx-release-notes … -->` comment\n   marker intact; it is how your edits are recognised when the release branch is\n   rebuilt. Use `###` or deeper for any heading you add — a `##` marks a release\n   boundary, and the next release refuses to splice rather than risk deleting\n   whatever ended up below it. Your edits are regenerated away when new\n   changesets land on `main` (the previous text is passed to the generator, so\n   phrasing is preserved best-effort, not guaranteed). They can also be lost\n   outright if a second push to `main` lands while a changelog run is still in\n   flight — the edit is held only in that run's artifact. If an edit matters,\n   re-check it on the release PR before merging. Don't edit the root\n   `CHANGELOG.md` in feature PRs; the only exception is the one-time seed that\n   introduced the file.\n\n### How the root changelog is generated\n\nDefined in `.github/workflows/release.yml`; the splicing logic lives in\n`.github/scripts/release-notes.mjs`.\n\n```\npush to main\n    |\n    v\ncheck_changesets\n    |  1. capture the branch's current CHANGELOG.md -> artifact\n    |     (must happen BEFORE the next step destroys it)\n    |  2. changesets/action force-rebuilds changeset-release/main from main\n    |     and opens/updates the \"Release HyperDX\" PR\n    v\nrelease_changelog_draft            contents: read - no push token\n    |\n    |  app version unchanged?  --yes-->  skip (CLI/common-utils-only release)\n    |  changeset hash matches?  --yes-->  reuse previous section verbatim\n    |                           --no-->  Claude writes a fresh body, given\n    |                                    the old section as context\n    v\n  body artifact                    the model's only output\n    |\n    v\nrelease_changelog_publish          contents: write - the model never ran here\n    |\n    |  branch moved since drafting?  --yes-->  skip, the newer run republishes\n    |  validate (no headings/markers/images/off-site links)\n    |  append the package list, splice into CHANGELOG.md\n    v\npush to changeset-release/main  ->  appears as a diff in the release PR,\n    |                               where a maintainer can edit it\n    v\nmerge the release PR  ->  CHANGELOG.md lands on main  ->  served in \"What's new\"\n```\n\nThe job split is a security boundary, not tidiness: the model reads changeset\nbodies, commit messages and PR bodies, which anyone opening a PR controls. Its\njob holds `ANTHROPIC_API_KEY` and a `contents: read` token, but no push\ncredential and no ability to alter the script that does the splicing. Because\nthe API key shares that process, the generator gets `--tools \"Read\" \"Write\"` and\nnothing else: no `Bash`, and no `Grep` or `Glob` either, since those read files\nwithout consulting a `Read` path rule. It may write exactly one file, granted by\nan `Edit(<path>)` rule, and `/proc`, `/sys`, `/home` and `/etc` are denied\noutright — `/proc/self/environ` carries the whole environment, and the output\nis published to a public branch.\n\nThree flags with three different jobs, which is worth keeping straight when\nediting this: `--tools` restricts what exists, `--allowedTools` only\npre-approves (it is what stops a `-p` run stalling on a prompt it cannot\nanswer), and `--disallowedTools` denies. A path rule attached to `Write` is\naccepted and then never consulted — file permissions are checked against\n`Edit` and `Read` rules — so write confinement is spelled `Edit(<path>)`.\n\nBecause the generator has no way to list a directory, every input is\nmaterialised for it at a known path by trusted shell, including all the\nchangesets concatenated into one file. Left to discover\n`.changeset/gentle-boats-serve.md` by name it cannot, and it writes a changelog\nthat quietly omits whatever it could not find.\n\nThe generator calls the Claude Code CLI, not\n`anthropics/claude-code-action`: that action accepts only GitHub entity events\nand rejects `push`, and everything it adds on top of the CLI — a token, entity\ncontext, PR comments — is what this job deliberately does without.\n\n## Responding to review feedback\n\nTwo bots review every PR (Claude Code Review inline + summary, Deep Review\nsummary). No finding blocks merge automatically; a maintainer decides what\nlands. Severity tells you what they will expect.\n\n1. **Triage before you touch code.** Two questions per comment: did this PR\n   introduce the problem (would reverting the PR make it go away?), and how\n   severe is it?\n   - Critical or major (P0/P1) that this PR introduced, in new or edited code:\n     fix it before asking for review. A maintainer will require it if it is\n     real.\n   - Minor (P2/P3) that this PR introduced: your call. Fix if small, else\n     reply.\n   - A defect that was already there before this PR, or a suggestion to widen\n     the change (hoist, dedupe, refactor neighbours, fix other call sites):\n     never fix here, whatever the severity. Reply in the thread with one\n     sentence; if it is critical, say so plainly so a maintainer sees it. The\n     reviewer reads replies and does not re-report what a human has answered.\n2. **Do not touch files the PR did not already touch** unless fixing a defect\n   in this PR's own change requires it.\n3. **Push review fixes as new commits, not a force-push.** The repo\n   squash-merges, so commit count never reaches `main`; review history does.\n4. **After two rounds of bot findings, stop.** Ask a maintainer to look at the\n   scope instead of addressing more automated comments. A PR that keeps\n   growing to satisfy a bot is drifting from its purpose.\n5. A finding you disagree with is not a defect. Say so and move on.\n\n## GitHub Action Workflow (when invoked via @claude)\n\nWhen working on issues or PRs through the GitHub Action:\n\n1. **Before writing any code**, post a comment outlining your implementation\n   plan — which files you'll change, what approach you'll take, and any\n   trade-offs or risks. Use `gh issue comment` for issues or `gh pr comment` for\n   PRs.\n\n2. **After making any code changes**, always run these in order and fix any\n   failures before opening a PR:\n\n   - `make ci-lint` — lint + TypeScript type check\n   - `make ci-unit` — unit tests\n\n3. Write a clear PR description explaining what changed and why.\n\n## Git Commits\n\nWhen committing code, use the git author's default profile (name and email from\ngit config). Do not add `Co-Authored-By` trailers.\n\n**Pre-commit hooks must pass before committing.** Do not use `--no-verify` to\nskip hooks. If the pre-commit hook fails (e.g. due to husky not being set up in\na worktree), run `npx lint-staged` manually before committing to ensure lint and\nformatting checks pass. Fix any issues before creating the commit.\n\n## Merge Conflict Resolution\n\n1. **Never blindly pick a side.** Read both sides of every conflict to\n   understand the intent of each change before choosing a resolution.\n\n2. **Refactor/move conflicts require extra verification.** When one side\n   refactored, moved, or extracted code (e.g., inline components to separate\n   files), always diff the discarded side against the destination files before\n   declaring the conflict resolved. Code can diverge after extraction — the\n   other branch may have made fixes or additions that the extracting branch\n   never picked up. A naive \"keep ours\" resolution silently drops those changes.\n\n3. **Verify the result compiles.** After resolving, check for missing imports,\n   broken references, or type errors introduced by the resolution — especially\n   when discarding a side that added new dependencies or exports.\n\n4. **Ask for help when uncertain.** If you are not 100% confident about which\n   side to keep, or whether a change can be safely discarded, stop and ask for\n   manual intervention rather than guessing. A wrong guess silently breaks\n   things; asking is always cheaper than debugging later.\n\n## Cursor Cloud specific instructions\n\n### Docker requirement\n\nDocker must be installed and running before starting the dev stack or running\nintegration/E2E tests. The VM update script handles `yarn install` and\n`yarn build:common-utils`, but Docker daemon startup is a prerequisite that must\nalready be available.\n\n### Starting the dev stack\n\n`yarn dev` uses `sh -c` to source `scripts/dev-env.sh`, which contains\nbash-specific syntax (`BASH_SOURCE`). On systems where `/bin/sh` is `dash`\n(e.g. Ubuntu), this fails with \"Bad substitution\". Work around it by running\nwith bash directly:\n\n```bash\nbash -c 'export PATH=\"/workspace/node_modules/.bin:$PATH\" && source ./scripts/dev-env.sh && yarn build:common-utils && dotenvx run --convention=nextjs -- docker compose -p \"$HDX_DEV_PROJECT\" -f docker-compose.dev.yml up -d && yarn app:dev'\n```\n\nPort isolation assigns a slot based on the worktree directory name. In the\ndefault `/workspace` directory, the slot is **76**, so services are at:\n\n- **App**: http://localhost:30276\n- **API**: http://localhost:30176\n- **ClickHouse**: http://localhost:30576\n- **MongoDB**: localhost:30476\n\n### Key commands reference\n\nSee `AGENTS.md` above and `agent_docs/development.md` for the full command\nreference. Quick summary:\n\n- `make ci-lint` — lint + TypeScript type check\n- `make ci-unit` — unit tests (all packages)\n- `make dev-int FILE=<name>` — integration tests (spins up Docker services)\n- `make dev-e2e FILE=<name>` — E2E tests (Playwright)\n\n### First-time registration\n\nWhen the dev stack starts fresh (empty MongoDB), the app shows a registration\npage. Create any account to get started — no external auth provider is needed.\n\n---\n\n_Need more details? Check the `agent_docs/` directory or ask which documentation\nto read._\n","packages/otel-collector/builder-config.yaml":"# Otel-collector Skill\n\nPath: `packages/otel-collector/builder-config.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/builder-config.yaml)","packages/otel-collector/CHANGELOG.md":"# Otel-collector Skill\n\nPath: `packages/otel-collector/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/CHANGELOG.md)","packages/otel-collector/package.json":"# Otel-collector Skill\n\nPath: `packages/otel-collector/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/package.json)","packages/otel-collector/README.md":"# otel-collector Documentation\n\nPath: `packages/otel-collector/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/README.md)","packages/common-utils/CHANGELOG.md":"# Common-utils Skill\n\nPath: `packages/common-utils/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/CHANGELOG.md)","packages/common-utils/package.json":"# Common-utils Skill\n\nPath: `packages/common-utils/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/package.json)","packages/common-utils/README.md":"# common-utils Documentation\n\nPath: `packages/common-utils/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/README.md)","packages/common-utils/tsconfig.json":"# Common-utils Skill\n\nPath: `packages/common-utils/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/tsconfig.json)","packages/cli/AGENTS.md":"# Cli Skill\n\nPath: `packages/cli/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/AGENTS.md)","packages/cli/CHANGELOG.md":"# Cli Skill\n\nPath: `packages/cli/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/CHANGELOG.md)","packages/cli/CONTRIBUTING.md":"# Cli Skill\n\nPath: `packages/cli/CONTRIBUTING.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/CONTRIBUTING.md)","packages/cli/package.json":"# Cli Skill\n\nPath: `packages/cli/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/package.json)","packages/cli/README.md":"# cli Documentation\n\nPath: `packages/cli/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/README.md)","packages/cli/tsconfig.json":"# Cli Skill\n\nPath: `packages/cli/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/tsconfig.json)","packages/app/CHANGELOG.md":"# App Skill\n\nPath: `packages/app/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/CHANGELOG.md)","packages/app/package.json":"# App Skill\n\nPath: `packages/app/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/package.json)","packages/app/tsconfig.build.json":"# App Skill\n\nPath: `packages/app/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tsconfig.build.json)","packages/app/tsconfig.json":"# App Skill\n\nPath: `packages/app/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tsconfig.json)","packages/api/.spectral.yaml":"# Api Skill\n\nPath: `packages/api/.spectral.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/.spectral.yaml)","packages/api/CHANGELOG.md":"# Api Skill\n\nPath: `packages/api/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/CHANGELOG.md)","packages/api/nodemon.json":"# Api Skill\n\nPath: `packages/api/nodemon.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/nodemon.json)","packages/api/openapi.json":"# Api Skill\n\nPath: `packages/api/openapi.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/openapi.json)","packages/api/package.json":"# Api Skill\n\nPath: `packages/api/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/package.json)","packages/api/tsconfig.build.json":"# Api Skill\n\nPath: `packages/api/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/tsconfig.build.json)","packages/api/tsconfig.json":"# Api Skill\n\nPath: `packages/api/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/tsconfig.json)","packages/app/public/pyodide/pyodide-lock.json":"# Pyodide Skill\n\nPath: `packages/app/public/pyodide/pyodide-lock.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/public/pyodide/pyodide-lock.json)","packages/app/src/dashboardTemplates/dotnet-runtime.json":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/dotnet-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/dotnet-runtime.json)","packages/app/src/dashboardTemplates/go-runtime.json":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/go-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/go-runtime.json)","packages/app/src/dashboardTemplates/jvm-runtime-metrics.json":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/jvm-runtime-metrics.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/jvm-runtime-metrics.json)","packages/app/src/dashboardTemplates/nodejs-runtime.json":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/nodejs-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/nodejs-runtime.json)","packages/app/src/dashboardTemplates/python-runtime.json":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/python-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/python-runtime.json)","packages/app/tests/e2e/README.md":"# e2e Documentation\n\nPath: `packages/app/tests/e2e/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tests/e2e/README.md)","packages/api/docs/auto_provision/AUTO_PROVISION.md":"# Auto_provision Skill\n\nPath: `packages/api/docs/auto_provision/AUTO_PROVISION.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/docs/auto_provision/AUTO_PROVISION.md)","packages/api/src/opamp/README.md":"# opamp Documentation\n\nPath: `packages/api/src/opamp/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/src/opamp/README.md)","packages/app/tests/e2e/fixtures/e2e-fixtures.json":"# Fixtures Skill\n\nPath: `packages/app/tests/e2e/fixtures/e2e-fixtures.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tests/e2e/fixtures/e2e-fixtures.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# HyperDX Development Guide\n\n## What is HyperDX?\n\nHyperDX is an observability platform that helps engineers search, visualize, and\nmonitor logs, metrics, traces, and session replays. It's built on ClickHouse for\nblazing-fast queries and supports OpenTelemetry natively.\n\n**Core value**: Unified observability with ClickHouse performance,\nschema-agnostic design, and correlation across all telemetry types in one place.\n\n## Architecture (WHAT)\n\nThis is a **monorepo** with six packages:\n\n- `packages/app` - Next.js frontend (TypeScript, Mantine UI, TanStack Query)\n- `packages/api` - Express backend (Node.js 22+, MongoDB for metadata,\n  ClickHouse for telemetry). Also hosts the **MCP server**, **External API v2**,\n  and **OpAMP server** as sub-applications.\n- `packages/common-utils` - Shared TypeScript utilities for query parsing and\n  validation\n- `packages/cli` - Terminal CLI and interactive TUI (`hdx`) for searching,\n  tailing, and inspecting logs and traces (Ink/React). Has its own\n  [`AGENTS.md`](packages/cli/AGENTS.md) with detailed architecture and\n  keybindings.\n- `packages/otel-collector` - Custom-built OpenTelemetry Collector (Go, OCB).\n  See its [`README.md`](packages/otel-collector/README.md) for architecture,\n  included components, and upgrade procedures.\n- `packages/hdx-eval` - AI eval framework for benchmarking MCP servers against\n  observability scenarios. Generates deterministic synthetic telemetry, spawns\n  agents, and grades with programmatic checks + LLM-as-judge. See its\n  [`README.md`](packages/hdx-eval/README.md) for setup and usage, and\n  [`agent_docs/evals.md`](agent_docs/evals.md) for the dual-slot A/B\n  comparison workflow.\n\n**Data flow**: Apps → OpenTelemetry Collector → ClickHouse (telemetry data) /\nMongoDB (configuration/metadata)\n\n## Development Setup (HOW)\n\n```bash\nyarn setup          # Install dependencies\nyarn dev            # Start full stack with worktree-isolated ports\n```\n\nThe project uses **Yarn 4.13.0** workspaces. Docker Compose manages ClickHouse,\nMongoDB, and the OTel Collector.\n\n**This repo is multi-agent friendly.** `yarn dev`, `make dev-int`, and\n`make dev-e2e` all use slot-based port isolation so multiple worktrees can run\ndev servers, integration tests, and E2E tests simultaneously without conflicts.\nA dev portal at http://localhost:9900 auto-starts and shows all running stacks.\nSee [`agent_docs/development.md`](agent_docs/development.md) for the full\nmulti-worktree setup, port allocation tables, and available commands.\n\n## Working on the Codebase (HOW)\n\n**Before starting a task**, read relevant documentation from the `agent_docs/`\ndirectory:\n\n- `agent_docs/architecture.md` - Detailed architecture patterns and data models\n- `agent_docs/tech_stack.md` - Technology stack details and component patterns\n- `agent_docs/development.md` - Development workflows, testing, and common tasks\n- `agent_docs/code_style.md` - Code patterns and best practices. **Read this\n  before writing or planning any `packages/app` UI change, and before adding a\n  type, Zod schema, helper, or component in any package**, not just while\n  typing code. It carries required patterns that are invisible from the\n  surrounding file (sentence-case UI text, mandated Button/ActionIcon variants,\n  `useConfirm` for confirmation dialogs, `EmptyState`, and where shared code\n  already lives), so copying the conventions of the component you are editing is\n  not sufficient.\n- `agent_docs/naming_objects.md` - How users name and rename objects\n  (`InlineNameInput`). Read before adding or changing any name field\n- `agent_docs/observability.md` - Instrumentation standards (tracing, metrics,\n  context) and the shared helpers (read when adding or changing a feature)\n\n**Package-specific guides** (read when working on that package):\n\n- `packages/cli/AGENTS.md` - CLI/TUI architecture, keybindings, web frontend\n  alignment, key patterns\n- `packages/otel-collector/README.md` - Collector build process, included\n  components, upgrade procedures, adding custom components\n- `MCP.md` - MCP server setup and available tools (user-facing)\n\n**After finishing all code edits**, run `yarn lint:fix` to auto-fix formatting\nand lint issues across all packages. Pre-commit hooks handle this when\ncommitting, but if you finish edits without committing, run `yarn lint:fix`\nbefore stopping.\n\n## Key Principles\n\n1. **Multi-tenancy**: All data is scoped to `Team` - ensure proper filtering\n2. **Type safety**: Use TypeScript strictly; Zod schemas for validation\n3. **Existing patterns**: Follow established patterns in the codebase - explore\n   similar files before implementing. **Before you define a type, Zod schema,\n   helper, or component, grep for one that already exists.** Search for the\n   operation it performs (`bucket`, `valid.*url`, `split.*trim`) - not the name\n   you were about to give it, because names differ. Look in\n   `packages/common-utils/src/` first, then the package you are editing. If you\n   find it, import or alias it; do not add a second definition. See\n   `agent_docs/code_style.md` → \"Before you add a type, schema, or helper\"\n4. **Component size**: Keep files under 300 lines; break down large components\n5. **UI Components**: Use custom Button/ActionIcon variants (`primary`,\n   `secondary`, `danger`), `useConfirm` for \"are you sure?\" dialogs rather than\n   a hand-rolled `Modal`, and sentence case for all user-facing text - see\n   `agent_docs/code_style.md` for required patterns\n6. **Testing**: Tests live in `__tests__/` directories; use Jest for\n   unit/integration tests\n7. **Observability**: This is an observability product - instrument new code as\n   you write it. Every team-scoped operation must carry team/user context\n   (`setBusinessContext`), and countable log events should also emit a metric.\n   For our own instrumentation we favor wide events — enrich the unit-of-work\n   span with rich, high-cardinality attributes and keep only span _names_ and\n   _metric_ attributes low-cardinality — while metrics stay first-class\n   (counters/histograms feed alerts and SLOs, and many deployments rely on\n   them). Use the shared helpers in\n   `packages/api/src/utils/instrumentation.ts`. See\n   [`agent_docs/observability.md`](agent_docs/observability.md).\n8. **Communication**: Be concise and straightforward - in chat, in code\n   comments, in commits, and in PR descriptions. See\n   [Communication style](#communication-style) below.\n\n## Communication style\n\nWrite plainly. This applies to everything you produce: chat replies, code\ncomments, commit messages, PR descriptions, and docs.\n\n- **Lead with the answer.** State the result first, then the detail that\n  supports it. No preamble, no restating the request back at the reader.\n- **Cut filler.** Drop hedges (\"it seems like\", \"essentially\", \"basically\"),\n  intensifiers (\"very\", \"extremely\", \"quite\"), and throat-clearing (\"in order\n  to\" → \"to\"). Prefer short concrete words over long abstract ones.\n- **Keep summaries short.** A handful of bullets or a short paragraph. Don't\n  recap what the diff already shows, and don't restate one point in three\n  different phrasings.\n- **No self-narration.** Skip the play-by-play of your own process, the options\n  you rejected, and the victory lap (\"Perfect!\", \"All done!\"). Report what\n  changed and what is still broken.\n- **Comments explain _why_, not _what_.** The code already says what it does.\n  Omit the comment when the line is self-evident; write one when a choice needs\n  justification — a workaround, a non-obvious constraint, a ClickHouse quirk. No\n  banner comments, no ASCII section dividers, and no `// increment the counter`\n  restatements. This applies to test bodies too: don't narrate each step of a\n  test that already reads top-to-bottom.\n- **Say it straight.** If something is broken, unverified, or skipped, say so in\n  one sentence. Don't soften bad news and don't oversell partial work.\n\n## Running Tests\n\nEach package has different test commands available:\n\n**packages/app** (unit tests only):\n\n```bash\ncd packages/app\nyarn ci:unit           # Run unit tests\nyarn dev:unit          # Watch mode for unit tests\n```\n\n**packages/api** (unit and integration tests):\n\n```bash\ncd packages/api\nyarn ci:unit                        # Run unit tests (no services needed)\n\nmake dev-int-build                  # Build dependencies (run once before integration tests)\nmake dev-int FILE=<TEST_FILE_NAME>  # Spins up Docker services and runs integration tests.\n                                    # Ctrl-C to stop and wait for all services to tear down.\n```\n\n**packages/common-utils** (both unit and integration tests):\n\n```bash\ncd packages/common-utils\nyarn ci:unit           # Run unit tests\nyarn dev:unit          # Watch mode for unit tests\nyarn ci:int            # Run integration tests\nyarn dev:int           # Watch mode for integration tests\n```\n\nTo run a specific test file or pattern:\n\n```bash\nyarn ci:unit <path/to/test.ts>                           # Run specific test file\nyarn ci:unit --testNamePattern=\"test name pattern\"       # Run tests matching pattern\n```\n\n**packages/cli** (type check only, no test suite):\n\n```bash\ncd packages/cli\nnpx tsc --noEmit        # Type check\n```\n\n**Lint & type check across all packages:**\n\n```bash\nmake ci-lint        # Lint + TypeScript check across all packages\nmake ci-unit        # Unit tests across all packages\n```\n\n**E2E tests (Playwright):**\n\n```bash\n# First-time setup (install Chromium browser):\ncd packages/app && yarn playwright install chromium\n\n# Run all E2E tests:\nmake e2e\n\n# Run a specific test file (dev mode: hot reload):\nmake dev-e2e FILE=navigation                    # Match files containing \"navigation\"\nmake dev-e2e FILE=navigation GREP=\"help menu\"   # Also filter by test name\nmake dev-e2e GREP=\"should navigate\"             # Filter by test name across all files\nmake dev-e2e FILE=navigation REPORT=1           # Open HTML report after run\nmake dev-e2e-clean                               # Remove test artifacts\n```\n\n## Important Context\n\n- **Authentication**: Passport.js with team-based access control\n- **State management**: Jotai (client), TanStack Query (server), URL params\n  (filters)\n- **UI library**: Mantine components are the standard (not custom UI)\n- **Database patterns**: MongoDB for metadata with Mongoose, ClickHouse for\n  telemetry queries\n\n## PR Hygiene for Agent-Generated Code\n\nWhen using agentic tools to generate PRs, follow these practices to keep reviews\nefficient and accurate:\n\n1. **Scope PRs to a single logical change**, even if the agent can produce more\n   in one session. Smaller, focused PRs move through the review pipeline faster\n   and are easier to classify accurately.\n\n2. **Write the PR description to explain intent (the \"why\"), not just what\n   changed.** Reviewers need to understand the goal to catch cases where the\n   agent solved the wrong problem or made a plausible-but-wrong trade-off.\n\n3. **Name agent-generated branches with a `claude/`, `agent/`, or `ai/` prefix**\n   (e.g., `claude/add-rate-limiting`) so reviewers can calibrate their attention.\n   This is a convention for humans: the PR triage classifier deliberately ignores\n   branch names and tiers every PR on what the diff touches and how big it is.\n\n4. **Write or update tests alongside the implementation**, not after. Configure\n   your agent to produce tests before writing implementation code. See the\n   Testing section below for the commands to use.\n\n5. **Attach before/after screenshots to any PR that changes the UI.** Anything\n   visible in `packages/app` needs a \"Before\" (`main`) and \"After\" (branch)\n   image in the PR template's screenshots table, taken on the same screen, data,\n   viewport, and theme. Use a short video for interactions. If you can't capture\n   screenshots yourself (no browser tool), say so in the PR description and\n   leave the table for the human author to fill; never submit an empty table\n   silently. See\n   [CONTRIBUTING.md](CONTRIBUTING.md#ui-changes-need-beforeafter-screenshots).\n\n6. **Write reproduction steps a reviewer can follow.** Fill in the PR\n   template's \"How to reproduce\" section with numbered steps that show the\n   problem on `main` and the fix on the branch. Start from\n   [play.hyperdx.io](https://play.hyperdx.io) when the bug shows there, or from\n   `yarn app:dev:local` connected to the demo server (onboarding → \"Connect to\n   Demo Server\"; the PR's Vercel preview runs the same local mode). Full-stack\n   `yarn dev` pre-provisions a local ClickHouse connection and never shows that\n   button, so use it only when the change needs the API. Name UI elements by\n   visible text, and list any env vars,\n   feature flags, schema, or seed data needed. When filing issues, apply the\n   same standard. See\n   [CONTRIBUTING.md](CONTRIBUTING.md#reproducing-issues-and-prs).\n\n7. **Ensure a changeset exists before pushing a PR.** Any change to a published\n   package (`@hyperdx/app`, `@hyperdx/api`, `@hyperdx/otel-collector`, etc.) that\n   is user-facing or affects behavior must include a changeset in `.changeset/`.\n   Add one with `yarn changeset` (or create the markdown file by hand following\n   the format of existing entries), choosing the appropriate semver bump, before\n   pushing the branch. Skip only for changes that don't warrant a release (docs,\n   internal tooling, tests, CI).\n\n8. **The root `CHANGELOG.md` is generated at release time.** During each\n   release, CI writes an AI-generated cross-package summary section into the\n   root `CHANGELOG.md` on the \"Release HyperDX\" PR. Review and edit it there\n   like any other file — but keep the `<!-- hyperdx-release-notes … -->` comment\n   marker intact; it is how your edits are recognised when the release branch is\n   rebuilt. Use `###` or deeper for any heading you add — a `##` marks a release\n   boundary, and the next release refuses to splice rather than risk deleting\n   whatever ended up below it. Your edits are regenerated away when new\n   changesets land on `main` (the previous text is passed to the generator, so\n   phrasing is preserved best-effort, not guaranteed). They can also be lost\n   outright if a second push to `main` lands while a changelog run is still in\n   flight — the edit is held only in that run's artifact. If an edit matters,\n   re-check it on the release PR before merging. Don't edit the root\n   `CHANGELOG.md` in feature PRs; the only exception is the one-time seed that\n   introduced the file.\n\n### How the root changelog is generated\n\nDefined in `.github/workflows/release.yml`; the splicing logic lives in\n`.github/scripts/release-notes.mjs`.\n\n```\npush to main\n    |\n    v\ncheck_changesets\n    |  1. capture the branch's current CHANGELOG.md -> artifact\n    |     (must happen BEFORE the next step destroys it)\n    |  2. changesets/action force-rebuilds changeset-release/main from main\n    |     and opens/updates the \"Release HyperDX\" PR\n    v\nrelease_changelog_draft            contents: read - no push token\n    |\n    |  app version unchanged?  --yes-->  skip (CLI/common-utils-only release)\n    |  changeset hash matches?  --yes-->  reuse previous section verbatim\n    |                           --no-->  Claude writes a fresh body, given\n    |                                    the old section as context\n    v\n  body artifact                    the model's only output\n    |\n    v\nrelease_changelog_publish          contents: write - the model never ran here\n    |\n    |  branch moved since drafting?  --yes-->  skip, the newer run republishes\n    |  validate (no headings/markers/images/off-site links)\n    |  append the package list, splice into CHANGELOG.md\n    v\npush to changeset-release/main  ->  appears as a diff in the release PR,\n    |                               where a maintainer can edit it\n    v\nmerge the release PR  ->  CHANGELOG.md lands on main  ->  served in \"What's new\"\n```\n\nThe job split is a security boundary, not tidiness: the model reads changeset\nbodies, commit messages and PR bodies, which anyone opening a PR controls. Its\njob holds `ANTHROPIC_API_KEY` and a `contents: read` token, but no push\ncredential and no ability to alter the script that does the splicing. Because\nthe API key shares that process, the generator gets `--tools \"Read\" \"Write\"` and\nnothing else: no `Bash`, and no `Grep` or `Glob` either, since those read files\nwithout consulting a `Read` path rule. It may write exactly one file, granted by\nan `Edit(<path>)` rule, and `/proc`, `/sys`, `/home` and `/etc` are denied\noutright — `/proc/self/environ` carries the whole environment, and the output\nis published to a public branch.\n\nThree flags with three different jobs, which is worth keeping straight when\nediting this: `--tools` restricts what exists, `--allowedTools` only\npre-approves (it is what stops a `-p` run stalling on a prompt it cannot\nanswer), and `--disallowedTools` denies. A path rule attached to `Write` is\naccepted and then never consulted — file permissions are checked against\n`Edit` and `Read` rules — so write confinement is spelled `Edit(<path>)`.\n\nBecause the generator has no way to list a directory, every input is\nmaterialised for it at a known path by trusted shell, including all the\nchangesets concatenated into one file. Left to discover\n`.changeset/gentle-boats-serve.md` by name it cannot, and it writes a changelog\nthat quietly omits whatever it could not find.\n\nThe generator calls the Claude Code CLI, not\n`anthropics/claude-code-action`: that action accepts only GitHub entity events\nand rejects `push`, and everything it adds on top of the CLI — a token, entity\ncontext, PR comments — is what this job deliberately does without.\n\n## Responding to review feedback\n\nTwo bots review every PR (Claude Code Review inline + summary, Deep Review\nsummary). No finding blocks merge automatically; a maintainer decides what\nlands. Severity tells you what they will expect.\n\n1. **Triage before you touch code.** Two questions per comment: did this PR\n   introduce the problem (would reverting the PR make it go away?), and how\n   severe is it?\n   - Critical or major (P0/P1) that this PR introduced, in new or edited code:\n     fix it before asking for review. A maintainer will require it if it is\n     real.\n   - Minor (P2/P3) that this PR introduced: your call. Fix if small, else\n     reply.\n   - A defect that was already there before this PR, or a suggestion to widen\n     the change (hoist, dedupe, refactor neighbours, fix other call sites):\n     never fix here, whatever the severity. Reply in the thread with one\n     sentence; if it is critical, say so plainly so a maintainer sees it. The\n     reviewer reads replies and does not re-report what a human has answered.\n2. **Do not touch files the PR did not already touch** unless fixing a defect\n   in this PR's own change requires it.\n3. **Push review fixes as new commits, not a force-push.** The repo\n   squash-merges, so commit count never reaches `main`; review history does.\n4. **After two rounds of bot findings, stop.** Ask a maintainer to look at the\n   scope instead of addressing more automated comments. A PR that keeps\n   growing to satisfy a bot is drifting from its purpose.\n5. A finding you disagree with is not a defect. Say so and move on.\n\n## GitHub Action Workflow (when invoked via @claude)\n\nWhen working on issues or PRs through the GitHub Action:\n\n1. **Before writing any code**, post a comment outlining your implementation\n   plan — which files you'll change, what approach you'll take, and any\n   trade-offs or risks. Use `gh issue comment` for issues or `gh pr comment` for\n   PRs.\n\n2. **After making any code changes**, always run these in order and fix any\n   failures before opening a PR:\n\n   - `make ci-lint` — lint + TypeScript type check\n   - `make ci-unit` — unit tests\n\n3. Write a clear PR description explaining what changed and why.\n\n## Git Commits\n\nWhen committing code, use the git author's default profile (name and email from\ngit config). Do not add `Co-Authored-By` trailers.\n\n**Pre-commit hooks must pass before committing.** Do not use `--no-verify` to\nskip hooks. If the pre-commit hook fails (e.g. due to husky not being set up in\na worktree), run `npx lint-staged` manually before committing to ensure lint and\nformatting checks pass. Fix any issues before creating the commit.\n\n## Merge Conflict Resolution\n\n1. **Never blindly pick a side.** Read both sides of every conflict to\n   understand the intent of each change before choosing a resolution.\n\n2. **Refactor/move conflicts require extra verification.** When one side\n   refactored, moved, or extracted code (e.g., inline components to separate\n   files), always diff the discarded side against the destination files before\n   declaring the conflict resolved. Code can diverge after extraction — the\n   other branch may have made fixes or additions that the extracting branch\n   never picked up. A naive \"keep ours\" resolution silently drops those changes.\n\n3. **Verify the result compiles.** After resolving, check for missing imports,\n   broken references, or type errors introduced by the resolution — especially\n   when discarding a side that added new dependencies or exports.\n\n4. **Ask for help when uncertain.** If you are not 100% confident about which\n   side to keep, or whether a change can be safely discarded, stop and ask for\n   manual intervention rather than guessing. A wrong guess silently breaks\n   things; asking is always cheaper than debugging later.\n\n## Cursor Cloud specific instructions\n\n### Docker requirement\n\nDocker must be installed and running before starting the dev stack or running\nintegration/E2E tests. The VM update script handles `yarn install` and\n`yarn build:common-utils`, but Docker daemon startup is a prerequisite that must\nalready be available.\n\n### Starting the dev stack\n\n`yarn dev` uses `sh -c` to source `scripts/dev-env.sh`, which contains\nbash-specific syntax (`BASH_SOURCE`). On systems where `/bin/sh` is `dash`\n(e.g. Ubuntu), this fails with \"Bad substitution\". Work around it by running\nwith bash directly:\n\n```bash\nbash -c 'export PATH=\"/workspace/node_modules/.bin:$PATH\" && source ./scripts/dev-env.sh && yarn build:common-utils && dotenvx run --convention=nextjs -- docker compose -p \"$HDX_DEV_PROJECT\" -f docker-compose.dev.yml up -d && yarn app:dev'\n```\n\nPort isolation assigns a slot based on the worktree directory name. In the\ndefault `/workspace` directory, the slot is **76**, so services are at:\n\n- **App**: http://localhost:30276\n- **API**: http://localhost:30176\n- **ClickHouse**: http://localhost:30576\n- **MongoDB**: localhost:30476\n\n### Key commands reference\n\nSee `AGENTS.md` above and `agent_docs/development.md` for the full command\nreference. Quick summary:\n\n- `make ci-lint` — lint + TypeScript type check\n- `make ci-unit` — unit tests (all packages)\n- `make dev-int FILE=<name>` — integration tests (spins up Docker services)\n- `make dev-e2e FILE=<name>` — E2E tests (Playwright)\n\n### First-time registration\n\nWhen the dev stack starts fresh (empty MongoDB), the app shows a registration\npage. Create any account to get started — no external auth provider is needed.\n\n---\n\n_Need more details? Check the `agent_docs/` directory or ask which documentation\nto read._\n","isInternal":false,"tokens":5521,"sizeBytes":23242},{"name":"architecture.md","path":"agent_docs/architecture.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/agent_docs/architecture.md","title":"agent_docs - System Architecture & Module Boundaries","category":"project-spec","format":"markdown","content":"# HyperDX Architecture\n\n## Core Services\n\n- **HyperDX UI (`packages/app`)**: Next.js frontend serving the user interface\n- **HyperDX API (`packages/api`)**: Node.js/Express backend handling queries and business logic\n- **OpenTelemetry Collector**: Receives and processes telemetry data\n- **ClickHouse**: Primary data store for all telemetry (logs, metrics, traces)\n- **MongoDB**: Metadata storage (users, dashboards, alerts, saved searches)\n\n## Data Flow\n\n1. Applications send telemetry via OpenTelemetry → OTel Collector\n2. OTel Collector processes and forwards data → ClickHouse\n3. Users interact with UI → API queries ClickHouse\n4. Configuration/metadata stored in MongoDB\n\n## Key MongoDB Models\n\nAll models follow consistent patterns with:\n- Team-based multi-tenancy (most entities belong to a `team`)\n- ObjectId references between related entities\n- Timestamps for audit trails\n- Zod schema validation\n\n**Key Models** (see `packages/api/src/models/`):\n- `Team`: Multi-tenant organization unit\n- `User`: Team members with authentication\n- `Source`: ClickHouse data source configuration\n- `Connection`: Database connection settings\n- `SavedSearch`: Saved queries and filters\n- `Dashboard`: Custom dashboard configurations\n- `Alert`: Monitoring alerts with thresholds\n\n## Frontend Architecture\n\n- **Pages**: `packages/app/pages/` (Next.js routing)\n- **Components**: `packages/app/src/` (reusable components)\n- **API communication**: Custom hooks wrapping TanStack Query\n- **State**: See tech_stack.md for state management details\n\n## Backend Architecture\n\nThe API package (`packages/api`) hosts several distinct applications, each with\nits own routing, authentication, and rate limiting:\n\n### Internal API (`src/routers/api/`)\n\nThe primary API consumed by the web frontend (`packages/app`). Uses session-based\nauthentication (Passport.js). Follows a standard layered structure:\n\n- **Routers**: `src/routers/api/` - Domain-specific API routes\n- **Controllers**: `src/controllers/` - Business logic separated from routes\n- **Middleware**: `src/middleware/` - Authentication, CORS, error handling\n- **Services**: `src/services/` - Reusable business logic (e.g., `agentService`)\n\n### External API v2 (`src/routers/external-api/v2/`)\n\nPublic REST API for programmatic access. Authenticated via Personal API Access\nKey (`validateUserAccessKey` middleware), rate-limited to 100 req/min.\n\n- **Routes**: `alerts.ts`, `charts.ts`, `dashboards.ts`, `sources.ts`,\n  `webhooks.ts`\n- **OpenAPI spec**: `packages/api/openapi.json` (auto-generated via\n  `yarn docgen`, linted via `yarn lint:openapi` using Spectral)\n- **Tests**: `src/routers/external-api/__tests__/`\n\nWhen adding or modifying external API endpoints, run `yarn docgen` to regenerate\nthe OpenAPI spec and `yarn lint:openapi` to validate it.\n\n`scripts/ci/check-openapi-sync.sh` (run by `make ci-lint` and by CI) fails if the\ncommitted spec is stale. `swaggerOptions` in `src/utils/swagger.ts` is also an\ninput, and the spec is in `.prettierignore` because docgen owns its formatting.\n\n### MCP Server (`src/mcp/`)\n\n[Model Context Protocol](https://modelcontextprotocol.io/) server that lets AI\nassistants query observability data and manage dashboards. Exposed as a stateless\nStreamable HTTP endpoint at `/api/mcp`, authenticated via Personal API Access\nKey, rate-limited to 600 req/min.\n\n- **Entry**: `app.ts` (Express middleware), `mcpServer.ts` (server factory)\n- **Tools**: `tools/alerts/`, `tools/dashboards/`, `tools/query/`,\n  `tools/savedSearches/` - each directory contains tool definitions and handlers\n- **Prompts**: `prompts/dashboards/` - context prompts for AI assistants\n- **Tests**: `src/mcp/__tests__/` (alerts, dashboards, query, savedSearches,\n  tracing)\n- **Dev/debug**: `yarn dev:mcp` launches the MCP Inspector for interactive\n  testing\n- **Response size**: each tool call records the UTF-8 bytes it returns\n  (`mcp.tool.response.size_bytes` span attribute,\n  `hyperdx.mcp.tool.response.size_bytes` histogram)\n\nSee `MCP.md` in the repo root for user-facing setup instructions.\n\n### OpAMP Server (`src/opamp/`)\n\nHTTP-based [OpAMP](https://github.com/open-telemetry/opamp-spec) server that\nserves configurations to supervised OpenTelemetry Collectors. The supervisor\npings `/v1/opamp` with status, and the server returns updated config when needed.\n\n- **Entry**: `app.ts` (Express sub-app)\n- **Controller**: `controllers/opampController.ts` - config derivation logic\n- **Service**: `services/agentService.ts` - agent management\n- **Model**: `models/agent.ts` - agent state persistence\n- **Proto**: `proto/` - Protocol Buffer definitions for OpAMP and anyvalue\n\nConfig is derived from the team document with the ingestion API key.\n\n### Background Tasks (`src/tasks/`)\n\nCron-driven tasks that run outside the request/response cycle. In development,\ntasks run via `yarn dev-task`; in production, they are triggered externally.\n\n- `checkAlerts/` - Alert evaluation (runs every minute in dev)\n- `provisionDashboards/` - Dashboard provisioning from config files\n- `usageStats.ts` - Usage statistics collection\n- `pingPongTask.ts` - Health check task\n- `metrics.ts` - Task execution metrics (duration, success/failure counters)\n\nNote: Background tasks do **not** run in Vercel preview deployments (see\n`agent_docs/development.md` for details).\n\n## Data & Query Patterns\n\n### ClickHouse Integration\n- **Query building**: Use `common-utils` for safe query construction\n- **Schema flexibility**: Support for various telemetry schemas via `Source` configuration\n\n### MongoDB Patterns\n- **Multi-tenancy**: All queries filtered by team context\n- **Relationships**: Use ObjectId references with proper population\n- **Indexing**: Strategic indexes for query performance\n- **Migrations**: Versioned migrations for schema changes (see `packages/api/migrations/`)\n\n## Security Requirements\n\n- **Server-side validation**: Always validate and sanitize on the backend\n- **Team isolation**: All data access must filter by team context\n- **API authentication**: Use authentication middleware on protected routes\n- **Secrets**: Never commit secrets; use `.env` files\n\n","isInternal":false,"tokens":1438,"sizeBytes":6119},{"name":"SKILL.md","path":".claude/skills/playwright/SKILL.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/.claude/skills/playwright/SKILL.md","title":"playwright","category":"anthropic-skill","format":"markdown","content":"---\nname: playwright\ndescription: Writes end-to-end tests code using Playwright browser automation.\n---\n\n# Playwright End-to-End Test Writer\n\nI am a Playwright End-to-End Test Writer. I generate test code that simulates user interactions with the HyperDX application in a real browser environment, allowing us to verify that the application behaves as expected from the user's perspective.\n\nI will write tests covering these requirements: $ARGUMENTS.\n\nIf the requirements are empty or unclear, I will ask the user for a detailed description of the test they want.\n\n## Workflow\n\nUse the agents below to carry out each phase. Do not write test code directly in the main context.\n\n### 1. Test Generation\nDelegate to the **`playwright-test-generator`** agent (via the Agent tool). Pass it:\n- A full description of the test scenario including steps, expected outcomes, and edge cases\n- The target spec file path (`packages/app/tests/e2e/features/<feature>.spec.ts`)\n- Any relevant page object files that already exist for this feature\n\nThe agent will drive a real browser, execute the steps live, and produce spec code that follows HyperDX conventions. Review the output before proceeding.\n\nNOTE: When there is an existing spec file covering the feature, add new tests to the existing file instead of creating a new one. This keeps related tests together and avoids fragmentation.\n\n### 2. Test Execution\nAfter the generator agent writes the file, run the test:\n\n```bash\n./scripts/test-e2e.sh --quiet <test-file-name> [--grep \"\\\"<test name pattern>\\\"\"]\n```\n\nAlways run in full-stack mode (default). Do not ask the user about this.\n\n### 3. Iterative Fixing\nIf the test fails, delegate to the **`playwright-test-healer`** agent (via the Agent tool). Pass it:\n- The failing test file path\n- The error output\n- Any relevant context about what the test is supposed to do\n\nThe healer agent will debug interactively, fix the code, and re-run until the test passes.\n\n## HyperDX Project Conventions\n\nThese conventions apply to ALL test code produced by any agent. Review generated output to ensure compliance.\n\n### File Structure\n- Specs: `packages/app/tests/e2e/features/`\n- Page objects: `packages/app/tests/e2e/page-objects/`\n- Components: `packages/app/tests/e2e/components/`\n- Utilities: `packages/app/tests/e2e/utils/`\n- Base test (extends playwright with fixtures): `utils/base-test.ts`\n- Constants (source names): `utils/constants.ts`\n\n### Page Object Pattern (REQUIRED)\n- ALL UI interactions in spec files must go through page objects (`page-objects/`) and components (`components/`)\n- No raw `page.getByTestId()`, `page.locator()`, or `page.getByRole()` calls directly in spec files\n- If a needed interaction doesn't exist in a page object, add it to the page object — don't work around it in the spec\n\n### Data Isolation (CRITICAL)\nTests run in parallel and share a database. Use `Date.now()` for **every field the API uniqueness-checks** — not just display names:\n\n```typescript\nconst ts = Date.now();\nconst name = `E2E Thing ${ts}`;\nconst url = `https://example.com/thing-${ts}`; // URL too, not just name\n```\n\nThe webhook API enforces uniqueness on `(team, service, url)`. A hardcoded URL will collide between parallel runs or retries.\n\n### Assertions\n- Never assert global counts (`toHaveCount(N)`) — other tests' data pollutes the page\n- Scope assertions to the current test's data: `pageContainer.getByRole('link').filter({ hasText: name })`\n- Use web-first assertions (`toBeVisible()`, `toBeHidden()`) not imperative checks\n- Never use hardcoded waits (`waitForTimeout`) — wait for specific elements or conditions\n- Assert successful chart loads by checking `.recharts-responsive-container` is visible\n\n### Tags\n- `{ tag: '@full-stack' }` — tests requiring MongoDB + API backend\n- Feature tags: `@dashboard`, `@alerts`, `@search`, etc.\n\n### Imports\nAlways import from the base test, not directly from `@playwright/test`:\n```typescript\nimport { expect, test } from '../utils/base-test';\n```\n\n### Mock ClickHouse Data\n- E2E tests run against a local Docker environment with seeded ClickHouse data\n- Update `packages/app/tests/e2e/seed-clickhouse.ts` only if the scenario requires specific data not already seeded\n","frontmatter":{"name":"playwright","description":"Writes end-to-end tests code using Playwright browser automation."},"isInternal":false,"tokens":961,"sizeBytes":4224},{"name":"SKILL.md","path":".claude/skills/refactor-component/SKILL.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/.claude/skills/refactor-component/SKILL.md","title":"refactor-component","category":"anthropic-skill","format":"markdown","content":"---\nname: refactor-component\ndescription: Refactor a large React component file into a directory of smaller files. Use when the user asks to break up, split, or refactor a big component file.\n---\n\n# Refactor Large Component into Directory\n\nBreak a monolithic React component file into a well-organized directory with no functionality changes.\n\nThe target component is: $ARGUMENTS\n\nIf no component is specified, ask the user which file to refactor.\n\n## Workflow\n\n### 1. Check E2E test coverage\n\nBefore touching any code, verify that the component's key user flows are covered by E2E tests. Search for Playwright test files (typically in `packages/app/tests/e2e/`) that exercise the component — look for references to its `data-testid` attributes, page object methods, or user-visible behaviour (e.g. clicking Run, Save, switching chart types, SQL mode).\n\n- **If good coverage exists**: note the relevant test files and move on. These tests become your safety net — you will re-run them after the refactor to catch regressions.\n- **If coverage is missing or thin**: stop and ask the user whether they want to add E2E tests before refactoring. Present the gaps you found (e.g. \"raw SQL chart creation has no E2E test\") and let the user provide test requirements. Use the `playwright` skill to create the tests, then run them to confirm they pass on the current (pre-refactor) code. Only proceed with the refactor once the baseline E2E tests are green.\n\nThis step is critical — E2E tests are the strongest guarantee that the refactor doesn't break real user flows. Unit tests alone cannot catch issues like missing DOM elements that only appear when the full app is composed.\n\n### 2. Analyse the file\n\nRead the entire target file. Identify:\n\n- **Main component** — the default export (becomes the primary file in the new directory)\n- **Sub-components** — named function/const components used only inside this file\n- **Types & interfaces** — exported or internal types tied to the sub-components\n- **Utilities** — pure functions, Zod schemas, constants that aren't React components\n- **Tests** — any test file in a sibling `__tests__/` directory that imports the target\n\nCreate a plan listing each new file, what goes in it, and which imports change. Present the plan to the user and wait for approval before writing code.\n\n### 3. Create the directory and files\n\nThe new directory is created inside `packages/app/src/components/`, replacing the original file. It keeps the same name (without extension), so external imports resolve unchanged.\n\n```\npackages/app/src/components/ComponentName/\n  index.ts              — barrel re-export of the default export\n  ComponentName.tsx     — main component (default export)\n  SubComponent.tsx      — one file per sub-component (named export)\n  utils.ts              — utility functions, schemas, constants\n  __tests__/            — moved test files with updated imports\n```\n\n#### Rules\n\n- **`index.ts`** is the single public API of the directory. All exports that consumers depend on must be re-exported through `index.ts`. Sub-components or utilities that are only used within the directory should **not** be re-exported.\n- Each sub-component file has a **named export** (not default).\n- **Sibling imports** within the directory use `./` relative paths. Files outside the directory must never import directly from a sub-file (e.g. `ComponentName/ChartActionBar`) — they import from the directory barrel (`ComponentName`) only.\n- **All other relative imports** (`../Foo`, `./Foo`) in the extracted files must be converted to `@/`-prefixed absolute imports (e.g. `@/components/Foo`). This is critical — files moved one level deeper will break if relative paths aren't updated.\n- Existing `@/`-prefixed imports stay unchanged.\n- Do not add, remove, or rename any exports. The refactoring must be invisible to consumers.\n\n### 4. Move tests\n\nMove `__tests__/ComponentName.test.tsx` into `ComponentName/__tests__/ComponentName.test.tsx`.\n\nUpdate in the test file:\n\n- The main import: `from '../ComponentName'` → `from '..'`\n- Mock paths: `../SiblingComponent` → `../../SiblingComponent` (one extra level up)\n\n### 5. Delete the original file\n\nRemove the original monolithic `.tsx` file only after all new files are written.\n\n### 6. Tidy up\n\nAfter the initial split, clean up duplication and improve structure within the new directory:\n\n#### Remove unnecessary indirection\n\n- If a component is declared as `function FooComponent` and then aliased as `export const Foo = FooComponent`, rename the function to `Foo` and export it directly.\n\n#### Deduplicate code across files\n\n- Look for validation+normalization logic repeated across callbacks — extract a shared helper (e.g. `validateAndNormalize`) that returns `{ errors, config }` so each caller only contains its unique logic.\n- Deduplicate `renderComponent` helpers in test files — hoist a single shared factory to file scope. Describe blocks with special defaults can wrap it in a thin helper (e.g. `renderAlertComponent`) that passes overrides.\n\n#### Extract pure logic into utils.ts\n\nScan component files for logic that can move into `utils.ts`:\n\n- **Pure functions in `useMemo` callbacks** — if the memo body is a pure transformation (no hooks, no JSX), extract it as a named function in `utils.ts` and call it from the memo.\n- **Constants and lookup tables** — arrays/sets used in conditionals (e.g. `['table', 'time', 'number', 'pie'].includes(tab)`) become named exports (e.g. `TABS_WITH_GENERATED_SQL`).\n- **Simple mappings** — switch/if chains that map one value to another (e.g. `DisplayType` → tab string) become standalone functions. These don't need `useMemo` since they're cheap.\n- **Complex config builders** — conditional logic that selects/transforms configs for display (e.g. building sample events config, chart explanation config) should be pure functions that receive all dependencies as parameters.\n\nGood extraction candidates:\n\n- Config builder functions (`buildSampleEventsConfig`, `buildChartConfigForExplanations`)\n- Enum/type mappers (`displayTypeToActiveTab`)\n- Computed values with alert logic (`computeDbTimeChartConfig`)\n\nLeave in the component:\n\n- Logic that reads/writes React state or calls hooks\n- Event handlers that call `setValue`, `onSubmit`, etc.\n- JSX rendering logic\n\n#### Use named prop types\n\nAll components should use named type aliases for their props, declared directly above the component function:\n\n```tsx\ntype FooProps = {\n  bar: string;\n  onBaz: () => void;\n};\n\nexport function Foo({ bar, onBaz }: FooProps) {\n```\n\nDo not use inline object types in the function signature.\n\n#### Split large components further\n\nIf a file exceeds ~500 lines after the initial split, look for natural extraction points:\n\n- **Form inputs + toolbar** — form fields, series editors, action buttons → `ChartEditorControls.tsx`\n- **Preview/results area** — chart rendering, accordions, result display → `ChartPreviewPanel.tsx`\n- **The main file** becomes a thin orchestrator: form state, hooks, callbacks, effects, and a JSX shell that renders the sub-components.\n\nWhen splitting JSX, the extracted component receives form state via props (`control`, `setValue`, etc.). Watches that are only used in the extracted component (e.g. `alertChannelType`) can use `useWatch` inside it rather than being passed as props.\n\n#### Classify shared vs conditional JSX before extracting\n\nBefore moving JSX into a new component, map the render tree's branching structure. Every piece of JSX must be classified as either:\n\n- **Branch-specific** — rendered inside one arm of a conditional (ternary, `&&`, if/else)\n- **Shared** — rendered as a sibling of the conditional, appearing for all branches\n\n**Extract from the bottom up**: pull out the conditional/branch-specific parts first, leaving shared sections in the parent. Never bundle shared JSX into a component that only renders for one branch.\n\n**Verify after extraction**: for each value of every conditional, confirm the new code renders the same set of components as the original. A toolbar, action bar, or footer that appeared for all chart types must still appear for all chart types after the split.\n\n### 7. Write unit tests for extracted code\n\nThis is a dedicated step — do not skip it or fold it into another step.\n\n#### Tests for `utils.ts`\n\nWrite unit tests in `__tests__/utils.test.ts` covering:\n\n- All pure functions with normal inputs, edge cases, and null/undefined guards\n- Constants (verify membership)\n- Config builders (test null returns for invalid inputs, verify output shape for valid inputs)\n\n#### Tests for each extracted component\n\nWrite unit tests for each extracted component in `__tests__/<ComponentName>.test.tsx` covering:\n\n- **Conditional rendering**: for each prop/state that controls visibility, verify elements appear and disappear correctly\n- **Callbacks**: verify that prop callbacks are invoked on user interaction (clicks, etc.)\n- **Prop-driven behaviour**: test that props like `activeTab`, `isRawSqlInput`, `isSaving` produce the correct UI state (disabled buttons, hidden sections, etc.)\n- **Regression coverage**: if the extraction was motivated by a bug (e.g. shared controls missing for a specific mode), include a test that explicitly renders the component in that mode and asserts the controls are present\n\nUse a `FormWrapper` test helper when the component requires react-hook-form's `control`/`handleSubmit` — create a small wrapper that calls `useForm` with sensible defaults and passes the form methods to the component under test via a render-prop pattern. Mock heavy child components (chart renderers, SQL editors, etc.) with simple stubs that render a `data-testid`.\n\n### 8. Verify\n\nRun in order — fix any failures before proceeding to the next step:\n\n```bash\nmake ci-lint    # TypeScript compilation + lint\n```\n\n```bash\ncd packages/app && yarn ci:unit   # Unit tests (or the appropriate package)\n```\n\n```bash\nmake e2e   # E2E tests — re-run the same tests from step 1 to catch regressions\n```\n\nIf lint fails with import-sort or formatting errors, run `npx eslint --fix <file>` on the affected files and re-check. If there are unused-import warnings, remove the unused imports manually.\n\nIf an E2E test fails, investigate whether the failure is related to the refactoring (e.g. a broken import path at runtime) or a pre-existing flake. Fix refactoring-related failures before presenting the result. The E2E tests identified in step 1 are the most important — if those pass, the refactor is safe.\n\n## Checklist (self-review before presenting result)\n\n- [ ] E2E test coverage verified (or added) before refactoring began\n- [ ] No functionality changes — pure file reorganisation\n- [ ] Shared JSX (toolbars, action bars, footers) not accidentally bundled into a conditional branch's component\n- [ ] `index.ts` barrel makes the directory a drop-in replacement\n- [ ] All relative imports in extracted files converted to `@/` prefixed\n- [ ] Sibling imports within directory use `./`\n- [ ] Test file moved and import paths updated (both main import and mocks)\n- [ ] Original monolith file deleted\n- [ ] Duplicated logic extracted into shared helpers\n- [ ] Pure functions moved from components to `utils.ts`\n- [ ] All components use named prop types declared above the function\n- [ ] No file exceeds ~500 lines (split further if needed)\n- [ ] Unit tests written for `utils.ts` functions\n- [ ] Unit tests written for each extracted component (conditional rendering, callbacks, regression cases)\n- [ ] `make ci-lint` passes\n- [ ] Unit tests pass\n- [ ] E2E tests pass\n","frontmatter":{"name":"refactor-component","description":"Refactor a large React component file into a directory of smaller files. Use when the user asks to break up, split, or refactor a big component file."},"isInternal":false,"tokens":2559,"sizeBytes":11628},{"name":".spectral.yaml","path":"packages/api/.spectral.yaml","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/.spectral.yaml","title":"Api Skill","category":"anthropic-skill","format":"yaml","content":"# Api Skill\n\nPath: `packages/api/.spectral.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/.spectral.yaml)","tokens":300,"sizeBytes":164},{"name":"CHANGELOG.md","path":"packages/api/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/CHANGELOG.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"# Api Skill\n\nPath: `packages/api/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/CHANGELOG.md)","tokens":300,"sizeBytes":160},{"name":"AUTO_PROVISION.md","path":"packages/api/docs/auto_provision/AUTO_PROVISION.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/docs/auto_provision/AUTO_PROVISION.md","title":"Auto_provision Skill","category":"anthropic-skill","format":"markdown","content":"# Auto_provision Skill\n\nPath: `packages/api/docs/auto_provision/AUTO_PROVISION.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/docs/auto_provision/AUTO_PROVISION.md)","tokens":300,"sizeBytes":221},{"name":"nodemon.json","path":"packages/api/nodemon.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/nodemon.json","title":"Api Skill","category":"anthropic-skill","format":"json","content":"# Api Skill\n\nPath: `packages/api/nodemon.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/nodemon.json)","tokens":300,"sizeBytes":160},{"name":"openapi.json","path":"packages/api/openapi.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/openapi.json","title":"Api Skill","category":"anthropic-skill","format":"json","content":"# Api Skill\n\nPath: `packages/api/openapi.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/openapi.json)","tokens":300,"sizeBytes":160},{"name":"package.json","path":"packages/api/package.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/package.json","title":"Api Skill","category":"anthropic-skill","format":"json","content":"# Api Skill\n\nPath: `packages/api/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/package.json)","tokens":300,"sizeBytes":160},{"name":"tsconfig.build.json","path":"packages/api/tsconfig.build.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/tsconfig.build.json","title":"Api Skill","category":"anthropic-skill","format":"json","content":"# Api Skill\n\nPath: `packages/api/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/tsconfig.build.json)","tokens":300,"sizeBytes":174},{"name":"tsconfig.json","path":"packages/api/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/tsconfig.json","title":"Api Skill","category":"anthropic-skill","format":"json","content":"# Api Skill\n\nPath: `packages/api/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/tsconfig.json)","tokens":300,"sizeBytes":162},{"name":"CHANGELOG.md","path":"packages/app/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/CHANGELOG.md","title":"App Skill","category":"anthropic-skill","format":"markdown","content":"# App Skill\n\nPath: `packages/app/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/CHANGELOG.md)","tokens":300,"sizeBytes":160},{"name":"package.json","path":"packages/app/package.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/package.json","title":"App Skill","category":"anthropic-skill","format":"json","content":"# App Skill\n\nPath: `packages/app/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/package.json)","tokens":300,"sizeBytes":160},{"name":"pyodide-lock.json","path":"packages/app/public/pyodide/pyodide-lock.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/public/pyodide/pyodide-lock.json","title":"Pyodide Skill","category":"anthropic-skill","format":"json","content":"# Pyodide Skill\n\nPath: `packages/app/public/pyodide/pyodide-lock.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/public/pyodide/pyodide-lock.json)","tokens":300,"sizeBytes":204},{"name":"dotnet-runtime.json","path":"packages/app/src/dashboardTemplates/dotnet-runtime.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/dotnet-runtime.json","title":"DashboardTemplates Skill","category":"anthropic-skill","format":"json","content":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/dotnet-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/dotnet-runtime.json)","tokens":300,"sizeBytes":235},{"name":"go-runtime.json","path":"packages/app/src/dashboardTemplates/go-runtime.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/go-runtime.json","title":"DashboardTemplates Skill","category":"anthropic-skill","format":"json","content":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/go-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/go-runtime.json)","tokens":300,"sizeBytes":227},{"name":"jvm-runtime-metrics.json","path":"packages/app/src/dashboardTemplates/jvm-runtime-metrics.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/jvm-runtime-metrics.json","title":"DashboardTemplates Skill","category":"anthropic-skill","format":"json","content":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/jvm-runtime-metrics.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/jvm-runtime-metrics.json)","tokens":300,"sizeBytes":245},{"name":"nodejs-runtime.json","path":"packages/app/src/dashboardTemplates/nodejs-runtime.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/nodejs-runtime.json","title":"DashboardTemplates Skill","category":"anthropic-skill","format":"json","content":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/nodejs-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/nodejs-runtime.json)","tokens":300,"sizeBytes":235},{"name":"python-runtime.json","path":"packages/app/src/dashboardTemplates/python-runtime.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/python-runtime.json","title":"DashboardTemplates Skill","category":"anthropic-skill","format":"json","content":"# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/python-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/python-runtime.json)","tokens":300,"sizeBytes":235},{"name":"e2e-fixtures.json","path":"packages/app/tests/e2e/fixtures/e2e-fixtures.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tests/e2e/fixtures/e2e-fixtures.json","title":"Fixtures Skill","category":"anthropic-skill","format":"json","content":"# Fixtures Skill\n\nPath: `packages/app/tests/e2e/fixtures/e2e-fixtures.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tests/e2e/fixtures/e2e-fixtures.json)","tokens":300,"sizeBytes":213},{"name":"tsconfig.build.json","path":"packages/app/tsconfig.build.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tsconfig.build.json","title":"App Skill","category":"anthropic-skill","format":"json","content":"# App Skill\n\nPath: `packages/app/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tsconfig.build.json)","tokens":300,"sizeBytes":174},{"name":"tsconfig.json","path":"packages/app/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tsconfig.json","title":"App Skill","category":"anthropic-skill","format":"json","content":"# App Skill\n\nPath: `packages/app/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tsconfig.json)","tokens":300,"sizeBytes":162},{"name":"AGENTS.md","path":"packages/cli/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/AGENTS.md","title":"Cli Skill","category":"anthropic-skill","format":"markdown","content":"# Cli Skill\n\nPath: `packages/cli/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/AGENTS.md)","tokens":300,"sizeBytes":154},{"name":"CHANGELOG.md","path":"packages/cli/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/CHANGELOG.md","title":"Cli Skill","category":"anthropic-skill","format":"markdown","content":"# Cli Skill\n\nPath: `packages/cli/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/CHANGELOG.md)","tokens":300,"sizeBytes":160},{"name":"CONTRIBUTING.md","path":"packages/cli/CONTRIBUTING.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/CONTRIBUTING.md","title":"Cli Skill","category":"anthropic-skill","format":"markdown","content":"# Cli Skill\n\nPath: `packages/cli/CONTRIBUTING.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/CONTRIBUTING.md)","tokens":300,"sizeBytes":166},{"name":"package.json","path":"packages/cli/package.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/package.json","title":"Cli Skill","category":"anthropic-skill","format":"json","content":"# Cli Skill\n\nPath: `packages/cli/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/package.json)","tokens":300,"sizeBytes":160},{"name":"tsconfig.json","path":"packages/cli/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/tsconfig.json","title":"Cli Skill","category":"anthropic-skill","format":"json","content":"# Cli Skill\n\nPath: `packages/cli/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/tsconfig.json)","tokens":300,"sizeBytes":162},{"name":"CHANGELOG.md","path":"packages/common-utils/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/CHANGELOG.md","title":"Common-utils Skill","category":"anthropic-skill","format":"markdown","content":"# Common-utils Skill\n\nPath: `packages/common-utils/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/CHANGELOG.md)","tokens":300,"sizeBytes":187},{"name":"package.json","path":"packages/common-utils/package.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/package.json","title":"Common-utils Skill","category":"anthropic-skill","format":"json","content":"# Common-utils Skill\n\nPath: `packages/common-utils/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/package.json)","tokens":300,"sizeBytes":187},{"name":"tsconfig.json","path":"packages/common-utils/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/tsconfig.json","title":"Common-utils Skill","category":"anthropic-skill","format":"json","content":"# Common-utils Skill\n\nPath: `packages/common-utils/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/tsconfig.json)","tokens":300,"sizeBytes":189},{"name":"builder-config.yaml","path":"packages/otel-collector/builder-config.yaml","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/builder-config.yaml","title":"Otel-collector Skill","category":"anthropic-skill","format":"yaml","content":"# Otel-collector Skill\n\nPath: `packages/otel-collector/builder-config.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/builder-config.yaml)","tokens":300,"sizeBytes":207},{"name":"CHANGELOG.md","path":"packages/otel-collector/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/CHANGELOG.md","title":"Otel-collector Skill","category":"anthropic-skill","format":"markdown","content":"# Otel-collector Skill\n\nPath: `packages/otel-collector/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/CHANGELOG.md)","tokens":300,"sizeBytes":193},{"name":"package.json","path":"packages/otel-collector/package.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/package.json","title":"Otel-collector Skill","category":"anthropic-skill","format":"json","content":"# Otel-collector Skill\n\nPath: `packages/otel-collector/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/package.json)","tokens":300,"sizeBytes":193},{"name":"playwright.mdc","path":".cursor/rules/playwright.mdc","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/.cursor/rules/playwright.mdc","title":"Cursor Rule: playwright","category":"cursor-rule","format":"mdc","content":"---\ndescription: HyperDX Playwright E2E test conventions for writing, reviewing, and fixing tests. Use when creating, editing, or debugging any E2E test in this project.\nglobs:\nalwaysApply: false\n---\n\nWhen writing, reviewing, or fixing Playwright E2E tests for this project, follow the conventions in @.claude/skills/playwright/SKILL.md.\n\nTo run tests:\n```bash\n./scripts/test-e2e.sh --quiet <file> [--grep \"\\\"<pattern>\\\"\"]\n```\n","frontmatter":{"description":"HyperDX Playwright E2E test conventions for writing, reviewing, and fixing tests. Use when creating, editing, or debugging any E2E test in this project.","globs":null,"alwaysApply":false},"isInternal":false,"tokens":110,"sizeBytes":427},{"name":"README.md","path":"packages/api/src/opamp/README.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/src/opamp/README.md","title":"opamp Documentation","category":"plugin-manifest","format":"markdown","content":"# opamp Documentation\n\nPath: `packages/api/src/opamp/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/src/opamp/README.md)","tokens":300,"sizeBytes":184},{"name":"README.md","path":"packages/app/tests/e2e/README.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tests/e2e/README.md","title":"e2e Documentation","category":"plugin-manifest","format":"markdown","content":"# e2e Documentation\n\nPath: `packages/app/tests/e2e/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tests/e2e/README.md)","tokens":300,"sizeBytes":182},{"name":"README.md","path":"packages/cli/README.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/README.md","title":"cli Documentation","category":"plugin-manifest","format":"markdown","content":"# cli Documentation\n\nPath: `packages/cli/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/README.md)","tokens":300,"sizeBytes":162},{"name":"README.md","path":"packages/common-utils/README.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/README.md","title":"common-utils Documentation","category":"plugin-manifest","format":"markdown","content":"# common-utils Documentation\n\nPath: `packages/common-utils/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/README.md)","tokens":300,"sizeBytes":189},{"name":"README.md","path":"packages/otel-collector/README.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/README.md","title":"otel-collector Documentation","category":"plugin-manifest","format":"markdown","content":"# otel-collector Documentation\n\nPath: `packages/otel-collector/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/otel-collector/README.md)","tokens":300,"sizeBytes":195},{"name":"mcp.json","path":".cursor/mcp.json","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/.cursor/mcp.json","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"json","content":"{\n  \"mcpServers\": {\n    \"playwright-test\": {\n      \"command\": \"npx\",\n      \"args\": [\"playwright\", \"run-test-mcp-server\"]\n    }\n  }\n}\n","frontmatter":{"mcpServers":{"playwright-test":{"command":"npx","args":["playwright","run-test-mcp-server"]}}},"isInternal":false,"tokens":43,"sizeBytes":133},{"name":"playwright-test-generator.md","path":".claude/agents/playwright-test-generator.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/.claude/agents/playwright-test-generator.md","title":"playwright-test-generator","category":"subagent-persona","format":"markdown","content":"---\nname: playwright-test-generator\ndescription: 'Use this agent when you need to create automated browser tests using Playwright Examples: <example>Context: User wants to generate a test for the test plan item. <test-suite><!-- Verbatim name of the test spec group w/o ordinal like \"Multiplication tests\" --></test-suite> <test-name><!-- Name of the test case without the ordinal like \"should add two numbers\" --></test-name> <test-file><!-- Name of the file to save the test into, like tests/multiplication/should-add-two-numbers.spec.ts --></test-file> <seed-file><!-- Seed file path from test plan --></seed-file> <body><!-- Test case content including steps and expectations --></body></example>'\ntools: Glob, Grep, Read, LS, mcp__playwright-test__browser_click, mcp__playwright-test__browser_drag, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_file_upload, mcp__playwright-test__browser_handle_dialog, mcp__playwright-test__browser_hover, mcp__playwright-test__browser_navigate, mcp__playwright-test__browser_press_key, mcp__playwright-test__browser_select_option, mcp__playwright-test__browser_snapshot, mcp__playwright-test__browser_type, mcp__playwright-test__browser_verify_element_visible, mcp__playwright-test__browser_verify_list_visible, mcp__playwright-test__browser_verify_text_visible, mcp__playwright-test__browser_verify_value, mcp__playwright-test__browser_wait_for, mcp__playwright-test__generator_read_log, mcp__playwright-test__generator_setup_page, mcp__playwright-test__generator_write_test\nmodel: sonnet\ncolor: blue\n---\n\nYou are a Playwright Test Generator, an expert in browser automation and end-to-end testing.\nYour specialty is creating robust, reliable Playwright tests that accurately simulate user interactions and validate\napplication behavior.\n\n# For each test you generate\n- Obtain the test plan with all the steps and verification specification\n- Run the `generator_setup_page` tool to set up page for the scenario\n- For each step and verification in the scenario, do the following:\n  - Use Playwright tool to manually execute it in real-time.\n  - Use the step description as the intent for each Playwright tool call.\n- Retrieve generator log via `generator_read_log`\n- Immediately after reading the test log, invoke `generator_write_test` with the generated source code\n  - File should contain single test\n  - File name must be fs-friendly scenario name\n  - Test must be placed in a describe matching the top-level test plan item\n  - Test title must match the scenario name\n  - Includes a comment with the step text before each step execution. Do not duplicate comments if step requires\n    multiple actions.\n  - Always use best practices from the log when generating tests.\n\n## HyperDX Project Conventions\n\nApply these rules to ALL tests you generate for this project.\n\n### File Structure\n- Specs: `packages/app/tests/e2e/features/`\n- Page objects: `packages/app/tests/e2e/page-objects/`\n- Components: `packages/app/tests/e2e/components/`\n- Base test import: `import { expect, test } from '../utils/base-test';` (NOT `@playwright/test`)\n\n### Page Object Pattern (REQUIRED)\n- ALL UI interactions must go through page objects and components — no raw `page.getByTestId()`, `page.locator()`, or `page.getByRole()` directly in spec files\n- If a needed interaction doesn't exist in a page object, add it to the page object first, then use it in the spec\n\n### Data Isolation (CRITICAL)\nTests run in parallel and share a database. Use `Date.now()` for **every field the API uniqueness-checks**:\n\n```typescript\nconst ts = Date.now();\nconst name = `E2E Thing ${ts}`;\nconst url = `https://example.com/thing-${ts}`; // URL too, not just name\n```\n\nThe webhook API enforces uniqueness on `(team, service, url)`. Hardcoded URLs will collide.\n\n### Assertions\n- Never assert global counts (`toHaveCount(N)`) — scope to the current test's data instead\n- Example: `pageContainer.getByRole('link').filter({ hasText: name })` not `getAlertCards().toHaveCount(1)`\n- Use `toBeVisible()` / `toBeHidden()` (web-first), never `waitForTimeout`\n- Assert successful chart loads by checking `.recharts-responsive-container` is visible\n\n### Tags\n- `{ tag: '@full-stack' }` for tests requiring the backend (MongoDB + API)\n- Feature tags: `@dashboard`, `@alerts`, `@search`, etc.\n\n   <example-generation>\n   For following plan:\n\n   ```markdown file=specs/plan.md\n   ### 1. Adding New Todos\n   **Seed:** `tests/seed.spec.ts`\n\n   #### 1.1 Add Valid Todo\n   **Steps:**\n   1. Click in the \"What needs to be done?\" input field\n\n   #### 1.2 Add Multiple Todos\n   ...\n   ```\n\n   Following file is generated:\n\n   ```ts file=add-valid-todo.spec.ts\n   // spec: specs/plan.md\n   // seed: tests/seed.spec.ts\n\n   test.describe('Adding New Todos', () => {\n     test('Add Valid Todo', async { page } => {\n       // 1. Click in the \"What needs to be done?\" input field\n       await page.click(...);\n\n       ...\n     });\n   });\n   ```\n   </example-generation>","frontmatter":{"name":"playwright-test-generator","description":"Use this agent when you need to create automated browser tests using Playwright Examples: <example>Context: User wants to generate a test for the test plan item. <test-suite><!-- Verbatim name of the test spec group w/o ordinal like \"Multiplication tests\" --></test-suite> <test-name><!-- Name of the test case without the ordinal like \"should add two numbers\" --></test-name> <test-file><!-- Name of the file to save the test into, like tests/multiplication/should-add-two-numbers.spec.ts --></test-file> <seed-file><!-- Seed file path from test plan --></seed-file> <body><!-- Test case content including steps and expectations --></body></example>","tools":"Glob, Grep, Read, LS, mcp__playwright-test__browser_click, mcp__playwright-test__browser_drag, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_file_upload, mcp__playwright-test__browser_handle_dialog, mcp__playwright-test__browser_hover, mcp__playwright-test__browser_navigate, mcp__playwright-test__browser_press_key, mcp__playwright-test__browser_select_option, mcp__playwright-test__browser_snapshot, mcp__playwright-test__browser_type, mcp__playwright-test__browser_verify_element_visible, mcp__playwright-test__browser_verify_list_visible, mcp__playwright-test__browser_verify_text_visible, mcp__playwright-test__browser_verify_value, mcp__playwright-test__browser_wait_for, mcp__playwright-test__generator_read_log, mcp__playwright-test__generator_setup_page, mcp__playwright-test__generator_write_test","model":"sonnet","color":"blue"},"isInternal":false,"tokens":1199,"sizeBytes":4976},{"name":"playwright-test-healer.md","path":".claude/agents/playwright-test-healer.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/.claude/agents/playwright-test-healer.md","title":"playwright-test-healer","category":"subagent-persona","format":"markdown","content":"---\nname: playwright-test-healer\ndescription: Use this agent when you need to debug and fix failing Playwright tests\ntools: Glob, Grep, Read, LS, Edit, MultiEdit, Write, mcp__playwright-test__browser_console_messages, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_generate_locator, mcp__playwright-test__browser_network_requests, mcp__playwright-test__browser_snapshot, mcp__playwright-test__test_debug, mcp__playwright-test__test_list, mcp__playwright-test__test_run\nmodel: sonnet\ncolor: red\n---\n\nYou are the Playwright Test Healer, an expert test automation engineer specializing in debugging and\nresolving Playwright test failures. Your mission is to systematically identify, diagnose, and fix\nbroken Playwright tests using a methodical approach.\n\nYour workflow:\n1. **Initial Execution**: Run all tests using `test_run` tool to identify failing tests\n2. **Debug failed tests**: For each failing test run `test_debug`.\n3. **Error Investigation**: When the test pauses on errors, use available Playwright MCP tools to:\n   - Examine the error details\n   - Capture page snapshot to understand the context\n   - Analyze selectors, timing issues, or assertion failures\n4. **Root Cause Analysis**: Determine the underlying cause of the failure by examining:\n   - Element selectors that may have changed\n   - Timing and synchronization issues\n   - Data dependencies or test environment problems\n   - Application changes that broke test assumptions\n5. **Code Remediation**: Edit the test code to address identified issues, focusing on:\n   - Updating selectors to match current application state\n   - Fixing assertions and expected values\n   - Improving test reliability and maintainability\n   - For inherently dynamic data, utilize regular expressions to produce resilient locators\n6. **Verification**: Restart the test after each fix to validate the changes\n7. **Iteration**: Repeat the investigation and fixing process until the test passes cleanly\n\nKey principles:\n- Be systematic and thorough in your debugging approach\n- Document your findings and reasoning for each fix\n- Prefer robust, maintainable solutions over quick hacks\n- Use Playwright best practices for reliable test automation\n- If multiple errors exist, fix them one at a time and retest\n- Provide clear explanations of what was broken and how you fixed it\n- You will continue this process until the test runs successfully without any failures or errors.\n- If the error persists and you have high level of confidence that the test is correct, mark this test as test.fixme()\n  so that it is skipped during the execution. Add a comment before the failing step explaining what is happening instead\n  of the expected behavior.\n- Do not ask user questions, you are not interactive tool, do the most reasonable thing possible to pass the test.\n- Never wait for networkidle or use other discouraged or deprecated apis\n\n## HyperDX Project Conventions\n\n### Test Runner\nAlways use this command — do NOT use `npx playwright test` directly:\n```bash\n./scripts/test-e2e.sh --quiet <file> [--grep \"\\\"<pattern>\\\"\"]\n```\n\n### Common Failure Patterns\n\n1. **API 400 \"already exists\" — form won't close**: Check network requests first. The webhook API enforces uniqueness on `(team, service, url)`. Hardcoded URLs collide between parallel tests or retries. Fix: use `` `https://example.com/thing-${Date.now()}` `` for URLs, not just names.\n\n2. **Strict mode violation — locator matches N elements**: A locator like `getByRole('link').filter({ hasText: name })` can match both a nav sidebar entry and a page content entry. Fix: scope to a container, e.g. `alertsPage.pageContainer.getByRole('link').filter({ hasText: name })`.\n\n3. **Global count assertion fails — `toHaveCount(N)` receives more**: Other tests' data is in the shared DB. Fix: replace `toHaveCount(1)` with `filter({ hasText: uniqueName }).toBeVisible()`, and `toHaveCount(0)` with `filter({ hasText: uniqueName }).toBeHidden()`.\n\n4. **`waitFor({ state: 'detached' })` times out**: Usually caused by a failed API call keeping a form open (see #1). Diagnose network first; fix the data issue rather than adjusting the wait.\n\n### Page Object Pattern\n- Fix broken tests by correcting or extending page objects (`page-objects/`, `components/`) — not by adding raw `page.getByTestId()` calls to spec files\n- The spec file should only call methods/getters defined on page objects","frontmatter":{"name":"playwright-test-healer","description":"Use this agent when you need to debug and fix failing Playwright tests","tools":"Glob, Grep, Read, LS, Edit, MultiEdit, Write, mcp__playwright-test__browser_console_messages, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_generate_locator, mcp__playwright-test__browser_network_requests, mcp__playwright-test__browser_snapshot, mcp__playwright-test__test_debug, mcp__playwright-test__test_list, mcp__playwright-test__test_run","model":"sonnet","color":"red"},"isInternal":false,"tokens":980,"sizeBytes":4411},{"name":"playwright-test-planner.md","path":".claude/agents/playwright-test-planner.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/.claude/agents/playwright-test-planner.md","title":"playwright-test-planner","category":"subagent-persona","format":"markdown","content":"---\nname: playwright-test-planner\ndescription: Use this agent when you need to create comprehensive test plan for a web application or website\ntools: Glob, Grep, Read, LS, mcp__playwright-test__browser_click, mcp__playwright-test__browser_close, mcp__playwright-test__browser_console_messages, mcp__playwright-test__browser_drag, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_file_upload, mcp__playwright-test__browser_handle_dialog, mcp__playwright-test__browser_hover, mcp__playwright-test__browser_navigate, mcp__playwright-test__browser_navigate_back, mcp__playwright-test__browser_network_requests, mcp__playwright-test__browser_press_key, mcp__playwright-test__browser_select_option, mcp__playwright-test__browser_snapshot, mcp__playwright-test__browser_take_screenshot, mcp__playwright-test__browser_type, mcp__playwright-test__browser_wait_for, mcp__playwright-test__planner_setup_page, mcp__playwright-test__planner_save_plan\nmodel: sonnet\ncolor: green\n---\n\nYou are an expert web test planner with extensive experience in quality assurance, user experience testing, and test\nscenario design. Your expertise includes functional testing, edge case identification, and comprehensive test coverage\nplanning.\n\nYou will:\n\n1. **Navigate and Explore**\n   - Invoke the `planner_setup_page` tool once to set up page before using any other tools\n   - Explore the browser snapshot\n   - Do not take screenshots unless absolutely necessary\n   - Use `browser_*` tools to navigate and discover interface\n   - Thoroughly explore the interface, identifying all interactive elements, forms, navigation paths, and functionality\n\n2. **Analyze User Flows**\n   - Map out the primary user journeys and identify critical paths through the application\n   - Consider different user types and their typical behaviors\n\n3. **Design Comprehensive Scenarios**\n\n   Create detailed test scenarios that cover:\n   - Happy path scenarios (normal user behavior)\n   - Edge cases and boundary conditions\n   - Error handling and validation\n\n4. **Structure Test Plans**\n\n   Each scenario must include:\n   - Clear, descriptive title\n   - Detailed step-by-step instructions\n   - Expected outcomes where appropriate\n   - Assumptions about starting state (always assume blank/fresh state)\n   - Success criteria and failure conditions\n\n5. **Create Documentation**\n\n   Submit your test plan using `planner_save_plan` tool.\n\n**Quality Standards**:\n- Write steps that are specific enough for any tester to follow\n- Include negative testing scenarios\n- Ensure scenarios are independent and can be run in any order\n\n**Output Format**: Always save the complete test plan as a markdown file with clear headings, numbered steps, and\nprofessional formatting suitable for sharing with development and QA teams.\n\n## HyperDX Project Context\n\n### Application\nHyperDX is an observability platform. Key pages: `/search` (logs/traces), `/dashboards`, `/alerts`, `/metrics`, `/sessions`.\n\n### Test File Locations\n- Plans: `specs/`\n- Specs: `packages/app/tests/e2e/features/`\n- Page objects: `packages/app/tests/e2e/page-objects/`\n- Components: `packages/app/tests/e2e/components/`\n\n### Plan Requirements for HyperDX\n- Scenarios must be independent and assume a fresh DB state (the test runner clears MongoDB before each run)\n- Note when a scenario creates shared resources (e.g. webhooks, saved searches) that could conflict with parallel runs — flag these for data isolation\n- Reference existing page objects when describing steps so the generator agent knows what abstractions are available","frontmatter":{"name":"playwright-test-planner","description":"Use this agent when you need to create comprehensive test plan for a web application or website","tools":"Glob, Grep, Read, LS, mcp__playwright-test__browser_click, mcp__playwright-test__browser_close, mcp__playwright-test__browser_console_messages, mcp__playwright-test__browser_drag, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_file_upload, mcp__playwright-test__browser_handle_dialog, mcp__playwright-test__browser_hover, mcp__playwright-test__browser_navigate, mcp__playwright-test__browser_navigate_back, mcp__playwright-test__browser_network_requests, mcp__playwright-test__browser_press_key, mcp__playwright-test__browser_select_option, mcp__playwright-test__browser_snapshot, mcp__playwright-test__browser_take_screenshot, mcp__playwright-test__browser_type, mcp__playwright-test__browser_wait_for, mcp__playwright-test__planner_setup_page, mcp__playwright-test__planner_save_plan","model":"sonnet","color":"green"},"isInternal":false,"tokens":783,"sizeBytes":3563},{"name":"do-linear.md","path":".opencode/commands/do-linear.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/.opencode/commands/do-linear.md","title":"Command: /do-linear","category":"command-prompt","format":"markdown","content":"---\ndescription:\n  Fetch a Linear ticket, implement the fix/feature, test, commit, push, and\n  raise a PR\n---\n\nLook up the Linear ticket $ARGUMENTS. Read the ticket description, comments, and\nany linked resources thoroughly.\n\n## Phase 1: Understand the Ticket\n\n- Summarize the ticket — what is being asked for (bug fix, feature, refactor,\n  etc.)\n- Identify acceptance criteria or expected behavior from the description\n- Note any linked issues, related tickets, or dependencies\n\nIf the ticket description is too vague or lacks enough information to proceed\nconfidently, **stop and ask me for clarification** before writing any code.\nExplain exactly what information is missing and what assumptions you would need\nto make.\n\n## Phase 2: Plan and Implement\n\nBefore writing code, read the relevant documentation from the `agent_docs/`\ndirectory to understand architecture and code patterns.\n\n1. Explore the codebase to understand the relevant code paths and existing\n   patterns\n2. Create an implementation plan — which files to change, what approach to take\n3. Implement the fix or feature following existing codebase patterns\n4. Keep changes minimal and focused on the ticket scope\n\n## Phase 3: Verify\n\nRun lint and type checks, then run the appropriate tests based on which packages\nwere modified:\n\n1. Run `make ci-lint` to verify lint and TypeScript types pass\n2. Run `make ci-unit` to verify unit tests pass across all packages\n3. If any checks fail, fix the issues and re-run until everything passes\n\n## Phase 4: Commit, Push, and Open PR\n\n1. Create a new branch named `<current-user>/$ARGUMENTS-<short-description>`.\n   Use the current git/OS username when available, and use `whoami` as a\n   fallback to determine the prefix (e.g. `warren/HDX-1234-fix-search-filter`)\n2. Commit the changes using conventional commit format (e.g. `feat:`, `fix:`,\n   `chore:`) and reference the ticket ID\n3. Push the branch to the remote\n4. Open a draft pull request with:\n   - Title: `[$ARGUMENTS] <description>`. If multiple tickets are being\n     addressed, omit the arguments from the title.\n   - Body: Use `.github/pull_request_template.md` as the template and fill it in\n     with the relevant summary, testing notes, and Linear ticket link\n   - Label: Attach the `ai-generated` label\n","frontmatter":{"description":"Fetch a Linear ticket, implement the fix/feature, test, commit, push, and raise a PR"},"isInternal":false,"tokens":529,"sizeBytes":2282},{"name":"plan-linear.md","path":".opencode/commands/plan-linear.md","rawUrl":"https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/.opencode/commands/plan-linear.md","title":"Command: /plan-linear","category":"command-prompt","format":"markdown","content":"---\ndescription: Research a Linear ticket and create an implementation plan\nagent: plan\n---\n\nLook up the Linear ticket $ARGUMENTS. Read the ticket description and all\ncomments on the ticket thoroughly.\n\nBased on your research of the ticket, come up with a detailed implementation\nplan. The plan should include:\n\n1. **Summary** — A concise summary of what the ticket is asking for\n2. **Context** — Relevant information gathered from the ticket description and\n   comments\n3. **Approach** — Step-by-step implementation plan with specific files and\n   components to modify\n4. **Testing** — How the changes should be tested\n5. **Open Questions** — Any ambiguities or decisions that need clarification\n\nBefore writing the plan, explore the codebase to understand the relevant code\npaths and existing patterns. Reference specific files and line numbers where\nchanges will be needed.\n","frontmatter":{"description":"Research a Linear ticket and create an implementation plan","agent":"plan"},"isInternal":false,"tokens":182,"sizeBytes":887}],"systemPromptSnippet":"<yakaai_skills repo=\"hyperdxio/hyperdx\">\n<!-- File: AGENTS.md (Tokens: ~5521 | Category: root-instruction) -->\n# HyperDX Development Guide\n\n## What is HyperDX?\n\nHyperDX is an observability platform that helps engineers search, visualize, and\nmonitor logs, metrics, traces, and session replays. It's built on ClickHouse for\nblazing-fast queries and supports OpenTelemetry natively.\n\n**Core value**: Unified observability with ClickHouse performance,\nschema-agnostic design, and correlation across all telemetry types in one place.\n\n## Architecture (WHAT)\n\nThis is a **monorepo** with six packages:\n\n- `packages/app` - Next.js frontend (TypeScript, Mantine UI, TanStack Query)\n- `packages/api` - Express backend (Node.js 22+, MongoDB for metadata,\n  ClickHouse for telemetry). Also hosts the **MCP server**, **External API v2**,\n  and **OpAMP server** as sub-applications.\n- `packages/common-utils` - Shared TypeScript utilities for query parsing and\n  validation\n- `packages/cli` - Terminal CLI and interactive TUI (`hdx`) for searching,\n  tailing, and inspecting logs and traces (Ink/React). Has its own\n  [`AGENTS.md`](packages/cli/AGENTS.md) with detailed architecture and\n  keybindings.\n- `packages/otel-collector` - Custom-built OpenTelemetry Collector (Go, OCB).\n  See its [`README.md`](packages/otel-collector/README.md) for architecture,\n  included components, and upgrade procedures.\n- `packages/hdx-eval` - AI eval framework for benchmarking MCP servers against\n  observability scenarios. Generates deterministic synthetic telemetry, spawns\n  agents, and grades with programmatic checks + LLM-as-judge. See its\n  [`README.md`](packages/hdx-eval/README.md) for setup and usage, and\n  [`agent_docs/evals.md`](agent_docs/evals.md) for the dual-slot A/B\n  comparison workflow.\n\n**Data flow**: Apps → OpenTelemetry Collector → ClickHouse (telemetry data) /\nMongoDB (configuration/metadata)\n\n## Development Setup (HOW)\n\n```bash\nyarn setup          # Install dependencies\nyarn dev            # Start full stack with worktree-isolated ports\n```\n\nThe project uses **Yarn 4.13.0** workspaces. Docker Compose manages ClickHouse,\nMongoDB, and the OTel Collector.\n\n**This repo is multi-agent friendly.** `yarn dev`, `make dev-int`, and\n`make dev-e2e` all use slot-based port isolation so multiple worktrees can run\ndev servers, integration tests, and E2E tests simultaneously without conflicts.\nA dev portal at http://localhost:9900 auto-starts and shows all running stacks.\nSee [`agent_docs/development.md`](agent_docs/development.md) for the full\nmulti-worktree setup, port allocation tables, and available commands.\n\n## Working on the Codebase (HOW)\n\n**Before starting a task**, read relevant documentation from the `agent_docs/`\ndirectory:\n\n- `agent_docs/architecture.md` - Detailed architecture patterns and data models\n- `agent_docs/tech_stack.md` - Technology stack details and component patterns\n- `agent_docs/development.md` - Development workflows, testing, and common tasks\n- `agent_docs/code_style.md` - Code patterns and best practices. **Read this\n  before writing or planning any `packages/app` UI change, and before adding a\n  type, Zod schema, helper, or component in any package**, not just while\n  typing code. It carries required patterns that are invisible from the\n  surrounding file (sentence-case UI text, mandated Button/ActionIcon variants,\n  `useConfirm` for confirmation dialogs, `EmptyState`, and where shared code\n  already lives), so copying the conventions of the component you are editing is\n  not sufficient.\n- `agent_docs/naming_objects.md` - How users name and rename objects\n  (`InlineNameInput`). Read before adding or changing any name field\n- `agent_docs/observability.md` - Instrumentation standards (tracing, metrics,\n  context) and the shared helpers (read when adding or changing a feature)\n\n**Package-specific guides** (read when working on that package):\n\n- `packages/cli/AGENTS.md` - CLI/TUI architecture, keybindings, web frontend\n  alignment, key patterns\n- `packages/otel-collector/README.md` - Collector build process, included\n  components, upgrade procedures, adding custom components\n- `MCP.md` - MCP server setup and available tools (user-facing)\n\n**After finishing all code edits**, run `yarn lint:fix` to auto-fix formatting\nand lint issues across all packages. Pre-commit hooks handle this when\ncommitting, but if you finish edits without committing, run `yarn lint:fix`\nbefore stopping.\n\n## Key Principles\n\n1. **Multi-tenancy**: All data is scoped to `Team` - ensure proper filtering\n2. **Type safety**: Use TypeScript strictly; Zod schemas for validation\n3. **Existing patterns**: Follow established patterns in the codebase - explore\n   similar files before implementing. **Before you define a type, Zod schema,\n   helper, or component, grep for one that already exists.** Search for the\n   operation it performs (`bucket`, `valid.*url`, `split.*trim`) - not the name\n   you were about to give it, because names differ. Look in\n   `packages/common-utils/src/` first, then the package you are editing. If you\n   find it, import or alias it; do not add a second definition. See\n   `agent_docs/code_style.md` → \"Before you add a type, schema, or helper\"\n4. **Component size**: Keep files under 300 lines; break down large components\n5. **UI Components**: Use custom Button/ActionIcon variants (`primary`,\n   `secondary`, `danger`), `useConfirm` for \"are you sure?\" dialogs rather than\n   a hand-rolled `Modal`, and sentence case for all user-facing text - see\n   `agent_docs/code_style.md` for required patterns\n6. **Testing**: Tests live in `__tests__/` directories; use Jest for\n   unit/integration tests\n7. **Observability**: This is an observability product - instrument new code as\n   you write it. Every team-scoped operation must carry team/user context\n   (`setBusinessContext`), and countable log events should also emit a metric.\n   For our own instrumentation we favor wide events — enrich the unit-of-work\n   span with rich, high-cardinality attributes and keep only span _names_ and\n   _metric_ attributes low-cardinality — while metrics stay first-class\n   (counters/histograms feed alerts and SLOs, and many deployments rely on\n   them). Use the shared helpers in\n   `packages/api/src/utils/instrumentation.ts`. See\n   [`agent_docs/observability.md`](agent_docs/observability.md).\n8. **Communication**: Be concise and straightforward - in chat, in code\n   comments, in commits, and in PR descriptions. See\n   [Communication style](#communication-style) below.\n\n## Communication style\n\nWrite plainly. This applies to everything you produce: chat replies, code\ncomments, commit messages, PR descriptions, and docs.\n\n- **Lead with the answer.** State the result first, then the detail that\n  supports it. No preamble, no restating the request back at the reader.\n- **Cut filler.** Drop hedges (\"it seems like\", \"essentially\", \"basically\"),\n  intensifiers (\"very\", \"extremely\", \"quite\"), and throat-clearing (\"in order\n  to\" → \"to\"). Prefer short concrete words over long abstract ones.\n- **Keep summaries short.** A handful of bullets or a short paragraph. Don't\n  recap what the diff already shows, and don't restate one point in three\n  different phrasings.\n- **No self-narration.** Skip the play-by-play of your own process, the options\n  you rejected, and the victory lap (\"Perfect!\", \"All done!\"). Report what\n  changed and what is still broken.\n- **Comments explain _why_, not _what_.** The code already says what it does.\n  Omit the comment when the line is self-evident; write one when a choice needs\n  justification — a workaround, a non-obvious constraint, a ClickHouse quirk. No\n  banner comments, no ASCII section dividers, and no `// increment the counter`\n  restatements. This applies to test bodies too: don't narrate each step of a\n  test that already reads top-to-bottom.\n- **Say it straight.** If something is broken, unverified, or skipped, say so in\n  one sentence. Don't soften bad news and don't oversell partial work.\n\n## Running Tests\n\nEach package has different test commands available:\n\n**packages/app** (unit tests only):\n\n```bash\ncd packages/app\nyarn ci:unit           # Run unit tests\nyarn dev:unit          # Watch mode for unit tests\n```\n\n**packages/api** (unit and integration tests):\n\n```bash\ncd packages/api\nyarn ci:unit                        # Run unit tests (no services needed)\n\nmake dev-int-build                  # Build dependencies (run once before integration tests)\nmake dev-int FILE=<TEST_FILE_NAME>  # Spins up Docker services and runs integration tests.\n                                    # Ctrl-C to stop and wait for all services to tear down.\n```\n\n**packages/common-utils** (both unit and integration tests):\n\n```bash\ncd packages/common-utils\nyarn ci:unit           # Run unit tests\nyarn dev:unit          # Watch mode for unit tests\nyarn ci:int            # Run integration tests\nyarn dev:int           # Watch mode for integration tests\n```\n\nTo run a specific test file or pattern:\n\n```bash\nyarn ci:unit <path/to/test.ts>                           # Run specific test file\nyarn ci:unit --testNamePattern=\"test name pattern\"       # Run tests matching pattern\n```\n\n**packages/cli** (type check only, no test suite):\n\n```bash\ncd packages/cli\nnpx tsc --noEmit        # Type check\n```\n\n**Lint & type check across all packages:**\n\n```bash\nmake ci-lint        # Lint + TypeScript check across all packages\nmake ci-unit        # Unit tests across all packages\n```\n\n**E2E tests (Playwright):**\n\n```bash\n# First-time setup (install Chromium browser):\ncd packages/app && yarn playwright install chromium\n\n# Run all E2E tests:\nmake e2e\n\n# Run a specific test file (dev mode: hot reload):\nmake dev-e2e FILE=navigation                    # Match files containing \"navigation\"\nmake dev-e2e FILE=navigation GREP=\"help menu\"   # Also filter by test name\nmake dev-e2e GREP=\"should navigate\"             # Filter by test name across all files\nmake dev-e2e FILE=navigation REPORT=1           # Open HTML report after run\nmake dev-e2e-clean                               # Remove test artifacts\n```\n\n## Important Context\n\n- **Authentication**: Passport.js with team-based access control\n- **State management**: Jotai (client), TanStack Query (server), URL params\n  (filters)\n- **UI library**: Mantine components are the standard (not custom UI)\n- **Database patterns**: MongoDB for metadata with Mongoose, ClickHouse for\n  telemetry queries\n\n## PR Hygiene for Agent-Generated Code\n\nWhen using agentic tools to generate PRs, follow these practices to keep reviews\nefficient and accurate:\n\n1. **Scope PRs to a single logical change**, even if the agent can produce more\n   in one session. Smaller, focused PRs move through the review pipeline faster\n   and are easier to classify accurately.\n\n2. **Write the PR description to explain intent (the \"why\"), not just what\n   changed.** Reviewers need to understand the goal to catch cases where the\n   agent solved the wrong problem or made a plausible-but-wrong trade-off.\n\n3. **Name agent-generated branches with a `claude/`, `agent/`, or `ai/` prefix**\n   (e.g., `claude/add-rate-limiting`) so reviewers can calibrate their attention.\n   This is a convention for humans: the PR triage classifier deliberately ignores\n   branch names and tiers every PR on what the diff touches and how big it is.\n\n4. **Write or update tests alongside the implementation**, not after. Configure\n   your agent to produce tests before writing implementation code. See the\n   Testing section below for the commands to use.\n\n5. **Attach before/after screenshots to any PR that changes the UI.** Anything\n   visible in `packages/app` needs a \"Before\" (`main`) and \"After\" (branch)\n   image in the PR template's screenshots table, taken on the same screen, data,\n   viewport, and theme. Use a short video for interactions. If you can't capture\n   screenshots yourself (no browser tool), say so in the PR description and\n   leave the table for the human author to fill; never submit an empty table\n   silently. See\n   [CONTRIBUTING.md](CONTRIBUTING.md#ui-changes-need-beforeafter-screenshots).\n\n6. **Write reproduction steps a reviewer can follow.** Fill in the PR\n   template's \"How to reproduce\" section with numbered steps that show the\n   problem on `main` and the fix on the branch. Start from\n   [play.hyperdx.io](https://play.hyperdx.io) when the bug shows there, or from\n   `yarn app:dev:local` connected to the demo server (onboarding → \"Connect to\n   Demo Server\"; the PR's Vercel preview runs the same local mode). Full-stack\n   `yarn dev` pre-provisions a local ClickHouse connection and never shows that\n   button, so use it only when the change needs the API. Name UI elements by\n   visible text, and list any env vars,\n   feature flags, schema, or seed data needed. When filing issues, apply the\n   same standard. See\n   [CONTRIBUTING.md](CONTRIBUTING.md#reproducing-issues-and-prs).\n\n7. **Ensure a changeset exists before pushing a PR.** Any change to a published\n   package (`@hyperdx/app`, `@hyperdx/api`, `@hyperdx/otel-collector`, etc.) that\n   is user-facing or affects behavior must include a changeset in `.changeset/`.\n   Add one with `yarn changeset` (or create the markdown file by hand following\n   the format of existing entries), choosing the appropriate semver bump, before\n   pushing the branch. Skip only for changes that don't warrant a release (docs,\n   internal tooling, tests, CI).\n\n8. **The root `CHANGELOG.md` is generated at release time.** During each\n   release, CI writes an AI-generated cross-package summary section into the\n   root `CHANGELOG.md` on the \"Release HyperDX\" PR. Review and edit it there\n   like any other file — but keep the `<!-- hyperdx-release-notes … -->` comment\n   marker intact; it is how your edits are recognised when the release branch is\n   rebuilt. Use `###` or deeper for any heading you add — a `##` marks a release\n   boundary, and the next release refuses to splice rather than risk deleting\n   whatever ended up below it. Your edits are regenerated away when new\n   changesets land on `main` (the previous text is passed to the generator, so\n   phrasing is preserved best-effort, not guaranteed). They can also be lost\n   outright if a second push to `main` lands while a changelog run is still in\n   flight — the edit is held only in that run's artifact. If an edit matters,\n   re-check it on the release PR before merging. Don't edit the root\n   `CHANGELOG.md` in feature PRs; the only exception is the one-time seed that\n   introduced the file.\n\n### How the root changelog is generated\n\nDefined in `.github/workflows/release.yml`; the splicing logic lives in\n`.github/scripts/release-notes.mjs`.\n\n```\npush to main\n    |\n    v\ncheck_changesets\n    |  1. capture the branch's current CHANGELOG.md -> artifact\n    |     (must happen BEFORE the next step destroys it)\n    |  2. changesets/action force-rebuilds changeset-release/main from main\n    |     and opens/updates the \"Release HyperDX\" PR\n    v\nrelease_changelog_draft            contents: read - no push token\n    |\n    |  app version unchanged?  --yes-->  skip (CLI/common-utils-only release)\n    |  changeset hash matches?  --yes-->  reuse previous section verbatim\n    |                           --no-->  Claude writes a fresh body, given\n    |                                    the old section as context\n    v\n  body artifact                    the model's only output\n    |\n    v\nrelease_changelog_publish          contents: write - the model never ran here\n    |\n    |  branch moved since drafting?  --yes-->  skip, the newer run republishes\n    |  validate (no headings/markers/images/off-site links)\n    |  append the package list, splice into CHANGELOG.md\n    v\npush to changeset-release/main  ->  appears as a diff in the release PR,\n    |                               where a maintainer can edit it\n    v\nmerge the release PR  ->  CHANGELOG.md lands on main  ->  served in \"What's new\"\n```\n\nThe job split is a security boundary, not tidiness: the model reads changeset\nbodies, commit messages and PR bodies, which anyone opening a PR controls. Its\njob holds `ANTHROPIC_API_KEY` and a `contents: read` token, but no push\ncredential and no ability to alter the script that does the splicing. Because\nthe API key shares that process, the generator gets `--tools \"Read\" \"Write\"` and\nnothing else: no `Bash`, and no `Grep` or `Glob` either, since those read files\nwithout consulting a `Read` path rule. It may write exactly one file, granted by\nan `Edit(<path>)` rule, and `/proc`, `/sys`, `/home` and `/etc` are denied\noutright — `/proc/self/environ` carries the whole environment, and the output\nis published to a public branch.\n\nThree flags with three different jobs, which is worth keeping straight when\nediting this: `--tools` restricts what exists, `--allowedTools` only\npre-approves (it is what stops a `-p` run stalling on a prompt it cannot\nanswer), and `--disallowedTools` denies. A path rule attached to `Write` is\naccepted and then never consulted — file permissions are checked against\n`Edit` and `Read` rules — so write confinement is spelled `Edit(<path>)`.\n\nBecause the generator has no way to list a directory, every input is\nmaterialised for it at a known path by trusted shell, including all the\nchangesets concatenated into one file. Left to discover\n`.changeset/gentle-boats-serve.md` by name it cannot, and it writes a changelog\nthat quietly omits whatever it could not find.\n\nThe generator calls the Claude Code CLI, not\n`anthropics/claude-code-action`: that action accepts only GitHub entity events\nand rejects `push`, and everything it adds on top of the CLI — a token, entity\ncontext, PR comments — is what this job deliberately does without.\n\n## Responding to review feedback\n\nTwo bots review every PR (Claude Code Review inline + summary, Deep Review\nsummary). No finding blocks merge automatically; a maintainer decides what\nlands. Severity tells you what they will expect.\n\n1. **Triage before you touch code.** Two questions per comment: did this PR\n   introduce the problem (would reverting the PR make it go away?), and how\n   severe is it?\n   - Critical or major (P0/P1) that this PR introduced, in new or edited code:\n     fix it before asking for review. A maintainer will require it if it is\n     real.\n   - Minor (P2/P3) that this PR introduced: your call. Fix if small, else\n     reply.\n   - A defect that was already there before this PR, or a suggestion to widen\n     the change (hoist, dedupe, refactor neighbours, fix other call sites):\n     never fix here, whatever the severity. Reply in the thread with one\n     sentence; if it is critical, say so plainly so a maintainer sees it. The\n     reviewer reads replies and does not re-report what a human has answered.\n2. **Do not touch files the PR did not already touch** unless fixing a defect\n   in this PR's own change requires it.\n3. **Push review fixes as new commits, not a force-push.** The repo\n   squash-merges, so commit count never reaches `main`; review history does.\n4. **After two rounds of bot findings, stop.** Ask a maintainer to look at the\n   scope instead of addressing more automated comments. A PR that keeps\n   growing to satisfy a bot is drifting from its purpose.\n5. A finding you disagree with is not a defect. Say so and move on.\n\n## GitHub Action Workflow (when invoked via @claude)\n\nWhen working on issues or PRs through the GitHub Action:\n\n1. **Before writing any code**, post a comment outlining your implementation\n   plan — which files you'll change, what approach you'll take, and any\n   trade-offs or risks. Use `gh issue comment` for issues or `gh pr comment` for\n   PRs.\n\n2. **After making any code changes**, always run these in order and fix any\n   failures before opening a PR:\n\n   - `make ci-lint` — lint + TypeScript type check\n   - `make ci-unit` — unit tests\n\n3. Write a clear PR description explaining what changed and why.\n\n## Git Commits\n\nWhen committing code, use the git author's default profile (name and email from\ngit config). Do not add `Co-Authored-By` trailers.\n\n**Pre-commit hooks must pass before committing.** Do not use `--no-verify` to\nskip hooks. If the pre-commit hook fails (e.g. due to husky not being set up in\na worktree), run `npx lint-staged` manually before committing to ensure lint and\nformatting checks pass. Fix any issues before creating the commit.\n\n## Merge Conflict Resolution\n\n1. **Never blindly pick a side.** Read both sides of every conflict to\n   understand the intent of each change before choosing a resolution.\n\n2. **Refactor/move conflicts require extra verification.** When one side\n   refactored, moved, or extracted code (e.g., inline components to separate\n   files), always diff the discarded side against the destination files before\n   declaring the conflict resolved. Code can diverge after extraction — the\n   other branch may have made fixes or additions that the extracting branch\n   never picked up. A naive \"keep ours\" resolution silently drops those changes.\n\n3. **Verify the result compiles.** After resolving, check for missing imports,\n   broken references, or type errors introduced by the resolution — especially\n   when discarding a side that added new dependencies or exports.\n\n4. **Ask for help when uncertain.** If you are not 100% confident about which\n   side to keep, or whether a change can be safely discarded, stop and ask for\n   manual intervention rather than guessing. A wrong guess silently breaks\n   things; asking is always cheaper than debugging later.\n\n## Cursor Cloud specific instructions\n\n### Docker requirement\n\nDocker must be installed and running before starting the dev stack or running\nintegration/E2E tests. The VM update script handles `yarn install` and\n`yarn build:common-utils`, but Docker daemon startup is a prerequisite that must\nalready be available.\n\n### Starting the dev stack\n\n`yarn dev` uses `sh -c` to source `scripts/dev-env.sh`, which contains\nbash-specific syntax (`BASH_SOURCE`). On systems where `/bin/sh` is `dash`\n(e.g. Ubuntu), this fails with \"Bad substitution\". Work around it by running\nwith bash directly:\n\n```bash\nbash -c 'export PATH=\"/workspace/node_modules/.bin:$PATH\" && source ./scripts/dev-env.sh && yarn build:common-utils && dotenvx run --convention=nextjs -- docker compose -p \"$HDX_DEV_PROJECT\" -f docker-compose.dev.yml up -d && yarn app:dev'\n```\n\nPort isolation assigns a slot based on the worktree directory name. In the\ndefault `/workspace` directory, the slot is **76**, so services are at:\n\n- **App**: http://localhost:30276\n- **API**: http://localhost:30176\n- **ClickHouse**: http://localhost:30576\n- **MongoDB**: localhost:30476\n\n### Key commands reference\n\nSee `AGENTS.md` above and `agent_docs/development.md` for the full command\nreference. Quick summary:\n\n- `make ci-lint` — lint + TypeScript type check\n- `make ci-unit` — unit tests (all packages)\n- `make dev-int FILE=<name>` — integration tests (spins up Docker services)\n- `make dev-e2e FILE=<name>` — E2E tests (Playwright)\n\n### First-time registration\n\nWhen the dev stack starts fresh (empty MongoDB), the app shows a registration\npage. Create any account to get started — no external auth provider is needed.\n\n---\n\n_Need more details? Check the `agent_docs/` directory or ask which documentation\nto read._\n\n<!-- File: agent_docs/architecture.md (Tokens: ~1438 | Category: project-spec) -->\n# HyperDX Architecture\n\n## Core Services\n\n- **HyperDX UI (`packages/app`)**: Next.js frontend serving the user interface\n- **HyperDX API (`packages/api`)**: Node.js/Express backend handling queries and business logic\n- **OpenTelemetry Collector**: Receives and processes telemetry data\n- **ClickHouse**: Primary data store for all telemetry (logs, metrics, traces)\n- **MongoDB**: Metadata storage (users, dashboards, alerts, saved searches)\n\n## Data Flow\n\n1. Applications send telemetry via OpenTelemetry → OTel Collector\n2. OTel Collector processes and forwards data → ClickHouse\n3. Users interact with UI → API queries ClickHouse\n4. Configuration/metadata stored in MongoDB\n\n## Key MongoDB Models\n\nAll models follow consistent patterns with:\n- Team-based multi-tenancy (most entities belong to a `team`)\n- ObjectId references between related entities\n- Timestamps for audit trails\n- Zod schema validation\n\n**Key Models** (see `packages/api/src/models/`):\n- `Team`: Multi-tenant organization unit\n- `User`: Team members with authentication\n- `Source`: ClickHouse data source configuration\n- `Connection`: Database connection settings\n- `SavedSearch`: Saved queries and filters\n- `Dashboard`: Custom dashboard configurations\n- `Alert`: Monitoring alerts with thresholds\n\n## Frontend Architecture\n\n- **Pages**: `packages/app/pages/` (Next.js routing)\n- **Components**: `packages/app/src/` (reusable components)\n- **API communication**: Custom hooks wrapping TanStack Query\n- **State**: See tech_stack.md for state management details\n\n## Backend Architecture\n\nThe API package (`packages/api`) hosts several distinct applications, each with\nits own routing, authentication, and rate limiting:\n\n### Internal API (`src/routers/api/`)\n\nThe primary API consumed by the web frontend (`packages/app`). Uses session-based\nauthentication (Passport.js). Follows a standard layered structure:\n\n- **Routers**: `src/routers/api/` - Domain-specific API routes\n- **Controllers**: `src/controllers/` - Business logic separated from routes\n- **Middleware**: `src/middleware/` - Authentication, CORS, error handling\n- **Services**: `src/services/` - Reusable business logic (e.g., `agentService`)\n\n### External API v2 (`src/routers/external-api/v2/`)\n\nPublic REST API for programmatic access. Authenticated via Personal API Access\nKey (`validateUserAccessKey` middleware), rate-limited to 100 req/min.\n\n- **Routes**: `alerts.ts`, `charts.ts`, `dashboards.ts`, `sources.ts`,\n  `webhooks.ts`\n- **OpenAPI spec**: `packages/api/openapi.json` (auto-generated via\n  `yarn docgen`, linted via `yarn lint:openapi` using Spectral)\n- **Tests**: `src/routers/external-api/__tests__/`\n\nWhen adding or modifying external API endpoints, run `yarn docgen` to regenerate\nthe OpenAPI spec and `yarn lint:openapi` to validate it.\n\n`scripts/ci/check-openapi-sync.sh` (run by `make ci-lint` and by CI) fails if the\ncommitted spec is stale. `swaggerOptions` in `src/utils/swagger.ts` is also an\ninput, and the spec is in `.prettierignore` because docgen owns its formatting.\n\n### MCP Server (`src/mcp/`)\n\n[Model Context Protocol](https://modelcontextprotocol.io/) server that lets AI\nassistants query observability data and manage dashboards. Exposed as a stateless\nStreamable HTTP endpoint at `/api/mcp`, authenticated via Personal API Access\nKey, rate-limited to 600 req/min.\n\n- **Entry**: `app.ts` (Express middleware), `mcpServer.ts` (server factory)\n- **Tools**: `tools/alerts/`, `tools/dashboards/`, `tools/query/`,\n  `tools/savedSearches/` - each directory contains tool definitions and handlers\n- **Prompts**: `prompts/dashboards/` - context prompts for AI assistants\n- **Tests**: `src/mcp/__tests__/` (alerts, dashboards, query, savedSearches,\n  tracing)\n- **Dev/debug**: `yarn dev:mcp` launches the MCP Inspector for interactive\n  testing\n- **Response size**: each tool call records the UTF-8 bytes it returns\n  (`mcp.tool.response.size_bytes` span attribute,\n  `hyperdx.mcp.tool.response.size_bytes` histogram)\n\nSee `MCP.md` in the repo root for user-facing setup instructions.\n\n### OpAMP Server (`src/opamp/`)\n\nHTTP-based [OpAMP](https://github.com/open-telemetry/opamp-spec) server that\nserves configurations to supervised OpenTelemetry Collectors. The supervisor\npings `/v1/opamp` with status, and the server returns updated config when needed.\n\n- **Entry**: `app.ts` (Express sub-app)\n- **Controller**: `controllers/opampController.ts` - config derivation logic\n- **Service**: `services/agentService.ts` - agent management\n- **Model**: `models/agent.ts` - agent state persistence\n- **Proto**: `proto/` - Protocol Buffer definitions for OpAMP and anyvalue\n\nConfig is derived from the team document with the ingestion API key.\n\n### Background Tasks (`src/tasks/`)\n\nCron-driven tasks that run outside the request/response cycle. In development,\ntasks run via `yarn dev-task`; in production, they are triggered externally.\n\n- `checkAlerts/` - Alert evaluation (runs every minute in dev)\n- `provisionDashboards/` - Dashboard provisioning from config files\n- `usageStats.ts` - Usage statistics collection\n- `pingPongTask.ts` - Health check task\n- `metrics.ts` - Task execution metrics (duration, success/failure counters)\n\nNote: Background tasks do **not** run in Vercel preview deployments (see\n`agent_docs/development.md` for details).\n\n## Data & Query Patterns\n\n### ClickHouse Integration\n- **Query building**: Use `common-utils` for safe query construction\n- **Schema flexibility**: Support for various telemetry schemas via `Source` configuration\n\n### MongoDB Patterns\n- **Multi-tenancy**: All queries filtered by team context\n- **Relationships**: Use ObjectId references with proper population\n- **Indexing**: Strategic indexes for query performance\n- **Migrations**: Versioned migrations for schema changes (see `packages/api/migrations/`)\n\n## Security Requirements\n\n- **Server-side validation**: Always validate and sanitize on the backend\n- **Team isolation**: All data access must filter by team context\n- **API authentication**: Use authentication middleware on protected routes\n- **Secrets**: Never commit secrets; use `.env` files\n\n<!-- File: .claude/skills/playwright/SKILL.md (Tokens: ~961 | Category: anthropic-skill) -->\n---\nname: playwright\ndescription: Writes end-to-end tests code using Playwright browser automation.\n---\n\n# Playwright End-to-End Test Writer\n\nI am a Playwright End-to-End Test Writer. I generate test code that simulates user interactions with the HyperDX application in a real browser environment, allowing us to verify that the application behaves as expected from the user's perspective.\n\nI will write tests covering these requirements: $ARGUMENTS.\n\nIf the requirements are empty or unclear, I will ask the user for a detailed description of the test they want.\n\n## Workflow\n\nUse the agents below to carry out each phase. Do not write test code directly in the main context.\n\n### 1. Test Generation\nDelegate to the **`playwright-test-generator`** agent (via the Agent tool). Pass it:\n- A full description of the test scenario including steps, expected outcomes, and edge cases\n- The target spec file path (`packages/app/tests/e2e/features/<feature>.spec.ts`)\n- Any relevant page object files that already exist for this feature\n\nThe agent will drive a real browser, execute the steps live, and produce spec code that follows HyperDX conventions. Review the output before proceeding.\n\nNOTE: When there is an existing spec file covering the feature, add new tests to the existing file instead of creating a new one. This keeps related tests together and avoids fragmentation.\n\n### 2. Test Execution\nAfter the generator agent writes the file, run the test:\n\n```bash\n./scripts/test-e2e.sh --quiet <test-file-name> [--grep \"\\\"<test name pattern>\\\"\"]\n```\n\nAlways run in full-stack mode (default). Do not ask the user about this.\n\n### 3. Iterative Fixing\nIf the test fails, delegate to the **`playwright-test-healer`** agent (via the Agent tool). Pass it:\n- The failing test file path\n- The error output\n- Any relevant context about what the test is supposed to do\n\nThe healer agent will debug interactively, fix the code, and re-run until the test passes.\n\n## HyperDX Project Conventions\n\nThese conventions apply to ALL test code produced by any agent. Review generated output to ensure compliance.\n\n### File Structure\n- Specs: `packages/app/tests/e2e/features/`\n- Page objects: `packages/app/tests/e2e/page-objects/`\n- Components: `packages/app/tests/e2e/components/`\n- Utilities: `packages/app/tests/e2e/utils/`\n- Base test (extends playwright with fixtures): `utils/base-test.ts`\n- Constants (source names): `utils/constants.ts`\n\n### Page Object Pattern (REQUIRED)\n- ALL UI interactions in spec files must go through page objects (`page-objects/`) and components (`components/`)\n- No raw `page.getByTestId()`, `page.locator()`, or `page.getByRole()` calls directly in spec files\n- If a needed interaction doesn't exist in a page object, add it to the page object — don't work around it in the spec\n\n### Data Isolation (CRITICAL)\nTests run in parallel and share a database. Use `Date.now()` for **every field the API uniqueness-checks** — not just display names:\n\n```typescript\nconst ts = Date.now();\nconst name = `E2E Thing ${ts}`;\nconst url = `https://example.com/thing-${ts}`; // URL too, not just name\n```\n\nThe webhook API enforces uniqueness on `(team, service, url)`. A hardcoded URL will collide between parallel runs or retries.\n\n### Assertions\n- Never assert global counts (`toHaveCount(N)`) — other tests' data pollutes the page\n- Scope assertions to the current test's data: `pageContainer.getByRole('link').filter({ hasText: name })`\n- Use web-first assertions (`toBeVisible()`, `toBeHidden()`) not imperative checks\n- Never use hardcoded waits (`waitForTimeout`) — wait for specific elements or conditions\n- Assert successful chart loads by checking `.recharts-responsive-container` is visible\n\n### Tags\n- `{ tag: '@full-stack' }` — tests requiring MongoDB + API backend\n- Feature tags: `@dashboard`, `@alerts`, `@search`, etc.\n\n### Imports\nAlways import from the base test, not directly from `@playwright/test`:\n```typescript\nimport { expect, test } from '../utils/base-test';\n```\n\n### Mock ClickHouse Data\n- E2E tests run against a local Docker environment with seeded ClickHouse data\n- Update `packages/app/tests/e2e/seed-clickhouse.ts` only if the scenario requires specific data not already seeded\n\n<!-- File: .claude/skills/refactor-component/SKILL.md (Tokens: ~2559 | Category: anthropic-skill) -->\n---\nname: refactor-component\ndescription: Refactor a large React component file into a directory of smaller files. Use when the user asks to break up, split, or refactor a big component file.\n---\n\n# Refactor Large Component into Directory\n\nBreak a monolithic React component file into a well-organized directory with no functionality changes.\n\nThe target component is: $ARGUMENTS\n\nIf no component is specified, ask the user which file to refactor.\n\n## Workflow\n\n### 1. Check E2E test coverage\n\nBefore touching any code, verify that the component's key user flows are covered by E2E tests. Search for Playwright test files (typically in `packages/app/tests/e2e/`) that exercise the component — look for references to its `data-testid` attributes, page object methods, or user-visible behaviour (e.g. clicking Run, Save, switching chart types, SQL mode).\n\n- **If good coverage exists**: note the relevant test files and move on. These tests become your safety net — you will re-run them after the refactor to catch regressions.\n- **If coverage is missing or thin**: stop and ask the user whether they want to add E2E tests before refactoring. Present the gaps you found (e.g. \"raw SQL chart creation has no E2E test\") and let the user provide test requirements. Use the `playwright` skill to create the tests, then run them to confirm they pass on the current (pre-refactor) code. Only proceed with the refactor once the baseline E2E tests are green.\n\nThis step is critical — E2E tests are the strongest guarantee that the refactor doesn't break real user flows. Unit tests alone cannot catch issues like missing DOM elements that only appear when the full app is composed.\n\n### 2. Analyse the file\n\nRead the entire target file. Identify:\n\n- **Main component** — the default export (becomes the primary file in the new directory)\n- **Sub-components** — named function/const components used only inside this file\n- **Types & interfaces** — exported or internal types tied to the sub-components\n- **Utilities** — pure functions, Zod schemas, constants that aren't React components\n- **Tests** — any test file in a sibling `__tests__/` directory that imports the target\n\nCreate a plan listing each new file, what goes in it, and which imports change. Present the plan to the user and wait for approval before writing code.\n\n### 3. Create the directory and files\n\nThe new directory is created inside `packages/app/src/components/`, replacing the original file. It keeps the same name (without extension), so external imports resolve unchanged.\n\n```\npackages/app/src/components/ComponentName/\n  index.ts              — barrel re-export of the default export\n  ComponentName.tsx     — main component (default export)\n  SubComponent.tsx      — one file per sub-component (named export)\n  utils.ts              — utility functions, schemas, constants\n  __tests__/            — moved test files with updated imports\n```\n\n#### Rules\n\n- **`index.ts`** is the single public API of the directory. All exports that consumers depend on must be re-exported through `index.ts`. Sub-components or utilities that are only used within the directory should **not** be re-exported.\n- Each sub-component file has a **named export** (not default).\n- **Sibling imports** within the directory use `./` relative paths. Files outside the directory must never import directly from a sub-file (e.g. `ComponentName/ChartActionBar`) — they import from the directory barrel (`ComponentName`) only.\n- **All other relative imports** (`../Foo`, `./Foo`) in the extracted files must be converted to `@/`-prefixed absolute imports (e.g. `@/components/Foo`). This is critical — files moved one level deeper will break if relative paths aren't updated.\n- Existing `@/`-prefixed imports stay unchanged.\n- Do not add, remove, or rename any exports. The refactoring must be invisible to consumers.\n\n### 4. Move tests\n\nMove `__tests__/ComponentName.test.tsx` into `ComponentName/__tests__/ComponentName.test.tsx`.\n\nUpdate in the test file:\n\n- The main import: `from '../ComponentName'` → `from '..'`\n- Mock paths: `../SiblingComponent` → `../../SiblingComponent` (one extra level up)\n\n### 5. Delete the original file\n\nRemove the original monolithic `.tsx` file only after all new files are written.\n\n### 6. Tidy up\n\nAfter the initial split, clean up duplication and improve structure within the new directory:\n\n#### Remove unnecessary indirection\n\n- If a component is declared as `function FooComponent` and then aliased as `export const Foo = FooComponent`, rename the function to `Foo` and export it directly.\n\n#### Deduplicate code across files\n\n- Look for validation+normalization logic repeated across callbacks — extract a shared helper (e.g. `validateAndNormalize`) that returns `{ errors, config }` so each caller only contains its unique logic.\n- Deduplicate `renderComponent` helpers in test files — hoist a single shared factory to file scope. Describe blocks with special defaults can wrap it in a thin helper (e.g. `renderAlertComponent`) that passes overrides.\n\n#### Extract pure logic into utils.ts\n\nScan component files for logic that can move into `utils.ts`:\n\n- **Pure functions in `useMemo` callbacks** — if the memo body is a pure transformation (no hooks, no JSX), extract it as a named function in `utils.ts` and call it from the memo.\n- **Constants and lookup tables** — arrays/sets used in conditionals (e.g. `['table', 'time', 'number', 'pie'].includes(tab)`) become named exports (e.g. `TABS_WITH_GENERATED_SQL`).\n- **Simple mappings** — switch/if chains that map one value to another (e.g. `DisplayType` → tab string) become standalone functions. These don't need `useMemo` since they're cheap.\n- **Complex config builders** — conditional logic that selects/transforms configs for display (e.g. building sample events config, chart explanation config) should be pure functions that receive all dependencies as parameters.\n\nGood extraction candidates:\n\n- Config builder functions (`buildSampleEventsConfig`, `buildChartConfigForExplanations`)\n- Enum/type mappers (`displayTypeToActiveTab`)\n- Computed values with alert logic (`computeDbTimeChartConfig`)\n\nLeave in the component:\n\n- Logic that reads/writes React state or calls hooks\n- Event handlers that call `setValue`, `onSubmit`, etc.\n- JSX rendering logic\n\n#### Use named prop types\n\nAll components should use named type aliases for their props, declared directly above the component function:\n\n```tsx\ntype FooProps = {\n  bar: string;\n  onBaz: () => void;\n};\n\nexport function Foo({ bar, onBaz }: FooProps) {\n```\n\nDo not use inline object types in the function signature.\n\n#### Split large components further\n\nIf a file exceeds ~500 lines after the initial split, look for natural extraction points:\n\n- **Form inputs + toolbar** — form fields, series editors, action buttons → `ChartEditorControls.tsx`\n- **Preview/results area** — chart rendering, accordions, result display → `ChartPreviewPanel.tsx`\n- **The main file** becomes a thin orchestrator: form state, hooks, callbacks, effects, and a JSX shell that renders the sub-components.\n\nWhen splitting JSX, the extracted component receives form state via props (`control`, `setValue`, etc.). Watches that are only used in the extracted component (e.g. `alertChannelType`) can use `useWatch` inside it rather than being passed as props.\n\n#### Classify shared vs conditional JSX before extracting\n\nBefore moving JSX into a new component, map the render tree's branching structure. Every piece of JSX must be classified as either:\n\n- **Branch-specific** — rendered inside one arm of a conditional (ternary, `&&`, if/else)\n- **Shared** — rendered as a sibling of the conditional, appearing for all branches\n\n**Extract from the bottom up**: pull out the conditional/branch-specific parts first, leaving shared sections in the parent. Never bundle shared JSX into a component that only renders for one branch.\n\n**Verify after extraction**: for each value of every conditional, confirm the new code renders the same set of components as the original. A toolbar, action bar, or footer that appeared for all chart types must still appear for all chart types after the split.\n\n### 7. Write unit tests for extracted code\n\nThis is a dedicated step — do not skip it or fold it into another step.\n\n#### Tests for `utils.ts`\n\nWrite unit tests in `__tests__/utils.test.ts` covering:\n\n- All pure functions with normal inputs, edge cases, and null/undefined guards\n- Constants (verify membership)\n- Config builders (test null returns for invalid inputs, verify output shape for valid inputs)\n\n#### Tests for each extracted component\n\nWrite unit tests for each extracted component in `__tests__/<ComponentName>.test.tsx` covering:\n\n- **Conditional rendering**: for each prop/state that controls visibility, verify elements appear and disappear correctly\n- **Callbacks**: verify that prop callbacks are invoked on user interaction (clicks, etc.)\n- **Prop-driven behaviour**: test that props like `activeTab`, `isRawSqlInput`, `isSaving` produce the correct UI state (disabled buttons, hidden sections, etc.)\n- **Regression coverage**: if the extraction was motivated by a bug (e.g. shared controls missing for a specific mode), include a test that explicitly renders the component in that mode and asserts the controls are present\n\nUse a `FormWrapper` test helper when the component requires react-hook-form's `control`/`handleSubmit` — create a small wrapper that calls `useForm` with sensible defaults and passes the form methods to the component under test via a render-prop pattern. Mock heavy child components (chart renderers, SQL editors, etc.) with simple stubs that render a `data-testid`.\n\n### 8. Verify\n\nRun in order — fix any failures before proceeding to the next step:\n\n```bash\nmake ci-lint    # TypeScript compilation + lint\n```\n\n```bash\ncd packages/app && yarn ci:unit   # Unit tests (or the appropriate package)\n```\n\n```bash\nmake e2e   # E2E tests — re-run the same tests from step 1 to catch regressions\n```\n\nIf lint fails with import-sort or formatting errors, run `npx eslint --fix <file>` on the affected files and re-check. If there are unused-import warnings, remove the unused imports manually.\n\nIf an E2E test fails, investigate whether the failure is related to the refactoring (e.g. a broken import path at runtime) or a pre-existing flake. Fix refactoring-related failures before presenting the result. The E2E tests identified in step 1 are the most important — if those pass, the refactor is safe.\n\n## Checklist (self-review before presenting result)\n\n- [ ] E2E test coverage verified (or added) before refactoring began\n- [ ] No functionality changes — pure file reorganisation\n- [ ] Shared JSX (toolbars, action bars, footers) not accidentally bundled into a conditional branch's component\n- [ ] `index.ts` barrel makes the directory a drop-in replacement\n- [ ] All relative imports in extracted files converted to `@/` prefixed\n- [ ] Sibling imports within directory use `./`\n- [ ] Test file moved and import paths updated (both main import and mocks)\n- [ ] Original monolith file deleted\n- [ ] Duplicated logic extracted into shared helpers\n- [ ] Pure functions moved from components to `utils.ts`\n- [ ] All components use named prop types declared above the function\n- [ ] No file exceeds ~500 lines (split further if needed)\n- [ ] Unit tests written for `utils.ts` functions\n- [ ] Unit tests written for each extracted component (conditional rendering, callbacks, regression cases)\n- [ ] `make ci-lint` passes\n- [ ] Unit tests pass\n- [ ] E2E tests pass\n\n<!-- File: packages/api/.spectral.yaml (Tokens: ~300 | Category: anthropic-skill) -->\n# Api Skill\n\nPath: `packages/api/.spectral.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/.spectral.yaml)\n\n<!-- File: packages/api/CHANGELOG.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Api Skill\n\nPath: `packages/api/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/CHANGELOG.md)\n\n<!-- File: packages/api/docs/auto_provision/AUTO_PROVISION.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Auto_provision Skill\n\nPath: `packages/api/docs/auto_provision/AUTO_PROVISION.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/docs/auto_provision/AUTO_PROVISION.md)\n\n<!-- File: packages/api/nodemon.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Api Skill\n\nPath: `packages/api/nodemon.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/nodemon.json)\n\n<!-- File: packages/api/openapi.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Api Skill\n\nPath: `packages/api/openapi.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/openapi.json)\n\n<!-- File: packages/api/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Api Skill\n\nPath: `packages/api/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/package.json)\n\n<!-- File: packages/api/tsconfig.build.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Api Skill\n\nPath: `packages/api/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/tsconfig.build.json)\n\n<!-- File: packages/api/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Api Skill\n\nPath: `packages/api/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/api/tsconfig.json)\n\n<!-- File: packages/app/CHANGELOG.md (Tokens: ~300 | Category: anthropic-skill) -->\n# App Skill\n\nPath: `packages/app/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/CHANGELOG.md)\n\n<!-- File: packages/app/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# App Skill\n\nPath: `packages/app/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/package.json)\n\n<!-- File: packages/app/public/pyodide/pyodide-lock.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Pyodide Skill\n\nPath: `packages/app/public/pyodide/pyodide-lock.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/public/pyodide/pyodide-lock.json)\n\n<!-- File: packages/app/src/dashboardTemplates/dotnet-runtime.json (Tokens: ~300 | Category: anthropic-skill) -->\n# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/dotnet-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/dotnet-runtime.json)\n\n<!-- File: packages/app/src/dashboardTemplates/go-runtime.json (Tokens: ~300 | Category: anthropic-skill) -->\n# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/go-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/go-runtime.json)\n\n<!-- File: packages/app/src/dashboardTemplates/jvm-runtime-metrics.json (Tokens: ~300 | Category: anthropic-skill) -->\n# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/jvm-runtime-metrics.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/jvm-runtime-metrics.json)\n\n<!-- File: packages/app/src/dashboardTemplates/nodejs-runtime.json (Tokens: ~300 | Category: anthropic-skill) -->\n# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/nodejs-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/nodejs-runtime.json)\n\n<!-- File: packages/app/src/dashboardTemplates/python-runtime.json (Tokens: ~300 | Category: anthropic-skill) -->\n# DashboardTemplates Skill\n\nPath: `packages/app/src/dashboardTemplates/python-runtime.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/src/dashboardTemplates/python-runtime.json)\n\n<!-- File: packages/app/tests/e2e/fixtures/e2e-fixtures.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Fixtures Skill\n\nPath: `packages/app/tests/e2e/fixtures/e2e-fixtures.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tests/e2e/fixtures/e2e-fixtures.json)\n\n<!-- File: packages/app/tsconfig.build.json (Tokens: ~300 | Category: anthropic-skill) -->\n# App Skill\n\nPath: `packages/app/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tsconfig.build.json)\n\n<!-- File: packages/app/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# App Skill\n\nPath: `packages/app/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/app/tsconfig.json)\n\n<!-- File: packages/cli/AGENTS.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Cli Skill\n\nPath: `packages/cli/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/AGENTS.md)\n\n<!-- File: packages/cli/CHANGELOG.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Cli Skill\n\nPath: `packages/cli/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/CHANGELOG.md)\n\n<!-- File: packages/cli/CONTRIBUTING.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Cli Skill\n\nPath: `packages/cli/CONTRIBUTING.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/CONTRIBUTING.md)\n\n<!-- File: packages/cli/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Cli Skill\n\nPath: `packages/cli/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/package.json)\n\n<!-- File: packages/cli/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Cli Skill\n\nPath: `packages/cli/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/cli/tsconfig.json)\n\n<!-- File: packages/common-utils/CHANGELOG.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Common-utils Skill\n\nPath: `packages/common-utils/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/CHANGELOG.md)\n\n<!-- File: packages/common-utils/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Common-utils Skill\n\nPath: `packages/common-utils/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/hyperdxio/hyperdx/HEAD/packages/common-utils/package.json)\n\n<!-- ... +16 more modular skills available via /api/skills/hyperdxio/hyperdx?path={path} -->\n</yakaai_skills>"}