Getting started
UNSeQueL queries are plain text files (suffix .unsequel) that describe a table transformation in execution order. The compiler runs them against local CSV, JSON, and Parquet files through DuckDB.
1. Install the compiler
Requires Node 22 or newer. The npm package is not on the registry yet, so install from a clone:
git clone https://github.com/absterjr/UNSeQueL.git cd UNSeQueL/compiler npm install npm install -g . # puts `unsequel` on PATH unsequel --version
The currently installed version is unsequel 0.1.0 with grammar v1.5. To remove the global install later: npm uninstall -g unsequel.
2. Write a self-contained query
A file can declare its own data sources, so no flags are needed. Create my_query.unsequel:
# source orders: examples/spec/orders.csv from orders group by country aggregate revenue = SUM(quantity * unit_price) sort -revenue
The # source name: path directive is resolved relative to the query file. Without a schema file, loaded tables are introspected, so columns and types just work.
3. Run it
unsequel run my_query.unsequel
country revenue -------------- ------- United States 328.5 United Kingdom 241.5 Netherlands 24 3 row(s)
Output formats: --format json or --format csv.
4. Run a selection, not the whole file
Multi-query files are normal: every stage is one line. Select a range in the editor and run only those lines — the file's directives still apply.
unsequel run my_query.unsequel --lines 2:5
Piped input works the same way; the query text arrives on stdin:
echo "from orders | take 1" | unsequel run - --data orders=examples/spec/orders.csv
5. Keep files canonical
unsequel fmt my_query.unsequel --write # rewrite in canonical form unsequel fmt my_query.unsequel --check # exit 1 if not canonical
The formatter lowercases stage keywords, uppercases expression keywords, canonicalizes strings and descending sorts, and preserves # source/# schema directives.
6. Try the REPL
unsequel repl unsequel> .load orders=examples/spec/orders.csv loaded orders unsequel> from orders ...> group by country ...> aggregate n = COUNT(*) ...> .run
One stage per line; a query executes on a blank line, a lone ;, or .run. Pasted unsequel>/...> prompt prefixes are stripped, so example transcripts can be copied wholesale.