Skip to main content
Pairs with: AI Gateway → CLI Integrations. The langwatch CLI is shared between Gateway and Governance, login and logout are gateway-side, ingest and governance status subcommands are governance-side, both behind the same device-flow OAuth.
A small set of read-only commands for SREs, governance admins, and on-call engineers to answer “is data flowing?” without opening the web UI. They reuse the same backend the admin oversight dashboard and the per-source detail page already render, so what you see in the terminal and what you see in the browser are guaranteed identical (byte-for-byte on --json).

When to use

  • “Did my OTLP push actually land?”: langwatch ingest tail <sourceId> and watch events stream as you fire from the upstream platform.
  • “Why isn’t the source flipping to Active?”: langwatch ingest health <sourceId> shows 24h, 7d, 30d counts plus the timestamp of the last successful event.
  • “Has anyone in this org started using governance yet?”: langwatch governance status mirrors the OR-of-flags that drives the MainMenu Govern entry promotion in the web app.
  • “I need machine output for a runbook step, SIEM script”: every command accepts --json and is contract-stable against the equivalent tRPC procedure.
These commands are not for end-user developers, they don’t proxy completions, debit budgets, or mutate state. For coding-CLI integration, see Coding CLI Integrations.

Prerequisites

The same ~/.langwatch/config.json the rest of the governance CLI uses persists the Bearer access token. Token TTL is 1h with a long-lived refresh token; the CLI rotates transparently. langwatch logout server-revokes both. The ingest and governance subcommands are always registered — langwatch --help lists them once the CLI is installed. Per-account governance entitlement is enforced server-side.

langwatch governance status

The org-level setup-state OR-of-flags. Mirrors api.governance.setupState exactly, same boolean shape that promotes the MainMenu Govern entry from hidden → visible once any 3 of 5 are true.
A is a flag the org already qualifies for; a · is one it does not. The bottom line (Governance active: yes/no) is the OR of the five, yes if any of them are on, no otherwise. --json for machine output (exact contract match with the tRPC procedure):
Pipe to jq for runbook predicates: langwatch governance status --json | jq -r '.setup.governanceActive'.

langwatch ingest list

The org’s IngestionSources, active by default. Pass --all to include archived rows.
Status colouring:
  • active (green), events received in the last 30d.
  • awaiting_first_event (yellow), secret minted, source created, no events yet.
  • archived (grey), soft-deleted, hidden by default.
--json returns the full row shape used by api.ingestionSources.list:
The id is the same one you pass to ingest health and ingest tail.

langwatch ingest health <sourceId>

A one-shot snapshot: events received in the last 24h, 7d, 30d, plus the timestamp of the most recent successful event. Wraps api.activityMonitor.sourceHealthMetrics, the same query the per-source detail page’s metric strip uses.
--json:
Useful for a Datadog, Grafana check: pipe events24h through jq and alert when it drops to zero on a source you expect traffic from.

langwatch ingest tail <sourceId>

Stream the most recent OCSF-normalised events for a source. Wraps api.activityMonitor.eventsForSource, the same query the per-source detail page renders, so the CLI tail and the web event list show identical data.
Format per row: <eventTimestamp> <eventType> <action> → <target> $cost <input>/<output> tok. cost and tokens render only when present (gated on the cost-enrichment + token-count attributes the OTel normaliser picks up, gen_ai.usage.cost_usd, gen_ai.usage.input_tokens, gen_ai.usage.output_tokens).

--follow

Polls every 3s for new events newest-first, deduplicating by eventId so re-replays don’t double-print:
Ctrl-C exits cleanly. The follow loop is robust to transient errors, control-plane 5xx prints a yellow warn and retries on the next tick rather than killing the stream.

--json

Each event prints as a single JSON line (NDJSON) so you can pipe to jq or save to a file:
The shape is the canonical ActivityEventDetailRow, same fields the per-source detail page consumes. Field names are kebab-friendly (eventTimestampIso, tokensInput, tokensOutput, costUsd).

Empty state

If a source exists but no events have landed yet (status awaiting_first_event), tail prints a hint pointing at the upstream-platform setup rather than an empty list:

Error paths

These commands respect the same auth contract every other governance REST adapter uses; the CLI surfaces the underlying tRPC errors with human-readable wording:
The 401-on-expired-session path also clears the cached token, so the next invocation lands on the “not logged in” branch and the user sees a clear next step. All three error paths are asserted in specs/ai-gateway/governance/cli-ingest-debug.feature (12 scenarios).

Error catalog

The langwatch login flow itself can fail before the device-flow handshake completes if the org isn’t configured for CLI sign-in. Each entry below names the error code returned by /api/auth/cli/personal-virtual-keys/approve, the human-readable hint shown to the developer, and the admin remediation.

409 no_default_routing_policy

Returned when the org has no default routing policy published. The CLI cannot bind the new Personal Virtual Key to a policy without a default, so it refuses to create the VK rather than creating an orphan.
Admin remediation:
  1. Sign in to the LangWatch web app as an org admin.
  2. Navigate to Settings → Routing Policies (/settings/routing-policies).
  3. Create at least one routing policy and toggle it to Default.
  4. Ask the developer to re-run langwatch login --device.
The CLI does not fall back to a non-default policy; selection is explicit. See the admin prerequisites callout in the AI Governance overview for the rest of the org-bootstrap checklist. The 409 contract is asserted in specs/ai-gateway/governance/personal-keys.feature (sign-in scenarios).

CLI wrapper e2e coverage

The five wrapped tools (langwatch claude, langwatch codex, langwatch cursor, langwatch gemini, langwatch opencode) are exercised by a Node-only end-to-end suite at typescript-sdk/__tests__/e2e/cli/governance-wrapper.e2e.test.ts, fake control-plane Express + fake gateway Express + mocked tool binaries on PATH. No Docker, no live LLM, ~3-second total runtime; runs on every PR. Per-tool assertions: The behavioral pins live in specs/ai-gateway/wrapper-e2e/{claude,codex,cursor,gemini,opencode}.feature; the concrete test-shape pin is specs/ai-governance/cli-wrappers/wrap-login-routing.feature.

How it fits

Three surfaces, one backend: The REST endpoints reuse the existing validateAccessToken() Bearer helper that’s been in production since the device-flow CLI shipped, so opening this surface doesn’t introduce a new auth path. Per-account governance entitlement is enforced at the endpoint layer. For the bigger picture, five-tier integration ladder, persona-based routing, the daily-use vs admin-authoring split, see the control plane overview.