{"owner":"hyperdxio","repo":"hyperdx","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"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 only when\n  actively coding)\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\n4. **Component size**: Keep files under 300 lines; break down large components\n5. **UI Components**: Use custom Button/ActionIcon variants (`primary`,\n   `secondary`, `danger`) - see `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).\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. **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\n6. **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## 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"},"files":{"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 only when\n  actively coding)\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\n4. **Component size**: Keep files under 300 lines; break down large components\n5. **UI Components**: Use custom Button/ActionIcon variants (`primary`,\n   `secondary`, `danger`) - see `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).\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. **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\n6. **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## 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"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","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 only when\n  actively coding)\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\n4. **Component size**: Keep files under 300 lines; break down large components\n5. **UI Components**: Use custom Button/ActionIcon variants (`primary`,\n   `secondary`, `danger`) - see `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).\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. **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\n6. **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## 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","category":"root","tokens":4345}]}