.do files to SQL. no DuckDB required.
Compile .do files to SQL without installing DuckDB. A single binary, no dependencies, designed for CI/CD pipelines and SQL preview workflows.
what is dodoc?
dodoc is a standalone CLI that reads .do files and outputs the equivalent SQL — the same translation the dodo DuckDB extension performs, but without needing DuckDB at all.
It shares the same core parser as the extension, so every command the extension understands, dodoc understands too.
why use it?
.do files as a build step, validate the SQL, commit the output.The dodo extension runs inside DuckDB and executes the translated SQL immediately. dodoc runs outside DuckDB and only produces SQL text. Both share the same parser and produce identical SQL for the same input.
installation
install script (macOS / Linux)
The fastest way — detects your platform and downloads the right binary:
› curl -fsSL https://getdodo.dev/install.sh | sh
Installs to /usr/local/bin (or ~/.local/bin if no sudo). Works on macOS (arm64 & x86_64) and Linux (x86_64 & arm64).
homebrew (macOS / Linux)
› brew install codedthinking/tap/dodoc
download pre-built binaries
Pre-built binaries are available on the GitHub Releases page for five platforms:
dodoc-macos-arm64.tar.gz.dodoc-macos-x86_64.tar.gz.dodoc-linux-x86_64.tar.gz.dodoc-linux-arm64.tar.gz.dodoc-windows-x86_64.zip.After downloading, extract and install:
› tar xzf dodoc-macos-arm64.tar.gz
› sudo install dodoc /usr/local/bin/
build from source
Requires git, make, and a C++17 compiler.
› git clone --recurse-submodules https://github.com/codedthinking/dodo.git
› cd dodo
› make dodoc
› sudo make dodoc-install
This installs the dodoc binary to /usr/local/bin/.
verify
› dodoc --help
usage
Read from stdin or file, output SQL to stdout or file. Pipe into DuckDB or save for later.
stdin to stdout
Pipe .do commands directly:
› echo 'use "data.csv", clear
keep if year >= 2020
generate profit = revenue - cost' | dodoc
compile a file
Pass the .do file as an argument:
› dodoc analysis/clean.do
Write to a file with -o:
› dodoc analysis/clean.do -o analysis/clean.sql
what the output looks like
Each .do command becomes a CTE, chained in order, with the original command as a comment. This four-line script:
use "data.csv", clear
keep if year >= 2020
generate profit = revenue - cost
collapse (mean) profit, by(industry)
compiles to:
WITH
-- [source] use "data.csv", clear
_s0 AS (
SELECT *
FROM read_csv('data.csv')
),
-- [source] keep if year >= 2020
_s1 AS (
SELECT *
FROM _s0
WHERE year >= 2020
),
-- [source] generate profit = revenue - cost
_s2 AS (
SELECT *, (revenue - cost) AS profit
FROM _s1
),
-- [source] collapse (mean) profit, by(industry)
_s3 AS (
SELECT industry, AVG(profit) AS profit
FROM _s2
GROUP BY industry
)
SELECT *
FROM _s3;
working with .dta files
When the script reads or writes Stata .dta files, the generated SQL uses DuckDB's .dta reader and writer:
use "panel.dta", clear
save "out.dta", replace
WITH
-- [source] use "panel.dta", clear
_s0 AS (
SELECT *
FROM read_dta('panel.dta')
)
...
COPY (...) TO 'out.dta';
To execute SQL that reads or writes .dta files, DuckDB needs the dta extension installed. dodoc itself compiles fine without it.
annotated output
The --annotate flag adds the original .do command as a SQL comment above each translated statement, making the output easier to read and debug:
› dodoc --annotate analysis/clean.do
piping to duckdb
The most common pattern: compile, then execute. Pipe dodoc output directly into DuckDB:
› dodoc script.do | duckdb
When piping to DuckDB this way, DuckDB does not need the dodo extension installed — it receives plain SQL. The extension is only needed when you type .do commands directly in the DuckDB REPL.
all flags
| Flag | Description |
|---|---|
-o, --output FILE | Write SQL to FILE instead of stdout |
--annotate | Emit original .do command as a SQL comment before each statement |
--terminal | Also emit SQL for terminal commands (list, count, etc.) |
-h, --help | Show help message |