Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions .claude/skills/otai/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,17 @@ column names, types, descriptions, and cross-dataset relationships/nested
subfields, parsed from the release's croissant schema.

### `otai run-sql "<query>" [--timeout SECONDS]`
Positional `<query>`, a read-only SQL string. No `--release` flag:
- Unqualified table names resolve against `latest`.
- Schema-qualify a table to target a specific (possibly non-latest)
release, e.g. `"26.03".target`; this also enables cross-release joins in
a single query, e.g. `"26.06".target JOIN "26.03".target ...`.
Positional `<query>`, a read-only SQL string.

**No `--release` flag, unlike the subcommands above — don't pass one.**
Each release is a DuckDB schema named after its identifier, and `otai`
reads which release(s) it needs straight off your query's schema
qualifiers: `select * from "26.06".target` → release `26.06`, fetched/built
automatically if needed. Unqualified names (e.g. `target`) resolve to
`latest`. A single call can span any number of releases this way, e.g.
`... "26.06".target join "26.03".target on ...` — no separate flag or step
for comparing releases.

- The CLI enforces read-only SQL, a ~1000-row cap (response says whether
results were truncated), and a timeout — do not attempt to replicate or
second-guess these checks yourself.
Expand Down Expand Up @@ -120,9 +126,17 @@ Every command emits one of:
<seconds>` if the query is already minimal and legitimately slow;
`sql_error` / `guardrail_violation` → fix the SQL; `release_not_found`
→ check `list-releases` before retrying.
6. **Cite your sources in the final answer**: state which release(s) were
queried and show the actual SQL you executed, so the user can verify or
rerun it.
6. **End your final answer with every `run-sql` query you ran**, not just
the last one if you iterated — plus the release(s) queried — so the
user can verify or rerun them.
7. **Check `data.truncated` on a successful `run-sql`, not just errors.**
A capped result (~1000 rows) is still `ok: true`; ignoring `truncated`
risks presenting a partial result as complete. When it's `true`, prefer
re-querying with an aggregate (`COUNT`, `GROUP BY`, `TOP N`) over the
raw rows; if the user genuinely needs row-level detail beyond 1000,
add an `ORDER BY` on a stable column and page with repeated
`LIMIT`/`OFFSET` calls. Either way, tell the user when what you're
showing is a subset.

## Example

Expand Down