DuckPack is a Rust-based CLI and Interactive TUI that completely changes how you manage DuckDB schemas. Instead of writing imperative UP/DOWN migration scripts, you simply write your desired database state as raw SQL files, and this engine automatically computes the diff and applies the necessary changes non-destructively.
I've spent time as an education journey into Rust vibe coding this application. I have personal reasons to want to use this application and had never tried to 'vibe code' anything before.
I know this may contain 'sub optimal' or 'vibe code' solutions and code that could be written more elegantly. I've also not fully tested everything yet so expect bugs, I'm fine with this! If you find this useful, want to tinker etc, please do.
Thanks, Ben.
- Declarative Schema: Define your tables, views, and macros as raw
.sqlfiles. No migration versions to track. - Git-Style Smart Renames: The engine uses heuristic similarity matching. If you rename a table or column, it automatically detects the similarity (>80%) and issues a non-destructive
ALTER TABLE RENAMEinstead of dropping and recreating your data. - Environment Variables: Dynamically inject an unlimited number of variables (e.g.
CREATE TABLE ${ENV}_users_${REGION}) directly into your SQL using.envfiles. The engine automatically parses them via regex and injects them seamlessly! - Views and Macros: Define views and macros using standard
CREATE VIEWstatements, and the engine automatically forcesOR REPLACEunder the hood to ensure seamless non-destructive updates. - Interactive TUI: Review proposed schema changes (
[NEW TABLE],[DROP VIEW],[RENAME TABLE]) in a gorgeous, side-by-side interactive terminal UI before deploying. - Built-in IDE & Explorer: Seamlessly explore your live DuckDB database, write queries, and save your scratchpad files directly within a powerful integrated terminal IDE.
- DuckPacks (
.duckpack): Compile your entire project into a single, immutable DuckDB snapshot artifact containing fully resolved environment variables and encapsulated pre/post deployment scripts. Deploy it instantly to production without the raw SQL files.
Download the latest pre-compiled binary for your operating system directly from the GitHub Releases page, or use the quick-install script below:
Linux:
curl -L https://github.com/Benjas86/duckpack/releases/latest/download/duckpack-linux-amd64 -o duckpack
chmod +x duckpack
sudo mv duckpack /usr/local/bin/macOS (Intel):
curl -L https://github.com/Benjas86/duckpack/releases/latest/download/duckpack-macos-amd64 -o duckpack
chmod +x duckpack
sudo mv duckpack /usr/local/bin/macOS (Apple Silicon / M1+):
curl -L https://github.com/Benjas86/duckpack/releases/latest/download/duckpack-macos-arm64 -o duckpack
chmod +x duckpack
sudo mv duckpack /usr/local/bin/Windows:
Download duckpack-windows-amd64.exe from the Releases page and add it to your system PATH.
No Rust installation is required!
Initialize a new declarative project directory:
duckpack init --project-dir my_projectThis automatically scaffolds the necessary directories (tables/, views/, macros/, scripts/) and configuration files.
Write your desired state into standard .sql files:
my_project/tables/users.sql
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR,
created_at TIMESTAMP
);Apply your schema to a target DuckDB database. This will open the interactive TUI so you can review the proposed execution plan:
duckpack apply --project-dir my_project --db local.duckdbDuckPack ships with a fully integrated terminal IDE! After deploying your schema, you often want to explore the live database to verify that the changes applied correctly.
Instead of switching to a different terminal window or dealing with DuckDB file locks, you can jump straight into the IDE in two ways:
- Standalone: Run
duckpack explore -p my_project -d local.duckdbto open the IDE directly. - Seamless Transition: After running
duckpack apply, simply presse(Explore) from the TUI!
- Integrated Query Editor: Write multi-line SQL queries directly in the application with a built-in text editor featuring Syntax Highlighting (bold cyan keywords) and Intelligent Autocomplete. Press
Ctrl+Spaceto dynamically cycle through matches from your database schema (tables, views, and columns)! - Multi-Tab Editor System & Independent Results: Manage multiple queries simultaneously! Each tab maintains its very own independent state for query results, scrolling, and column headers! Hit
Ctrl+Tto open a new tab,Ctrl+Wto close it, and navigate between them usingCtrl+N/Ctrl+P. - Full Mouse Support: The entire IDE is highly interactive. You can instantly switch context by clicking on the Tab headers directly. The action bar at the bottom also provides intuitive
[+ New]and[❌ Close]buttons you can click with your mouse! - Instant Transitions: Hitting
efrom theapplyscreen instantly transfers your locked DuckDB connection over to the IDE, allowing you to seamlessly begin querying your tables without restarting. - Interactive & Expandable Explorer: The left-hand sidebar acts as your navigation hub. You can click on any Table or View (or press
Enter) to expand it hierarchically and dynamically query DuckDB for all nested columns and their exact data types! Click on any saved.sqlfile to load it instantly into your active tab. - Execution & Isolate Queries: Hit
Ctrl+Eto execute your query! The dynamic engine parses the typed DuckDB rows and presents your results instantly in a formatted grid. You can navigate large datasets freely usingUp/Down/PgUp/PgDnand scroll horizontally usingLeft/Right. To isolate a query: Highlight text usingShift+ Arrow Keys and pressCtrl+Eto execute only the highlighted snippet! - Real-time Syntax Error Detection: If DuckDB throws a syntax parsing error during execution, the engine intercepts the stack trace, extracts the exact offending token, and injects a dynamic regex highlight patch—turning that specific broken word bright red and halting execution until it is fixed!
- Auto-Formatting: Hit
Ctrl+Fto instantly pass your raw query through the internalsqlformatparser and auto-indent your code beautifully. - Auto-Save: Hit
Ctrl+Sto instantly save your active editor contents to a scratchpad.sqlfile in yourqueries/directory.
For remote deployments (like production servers running Quack/DuckDB), executing migrations over a live network connection is risky and slow. Instead, you can compile your project into an immutable .duckpack:
duckpack compile --project-dir my_project --out release_v1.duckpackThis resolves all environment variables and encapsulates your schema.
You might be wondering: "If I compile my entire project into an artifact and apply it to production, won't it just destructively replace my live database?"
No! A .duckpack is actually an offline, empty DuckDB database file containing your fully resolved CREATE statements. It perfectly represents your Desired State.
When you run apply against your production server using a DuckPack, the engine:
- Opens the
.duckpack(Desired State). - Opens your live
prod.duckdb(Current State). - Calculates the Diff: It dynamically compares the schemas of the two databases in-memory.
- It then applies only the delta non-destructively. If you added a column, it issues an
ALTER TABLE ADD COLUMN. If you renamed a table, the Git-style similarity engine issues anALTER TABLE RENAME TO. Your live data is never wiped out.
Because DuckDB is an embedded database without a traditional client-server protocol, the safest way to deploy changes is to run them locally on the server's disk.
By installing this duckpack CLI on your remote server as a companion tool, your CI/CD pipeline becomes incredibly powerful:
- GitHub Actions compiles your offline SQL files into a
release_v1.duckpack. - The pipeline securely transfers the
.duckpackto your remote server via SCP/SSH. - The pipeline executes the companion CLI remotely via SSH to deploy the artifact:
ssh user@production-server "duckpack apply --project-dir /tmp/release_v1.duckpack --db /var/lib/duckdb/prod.duckdb --auto-approve"
(Note: The --auto-approve flag ensures the CLI bypasses the interactive TUI and runs entirely headless.)
This architecture completely eliminates network latency during deployment, prevents file-locking issues, and gives you a fully automated, Git-backed declarative pipeline for your embedded database!
If you want to deploy directly to a local server or VM without setting up GitHub Actions or a CI/CD pipeline, you can use the native deploy command!
duckpack deploy --project-dir my_project --remote user@10.0.0.5 -P 2222 --db /var/lib/duckdb/prod.duckdbThis command automatically handles the entire "Companion Install" pipeline for you:
- It locally compiles your project into a temporary DuckPack.
- It uses your system's built-in
scpto securely transfer the DuckPack to the remote server. - It uses your system's built-in
sshto execute the remote companion CLI and apply the changes headless. - It safely cleans up the temporary files from both machines!
When you run init, the following structure is created:
tables/: Place yourCREATE TABLEdefinitions here.views/: Place yourCREATE VIEWdefinitions here (engine auto-forcesOR REPLACE).macros/: Place yourCREATE MACROdefinitions here.queries/: Save your ad-hoc.sqlqueries and scratchpad files here. These are ignored during deployment and are exclusively available within the IDE.scripts/pre-deploy/: Raw SQL scripts that run before any schema diffs are applied.scripts/post-deploy/: Raw SQL scripts that run after schema diffs are applied..env: Define environment variables for${VAR}interpolation in your SQL..duckdbignore: Specify tables or views to ignore during diffing (wildcards supported).
You can securely explore and apply your declarative schema directly to a remote Quack DuckDB instance! We have fully integrated native Quack database discovery.
You can connect seamlessly by supplying your Quack token via the --quack-token flag (or the DUCKDB_QUACK_TOKEN environment variable):
duckpack apply --project-dir my_project --db quack:localhost:9494 --quack-token super_secretQuack is currently an experimental extension and does not yet support ALTER TABLE statements. Because duckpack relies on non-destructive ALTER TABLE commands to safely apply schema diffs (adding columns, renaming tables, etc.), schema modifications over a live Quack connection will fail with a Not implemented error.
For production and remote deployments where schema modifications are required, we highly recommend bypassing Quack's execution engine entirely and using the Native Remote Deploy (duckpack deploy) command. This uses standard SSH to ship your schema and execute the migration locally on the remote server's disk, granting you 100% full DuckDB functionality.

0 comments
log in to comment.