hyperdx/.changeset/cli-app-url-migration.md
Warren Lee 4dea3621a7
[HDX-3976] CLI: migrate from apiUrl to appUrl with interactive login flow (#2101)
## Summary

Migrates the CLI from using API URLs (`-s, --server`) to app URLs (`-a, --app-url`), and adds interactive login prompts on expired/missing sessions.

Linear: https://linear.app/clickhouse/issue/HDX-3976

---

## Breaking Change

**The `-s` / `--server` flag has been removed.** All commands (except `upload-sourcemaps`) now use `-a` / `--app-url` instead.

The URL semantics have changed: users should now provide the **HyperDX app URL** (e.g. `http://localhost:8080`), not the API URL. The CLI derives the API URL internally by appending `/api`.

| Before | After |
|---|---|
| `hdx auth login -s http://localhost:8080/api` | `hdx auth login -a http://localhost:8080` |
| `hdx tui -s http://localhost:8080/api` | `hdx tui -a http://localhost:8080` |
| `hdx sources -s http://localhost:8080/api` | `hdx sources -a http://localhost:8080` |

> **Note:** `upload-sourcemaps` is unchanged — it still uses `--apiUrl` / `-u` as before.

**Existing saved sessions are auto-migrated** — old `session.json` files with `apiUrl` are converted to `appUrl` on first load.

---

## Changes

### `apiUrl` → `appUrl` migration
- `ApiClient` now accepts `appUrl` and derives `apiUrl` by appending `/api`
- `SessionConfig` stores `appUrl`; legacy sessions with `apiUrl` auto-migrate on load
- All commands use `-a, --app-url` instead of `-s, --server`

### Interactive login flow (HDX-3976)
- `hdx auth login` no longer requires `-a` — it prompts interactively for login method, app URL, then credentials
- Login method selector is extensible (currently Email/Password, designed for future OAuth support)
- **Expired sessions now prompt for re-login** instead of printing an error and exiting
- The app URL field is autofilled with the last used value so users can just hit Enter
- No longer requires manual deletion of `~/.config/hyperdx/cli/session.json` to recover from expired sessions
- Non-TUI commands (`sources`, `dashboards`, `query`) also launch interactive login on expired/missing sessions via `ensureSession()` helper

### TUI (`App.tsx`)
- Detects expired session on mount and shows "Session expired" message with editable URL field
- If the user changes the URL during re-login, the client is recreated
- 401/403 errors during data loading bounce back to the login screen instead of showing raw error messages

### Input validation & error handling
- App URL inputs are validated — rejects non-`http://` or `https://` URLs with a clear inline error
- `ApiClient.login()` catches network/URL errors and returns `false` instead of crashing
- `ApiClient.login()` verifies the session after a 302/200 response by calling `checkSession()` — prevents false "Logged in" messages from servers that return 302 without a valid session (e.g. SSO redirects)
- Login failure messages now mention both credentials and server URL

---

## Files changed

- `packages/cli/src/api/client.ts` — accepts `appUrl`, derives `apiUrl`, exposes `getAppUrl()`, login validation
- `packages/cli/src/utils/config.ts` — `SessionConfig.appUrl`, backward-compat migration
- `packages/cli/src/cli.tsx` — `-a` flag, `LoginPrompt`, `ReLoginPrompt`, `ensureSession()`, URL validation
- `packages/cli/src/App.tsx` — expired session detection, editable URL on re-login, 401/403 handling
- `packages/cli/src/components/LoginForm.tsx` — app URL prompt field, `message` prop, URL validation
2026-04-10 22:45:48 +00:00

618 B

@hyperdx/cli
minor

Breaking: Replace -s/--server flag with -a/--app-url across all CLI commands (except upload-sourcemaps). Users should now provide the HyperDX app URL instead of the API URL — the CLI derives the API URL by appending /api.

  • hdx auth login now prompts interactively for login method, app URL, and credentials (no flags required)
  • Expired/missing sessions prompt for re-login with the last URL autofilled instead of printing an error
  • Add URL input validation and post-login session verification
  • Existing saved sessions are auto-migrated from apiUrl to appUrl