Skip to main content
The Moda CLI (@moda-ai/cli, installed as moda) queries your production conversation data from the terminal, manages prompt versions, and syncs your harness. This page covers installation, authentication, profiles, output formats, and exit codes. The full command list is in the CLI reference, and agent/CI integration patterns are in Using the CLI from agents and CI.

Install

Requires Node.js 18 or later.

Authentication

The CLI uses two credentials for two different groups of commands: API keys (called ingestion keys in the dashboard) are tenant-bound: a key always operates on the tenant it was created for, and MODA_TENANT_ID cannot re-point it.

Log in (browser flow)

The command opens your browser to moda.dev, where you sign in; the CLI completes a PKCE exchange against a localhost callback (ports 8432–8435, first free port). If the browser cannot reach the CLI — for example when you run the CLI over SSH — paste the callback URL or the one-time code shown in the browser back into the terminal. The resulting CLI session lasts 30 days on a sliding window and renews in the background. Related commands:
  • moda auth status — reports session state; exits 4 when logged out. --online also probes the API.
  • moda auth whoami — shows the authenticated user and available tenants.
  • moda auth token — prints the raw session token (for scripting control-plane calls).
  • moda auth logout — revokes the session server-side and clears local credentials, including the stored API key.
The session token authenticates control-plane commands only. Data commands require a moda_sk_ API key: set MODA_API_KEY, or mint one with moda init or moda provision. moda auth token output is not valid for the Data API.

API key resolution order

Data commands resolve the API key in this order:
  1. MODA_API_KEY environment variable
  2. The active profile’s stored key
  3. ~/.moda/config.json (api_key)

Headless provisioning: moda provision

moda provision mints (or reuses) a tenant API key without any interactive prompts and prints exactly one JSON document to stdout — nothing else. It is built for CI bootstrap scripts and agents:
Output
The field names are a stable contract. reused is true when an existing stored key passed a liveness check and no new key was created. Behavior to script around:
  • Provision requires an existing CLI session (moda auth login run previously on that machine) and never opens a browser. Without a session it fails with exit code 4 and instructions to log in first.
  • With access to multiple tenants, --tenant-id (or the MODA_TENANT_ID env var; the flag wins) is required. Without it, provision fails with exit code 5 and a machine-readable input_request that lists every tenant with its resume flags — it never prompts, even on an interactive terminal.
  • --label=TEXT names the key (default: machine hostname). --save also persists the key and tenant to ~/.moda/config.json; by default provision only prints, so headless callers own storage.
Provision’s stdout contains a live API key. Capture it into a secret store or variable; do not pipe it to logs.

Profiles and configuration

CLI state lives in ~/.moda/: config.json (API key, tenant ID, ingest URL), profiles.json, and per-profile secrets under ~/.moda/secrets/. Three profiles exist by default: prod (https://moda.dev, the default), staging, and local.
Select a profile per invocation with --profile=NAME or the MODA_PROFILE env var. Two env vars override URLs directly:
  • MODA_BASE_URL — the moda.dev host used for the Data API and control-plane calls.
  • MODA_INGEST_URL — the Ingestion API host (used by skills commands and remote harness analysis).

Output formats

The CLI picks an output mode automatically, in this priority order:
  1. Explicit flags: --human (or --prose), --json, --agent, --agent --stream
  2. MODA_FORMAT env var: human | json | agent | agent-stream | ndjson
  3. Agent environment detection: a truthy CLAUDECODE, CURSOR, CI, or MODA_AGENT env var selects agent
  4. TTY detection: piped or redirected stdout selects agent; an interactive terminal selects human
The modes: This means a piped or CI invocation gets machine-parseable output with zero flags. Three commands bypass envelopes in every mode because their stdout is meant to be captured directly: moda provision (one JSON credentials document), moda auth token (the bare token), and moda tail (NDJSON — one JSON line per event, since a live tail is a stream rather than a single response).

The moda.agent.v1 envelope

In agent mode every command emits a single JSON envelope:
status is ok, degraded, or error; the command’s payload is always under data. The full field reference, the streaming event schema, and exit-code recipes are on Using the CLI from agents and CI. moda manifest --json and moda --json-schemas describe the protocol machine-readably.

Exit codes

Update check and telemetry

Both are on by default and both can be turned off:
  • Update check. At most once a day the CLI checks the npm registry for a newer @moda-ai/cli version and prints a notice to stderr. Disable with --no-update-check or MODA_CLI_UPDATE_CHECK=0. The check is automatically skipped in CI and when DO_NOT_TRACK=1 is set.
  • Usage telemetry. The CLI reports command name, flag names (never values or arguments), exit status, and duration. Disable with --no-telemetry, MODA_CLI_TELEMETRY=0, or DO_NOT_TRACK=1.
  • Feedback tip. Successful commands print a one-line moda feedback tip (stderr on a TTY, meta.tip in envelopes). Hide the stderr line with MODA_CLI_TIPS=0.

Environment variables

Next steps