CLI

otell is a single binary for ingest + query.

Global flags:

Commands

otell run

Example:

otell run

Example output:

INFO otell starting
INFO ingest gRPC listening on 127.0.0.1:4317
INFO ingest HTTP listening on 127.0.0.1:4318
INFO query UDS listening on /tmp/otell.sock
INFO query TCP listening on 127.0.0.1:1777
INFO query HTTP listening on 127.0.0.1:1778

otell search <pattern>

Example:

otell search "timeout" --since 15m --stats

Example output:

2026-02-12T20:22:45.102Z api ERROR trace=4bf92f3577b34da6a3ce929d0e0e4736 span=00f067aa0ba902b7 | context deadline exceeded peer=redis:6379
-- 1 matches (1 returned) --
stats.by_service=[("api", 1)]
stats.by_severity=[("ERROR", 1)]
handle=eyJTZWFyY2giOnsicGF0dGVybiI6InRpbWVvdXQiLC4uLn19

otell traces

Example:

otell traces --since 15m --limit 2

Example output:

trace=4bf92f3577b34da6a3ce929d0e0e4736 duration=1800ms spans=3 status=ERROR root="GET /v1/orders"
trace=5af7183f9cbe40f598b7ebf9f9830cbf duration=230ms spans=2 status=OK root="GET /healthz"
-- 2 traces --
handle=eyJUcmFjZXMiOnsibGltaXQiOjIsLi4ufX0=

otell trace <trace_id>

Example:

otell trace 4bf92f3577b34da6a3ce929d0e0e4736

Example output:

TRACE 4bf92f3577b34da6a3ce929d0e0e4736 duration=1800ms spans=3 errors=1
api GET /v1/orders (1800ms) ERROR
  api cache.get redis (700ms) ERROR
logs=bounded limit=50 truncated=false
2026-02-12T20:22:45.102Z api ERROR | context deadline exceeded
handle=eyJUcmFjZSI6eyJ0cmFjZV9pZCI6IjRiZjkyLi4uIn19

otell span <trace_id> <span_id>

Example:

otell span 4bf92f3577b34da6a3ce929d0e0e4736 00f067aa0ba902b7

Example output:

SPAN 00f067aa0ba902b7 service=api name=cache.get redis status=ERROR duration=700ms
attrs={"peer":"redis:6379"}
events=[]
logs=bounded limit=30 truncated=false
2026-02-12T20:22:45.102Z ERROR | context deadline exceeded
handle=eyJTcGFuIjp7InRyYWNlX2lkIjoiNGJmOTIuLi4ifX0=

otell metrics [<name>|list]

Examples:

otell metrics list --since 15m
name=http.server.duration count=42
name=process.runtime.nodejs.eventloop.utilization count=9
-- 2 metric names --
handle=eyJNZXRyaWNzTGlzdCI6eyJsaW1pdCI6NTAsLi4ufX0=
otell metrics http.server.duration --group-by service --agg p95
points=42
group=api value=182.4
-- 1 series (42 points) --
handle=eyJNZXRyaWNzIjp7Im5hbWUiOiJodHRwLnNlcnZlci5kdXJhdGlvbiIsLi4ufX0=

otell status

Example:

otell status

Example output:

db_path=/Users/me/.local/share/otell/otell.duckdb
db_size_bytes=786432
logs=312 spans=122 metrics=88
oldest=2026-02-12T19:31:02.481Z
newest=2026-02-12T20:22:45.102Z
handle=eyJTdGF0dXMiOm51bGx9

otell handle <base64>

Example:

otell handle eyJTdGF0dXMiOm51bGx9

Example output:

db_path=/Users/me/.local/share/otell/otell.duckdb
db_size_bytes=786432
logs=312 spans=122 metrics=88
oldest=2026-02-12T19:31:02.481Z
newest=2026-02-12T20:22:45.102Z
handle=eyJTdGF0dXMiOm51bGx9

otell intro

Example:

otell intro

Example output:

INTRO mode=llm connected=true
probe=status
db_path=/Users/me/.local/share/otell/otell.duckdb
db_size_bytes=786432
logs=312 spans=122 metrics=88
probe=metrics_list
name=http.server.duration count=42
-- 1 metric names --
probe=search_count_stats pattern=error|timeout
-- 7 matches (0 returned) --
stats.by_service=[("api", 7)]
next=otell traces --since 15m --limit 20
next=otell trace <trace_id>
next=otell span <trace_id> <span_id>
next=otell handle <base64>

otell mcp

Example:

printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}\n' | otell mcp

Example output:

{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"0.1.0","serverInfo":{"name":"otell","version":"0.1.0"},"capabilities":{"tools":{"listChanged":false}}}}

Typical flow

# Run the server
otell run

# Onboarding for LLMs
otell intro

# Query the server
otell search "error|timeout" --since 15m --stats
otell traces --since 15m --limit 20
otell trace <trace_id>
otell span <trace_id> <span_id>