Skip to main content
The comis trace command is your one-stop tool for going from a user complaint to a diagnostic bundle. Five subcommands cover every correlation pattern: search by messageId, search by traceId, live-tail a chat, scan failures by time, and export a bundle.
The comis CLI is not on PATH by default. All invocations on this page use the canonical form:
If you’ve aliased comis to that path, the shorter form works too.

Subcommands at a Glance

All subcommands support --json for machine-readable output.

--message-id <uuid>

Search for all trace events associated with a specific inbound message. Use this when a user can give you the messageId from their chat — it’s the fastest path from complaint to trace.
Returns the channel → queue → agent → delivery row sequence for that message. On a 100-turn session the result is available in under 2 seconds (LRU O(1) lookup, falling back to a bounded 2-day session-index scan on miss).

Default (human-readable) output

JSON mode

Returns:

--trace-id <uuid>

Search all log and trajectory events by traceId. Use this when you’ve found a traceId in a log line and want the full causal chain across the channel / queue / agent / delivery stages.
Returns every row sharing the traceId. The traceId is injected via AsyncLocalStorage for the entire request lifecycle, so all events from inbound parse through final delivery share the same value — including error events and retry attempts.

JSON mode

Same {"rows": [...]} structure as --message-id --json.

--chat <chatId> --tail

Stream trace events live for a specific chat. Use this when a user reports an issue while it’s happening — open a terminal, start --tail on their chat, and watch the next message in real time.
Polls the obs.trace.tail RPC approximately every second. Press Ctrl+C to exit cleanly (handled via AbortController; the connection closes gracefully).
--tail requires --chat. Running --tail without specifying a chat exits immediately with: --tail requires --chat <chatId>

Tail output (human-readable)

Three space-separated fields per line:

JSON tail mode (NDJSON)

Emits one JSON object per line (newline-delimited JSON). Suitable for piping into jq or another consumer:
Each line is a JSON object with the same shape as a rows[] entry.

--since <dur> --where <filter>

Scan the session index for recent failures. Use this when you need a quick overview of what went wrong in the last N minutes across all chats.
The --since argument accepts duration suffixes: 10m, 1h, 2d. The --where argument is a filter expression — error matches sessions that have a non-null lastError in the session index.

Common queries

JSON mode

Returns {"rows": [...]} with the same 4-field shape (ts, event, sessionId, traceId).

export <sessionId>

Export a self-contained diagnostic bundle for a session. Invokes the bundle pipeline, applies platform-aware-v1 redaction, and prints the bundle directory path.
Output:

JSON mode

Returns:
JSON mode is useful in scripts:
Full bundle export documentation — 8-file shape, hard limits, redaction policy, /export-trajectory slash command — is at Incident Bundle.

Output Format Reference

Human-readable — search modes (--message-id, --trace-id, --since/--where)

Four-column space-padded table. Column widths auto-fit content:
Fields: ts (ISO 8601), event (dot-notation event name), sessionId (first 8 chars of UUID), traceId (full UUID).

Human-readable — tail mode (--chat --tail)

Three space-separated fields per line:

Human-readable — export mode

Single line:

JSON — search modes

JSON — tail mode (NDJSON)

One JSON object per line. Each object has the same shape as a rows[] entry:
The tail RPC also returns a nextSinceMs cursor internally (used by the polling loop); it is not surfaced in the per-line JSON objects.

JSON — export mode


Worked Example — User Complaint to Bundle in 3 Commands

A user reports: “I asked the bot a question 10 minutes ago and it never replied.”
The target — under 5 minutes from complaint to bundle. Command 1 — Find sessions with recent errors:
Output: a list of distinct sessionIds with errors in the last 10 minutes. Pick the one that matches the user’s chat (you can cross-reference channelType in the session-index JSONL if needed). Command 2 — Verify the failure mode:
Output: channel / queue / agent / delivery rows for that exact message. Look for:
  • Missing delivery rows — execution completed but delivery failed
  • Retry events — message was retried (check for queue.retry events)
  • Dedup events — message was seen before (dedup.duplicate_inbound)
  • Execution absent — message enqueued but no execution.started (queue stall or gate rejection)
Command 3 — Export the bundle:
Output: Bundle written to: <path>. Compress, share with engineer per Incident Bundle. Three commands. Under 5 minutes from complaint to bundle.

Performance Bounds

The backend uses an LRU bounded at 1024 entries for messageId lookups, falling back to a 2-day session-index scan on miss. The LRU starts cold on daemon restart — if a restart just happened, --message-id may return empty rows for messages processed before the restart. Use --since <dur> --where error as a fallback in that case.

Incident Bundle

Bundle export workflow — 8-file shape, hard limits, redaction policy, and the /export-trajectory slash command.

Observability

Bridge mapping, lifecycle envelopes, INFO promotions, and the dedup detector.

Logging

Log levels, field dictionary, and log rotation policy.

Daemon

The process that serves the RPCs — startup, shutdown, and configuration.