attach-db
Attach a DuckDB database file for use with /duckdb-skills:query. Explores the schema (tables, columns, row counts) and writes a…
Run SQL queries against the attached DuckDB database or ad-hoc against files. Accepts raw SQL or natural language questions. Uses DuckDB Friendly SQL idioms.
Claude Code
$ npx -y skills add duckdb/duckdb-skills --skill query --agent claude-code
Codex
$ npx skills add duckdb/duckdb-skills --skill query -a codex -y
Cursor
$ npx skills add duckdb/duckdb-skills --skill query -a cursor -y
Gemini CLI
$ npx skills add duckdb/duckdb-skills --skill query -a gemini-cli -y
GitHub Copilot
$ npx skills add duckdb/duckdb-skills --skill query -a github-copilot -y
OpenCode
$ npx skills add duckdb/duckdb-skills --skill query -a opencode -y
Windsurf
$ npx skills add duckdb/duckdb-skills --skill query -a windsurf -y
name: query description: > Run SQL queries against the attached DuckDB database or ad-hoc against files. Accepts raw SQL or natural language questions. Uses DuckDB Friendly SQL idioms. argument-hint: <SQL or question> [--file path] allowed-tools: Bash
You are helping the user query data using DuckDB.
Input: `$@`
Follow these steps in order.
Look for an existing state file in either location:
STATE_DIR="" test -f .duckdb-skills/state.sql && STATE_DIR=".duckdb-skills" PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")" PROJECT_ID="$(echo "$PROJECT_ROOT" | tr '/' '-')" test -f "$HOME/.duckdb-skills/$PROJECT_ID/state.sql" && STATE_DIR="$HOME/.duckdb-skills/$PROJECT_ID"
If found, verify the databases it references are still accessible:
duckdb -init "$STATE_DIR/state.sql" -c "SHOW DATABASES;"
Now determine the mode:
If no state file exists and no file is referenced, fall back to ad-hoc mode against `:memory:` — the user must reference files directly in their SQL.
If the state file exists but any ATTACH in it fails, warn the user and fall back to ad-hoc mode.
command -v duckdb
If not found, delegate to `/duckdb-skills:install-duckdb` and then continue.
If the input is natural language (not valid SQL), generate SQL using the Friendly SQL reference below.
In **session mode**, first retrieve the schema to inform query generation:
duckdb -init "$STATE_DIR/state.sql" -csv -c " SELECT table_name FROM duckdb_tables() ORDER BY table_name; "
Then for relevant tables:
duckdb -init "$STATE_DIR/state.sql" -csv -c "DESCRIBE <table_name>;"
Use the schema context and the Friendly SQL reference to generate the most appropriate query.
Before executing, estimate whether the query could produce a very large result that would consume excessive tokens when returned to this conversation.
**Session mode** — check row counts for the tables involved:
duckdb -init "$STATE_DIR/state.sql" -csv -c "
SELECT table_name, estimated_size, column_count
FROM duckdb_tables()
WHERE table_name IN ('<table1>', '<table2>');
"**Ad-hoc mode** — probe the source:
duckdb :memory: -csv -c " SET allowed_paths=['FILE_PATH']; SET enable_external_access=false; SET allow_persistent_secrets=false; SET lock_configuration=true; SELECT count() AS row_count FROM 'FILE_PATH'; "
**Evaluate**:
*"This query would return a very large result set. Displaying it here would consume a lot of tokens and increase cost. I'd recommend adding `LIMIT 1000` or an aggregation to keep the output manageable."* Ask for confirmation before running as-is.
*"This table is over 10 GB — the query may take a while to complete."* Proceed if the user confirms.
Skip this step for queries that are intrinsically bounded (e.g. `DESCRIBE`, `SUMMARIZE`, aggregations, `count()`).
**Ad-hoc mode** (sandboxed — only the referenced file is accessible):
duckdb :memory: -csv <<'SQL' SET allowed_paths=['FILE_PATH']; SET enable_external_access=false; SET allow_persistent_secrets=false; SET lock_configuration=true; <QUERY>; SQL
Replace `FILE_PATH` with the actual file path extracted from the query or `--file` argument. If multiple files are referenced, include all paths in the `allowed_paths` list.
**Session mode** (user-trusted database):
duckdb -init "$STATE_DIR/state.sql" -csv -c "<QUERY>"
For multi-line queries, use a heredoc with `-init`:
duckdb -init "$STATE_DIR/state.sql" -csv <<'SQL' <QUERY>; SQL
Always use heredocs (`<<'SQL'`) for multi-line queries to avoid shell quoting issues.
Show the query output to the user. If the result has more than 100 rows, note the truncation and suggest adding `LIMIT` to the query.
For natural language questions, also provide a brief interpretation of the results.
---
When generating SQL, prefer these idiomatic DuckDB constructs:
A Claude Code plugin that adds DuckDB-powered skills for data exploration and session memory.
Attach a DuckDB database file for use with /duckdb-skills:query. Explores the schema (tables, columns, row counts) and writes a…
Convert any data file to another format: CSV, Parquet, JSON, Excel, GeoJSON, and more. Use when the user says "convert to…
Search DuckDB and DuckLake documentation and blog posts. Returns relevant doc chunks for a question or keyword using full-text…
Install or update DuckDB extensions. Each argument is either a plain extension name (installs from core) or name@repo (e.g.…
Read any data file (CSV, JSON, Parquet, Avro, Excel, spatial, SQLite) or remote URL (S3, HTTPS). Use when user references a data…
Search past Claude Code session logs to recall prior decisions, patterns, or unresolved work. Use when user says "do you…
Use this skill to extract structured Markdown/JSON from PDFs and document images—tables with cell-level precision, formulas as…
Estimates intracellular metabolic fluxes from steady-state carbon-13 isotope-tracing measurements using validated atom maps,…