Skip to content

[HDX-3919] Add @hyperdx/cli package — terminal TUI, source map upload, and agent-friendly commands#2043

Merged
kodiakhq[bot] merged 50 commits intomainfrom
hyperdx-tui
Apr 9, 2026
Merged

[HDX-3919] Add @hyperdx/cli package — terminal TUI, source map upload, and agent-friendly commands#2043
kodiakhq[bot] merged 50 commits intomainfrom
hyperdx-tui

Conversation

@wrn14897
Copy link
Copy Markdown
Member

@wrn14897 wrn14897 commented Apr 2, 2026

Summary

Adds packages/cli (@hyperdx/cli) — a unified CLI for HyperDX that provides an interactive TUI for searching/tailing logs and traces, source map upload (migrated from hyperdx-js), and agent-friendly commands for programmatic access.

Ref: HDX-3919
Ref: HDX-3920
Ref: HDX-3927

CLI Commands

hdx tui -s <url>                    # Interactive TUI (main command)
hdx sources -s <url>                # List sources with ClickHouse schemas
hdx sources -s <url> --json         # JSON output for agents / scripts
hdx dashboards -s <url>             # List dashboards with tile summaries
hdx dashboards -s <url> --json      # JSON output for agents / scripts
hdx query --source "Logs" --sql "SELECT count() FROM default.otel_logs"
hdx upload-sourcemaps -k <key>      # Upload source maps (ported from hyperdx-js)
hdx auth login -s <url>             # Sign in (interactive or -e/-p flags)
hdx auth status                     # Show auth status
hdx auth logout                     # Clear saved session

Key Features

Interactive TUI (hdx tui)

  • Table view with dynamic columns derived from query results (percentage-based widths)
  • Follow mode (live tail) enabled by default, auto-pauses when detail panel is open
  • Vim-like keybindings: j/k navigation, G/g jump, Ctrl+D/U half-page scroll
  • / for Lucene search, s to edit SELECT clause in $EDITOR, t to edit time range
  • Tab to cycle between sources and saved searches
  • w to toggle line wrap

Detail Panel (3 tabs, full-screen with Ctrl+D/U scrolling)

  • Overview — Structured view: Top Level Attributes, Log/Span Attributes, Resource Attributes
  • Column Values — Full SELECT * row data with __hdx_* aliased columns
  • Trace — Waterfall chart (port of DBTraceWaterfallChart DAG builder) with correlated log events, j/k span navigation, inverse highlight, Event Details section

Agent-friendly commands

  • hdx sources --json — Full source metadata with ClickHouse CREATE TABLE DDL, expression mappings, and correlated source IDs. Detailed --help describes the JSON schema for LLM consumption. Schema queries run in parallel.
  • hdx dashboards --json — Dashboard metadata with simplified tile summaries (name, type, source, sql). Resolves source names for human-readable output.
  • hdx query --source <name> --sql <query> — Raw SQL execution against any source's ClickHouse connection. Supports --format for ClickHouse output formats (JSON, JSONEachRow, CSV, etc.).

Source map upload (hdx upload-sourcemaps)

  • Ported from hyperdx-js/packages/cli to consolidate on a single @hyperdx/cli package
  • Authenticates via service account API key (-k / HYPERDX_SERVICE_KEY env var)
  • Globs .js and .js.map files, handles Next.js route groups
  • Uploads to presigned URLs in parallel with retry (3 attempts) and progress
  • Modernized: native fetch (Node 22+), ESM-compatible, proper TypeScript types

Architecture

packages/cli/
├── src/
│   ├── cli.tsx              # Commander CLI: tui, sources, dashboards, query,
│   │                        #   upload-sourcemaps, auth
│   ├── App.tsx              # Ink app shell (login → source picker → EventViewer)
│   ├── sourcemaps.ts        # Source map upload logic (ported from hyperdx-js)
│   ├── api/
│   │   ├── client.ts        # ApiClient + ProxyClickhouseClient
│   │   └── eventQuery.ts    # Query builders (renderChartConfig, raw SQL)
│   ├── components/
│   │   ├── EventViewer/     # Main TUI (9 files)
│   │   │   ├── EventViewer.tsx    # Orchestrator (state, hooks, render shell)
│   │   │   ├── types.ts           # Shared types & constants
│   │   │   ├── utils.ts           # Row formatting functions
│   │   │   ├── SubComponents.tsx  # Header, TabBar, SearchBar, Footer, HelpScreen, TableHeader
│   │   │   ├── TableView.tsx      # Table rows rendering
│   │   │   ├── DetailPanel.tsx    # Detail panel (overview/columns/trace tabs)
│   │   │   ├── useEventData.ts    # Data fetching hook
│   │   │   └── useKeybindings.ts  # Input handler hook
│   │   ├── TraceWaterfall/  # Trace chart (6 files)
│   │   │   ├── TraceWaterfall.tsx  # Orchestrator + render
│   │   │   ├── types.ts           # SpanRow, SpanNode, props
│   │   │   ├── utils.ts           # Duration/status/bar helpers
│   │   │   ├── buildTree.ts       # DAG builder (port of DBTraceWaterfallChart)
│   │   │   └── useTraceData.ts    # Data fetching hook
│   │   ├── RowOverview.tsx
│   │   ├── ColumnValues.tsx
│   │   ├── LoginForm.tsx
│   │   └── SourcePicker.tsx
│   ├── shared/              # Ported from packages/app (@source annotated)
│   └── utils/               # Config, editor, log silencing
├── AGENTS.md
├── CONTRIBUTING.md
└── README.md

Tech Stack

  • Ink v6.8.0 (React 19 for terminals) + Commander.js
  • @clickhouse/client via ProxyClickhouseClient (routes through /clickhouse-proxy)
  • @hyperdx/common-utils for query generation (renderChartConfig, chSqlToAliasMap)
  • glob v13 for source map file discovery
  • tsup for bundling (all deps bundled via noExternal: [/.*/], zero runtime deps)
  • Bun 1.3.11 for standalone binary compilation
  • Session stored at ~/.config/hyperdx/cli/session.json

CI/CD (release.yml)

  • CLI binaries compiled for macOS ARM64, macOS x64, and Linux x64
  • GitHub Release created with download instructions
  • Version-change gate: skips release if cli-v{version} tag already exists
  • softprops/action-gh-release pinned to full SHA (v2.6.1) for supply chain safety
  • Bun pinned to 1.3.11 for reproducible builds
  • npm publishing handled by changesets

Keybindings

Key Action
j/k Navigate rows (or spans in Trace tab)
l/Enter Expand row detail
h/Esc Close detail / blur search
G/g Jump to newest/oldest
Ctrl+D/U Scroll half-page (table, detail panels, Event Details)
/ Search (global or detail filter)
Tab Cycle sources/searches or detail tabs
s Edit SELECT clause in $EDITOR
t Edit time range in $EDITOR
f Toggle follow mode (live tail)
w Toggle line wrap
? Help screen

Demo

Main Search View

image

Event Details Overview

image

Trace Waterfall

image

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview, Comment Apr 9, 2026 8:15pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 2, 2026

🦋 Changeset detected

Latest commit: 6cebd1e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@hyperdx/cli Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

E2E Test Results

All tests passed • 130 passed • 3 skipped • 1085s

Status Count
✅ Passed 130
❌ Failed 0
⚠️ Flaky 3
⏭️ Skipped 3

Tests ran across 4 shards in parallel.

View full report →

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

PR Review

  • ⚠️ oven-sh/setup-bun@v2 uses a mutable floating tag in the release workflow → Pin to a commit SHA like oven-sh/setup-bun@4723c6f (note: softprops/action-gh-release correctly uses a pinned SHA already). This job publishes binaries to end users, making supply chain integrity important.

  • ⚠️ Shell injection / broken editor paths in editor.tsexecSync(\${editor} ${tmpFile}`, ...)uses a string form (goes through/bin/sh -c), so editor paths with spaces (e.g., Sublime Text, VS Code) will silently break or execute incorrectly. Use execFileSyncwith an array:execFileSync(editor, [tmpFile], { stdio: 'inherit' }). Affects both openEditorForSelectandopenEditorForTimeRange(lines 161, 190 ineditor.ts`).

  • ⚠️ -p, --password <password> CLI flag exposes credentials in shell history and ps aux output → At minimum, document the risk or prefer reading from stdin when the flag is omitted (interactive prompt via ink is already supported in the TUI path; the non-interactive path should follow suit).

✅ Session file permissions (0o600), config dir permissions (0o700), no hardcoded credentials, and proxy-based ClickHouse auth look good.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

🔴 Tier 4 — Critical

Touches auth, data models, config, tasks, OTel pipeline, ClickHouse, or CI/CD.

Why this tier:

  • Critical-path files (1):
    • .github/workflows/release.yml

Additional context: large diff (6771 lines)

Review process: Deep review from a domain expert. Synchronous walkthrough may be required.
SLA: Schedule synchronous review within 2 business days.

Stats
  • Files changed: 41
  • Lines changed: 6771
  • Branch: hyperdx-tui
  • Author: wrn14897

To override this classification, remove the review/tier-4 label and apply a different review/tier-* label. Manual overrides are preserved on subsequent pushes.

wrn14897 added 23 commits April 9, 2026 13:12
- Port upload-sourcemaps from hyperdx-js/packages/cli with modernizations:
  native fetch (Node 22+), ESM-compatible version string, proper types
- Add query command for raw SQL execution against a source's ClickHouse
  connection, with --format support and LLM-friendly --help
- Remove stream command (superseded by query + tui)
- Add glob@^13.0.6 dependency for source map file discovery

Ref: HDX-3920
- Add dashboards command listing all dashboards with tile summaries,
  supports --json with simplified tile metadata for agent consumption
- Add query command for raw SQL execution against a source's ClickHouse
  connection, with --format support and LLM-friendly --help
- Remove stream command (superseded by query + tui)
- Remove dead code: formatEventRow, formatTraceRow, getSeverityColor,
  getSpanEventBody (replaced by formatDynamicRow)
- Remove unused re-export of ROW_DATA_ALIASES from eventQuery.ts
- Un-export internal-only symbols: INTERNAL_ROW_FIELDS,
  processRowToWhereClause, buildAliasWith, _origDebug, _origWarn
- Un-export internal-only interfaces: ApiClientOptions, MeResponse,
  ConnectionResponse, DashboardTileConfig, DashboardTile,
  DashboardFilter, DashboardResponse
…mands

- Add release-cli job: builds npm package + standalone binaries, publishes
  to npm as @hyperdx/cli, creates GitHub Release with all 3 binaries
- Remove private:true from package.json to enable npm publish
- Remove Homebrew formula and related workflow steps
- Update README with all current commands: tui, query, sources, dashboards,
  upload-sourcemaps, auth (login/logout/status)
- Add upload-sourcemaps docs with v2 API version note
- Add npm + npx + standalone binary installation instructions
…arate

- npm publish now handled by changesets in check_changesets job
  (same flow as other packages in the monorepo)
- Add publishConfig.access: public to CLI package.json
- Add prepublishOnly: yarn build to ensure tsup bundles before publish
- Remove manual npm publish step from release-cli job
- release-cli job now only compiles standalone binaries + GitHub Release
- Remove skipNodeModulesBundle, add noExternal: [/.*/] to bundle
  all dependencies (ink, react, commander, @hyperdx/common-utils, etc.)
- Keep Node.js built-ins external via module.builtinModules
- Add createRequire banner shim so CJS deps (signal-exit, etc.) can
  use require() for Node built-ins inside the ESM bundle
- dist/cli.js is now ~8MB self-contained, no node_modules needed
- Bun binary compilation (yarn compile:*) unaffected
- Fix absolute path handling: use path.resolve() instead of
  path.join(cwd(), path) which double-joined absolute paths
- Fix URL construction: use URL constructor instead of path.join()
  which stripped protocol slashes from URLs
- Read PKG_VERSION from package.json instead of hardcoding
Remove query, sources, and dashboards docs from public README.
Clarify that -s flag takes the HyperDX API URL. Add Ctrl+D/U
and other missing keybindings to the table.
Check response.ok before parsing JSON to avoid SyntaxError on
'Forbidden' or other non-JSON error responses. Show clear error
message: 'Authentication failed (403). Check your --serviceKey
and --apiUrl.'
console.error/log/info are silenced by silenceLogs.ts for TUI mode,
which hid all error messages from upload-sourcemaps. Use direct
process.stdout/stderr.write so errors are always visible.
Also include the response body in the 'Unable to generate upload URLs'
error for debugging.
- Retry failed uploads up to 3 times with 1s/3s exponential backoff
- Only retry on network errors and 5xx; no retry on 4xx (permanent)
- Show [1/177] progress prefix on every upload message
- Print summary at end: X succeeded, Y failed out of Z files
- Individual failures don't crash the batch (all files get attempted)
- Pin softprops/action-gh-release@v2 to full commit SHA (v2.2.1)
  to mitigate supply chain risk with GITHUB_TOKEN write access
- Pin bun-version to 1.3.11 in CI workflow for reproducible builds
- Add bun engine constraint to packages/cli/package.json
Add a check step that queries gh release view before compiling
binaries. If cli-v{version} already exists, the compile and
release steps are skipped — prevents failures on repeated Docker
releases that don't bump the CLI version.
tsup bundles everything (noExternal: [/.*/]) into a single dist/cli.js,
so runtime dependencies are not needed at install time. This reduces
the npm install footprint for consumers.
Copy link
Copy Markdown
Member

@brandon-pereira brandon-pereira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wrn14897 wrn14897 changed the title [HDX-TUI] Add @hyperdx/cli package — terminal TUI for searching and tailing events [HDX-3919] Add @hyperdx/cli package — terminal TUI, source map upload, and agent-friendly commands Apr 9, 2026
@kodiakhq kodiakhq bot merged commit d995b78 into main Apr 9, 2026
18 checks passed
@kodiakhq kodiakhq bot deleted the hyperdx-tui branch April 9, 2026 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automerge review/tier-4 Critical — deep review + domain expert sign-off

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants