Queries and Analytics
Four read tools, each answering a different question:
querylists a stream's events on the standard list contract: filters on time, type, tags and any field of the event'sdata, sorted by timestamp and paged by cursor.query --sort -timestamptails the newest events - no window needed.countbuckets event counts per interval across a window.aggregatereduces a numeric field to one value, optionally per group.
count and aggregate take a window with --start/--end, which accept
relative expressions (-1h, -7d, now) or epoch milliseconds and
default to -1h..now. Negative relative values need the = form
(--start=-1h); the space form is eaten by the flag parser.
Query
snug timeline query -s docs4-activity --filter 'timestamp[gte]=-1h' --filter 'type[prefix]=user.'
snug timeline query -s docs4-activity --filter 'data.user_id[eq]=u123'
snug timeline query -s docs4-activity --filter 'data.amount[gt]=50' --sort -timestamp
snug timeline query -s docs4-activity --filter 'tags[all]=region:us'
snug timeline query -s docs4-activity --filter 'data.error[exists]=false' --allThe list filters on:
timestampwithgt,gte,lt,lte: RFC 3339,now, or a time before now such as-30m,-6h,-7d. With no timestamp filter the whole stream is listed.typewitheq,ne,in,prefix(type[prefix]=user.matches everyuser.*type).tagswitheq,ne,in,all.data.<path>for any dot-separated path into the event payload, witheq,ne,in,gt,gte,lt,lte,containsandexists(trueorfalse). A value reads astrue/false, a number, or text; a whole number also matches the same digits stored as a string. An absent or null field matches onlyneandexists=false.
Events come oldest first; --sort -timestamp lists newest first. The
list pages by cursor only (page and total are refused): pass
page.next_cursor back with --cursor, or read every page with --all.
Filters other than the time window are checked as events are scanned,
and one request scans at most TIMELINE_MAX_QUERY_RESULTS events, so a
narrow filter can return a short page whose has_more is still true -
keep following the cursor. The JSON payload:
{
"events": [
{
"id": "evt_fKWcGTwVDgrs",
"stream": "docs4-activity",
"type": "user.login",
"timestamp": 1787893274528,
"sequence": 1,
"data": { "amount": 25, "user_id": "u123" },
"tags": ["region:us"]
}
],
"page": { "has_more": false }
}Count
count returns one bucket per interval (minute, hour, day,
week) across the whole window, including empty buckets:
snug timeline count -s docs4-activity --start=-24h --end now -i hour{
"interval": "hour",
"counts": [
{ "timestamp": 1787806897279, "count": 0, "start": "2026-08-27T05:01:37.279+00:00", "end": "2026-08-27T06:01:37.279+00:00" },
...
{ "timestamp": 1787889697279, "count": 3, "start": "2026-08-28T04:01:37.279+00:00", "end": "2026-08-28T05:01:37.279+00:00" }
],
"total": 3
}An interval outside that set fails with 400 invalid_time_interval, and
a window whose start is after its end fails with 400 invalid_time_range.
Aggregate
aggregate runs count, sum, avg, min, or max over a
dot-notation field, optionally grouped:
snug timeline aggregate -s docs4-activity --start=-24h --end now -a sum -f data.amount -g type{
"aggregation": "sum",
"field": "data.amount",
"result": 100.0,
"groups": [
{ "key": "page.view", "value": -0.0 },
{ "key": "user.login", "value": 100.0 }
]
}Here a leading data. is optional:
amount and data.amount resolve identically (verified: both sum the
same). A group whose events lack the field reports 0 (rendered -0.0).
The exact parameters for every endpoint are in the Timeline API reference.
