| name | duckdb-cli |
| description | Query and analyze data using the DuckDB CLI. Use when the user needs to run SQL queries, analyze CSV/Parquet/JSON files, create or query databases, export data, or perform any ad-hoc data analysis from the command line. Triggers include requests to "query a file", "analyze data", "run SQL", "read a CSV/Parquet/JSON", "create a database", "export to CSV/Parquet", or any data analysis task that benefits from SQL. |
DuckDB CLI
DuckDB is a fast, in-process analytical database. The CLI is a single, dependency-free executable.
Core Usage
duckdb
duckdb my.duckdb
duckdb :memory: "SELECT 42"
duckdb -c "SELECT 42"
duckdb < script.sql
duckdb -f script.sql
Command Line Arguments
| Argument | Description |
|---|
-c COMMAND | Run SQL command and exit |
-f FILENAME | Run script file and exit |
-csv | Set output to CSV |
-json | Set output to JSON |
-markdown | Set output to markdown |
-table | Set output to ASCII table |
-box | Set output to box-drawing table |
-line | Set output to one-value-per-line |
-list | Set output to pipe-delimited list |
-readonly | Open database read-only |
-header / -noheader | Toggle column headers |
-separator SEP | Set column separator |
-nullvalue TEXT | Set NULL display text |
-unsigned | Allow unsigned extensions |
-bail | Stop after first error |
-batch | Force batch I/O (non-interactive) |
Arguments are processed in order:
duckdb -csv -c 'SELECT 42 AS x' -json -c 'SELECT 84 AS y'
Dot Commands
| Command | Description |
|---|
.open FILE | Close current db, open FILE |
.databases | List attached databases |
.tables [PATTERN] | List tables (optional LIKE pattern) |
.schema [PATTERN] | Show CREATE statements |
.mode MODE | Set output format |
.headers on/off | Toggle column headers |
.timer on/off | Toggle query timing |
.output FILE | Redirect all output to FILE |
.output | Revert to stdout |
.once FILE | Redirect next query output only |
.once -x / .excel | Open next result in spreadsheet app |
.read FILE | Execute SQL from FILE |
.import FILE TABLE | Import data from FILE into TABLE |
.show | Show current settings |
.quit / .exit | Exit CLI |
Output Formats
Set via .mode MODE or CLI arguments (-csv, -json, etc.):
duckbox (default), box, table, csv, json, jsonlines, markdown, latex, html, insert, line, list, tabs, column, trash
Querying Files Directly
SELECT * FROM 'data.csv';
SELECT * FROM read_csv('data.csv');
SELECT * FROM read_csv('data/*.csv');
SELECT * FROM 'data.parquet';
SELECT * FROM read_parquet('data.parquet');
SELECT * FROM read_parquet('s3://bucket/data.parquet');
SELECT * FROM 'data.json';
SELECT * FROM read_json('data.json');
SELECT * FROM read_csv(['file1.csv', 'file2.csv']);
SELECT * FROM 'data/**/*.parquet';
Exporting Data
COPY (SELECT * FROM tbl) TO 'output.csv' (HEADER, DELIMITER ',');
COPY (SELECT * FROM tbl) TO 'output.parquet' (FORMAT PARQUET);
COPY (SELECT * FROM tbl) TO 'output.json' (FORMAT JSON, ARRAY true);
Or via dot commands:
.mode csv
.output results.csv
SELECT * FROM tbl;
.output
Piping (stdin/stdout)
cat data.csv | duckdb -c "SELECT * FROM read_csv('/dev/stdin')"
duckdb -c "COPY (SELECT 1 AS x) TO '/dev/stdout' WITH (FORMAT csv, HEADER)"
cat data.csv | duckdb -c "COPY (SELECT * FROM read_csv('/dev/stdin') WHERE x > 10) TO '/dev/stdout' WITH (FORMAT csv, HEADER)" | wc -l
Non-Interactive Patterns
duckdb :memory: "SELECT 42 AS answer"
duckdb :memory: -c "CREATE TABLE t AS SELECT 1 AS x; SELECT * FROM t;"
duckdb my.duckdb < queries.sql
duckdb -json -c "SELECT * FROM 'data.csv' LIMIT 5"
duckdb -csv -noheader -c "SELECT col FROM 'data.csv'"
Extensions
INSTALL httpfs;
LOAD httpfs;
INSTALL spatial;
INSTALL fts;
INSTALL vss;
INSTALL postgres;
INSTALL sqlite;
INSTALL excel;
Text Analysis Functions
Tier 1: Built-in Text Functions (no extension needed)
Exact matching:
SELECT * FROM docs WHERE CONTAINS(text, 'search term');
SELECT * FROM docs WHERE text ILIKE '%pattern%';
SELECT * FROM docs WHERE text LIKE '%pattern%';
Fuzzy string matching (approximate, not semantic):
SELECT jaccard('duck', 'luck');
SELECT jaro_winkler_similarity('duckdb', 'duckbd');
SELECT damerau_levenshtein('duck', 'dukc');
SELECT editdist3('kitten', 'sitting');
Regex:
SELECT regexp_matches(text, 'pattern');
SELECT regexp_extract(text, '(\d+)-(\d+)', 1);
SELECT regexp_replace(text, 'old', 'new', 'g');
Tokenization:
SELECT regexp_split_to_table(text, '\s+') AS token FROM docs;
Tier 2: Full Text Search (fts extension)
Keyword-based search with BM25 ranking. Handles word forms via stemming, but not semantic meaning.
INSTALL fts; LOAD fts;
PRAGMA create_fts_index('docs', 'id', 'text', stemmer = 'english');
SELECT d.*, score
FROM docs d
JOIN (
SELECT *, fts_main_docs.match_bm25(id, 'search query') AS score
FROM docs
) s ON d.id = s.id
WHERE score IS NOT NULL
ORDER BY score DESC;
SELECT stem('learning', 'english');
Tier 3: Vector Similarity Search (vss extension)
Semantic search using vector embeddings. DuckDB provides index and distance functions; generate embeddings externally (e.g., sentence-transformers, OpenAI API).
INSTALL vss; LOAD vss;
CREATE TABLE docs (id INT, text VARCHAR, embedding FLOAT[384]);
CREATE INDEX idx ON docs USING HNSW (embedding) WITH (metric = 'cosine');
SELECT array_cosine_distance(a.embedding, b.embedding) FROM ...;
SELECT array_distance(a.embedding, b.embedding) FROM ...;
SELECT array_negative_inner_product(a.embedding, b.embedding) FROM ...;
SELECT * FROM docs
ORDER BY array_cosine_distance(embedding, [0.1, 0.2, ...]::FLOAT[384])
LIMIT 10;
SELECT * FROM vss_join(table_a, table_b, a_embed, b_embed, 10, 'cosine');
SELECT * FROM vss_match(docs, embedding, query_vector, 10, 'cosine');
Common Recipes
duckdb -c "SUMMARIZE SELECT * FROM 'data.csv'"
duckdb -c "DESCRIBE SELECT * FROM 'data.csv'"
duckdb -c "SELECT count(*) FROM 'data.csv'"
duckdb -c "COPY (SELECT * FROM 'input.csv') TO 'output.parquet' (FORMAT PARQUET)"
duckdb -c "COPY (SELECT * FROM 'input.parquet') TO 'output.csv' (HEADER)"
duckdb -c "COPY (SELECT * FROM 'input.json') TO 'output.parquet' (FORMAT PARQUET)"
INSTALL httpfs; LOAD httpfs;
SELECT * FROM 'https://example.com/data.parquet' LIMIT 10;
ATTACH 'other.duckdb' AS other;
SELECT * FROM other.main.my_table;