@moda-ai/cli
v1.1.1
Published
CLI for Moda - AI agent analytics and observability
Maintainers
Readme
moda-cli
CLI for Moda -- AI agent analytics and observability.
Query your conversation analytics from the terminal.
Install
npm install -g @moda-ai/cliOr use without installing:
npx -p @moda-ai/cli moda overviewSetup
Run the wizard to authenticate, pick an org, and provision an API key:
moda initOr set the key manually:
export MODA_API_KEY="moda_sk_..."Get your API key from moda.dev/settings.
Usage
moda overview # Dashboard overview
moda overview --days-back=30 # Last 30 days
moda clusters # Browse topic clusters
moda clusters --parent-id=node-abc # Drill into a category
moda cluster-conversations <node_id> # Conversations in a cluster
moda conversations --search="error" # Search conversations
moda conversations --time-range=24h # Filter by time
moda conversations --environment=production # Filter by environment
moda context <conversation_id> # Get conversation context
moda context <conversation_id> --msg-index=5 # Center on message 5
moda frustrations # User frustration detections
moda frustrations --days-back=14 --limit=20
moda frustrations --include-window --window=1 # Attach 3-message slice per row
moda tool-failures # Tool failure overview
moda tool-failure-detail <tool_name> # Per-tool failure detail
moda tool-failure-detail <tool_name> --include-window --window=1
# Agent runs runtime (workflows = recurring class, run = one execution)
moda workflows --time-range=7d # Recurring workflow catalog with health
moda runs # Last 7d of workflow executions
moda runs --time-range=24h --outcome=partial # Last 24h, partial completions only
moda runs --class-id=cron:helpscout-triage-hourly # Scoped to one workflow class
moda run <run_id> # One execution + its side-effect receipts
moda loops # Currently-active loop detections
moda loop <detection_id> # One loop detail (signature + blast radius)All commands output JSON. Pipe to jq for filtering:
moda overview | jq '.frustrations'
moda frustrations | jq '.frustrations[].primary_cause'
moda runs --outcome=partial | jq '.runs[] | {job_id, intent_summary, outcome_reason}'
moda loops | jq '.loops | sort_by(-.cycle_visits) | .[0:5] | .[].loop_signature_human'
moda workflows | jq '.workflows | sort_by(.health) | .[] | select(.health < 0.8)'Anchors and message windows
Rows returned by moda frustrations and moda tool-failure-detail carry
a top-level anchor block naming the exact turn the event fired on:
// frustrations
{ "kind": "frustration", "conversation_id": "...", "msg_index": 12,
"signal": "exasperation", "quote_preview": "...", "all_turns": [...],
"no_anchor": false }
// tool-failure-detail examples
{ "kind": "tool_failure", "conversation_id": "...", "msg_index": 7,
"tool_name": "search", "tool_use_id": "...",
"error_subtype": "SEARCH_NO_RESULTS", "no_anchor": false }msg_index is the 0-indexed turn where the breakage happened. For
frustrations it's derived from key_turns[0] (the same turn the API centers
the embedded window on), falling back to user_quotes[0].turn when
key_turns is empty. no_anchor: true means no anchor could be derived for
that row.
Both commands accept two flags to inline a message window per row:
| Flag | Default | Description |
|------|---------|-------------|
| --include-window | off | Attach a window field with the message slice centered on the anchor |
| --window=N | 1 | Half-width (1–5). --window=1 ⇒ 3 messages total (anchor ± 1) |
Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| MODA_API_KEY | Yes | -- | Your Moda API key (moda_sk_...) |
| MODA_BASE_URL | No | https://moda.dev | Base URL for the Data API |
Documentation
License
MIT
