Skip to main content
skill CX Codex

read-file — Claude Code skill: open any data file with DuckDB

Reads a CSV, Parquet, Excel, SQLite file or a remote link over S3 and HTTPS, then reports the schema and sample rows. Handy when a dataset lands in the repo and you need a quick look.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add duckdb/duckdb-skills --skill read-file -a claude-code
Open on GitHub

What read-file does

The skill takes a path or a URL as $0 plus an optional question in ${1:-describe the data}. A bare filename without a slash gets resolved to a full path through find. Then one duckdb call defines the read_any macro and runs three statements: the schema, a row count, the first 20 rows.

The reader follows the file extension. JSON and JSONL use read_json_auto; CSV and TSV use read_csv; Parquet, Avro, read_xlsx, st_read for spatial data and sqlite_scan for databases each have their own branch. Notebooks in .ipynb are handled separately, pulling the cell type, its source text and the execution counter. Anything unrecognised falls through to read_blob.

Remote paths need httpfs loaded first, and s3://, gs:// or az:// also need a secret built with credential_chain. No duckdb binary in PATH means the first step fails; the skill then hands off to /duckdb-skills:install-duckdb. A missing extension such as spatial or sqlite_scanner gets fixed by prefixing INSTALL and LOAD. Source code files are outside its scope — ask another tool for those.

What it helps with

  • inspect the schema and row count of an unfamiliar dataset
  • open a Parquet file without adding a library
  • see what an Excel export or SQLite database holds
  • read a data file hosted on S3 or behind an HTTPS link
  • scan notebook cells as plain text

Example prompts for the agent

  • Read orders.parquet and list its columns with the row count
  • What's inside report.xlsx? Describe the field types
  • Open s3://bucket/events.jsonl and show me the first rows

How to install read-file

1Skills CLI (Vercel)

npx skills add duckdb/duckdb-skills --skill read-file -a claude-code

2Manually: put the files in place

~/.claude/skills/read-file/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/read-file/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about read-file

How do I install read-file in Claude Code?

Run npx skills add duckdb/duckdb-skills --skill read-file -a claude-code, then confirm that ~/.claude/skills/read-file/SKILL.md is in place.

What does read-file do?

It builds a DuckDB macro that picks a reader by extension, then answers your question from the schema, the row count and sample rows.

Which formats does it handle?

CSV, TSV, JSON and JSONL, Parquet, Avro, Excel, spatial formats, SQLite and .ipynb notebooks; anything else is read as a blob.

Source text

SKILL.md · MIT
---
name: read-file
description: >
  Read any data file (CSV, JSON, Parquet, Avro, Excel, spatial, SQLite) or remote URL (S3, HTTPS).
  Use when user references a data file, asks "what's in this file", or wants to preview/profile a dataset.
  Not for source code.
argument-hint: <filename or URL> [question about the data]
allowed-tools: Bash
---

You are helping the user read and analyze a data file using DuckDB.

Filename given: `$0`
Question: `${1:-describe the data}`

## Step 1 — Read it

`RESOLVED_PATH` is `$0`. If the user gave a bare filename (no `/`), resolve it to a full path with `find` first.

Run a single DuckDB command that defines the `read_any` macro inline and reads the file.

For **remote files**, prepend the necessary LOAD/SECRET before the macro:

| Protocol | Prepend |
|---|---|
| `https://` / `http://` | `LOAD httpfs;` |
| `s3://` | `LOAD httpfs; CREATE SECRET (TYPE S3, PROVIDER credential_chain);` |
| `gs://` / `gcs://` | `LOAD httpfs; CREATE SECRET (TYPE GCS, PROVIDER credential_chain);` |
| `az://` / `azure://` / `abfss://` | `LOAD httpfs; LOAD azure; CREATE SECRET (TYPE AZURE, PROVIDER credential_chain);` |

For **local files**, no prefix needed.

```bash
duckdb -csv -c "
CREATE OR REPLACE MACRO read_any(file_name) AS TABLE
  WITH json_case AS (FROM read_json_auto(file_name))
     , csv_case AS (FROM read_csv(file_name))
     , parquet_case AS (FROM read_parquet(file_name))
     , avro_case AS (FROM read_avro(file_name))
     , blob_case AS (FROM read_blob(file_name))
     , spatial_case AS (FROM st_read(file_name))
     , excel_case AS (FROM read_xlsx(file_name))
     , sqlite_case AS (FROM sqlite_scan(file_name, (SELECT name FROM sqlite_master(file_name) LIMIT 1)))
     , ipynb_case AS (
         WITH nb AS (FROM read_json_auto(file_name))
         SELECT cell_idx, cell.cell_type,
                array_to_string(cell.source, '') AS source,
                cell.execution_count
         FROM nb, UNNEST(cells) WITH ORDINALITY AS t(cell, cell_idx)
         ORDER BY cell_idx
     )
  FROM query_table(
    CASE
      WHEN file_name ILIKE '%.json' OR file_name ILIKE '%.jsonl' OR file_name ILIKE '%.ndjson' OR file_name ILIKE '%.geojson' OR file_name ILIKE '%.geojsonl' OR file_name ILIKE '%.har' THEN 'json_case'
      WHEN file_name ILIKE '%.csv' OR file_name ILIKE '%.tsv' OR file_name ILIKE '%.tab' OR file_name ILIKE '%.txt' THEN 'csv_case'
      WHEN file_name ILIKE '%.parquet' OR file_name ILIKE '%.pq' THEN 'parquet_case'
      WHEN file_name ILIKE '%.avro' THEN 'avro_case'
      WHEN file_name ILIKE '%.xlsx' OR file_name ILIKE '%.xls' THEN 'excel_case'
      WHEN file_name ILIKE '%.shp' OR file_name ILIKE '%.gpkg' OR file_name ILIKE '%.fgb' OR file_name ILIKE '%.kml' THEN 'spatial_case'
      WHEN file_name ILIKE '%.ipynb' THEN 'ipynb_case'
      WHEN file_name ILIKE '%.db' OR file_name ILIKE '%.sqlite' OR file_name ILIKE '%.sqlite3' THEN 'sqlite_case'
      ELSE 'blob_case'
    END
  );

DESCRIBE FROM read_any('RESOLVED_PATH');
SELECT count(*) AS row_count FROM read_any('RESOLVED_PATH');
FROM read_any('RESOLVED_PATH') LIMIT 20;
"
```

**If this fails:**
- **`duckdb: command not found`** → invoke `/duckdb-skills:install-duckdb` and retry.
- **Missing extension** (e.g. spatial files, xlsx, sqlite) → retry with `INSTALL spatial; LOAD spatial;` or `INSTALL sqlite_scanner; LOAD sqlite_scanner;` prepended before the macro.
- **Wrong reader / parse error** → use the correct `read_*` function directly instead of `read_any`.

## Step 2 — Answer

Using the schema, row count, and sample rows, answer:

`${1:-describe the data: summarize column types, row count, and any notable patterns.}`

© duckdb · MIT · duckdb/duckdb-skills

Similar skills

All skills for Data and databases →

From the same set7

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor