Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>preen — DuckDB SQLNew to Visual Studio Code? Get it now.
preen — DuckDB SQL

preen — DuckDB SQL

Meridian Tech Labs

|
1 install
| (0) | Free
Lint, format and run DuckDB SQL: DuckDB-aware rules and quick fixes, one consistent format, and scripts run through your own duckdb CLI (1.5 and 2.0).
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

preen — DuckDB SQL for VS Code

Works with DuckDB 1.5 | 2.0 Lint · Format · Run

Write, check and run DuckDB SQL without leaving the editor. preen lints and formats DuckDB SQL with a parser built from DuckDB's own grammar, and runs your scripts through your own duckdb CLI — the exact version you installed, not a copy bundled inside the editor.

Built for people who move and shape data in SQL: ETL scripts, migrations, analytics notebooks-as-files. Works in VS Code, Cursor, VSCodium and other forks.

What you get

  • Run SQL — Cmd/Ctrl+Enter runs the statement under the cursor (or everything you selected); Cmd/Ctrl+Shift+Enter runs the file. Results open beside the editor, one block per statement.
  • Lint as you type — 27 DuckDB-aware rules, from real bugs (x = NULL, a UNION that silently mispairs columns, an INSERT that pairs columns by position) to DuckDB idioms (GROUP BY ALL, QUALIFY, FILTER, count()).
  • Quick fixes — Cmd/Ctrl+. on a squiggle. Fixes that could change a query's results are labelled unsafe so you decide.
  • Format — Format Document gives one consistent DuckDB style, keywords uppercase, lists broken one item per line when they don't fit.
  • Highlighting that knows DuckDB — PIVOT, QUALIFY, ASOF, SUMMARIZE and friends, and a table called data coloured as a table, not a keyword. Nothing inside a comment is ever highlighted as code.

Quick start

  1. Install this extension. Linting, formatting and highlighting work immediately — nothing else to install.

  2. To run SQL, install the DuckDB CLI (macOS: brew install duckdb; others: see duckdb.org) and, if the editor doesn't find it on its own, set its path:

    "preen.duckdb.path": "/opt/homebrew/bin/duckdb"
    
  3. Open a .sql file, put the cursor on a statement, press Cmd/Ctrl+Enter.

The status bar shows the DuckDB version in use and the database; click it to switch between :memory: and a database file.

Running SQL

key or command what it does
Cmd/Ctrl+Enter run the statement at the cursor, or every statement the selection touches
Cmd/Ctrl+Shift+Enter run the whole file
▶ in the editor title bar the same, with the mouse
preen: Choose DuckDB Database :memory: or a .duckdb file
preen: Restart DuckDB Session start fresh (also stops a long query)
  • One session stays open, like a terminal: TEMP tables, SET options and in-memory data survive from one run to the next.
  • Statements run one at a time and each result shows under its own statement. A ; inside a string or comment never splits a statement.
  • A run stops at the first error and marks it in the editor where DuckDB reported it.
  • Relative paths in SQL (read_csv('data/orders.csv')) resolve from the workspace folder, as if you ran duckdb from the project root.
  • DuckDB 1.5 and 2.0 both work — point preen.duckdb.path at the one you want. A database file written by 2.0 cannot be opened by 1.5; if that's why a run fails, the error says so.

Rules

Correctness and DuckDB idioms:

code what it catches fix
MOD002 x = NULL is never true; use IS NULL unsafe
MOD005 DISTINCT together with GROUP BY —
MOD007 NATURAL JOIN re-pairs silently when columns change —
MOD016 a CTE that is never used safe
MOD026 INSERT INTO t SELECT … pairs columns by position; use BY NAME unsafe
MOD027 UNION arms with the same columns in a different order unsafe
MOD028 DROP … IF EXISTS then CREATE → CREATE OR REPLACE safe
MOD001, 003, 006, 013–015, 021 DuckDB idioms: count(), GROUP BY ALL, COALESCE, ORDER BY ALL, FILTER, CASE x WHEN, QUALIFY mostly safe
MOD004, 008, 009, 011, 012 order and naming hazards: ORDER BY in subqueries and views, bare UNION, GROUP BY 1, redundant aliases some

House style: MOD010 comma joins, MOD017 SELECT * into tables, MOD018 constraints on bulk loads, MOD019 huge IN lists, MOD020 1_000_000, MOD022 FROM-first, MOD023 x: expr aliases, MOD025 SELECT * in final queries.

The editor shows every rule out of the box; remove codes from preen.select to hide them. (On the preen command line the house-style rules are off unless you select them.)

Silence one finding with a comment on or above the statement: -- preen: ignore[MOD026].

Settings

setting default
preen.duckdb.path duckdb on PATH the CLI that runs your SQL
preen.duckdb.database :memory: or a database file (relative to the workspace)
preen.duckdb.maxRows 1000 rows shown per result; the count is always exact
preen.select every rule the rule codes to show
preen.path the bundled binary use a different preen build

A preen.toml in your project (the same file the preen command line reads) sets formatting options and rule severities, so the editor and CI never disagree.

Privacy

preen makes no network calls and collects no telemetry. The SQL you run goes only to the duckdb CLI you chose; what that SQL does (for example, reading from S3) is up to you.

Not yet

No autocomplete or hover yet, no schema browser, and no cancel button (Restart DuckDB Session stops a running query).


preen is made by Meridian Tech Labs. It is an independent project, not affiliated with or endorsed by DuckDB Labs or the DuckDB Foundation. DuckDB is a trademark of the DuckDB Foundation. MIT licensed; see ThirdPartyNotices.txt for DuckDB's license, whose grammar preen's parser is built from.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft