You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+8-2Lines changed: 8 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -299,7 +299,8 @@ Freshness is treated asymmetrically (since v1.7.0):
299
299
300
300
Use `ctvs query refresh <file.jsonl>` to refresh selected source files, or
301
301
`ctvs query refresh --all [dataset]` when you explicitly want the broader
302
-
walk. Use `--refresh always` to force a refresh before the query runs. Use
302
+
walk. Repeat `--date` to query or refresh several UTC date partitions at once.
303
+
Use `--refresh always` to force a refresh before the query runs. Use
303
304
`--strict-freshness` to restore the pre-1.7 behavior where stale partitions
304
305
are a hard error (useful in CI / scheduled jobs that must never read
305
306
outdated data).
@@ -310,7 +311,12 @@ outdated data).
310
311
> unchanged; the new warning is written only to stderr. `missing`
311
312
> partitions still error.
312
313
313
-
Logical datasets are `logs`, `traces`, `metrics`, `proxy_messages`, and `gascity_messages`. `ctvs collect <file.jsonl> --name <name>` registers an external JSONL file as a dynamic table; `ctvs collect --glob '<pattern>' --name <name>` backs one table with many source files. Names are normalized for SQL, so `--name random-log` becomes table `random_log`. Collection tables include `_ctvs_source_path`, `_ctvs_line_number`, `_ctvs_raw`, and inferred top-level JSON fields. Deleted glob sources remain queryable from their cache-only partitions until the collection is removed. `ctvs query schema <dataset>` prints the schema, and `ctvs query catalog` shows which datasets have source and cached rows.
314
+
Logical datasets are `logs`, `traces`, `metrics`, `proxy_messages`, and `gascity_messages`. `ctvs collect <file.jsonl> --name <name>` registers an external JSONL file as a dynamic table; `ctvs collect --glob '<pattern>' --name <name>` backs one table with many source files. Names are normalized for SQL, so `--name random-log` becomes table `random_log`; quoted SQL can also reference the original collection name as `"random-log"`. Collection tables include `_ctvs_source_path`, `_ctvs_line_number`, `_ctvs_raw`, and inferred top-level JSON fields. Deleted glob sources remain queryable from their cache-only partitions until the collection is removed. `ctvs query schema <table>` prints the schema, and `ctvs query catalog` shows which datasets have source and cached rows.
315
+
316
+
```bash
317
+
ctvs query sql "select date, count(*) from proxy_messages group by date" \
Copy file name to clipboardExpand all lines: skills/collectivus-query/SKILL.md
+9-5Lines changed: 9 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
name: collectivus-query
3
-
description: Inspect local Collectivus recordings with the ctvs query CLI. Use when the user asks about recorded logs, traces, metrics, LLM proxy exchanges, query cache freshness, or wants SQL over local Collectivus data.
3
+
description: Inspect local Collectivus recordings with the ctvs query CLI. Use when the user asks about recorded logs, traces, metrics, LLM proxy exchanges, query cache freshness, or wants SQL over local Collectivus data, including collected JSONL tables.
4
4
---
5
5
6
6
# Collectivus Query
@@ -18,6 +18,7 @@ Use `ctvs query` to inspect local Collectivus recordings. It reads local JSONL r
18
18
- Pass `--strict-freshness` only when the user explicitly needs the pre-1.7 strict mode (e.g., scheduled checks that must never read stale data); it turns stale partitions back into a hard error.
19
19
4. Prefer structured output for analysis: use `--format json` for follow-up reasoning, `--format markdown` when showing a table to the user, and `--limit` to keep output bounded.
20
20
5. Use high-level query commands before custom SQL. Switch to `ctvs query sql` only when the built-in commands cannot answer the question.
21
+
6. For unfamiliar SQL tables, run `ctvs query schema <table> --format json` before querying. It works for built-in recording tables and tables registered with `ctvs collect`.
`ctvs collect` registers an external local JSONL file as a dynamic SQL table and immediately refreshes its query cache. Collection names are normalized for SQL (`random-log` -> `random_log`). Query them with `ctvs query sql "select * from random_log"`. Pass `--glob '<pattern>'` instead of a single path to back one logical table with many files; each matched file becomes its own cache partition and `_ctvs_source_path` tells you which file a row came from.
44
+
`ctvs collect` registers an external local JSONL file as a dynamic SQL table and immediately refreshes its query cache. `ctvs query sql` resolves table names from the SQL AST and injects built-in recording tables plus registered collection tables by name. Collection SQL can use either the normalized table name (`random-log` -> `random_log`) or the original quoted collection name (`"random-log"`), for example `ctvs query sql 'select * from "random-log"'`. Pass `--glob '<pattern>'` instead of a single path to back one logical table with many files; each matched file becomes its own cache partition and `_ctvs_source_path` tells you which file a row came from.
45
+
46
+
Repeat `--date` to query or refresh multiple UTC date partitions at once, for example `ctvs query sql "select count(*) from proxy_messages" --date 2026-05-14 --date 2026-05-15`.
43
47
44
48
## Proxy conversation log model
45
49
@@ -109,9 +113,9 @@ Use `JSON_VALUE(<col>, '$.path')` to extract scalars from the `attributes` / `st
109
113
- Do not assume the cache auto-refreshes. Query commands default to `--refresh never`, and stale partitions return data with a stderr warning rather than refreshing themselves.
110
114
- Always read stderr. A successful exit code does not mean the cache is current — a `warning: query cache last refreshed at …` line on stderr means stdout reflects cache rows from that refresh, and the user should be told before drawing conclusions.
111
115
- Do not paste `--config` into every command by habit. Use it when discovery shows the service is not using `~/.hyp/collectivus.json`.
112
-
- Do not read arbitrary Parquet files directly for `ctvs query sql`; the CLI only allows logical tables.
113
-
- Keep SQL read-only and use only logical datasets: `logs`, `traces`, `metrics`, `proxy_messages`, `gascity_messages`, and registered collection tables from `ctvs query catalog`.
114
-
- Use UTC dates with `--date YYYY-MM-DD`.
116
+
- Do not read arbitrary Parquet or Iceberg files directly for `ctvs query sql`; the CLI resolves SQL table names and injects only known query tables.
117
+
- Keep SQL read-only and use only query tables from `ctvs query catalog`: built-ins (`logs`, `traces`, `metrics`, `proxy_messages`, `gascity_messages`) and registered collection tables.
118
+
- Use UTC dates with `--date YYYY-MM-DD`; repeat `--date` when the user wants a union across multiple date partitions.
115
119
- Use `--service`, `--gateway-id`, `--from`, `--to`, or `--since` to narrow broad investigations.
Their query cache lives under `<recording-root>/.collectivus-query/cache/collections/<table>/source=<hash>/cursor.json`, with rows stored in local Iceberg tables below each source partition. Names are normalized for SQL, so `--name random-log` exposes table `random_log`.
15
+
Their query cache lives under `<recording-root>/.collectivus-query/cache/collections/<table>/source=<hash>/cursor.json`, with rows stored in local Iceberg tables below each source partition. SQL can reference either the normalized table name (`--name random-log` exposes `random_log`) or the original quoted collection name (`"random-log"`).
16
16
17
17
The cache is explicit. Query commands do not refresh it unless `--refresh always` is passed.
18
18
@@ -32,7 +32,7 @@ Commands default to `~/.hyp/collectivus.json`. If the running gateway or OTEL co
32
32
-`--cache-dir <dir>`: Override the query cache directory.
ctvs query sql "select * from random_log" --format json
72
+
ctvs query sql 'select * from "random-log"' --format json
72
73
```
73
74
74
-
`ctvs collect` stores the absolute source path (or glob) and immediately refreshes the query cache. If the source file changes later, normal query freshness rules apply: stale cached data is queryable with a stderr warning, `--strict-freshness` turns that into an error, and `ctvs query refresh <file.jsonl>` refreshes selected files. Use `--refresh always` to refresh before running the query.
75
+
`ctvs collect` stores the absolute source path (or glob) and immediately refreshes the query cache. If the source file changes later, normal query freshness rules apply: stale cached data is queryable with a stderr warning, `--strict-freshness` turns that into an error, and `ctvs query refresh <file.jsonl>` refreshes selected files. Use `--refresh always` to refresh before running the query. SQL can reference the normalized table name or the original quoted collection name, such as `"random-log"`.
75
76
76
77
With `--glob`, one logical table is backed by many source files: each matched file becomes its own cache partition under `.collectivus-query/cache/collections/<table>/source=<hash>/cursor.json`, and refresh appends from each file's recorded cursor when possible. Files that no longer match the glob remain queryable as cache-only partitions. Inside SQL, use `_ctvs_source_path` to see which file a row came from.
77
78
@@ -85,7 +86,7 @@ Collection tables always include `_ctvs_source_path`, `_ctvs_line_number`, and `
85
86
-`proxy_messages`: One row per LLM proxy content part (text block, tool call, tool result, etc.), globally deduped by content-derived `message_id`. See **proxy_messages columns** below for the full 26-column schema; `gateway_id` and `date` are added as partition columns in the query cache.
86
87
-`gascity_messages`: One row per content block from gascity-captured agent sessions (text, thinking, tool_use, tool_result, attachment). Captured by the `ctvs gascity` supervisor source — agent-attributed (`gascity_template` / `gascity_rig` / `gascity_alias`) and includes per-frame token usage with cache breakdown. Always fresh: the daemon writes Parquet directly to `~/.collectivus/sink/gascity_messages/date=<YYYY-MM-DD>/city=<name>/` (no JSONL stage, no `.meta.json` sidecar). The constant `gateway_id = 'gascity-scribe'` tags the source for cross-source UNIONs with `proxy_messages`. Run `ctvs query schema gascity_messages --format markdown` for the full 47-column schema.
87
88
88
-
Run `ctvs query schema <dataset> --format json` for the exact columns in the installed version.
89
+
Run `ctvs query schema <table> --format json` for the exact columns in the installed version. Schema lookup works for built-in tables and tables registered with `ctvs collect`.
89
90
90
91
## proxy_messages columns
91
92
@@ -129,6 +130,7 @@ ctvs query sql "select serviceName, count(*) as logs from logs group by serviceN
129
130
ctvs query sql "select traceId, name, durationMs from traces order by durationMs desc limit 20" --refresh always --format json
130
131
ctvs query sql "select model, count(distinct message_id) as messages, count(*) as parts from proxy_messages where role = 'assistant' group by model order by messages desc" --format markdown
131
132
ctvs query sql "select conversation_id, count(distinct message_id) as messages from proxy_messages group by conversation_id order by messages desc limit 10" --format markdown
133
+
ctvs query sql "select date, count(*) as parts from proxy_messages group by date order by date" --date 2026-05-14 --date 2026-05-15 --format markdown
132
134
```
133
135
134
136
For JSON columns (`attributes`, `status`, `tools`, `tool_args`), extract scalars with `JSON_VALUE(<col>, '$.path')`:
ctvs query sql "select model, sum(cast(JSON_VALUE(attributes, '\$.usage.input_tokens') as bigint)) as input_tokens from (select distinct message_id, model, attributes from proxy_messages where role = 'assistant') group by model order by input_tokens desc" --format markdown
138
140
```
139
141
140
-
SQL must be a read-only `select` over the logical datasets above or registered collection tables.
142
+
SQL must be a read-only `select` over known query tables. Table names are resolved from the SQL AST and may be built-ins (`logs`, `traces`, `metrics`, `proxy_messages`, `gascity_messages`) or registered collection tables from `ctvs query catalog`.
0 commit comments