tuneloop-query
GitHub通过只读SQL查询本地tuneloop SQLite存储中的AI代理会话数据。支持成本、Token、工具使用等指标分析,提供Schema探索、存在性确认及按粒度聚合的步骤,严禁写入操作。
Trigger Scenarios
Install
npx skills add tuneloop/tuneloop --skill tuneloop-query -g -y
SKILL.md
Frontmatter
{
"name": "tuneloop-query",
"description": "Query the local tuneloop store of AI agent sessions with read-only SQL. Use when the user wants any metric, slice, or aggregation of their tuneloop data — cost, tokens, tool usage, or artifacts."
}
Querying the tuneloop store
tuneloop analyze builds a local SQLite store of your AI agent sessions. This
skill runs read-only SQL over it — any query, from a quick count to a custom
aggregation.
Prerequisite: the tuneloop CLI must be on your PATH — install with
npm i -g tuneloop, or run it through npx tuneloop. If the command isn't found,
the store isn't set up; say so instead of guessing at the data.
Run queries with:
tuneloop query "<SQL>" # text table
tuneloop query --json "<SQL>" # JSON rows
tuneloop query --limit 200 … # row cap (default 1000)
tuneloop query --schema # tables + facets + measures
tuneloop query --db <path> … # non-default store location
Only SELECT / WITH … SELECT run — writes, PRAGMA, ATTACH, and stacked
statements are rejected, and session_blobs (raw transcripts) is off-limits.
Query the fact tables.
Steps
- Learn the shape and extent. Run
tuneloop query --schema— it prints the store's coverage (session count, date span, sources, repos, analyzed directories, last analyzed) then every table, facet, and measure. Done when you can name each table/column the query touches and know the data's span — never guess a column or a date range. (reference/schema.md has the table shapes offline.) - Confirm the rows exist.
artifacts,annotations, andblock_annotationsare populated only if the relevant processor/enrichment ran. Probe first — e.g.SELECT kind, COUNT(*) FROM artifacts GROUP BY kindorSELECT DISTINCT processor, key FROM annotations. Done when every table the query depends on is confirmed non-empty (or the query is adjusted to what is). - Aggregate at the right grain. Apply the grain rules below. Done when every SUM/COUNT sits at the grain that owns the number and no join crosses grains to fan out.
- Run and read the caps. A result stops at the row/byte/time cap and prints
why. Widen with
--limit, or narrow the query. Done when the result is complete, or the truncation is reported to the user with its cause.
Grain
Every row lives at a grain, nested:
session ⊃ block ⊃ { usage_facts , tool_calls }
Aggregate each number at the grain that owns it, or you double-count. Three rules:
- Cost and tokens live at usage grain —
usage_facts, one row per assistant message (model,is_sidechain, token columns,cost_usd). Break cost down by model here.sessions.cost_usd/sessions.modelsare convenience rollups; neverGROUP BYa model offsessions— itsmodelsis a JSON array and you would double-count. - Never join
usage_factstotool_calls. They are siblings under a block, so a direct join fans out — every usage row × every tool row — and inflates every SUM. Aggregate each tosession_idin separate subqueries, then join those. - Sidechain rolls up — it's counted, not dropped. Block boundaries are cut on
the main thread, but
block_usage/block_toolmap EVERY row into a block: sub-agent (sidechain) usage rolls up to the block whoseTaskcall spawned it (nearest-by-time for orphans). So block-grain is exhaustive over all usage — a per-PR / per-feature cost already includes sub-agent spend.
EAV / JSON values
Enrichment lands in generic key/value tables whose value is JSON-encoded:
annotations (session grain — e.g. complexity, autonomy, intent) and
block_annotations (block grain — e.g. use_case). Extract with
json_extract(value, '$').
What's populated
Only artifacts.kind IN ('file','pr','feature') populate in the OSS CLI;
commit/ticket and artifact_links are usually empty. Reach artifacts from
sessions via session_artifacts / block_artifacts.
Recipes
Worked queries for the common analyses — sidechain split, cost-per-model, cache
leverage, tool latency, action breakdown, PR cycle time, spend-by-branch — in
reference/recipes.md.
Version History
- 1f3c857 Current 2026-07-11 16:57


