Declarative Schema Management, Interactive Terminal IDE, and In-Memory Inspection for DuckDB
DuckPack transforms how you develop with and manage DuckDB. Instead of maintaining fragile imperative UP and DOWN migration files, you define your desired database state as plain SQL files. Acting as a modern SQL Server Data Tools (SSDT) for DuckDB, DuckPack automatically computes structural deltas, detects renames heuristically, and applies non-destructive schema migrations.
DuckPack includes a rich terminal IDE for live database exploration and first-class Python bindings to query, migrate, and inspect in-memory and persistent databases directly inside your Python pipelines, test suites, and Jupyter notebooks.
📌 Table of Contents
- ✨ Features
- 🚀 Quick Start & Installation
- 📋 CLI Command Reference
- 🏛️ Architecture & Design Philosophy
- 🧑💻 DuckPack Terminal IDE
- Keyboard Shortcuts Cheat Sheet
- Primary Key & Foreign Key Visual Identifiers
- Dynamic Explorer Width Resizing & Snappy Scrolling
- Catalog-Aware Multi-Database Exploration & Cross-DB Joins
- Live Database Attachment with Provider Presets (
Ctrl+A/d) - Cloud Secrets Management & S3 Bucket Explorer (
Ctrl+K) - Multi-Tab Query System & Isolated Results
- Interactive Schema Visualizer & Mermaid.js ERD
- Dynamic Status Bar & Error Interception
- 🐍 Python Integration
- 🦆 Quack Remote Server Integration
- 📁 Declarative Project Structure
- 📦 DuckPacks (
.duckpack) for CI/CD - NOTE
✨ Features
- Declarative Schema Management ("SSDT for DuckDB"): Define your schemas, tables, views, and macros as raw
.sqlfiles. No migration timestamps, sequence numbers, or rollback scripts to maintain. - Table Constraint Diffing & Copy-and-Swap Migrations: Automatically introspects
PRIMARY KEY,UNIQUE,FOREIGN KEY, andCHECKconstraints. Generates in-placeALTER TABLEstatements for safe additions and transactional copy-and-swap (__duckpack_swap) staging tables for complex constraint modifications. - Catalog-Aware Multi-Database Targeting: Seamlessly target specific attached databases (via
--database <name>,duckpack.toml [target] database = "...", or Pythonduckpack.apply(con, database="analytics")) with strict catalog isolation. - Clear Engine Boundary (SSDT vs Federation): Full declarative DDL lifecycle management specifically engineered for DuckDB, Quack, and MotherDuck. External attached engines (MSSQL, PostgreSQL, MySQL, SQLite) are first-class citizens in Explore for ad-hoc querying, cross-DB joins, and DML (
INSERT INTO,UPDATE), with schema DDL safely managed by external native tools. - Interactive Apply Parity (CLI & Notebook): Review visual colored diffs and apply migrations interactively with live confirmation prompts in terminal, Python scripts, or Jupyter notebooks (with automated external terminal pop-out).
- Schema Drift Detection (
duckpack diff): Instant dry-run inspection to detect divergence between your declarative codebase and live databases without mutating state. - Git-Style Smart Renames: Uses Jaro-Winkler similarity matching (>80%) to detect renamed tables or columns, issuing non-destructive
ALTER TABLE RENAMEstatements instead of dropping and recreating data. - Built-in Interactive Terminal IDE: Explore live databases, write queries with syntax highlighting and autocompletion (
Ctrl+Space), and manage independent query tabs. - Unified IDE Authoring & Project Mode (
F3: DB | F4: Project): Toggle between live database catalog inspection and declarative project authoring. Scaffold tables, views, macros, and schemas (a/n), edit with dirty tab indicators (*), validate project syntax and dependencies against an in-memory Shadow DB (Ctrl+B/v), inspect passive Git status badges ([M],[+],[D]), and run declarative diff & apply (F6/Ctrl+D) directly without quitting the IDE. - Visual Primary Key & Foreign Key Indicators: Inspect table structures in the Explorer tree with visual icons (
🔑for Primary Keys,🔗for Foreign Keys with reference targets[FK -> table.col], and composite🔑🔗badges). - Dynamic Explorer Width Resizing & Snappy Scrolling: Adjust sidebar width on the fly via
W(cycling 25%/35%/50% presets) or+/-and[/](5% increments from 15% to 60%). Navigate wide schemas quickly with 4-char arrow scrolling,Shift+Arrow10-char jumps, andHomemargin snap. - Catalog-Aware Multi-Database Exploration: Inspect multiple attached catalogs (local DuckDB, in-memory
memoryscratchpad, attached SQLite/Postgres/MySQL/MSSQL, and remote Quacktarget_dbinstances) in a unified hierarchical tree with catalog-qualified query generation and cross-database joins. - Live Catalog Attach with Provider Presets (
Ctrl+A/d/b): Dynamically attach third-party databases, DuckDB files, MotherDuck, or remote Quack instances directly inside the IDE with provider presets and auto-installed extensions; cycle target catalogs on the fly. - Cloud Secrets Management & S3 Bucket Explorer (
Ctrl+K): Visually configure cloud storage credentials (AWS S3, Cloudflare R2, MinIO, Wasabi, Custom S3) with masked inputs (*) and dual-persistence (CREATE PERSISTENT SECRET+.env). Live-explore remote S3 buckets (glob()) and sample remote files (read_parquet,read_csv) with a single keypress. - Temporary Table Discovery & Python Two-Way Sync: Temporary tables and views (
CREATE TEMP TABLE ...) appear seamlessly in the active database's Explorer tree with a distinct[temp]badge. Instant DDL auto-refresh updates the sidebar onCREATE/DROP/ALTER, and interactive Python exploration (duckpack.explore(con)) performs safe two-way session synchronization across the Quack bridge. - Python Integration with Jupyter / VS Code Support: Import
duckpackinto Python pipelines, pytest fixtures, or Jupyter notebooks (duckpack.explore(con)). Automatically spawns a connected native terminal window in non-interactive notebook environments. - Embedded DuckDB Version Transparency: Engine version reporting via
duckpack --versionand Python__duckdb_version__, backed by proactive storage format compatibility diagnostics. - In-Memory & Remote Attach: Connect to local files,
:memory:instances, MotherDuck (md:...), or remote DuckDB instances over the Quack protocol. - Remote Query Directive (
-- @remote): Forward session-scoped statements (e.g. S3 secrets, settings, and catalog scans) directly to remote engines with automated diagnostic hints. - ASCII & Mermaid.js Schema Visualizer: Press
Ctrl+G(orF2) to view table relationships and automatically copy formatted Mermaid.js Entity-Relationship diagrams to your system clipboard. - Environment Variable Templating: Write
${ENV}_orders_${REGION}directly in SQL; DuckPack dynamically interpolates values from.envfiles. - Immutable Snapshots (
.duckpack): Compile your entire project into a single, portable snapshot artifact for deterministic zero-dependency deployments.
🚀 Quick Start & Installation
1. Standalone Binary
Download pre-compiled binaries from the GitHub Releases page, or install via terminal:
Linux (x86_64 / AMD64):
curl -L https://github.com/Benjas86/duckpack/releases/latest/download/duckpack-linux-amd64 -o duckpack
chmod +x duckpack
sudo mv duckpack /usr/local/bin/
Linux (ARM64 / aarch64):
curl -L https://github.com/Benjas86/duckpack/releases/latest/download/duckpack-linux-arm64 -o duckpack
chmod +x duckpack
sudo mv duckpack /usr/local/bin/
Linux (Musl Static — Alpine, Docker, minimal distros):
curl -L https://github.com/Benjas86/duckpack/releases/latest/download/duckpack-linux-amd64-static -o duckpack
chmod +x duckpack
sudo mv duckpack /usr/local/bin/
macOS (Apple Silicon M1/M2/M3/M4):
curl -L https://github.com/Benjas86/duckpack/releases/latest/download/duckpack-macos-arm64 -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/
Windows:
Download duckpack-windows-amd64.exe from GitHub Releases and add it to your system PATH.
2. Python Package (pip / uv)
Installing DuckPack via Python installs both the Python package (import duckpack) and the standalone CLI binary (duckpack command in your virtualenv bin/):
# Using pip
pip install duckpack
# Using uv
uv add duckpack
Requires Python ≥ 3.10. Pre-compiled wheels are available for Linux, macOS, and Windows.
3. Cargo (Rust Developers)
cargo install duckpack
📋 CLI Command Reference
| Command | Description | Key Arguments / Flags | Default |
|---|---|---|---|
duckpack init |
Scaffold a new declarative database project | -p, --project-dir <DIR> |
. |
duckpack build |
Validate SQL syntax against an in-memory Shadow DB | -p, --project-dir <DIR> |
. |
duckpack diff |
Compare declarative project state against target database without applying changes | -p, --project-dir <DIR>-d, --db <URI>--database, --catalog <NAME>--quack-token <TOKEN>--insecure |
.local.duckdbNoneNonefalse |
duckpack apply |
Compute diff and apply migrations to target database | -p, --project-dir <DIR>-d, --db <URI>--database, --catalog <NAME>--auto-approve--interactive--force-drop--out <FILE>--quack-token <TOKEN>--insecure |
.local.duckdbNonefalsefalsefalseNoneNonefalse |
duckpack explore |
Open the interactive terminal IDE / query editor | -p, --project-dir <DIR>-d, --db <URI>--database, --catalog <NAME>--remote <SSH_TARGET>-P, --port <PORT>--auto-install--quack-token <TOKEN>--insecure |
.local.duckdbNoneNone22falseNonefalse |
duckpack compile |
Package project into an immutable .duckpack snapshot |
-p, --project-dir <DIR>-o, --out <FILE> |
.(Required) |
duckpack deploy |
Deploy compiled project to a remote server over SSH | -p, --project-dir <DIR>-r, --remote <HOST>-d, --db <URI>-P, --port <PORT>--auto-install |
.(Required) local.duckdb22false |
duckpack python status |
Check if Python bindings are installed in active environment | — | — |
duckpack python install |
Install/upgrade duckpack Python package via pip |
--upgrade |
false |
🏛️ Architecture & Design Philosophy
DuckPack is built on core design principles established to provide reliable, enterprise-grade declarative schema management and database exploration for the modern DuckDB ecosystem.
DuckPack as "SSDT for DuckDB"
For decades, Microsoft's SQL Server Data Tools (SSDT) defined the gold standard for enterprise database lifecycle management: developers maintain their desired database state as plain SQL DDL files in source control, and a compiler/engine determines the exact delta and migration plan to bring a live database into alignment.
Traditional data tooling often relies on imperative migration files (001_create_users.sql, 002_add_email.sql, 002_rollback.sql). In analytical and serverless data environments, this model leads to friction:
- Migrations drift out of sync when schemas are iterated rapidly.
- Rollbacks are difficult or untested.
- Branch merges in Git create migration ordering conflicts.
DuckPack brings the SSDT paradigm to DuckDB:
- Desired-State First: You define the current desired state of tables, views, schemas, and macros as plain
.sqlfiles in your repository (tables/users.sql,views/active_orders.sql). - Automated Delta Calculation: DuckPack parses your codebase into an in-memory Shadow database, inspects the target database catalog, and computes the exact difference (tables to create, columns to alter, views to replace).
- Smart Heuristic Renames: DuckPack employs Jaro-Winkler string similarity analysis (>80% threshold) on column signatures. If you rename
user_emailtoemail_address, DuckPack issues a non-destructiveALTER TABLE RENAME COLUMNrather than dropping the column and losing data. - Deterministic & Safe Deployments: In production and CI/CD pipelines, changes can be packaged into an immutable
.duckpacksnapshot artifact or verified dry-run viaduckpack diff.
Engine Scope: DuckDB DDL vs External Query Federation
DuckDB has powerful native federation capabilities: via official extensions, DuckDB can attach external relational engines such as PostgreSQL, MySQL, SQLite, and Microsoft SQL Server (MSSQL via ODBC).
A common question is: Can DuckPack act as a declarative SSDT schema manager for MSSQL or Postgres through DuckDB?
The architectural boundary is strictly defined:
| Capability | DuckDB Native / Quack / MotherDuck | External Engines (MSSQL, Postgres, MySQL, SQLite) |
|---|---|---|
| Interactive Terminal IDE (Explore) | ✅ Full Support | ✅ Full Support (browse catalogs, inspect tables/columns) |
| Cross-Database Joins & Queries | ✅ Full Support | ✅ Full Support (SELECT * FROM mssql.tbl JOIN duckdb.tbl) |
Data Manipulation (DML: INSERT, UPDATE) |
✅ Full Support | ✅ Full Support |
Declarative Schema Management (apply, diff) |
✅ Core Purpose | ❌ Intentionally Excluded & Guarded |
Why External DDL is Out of Scope for apply:
- Dialect Mismatches: DuckDB's SQL parser and pushdown DDL cannot express enterprise engine-specific features such as SQL Server
IDENTITY(1,1),CLUSTERED INDEX,NVARCHAR(MAX) FILESTREAM, partitioned tables, or T-SQL triggers. - Silent Failure & Loss of Semantics: Applying DuckDB DDL to an attached external engine strips database-specific column constraints, default expressions, and index options.
- Guardrails: If you accidentally attempt to run
duckpack apply --database mssql_db, DuckPack inspectsduckdb_databases(), detects the engine type, and halts immediately with an informative message guiding you to use native tools (SSDT, Flyway, Liquibase, Alembic) for external engines while keeping DuckPack for your DuckDB workloads.
Multi-Database Catalog Targeting
Modern analytical setups attach multiple databases simultaneously (e.g. ATTACH 'analytics.duckdb' AS analytics;). DuckPack provides fine-grained catalog targeting across the CLI, configuration files, Python API, and TUI:
Resolution Hierarchy:
- CLI Flag:
--database <NAME>or--catalog <NAME>(e.g.duckpack apply --database analytics). - Python Parameter:
duckpack.apply(con, database="analytics")orduckpack.diff(con, database="analytics"). - Configuration File:
duckpack.tomltarget or environment setting:[target] database = "analytics"
- Active Fallback: The active database returned by
current_database()(ormemoryfor standalone in-memory sessions).
Strict Catalog Isolation:
When a specific catalog is targeted:
- DuckPack introspects only tables, views, and macros belonging to that specific catalog (
database_name = '<name>'), ignoring objects in other attached databases. - Migrations are executed within the target database context using safe
USE "<database>"switching, ensuring unqualified DDL statements deploy cleanly without touching default or scratchpad databases. - In the TUI Explorer, press
bto cycle between attached writable DuckDB catalogs for diff and apply operations.
Table Constraint Diffing & Copy-and-Swap Migrations
DuckDB's internal duckdb_columns() view maps column names to data types, but does not capture relational constraints (PRIMARY KEY, FOREIGN KEY, UNIQUE, or CHECK). DuckPack bridges this by querying duckdb_constraints() across both your declarative models (in the in-memory shadow database) and the target database:
1. In-Place Constraint Alterations ([ADD CONSTRAINT])
When a new PRIMARY KEY or UNIQUE constraint is added to a table that previously lacked one, DuckPack applies an in-place DDL mutation without recreating the table:
ALTER TABLE users ADD PRIMARY KEY (user_id);
ALTER TABLE users ADD UNIQUE (email_address);
These changes are classified as non-destructive additions and are enabled by default during interactive apply.
2. Atomic Copy-and-Swap Migrations ([RECREATE TABLE])
DuckDB does not natively support in-place ALTER TABLE ... ADD FOREIGN KEY, ADD CHECK, or constraint drops. For these modifications, DuckPack generates an atomic, transactional copy-and-swap migration using a staging table:
BEGIN TRANSACTION;
CREATE TABLE orders__duckpack_swap (
order_id INTEGER PRIMARY KEY,
user_id INTEGER,
amount DECIMAL(18,2),
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
INSERT INTO orders__duckpack_swap (order_id, user_id, amount)
SELECT order_id, user_id, amount FROM orders;
DROP TABLE orders;
ALTER TABLE orders__duckpack_swap RENAME TO orders;
COMMIT;
- Data Protection: Because table recreation replaces the existing table structure, DuckPack classifies
[RECREATE TABLE]as a protected operation. In interactive mode, it is deselected by default, and in automated pipelines (duckpack apply --auto-approve), it requires the--force-dropflag to proceed. - Rollback Safety: If data in the existing table violates the new constraint, DuckDB automatically aborts and rolls back the transaction, keeping your existing table and data intact.
Interactive Apply & Notebook Parity
DuckPack bridges the gap between terminal CLI power users, CI/CD pipelines, and Python data scientists:
- CLI Workflow: By default,
duckpack applyopens a rich, color-coded visual confirmation screen listing every added table, altered column, and replaced view before applying changes. Pressyto confirm,n/Escto cancel, oreto jump directly into the Explore IDE. (Pass--auto-approvefor non-interactive CI/CD runs). - Python Script Parity: Calling
duckpack.apply(con, auto_approve=False)(orinteractive=True) brings the exact same interactive visual approval workflow to Python scripts. - Jupyter & VS Code Notebook Parity: In notebook environments lacking an interactive TTY, DuckPack automatically spins up a background bridge and spawns a connected external terminal window (Ghostty, Foot, Kitty, WezTerm, Alacritty, GNOME Terminal, Konsole, Windows Terminal, or macOS Terminal.app). Developers get the full interactive confirmation UI without notebook hang-ups.
Embedded DuckDB Version Transparency & Diagnostics
DuckPack embeds DuckDB directly as an in-process engine:
- Storage Stability: DuckDB has guaranteed forward and backward storage format compatibility for
.duckdbfiles across minor versions following DuckDB v1.0.0. - Engine Transparency: Check the exact embedded DuckDB engine version anytime via:
duckpack --version # DuckPack v0.2.0 (embedded DuckDB v1.2.0)
Or in Python:import duckpack print(duckpack.__version__) # e.g. "0.2.0" print(duckpack.__duckdb_version__) # e.g. "1.2.0"
- Proactive Storage Diagnostics: If an older database file with an incompatible legacy storage format is encountered, DuckPack catches the internal engine error and prints clear migration guidance rather than an unhelpful internal crash dump.
🧑💻 DuckPack Terminal IDE
DuckPack includes a fully integrated terminal IDE built with Ratatui and Crossterm.
Launch it directly:
duckpack explore --db local.duckdb
Or explore a remote Quack server:
duckpack explore --db quack:0.0.0.0:9494 --quack-token <TOKEN>
Or transition instantly from duckpack apply by pressing e.
┌ Explorer (25%) [W: Width | +/-: Resize | R: Refresh | q: Query] ──┬─ [Tab 1: cross_join.sql] ── [+ New] ── [❌ Close] ────┐
│ ▼ 📁 target_db [Active] (quack) │ SELECT │
│ ▼ 📦 Tables (2) │ ro.order_id, │
│ ├─ customers (1,450 rows) │ ro.amount, │
│ │ ├─ 🔑 customer_id (BIGINT) [PK] │ lu.user_email │
│ │ └─ email (VARCHAR) │ FROM target_db.orders ro │
│ └─ orders (8,920 rows) │ JOIN memory.local_users lu │
│ ├─ 🔑 order_id (BIGINT) [PK] │ ON ro.customer_id = lu.id │
│ └─ 🔗 customer_id (BIGINT) [FK -> cust...] │ LIMIT 100; │
│ ▼ 👁️ Views (1) │ │
│ └─ active_orders │ │
│ ▼ 📁 memory (duckdb) │ │
│ ▼ 📦 Tables (1) │ │
│ └─ local_users (50 rows) │ │
├─────────────────────────────────────────────────────┴───────────────────────────────────────────────────────┤
│ Query Results [Page 1/1] (Showing 50 rows) │
│ order_id │ amount │ user_email │
│ 1001 │ 149.99 │ alice@example.com │
│ 1002 │ 89.50 │ bob@example.com │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Keyboard Shortcuts Cheat Sheet
| Scope | Shortcut | Action |
|---|---|---|
| Global / Navigation | Tab |
Cycle focus between Explorer, Editor, and Results panes |
? |
Toggle the Help Modal | |
F3 / 1 |
Switch Explorer to Database Catalog view (target_db, memory, attached DBs) |
|
F4 / 2 |
Switch Explorer to Project Files view (schemas/, tables/, views/, macros/, triggers/, queries/, seeds/, duckpack.toml) |
|
F6 / Ctrl+D |
In-IDE Declarative Diff & Apply: Review diff modal with Space toggling, dependency locks, and migration apply |
|
Ctrl+B / v |
Validate Project: Verify SQL syntax and cross-asset dependencies against Shadow DB | |
Alt+W |
Cycle Explorer width presets (25% $\rightarrow$ 35% $\rightarrow$ 50%) |
|
Alt+] / Alt+[ |
Widen / narrow Explorer pane by 5% | |
Ctrl+C / Esc |
Cancel operation / exit modal / confirm quit IDE | |
| Editor | Ctrl+E / F5 |
Execute query in active tab (or execute highlighted selection) |
Shift + Arrows |
Highlight text to isolate and execute only the selection on Ctrl+E |
|
F2 |
Switch Attached Database: Quick-picker modal to switch active tab's target catalog (▲/▼ or j/k, Enter, Esc) |
|
Ctrl+Space |
Trigger Intelligent Autocomplete (prioritizes active tab's target catalog entities) | |
Ctrl+F |
Auto-format SQL statement using SQL parser | |
Ctrl+S |
Save active query or project file to disk (clears dirty * indicator) |
|
Ctrl+Y / Ctrl+C |
Copy selected text (or active cell/line) to system clipboard | |
Ctrl+V |
Paste from OS system clipboard into editor | |
Ctrl+G |
Open Schema Visualizer (ASCII tree + copies Mermaid.js ERD to clipboard) | |
| Tabs | Ctrl+T |
Open a new blank query tab (inherits target database of current tab) |
Ctrl+W |
Close the active query tab | |
Ctrl+N / Ctrl+P |
Switch to the Next / Previous tab | |
| Explorer | Up / Down |
Navigate through databases/categories, table groups, tables, and columns |
Enter / Space |
Expand or collapse tree folder / open SQL file in editor tab | |
a / n |
Quick Add Asset Modal (in Project mode: Table, View, Macro, Trigger, Schema, Query, Seed) | |
v |
Validate Project syntax and dependencies against Shadow DB (in Project mode) | |
W / w |
Cycle width presets: 25% $\rightarrow$ 35% $\rightarrow$ 50% $\rightarrow$ 25% |
|
+ / = / ] |
Widen Explorer by +5% (up to 60%) | |
- / [ |
Narrow Explorer by -5% (down to 15%) | |
Left / Right / h / l |
Scroll horizontally by 4 characters | |
Shift + Left / Right |
Fast horizontal scroll by 10 characters | |
Home |
Snap horizontal scroll back to left margin | |
q / s |
Query table/view (generates catalog-qualified SQL into editor) | |
Ctrl+A |
Attach Database dialog with Provider Presets (DuckDB, SQLite, Postgres, MySQL, MotherDuck, Quack) | |
Ctrl+K |
Cloud Secrets & S3 Buckets: Add S3/R2/MinIO credentials with masking, .env persistence, and bucket exploration |
|
d |
Detach Database from current session | |
b |
Cycle Target Catalog for diff/apply operations | |
r / R |
Refresh Explorer: re-scans live database (in DB mode) or disk & git status (in Project mode) | |
| In-IDE Diff & Apply | Space |
Toggle selection [x] / [ ] of highlighted migration with dependency locking [L] |
a |
Toggle All: select or deselect all eligible migrations | |
Enter |
Apply selected changes directly to target database catalog | |
Esc |
Close diff review dialog without applying changes | |
| Apply Review Screen | y |
Confirm and apply all pending declarative migrations |
n / Esc |
Abort and cancel migrations without modifying database | |
e |
Explore IDE: launch full terminal query IDE on target database | |
| Results Grid | Arrows |
Scroll vertically through rows and horizontally through columns |
Shift + ◄ / ► |
Fast horizontal scroll across wide result tables | |
Home / End |
Jump directly to the First / Last column | |
PgUp / PgDn |
Fast scroll vertically | |
n / p |
Navigate to Next / Previous page (500-row pagination chunks) | |
Ctrl+O |
Export active query results to a CSV file in queries/ |
|
| Mouse Support | Mouse Wheel | Vertical & horizontal (tilt or Shift+Wheel) scrolling in focused pane |
| Click Tabs | Click on tab headers to switch or click [+ New] / [❌ Close] buttons |
|
| Click Explorer Header | Click [F3: DB] or [F4: Project] in header to switch modes, or click [+ Attach] / [+ New] |
Project Authoring Mode & In-IDE Declarative Workflow (F4)
DuckPack Explore features a dual-mode sidebar that brings the complete declarative workflow directly into your terminal workspace:
- Mode Switching (
F3/1vsF4/2):[F3: Database Catalog]: Inspect live target and attached database catalogs, schemas, tables, views, triggers, columns, and constraints (🔑,🔗).[F4: Project Files]: Browse declarative asset files organized categorically (📁 Schemas,📦 Tables,👁️ Views,🔧 Macros,⚡ Triggers,📄 Queries,🌱 Seeds,⚙️ Config).
- Complete Scaffolding & Zero-Exit Authoring: All canonical project categories (
schemas/,tables/,views/,macros/,triggers/,queries/,seeds/) are always rendered in the project sidebar tree—even if the underlying folder does not exist on disk yet. Empty categories show an interactive(empty - press 'a' to add)placeholder so developers never need to leave DuckPack to scaffold new directories or assets. - Passive Git Awareness: The Explorer header dynamically shows the current branch (e.g.
Project (main*) (25%)), and files display status badges ([M]modified,[+]untracked,[D]deleted). DuckPack never commits or pushes, preserving index safety and SSH autonomy. - Guided Asset Scaffolding (
aorn): Quick Add modal to scaffold a new Table, View, Macro, Trigger, Schema, Query, or Seed with clean boilerplate SQL/CSV. It automatically detects the selected folder category, creates the directory on disk if needed, writes the boilerplate, and opens the file in a new editor tab. - Direct File Editing & Dirty Tab Tracking: Opened files bind directly to disk. Tabs show
*when dirty (users.sql *). PressingCtrl+Swrites changes to disk, clears the dirty indicator, and refreshes project file badges. - In-IDE Syntax Validation (
Ctrl+Borv): Compiles the entire project against an in-memory Shadow DB to verify SQL syntax, macros, and cross-asset dependencies with error line jumps. - In-IDE Diff & Selective Apply (
F6orCtrl+D): Computes declarative diffs against the active target database and presents an interactive diff modal directly inside the IDE. SupportsSpaceto select/deselect individual changes with automatic dependency locking ([L]) and applies only the selected migrations onEnter.
Primary Key & Foreign Key Visual Identifiers
The Explorer sidebar introspects constraints from duckdb_constraints() for both local DuckDB databases and remote Quack instances, rendering relational relationships directly beside column names:
- Primary Key (
🔑):🔑 customer_id (BIGINT) [PK]
- Foreign Key (
🔗): Explicitly indicates the referenced table and column target:🔗 user_id (INTEGER) [FK -> users.user_id]
- Composite Primary Key + Foreign Key (
🔑🔗): When a column serves as both a primary key and a foreign key:🔑🔗 tenant_id (BIGINT) [PK, FK -> tenants.id]
Dynamic Explorer Width Resizing & Snappy Scrolling
When inspecting tables with long column names, complex data types (MAP(VARCHAR, JSON)), or nested catalog schemas, standard sidebar widths can feel cramped:
- Width Presets (
WorAlt+W): Instantly cycle the Explorer width between25%,35%, and50%without leaving the keyboard. - Fine Adjustment (
+/-or[/]): Fine-tune sidebar width in 5% increments between 15% and 60% (e.g.Alt+]orAlt+[from any pane). - Responsive Header: The Explorer title updates dynamically with the active percentage and shortcut hints:
Explorer (35%) [W: Width | +/-: Resize | R: Refresh | q: Query]
- Snappy Horizontal Scrolling:
Left/Right(orh/l): Shifts by 4 characters.Shift + Left/Shift + Right: Jumps by 10 characters.Home: Instantly snaps back to column 0.- Mouse wheel tilt or
Shift + Wheel: Smooth horizontal scrolling across long metadata strings.
Catalog-Aware Multi-Database Exploration & Cross-DB Joins
DuckPack dynamically detects your active catalogs:
- Single-Database Mode: When working with an isolated database file, DuckPack renders a streamlined flat view (
📦 Tablesand👁️ Views). - Multi-Database Mode: When multiple databases are attached—such as when connecting to a remote Quack server, attaching an external database via
Ctrl+A, or attaching in Python—DuckPack organizes the sidebar into an explicit catalog hierarchy:📁 <database_name> [Active] (<type>)- The
[Active]badge highlights the database currently selected ascurrent_database(). - Pressing
qor double-clicking any table/view automatically produces the catalog-qualified SQL (e.g.SELECT * FROM target_db.orders LIMIT 500;orSELECT * FROM memory.local_users LIMIT 500;). - Cross-Database Joins: Because DuckDB supports federated queries, you can join remote Quack tables, local scratchpad tables in
memory, and attached databases directly in the editor:SELECT * FROM target_db.remote_orders ro JOIN memory.local_users lu ON ro.customer_id = lu.id;
Live Database Attachment with Provider Presets (Ctrl+A / d)
Press Ctrl+A from anywhere in the IDE to open the interactive Attach Database modal dialog with field-adaptive provider presets and structured input boxes:
- Provider Presets (cycle via
◄/►orh/l):DuckDB (Local / In-Memory): Attach.duckdbfiles or:memory:scratchpads.Remote Quack Server: Connect to live remote Quack server instances with optional token credentials and SSL disable toggles.MotherDuck Cloud: Attach MotherDuck cloud databases (md:database_name) with optional service token injection.SQLite: Attach SQLite database files (.db,.sqlite) with automatic installation and loading of the DuckDBsqliteextension.PostgreSQL: Connect to remote Postgres servers via structured input fields (Host, Port, Database, User ID, Password, SSL Mode).MySQL: Connect to remote MySQL servers via structured input fields (Host, Port, Database, User ID, Password, SSL Mode).Microsoft SQL Server (MSSQL): Connect to remote SQL Server instances via structured input fields (Host, Port1433, Database, User IDsa, Password, Trust Server Certificate toggle).
- Structured Form Inputs: No need to manually format complex connection strings; dedicated input boxes for Host, Port, Database, Username, Password, and Alias automatically assemble standard connection parameters.
- Masked Token/Password Field: Passwords and service tokens are rendered with
*mask characters to protect against shoulder surfing or screen shares. - Read-Only Toggle: Press
Spaceto toggleREAD_ONLYmode. - Safe Detach: Select any attached database in the Explorer and press
d(orDelete) to safely detach it from the active session.
Per-Tab Attached Database Context & Quick-Picker (F2)
DuckPack enables seamless multitasking across multiple attached database catalogs:
- Per-Tab Isolation: Each editor tab independently tracks its own target database context (
target_database). Switching between tabs automatically changes the active DuckDB catalog search path (USE "<target_db>";). - Dual Visual Indicators:
- Tab Strip: Displays catalog badges beside filenames (e.g.
New Query 1 (mssql_db) * | report.sql (memory)). - Editor Header: Prominently displays the provider icon, catalog alias, and engine type (e.g.
Editor [query.sql *] ── DB: 🔌 mssql_db (mssql) [F2: Switch DB]).
- Tab Strip: Displays catalog badges beside filenames (e.g.
- Database Quick-Picker Modal (
F2): PressF2(or click🗄️ DB (F2)in the editor footer) from anywhere to summon a modal dialog listing all attached databases. Navigate with▲/▼orj/k, and pressEnterto switch the active tab's target catalog instantly. - Catalog-Aware Autocomplete: Pressing
Ctrl+Spaceprioritizes tables, views, and columns from the active tab's target database at the top of the suggestion list. - Context Inheritance: Creating a new tab (
Ctrl+T), querying a table from Explorer (q/s), or attaching a new database (Ctrl+A) automatically initializes the tab's target catalog. - Federated Cross-Database Queries: DuckDB's cross-database querying is completely preserved; queries can still freely
JOINacross any attached catalogs (SELECT * FROM mssql_db.dbo.orders JOIN memory.local_users ...).
Cloud Secrets Management & S3 Bucket Explorer (Ctrl+K)
DuckPack provides complete cloud data lake support directly in your terminal without requiring you to remember low-level CREATE SECRET SQL syntax:
- Dedicated "Secrets & Cloud Buckets" Sidebar Drawer (
🔐 Secrets & Cloud):- Displays all active secrets from
duckdb_secrets()(e.g.🔑 s3_secret [s3]). - Lists tracked cloud buckets (
🪣 s3://analytics-lake). - Displays quick action
➕ Add Cloud Secret (Ctrl+K).
- Displays all active secrets from
- Live S3 Bucket Explorer:
- Expanding a bucket node runs a background DuckDB
glob('{bucket}/*')query to list remote files and directories. - Formatted file icons identify
.parquet(📊),.csv(📝), and general files (📄). - Pressing
Enter,q, orson any cloud file instantly loads an optimized query into the editor tab:SELECT * FROM read_parquet('s3://my-bucket/events/2026/01/data.parquet') LIMIT 500;
- Expanding a bucket node runs a background DuckDB
- Cloud Secrets Modal (
Ctrl+Kor Explorera/n):- Provider Presets: Cycle between AWS S3, Cloudflare R2, MinIO, Wasabi, and Custom S3 Endpoint.
- Visual Masking: Secret access keys are visually masked with
*to protect against screen-sharing leaks. - Dual Persistence Architecture:
- DuckDB Persistent Secret: Creates persistent secrets in DuckDB via
CREATE OR REPLACE PERSISTENT SECRET(with fallback to session secrets). - Project
.envPersistence: Optionally appends or updatesAWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_REGION,AWS_ENDPOINT, andDUCKPACK_S3_BUCKETin the project.envfile (strictly git-ignored).
- DuckDB Persistent Secret: Creates persistent secrets in DuckDB via
- Automatic Extension Installation: Transparently executes
INSTALL httpfs; LOAD httpfs;so remote operations never fail.
🐍 Python Integration
DuckPack provides native Python bindings compiled via PyO3. It allows data engineers and developers to programmatically inspect in-memory DuckDB connections, run declarative migrations in test fixtures, and detect schema drift without leaving Python.
1. Interactive In-Memory Debugging
Drop into the full DuckPack terminal IDE during pipeline execution or inside a breakpoint() / pdb session:
import duckdb
import duckpack
# In-memory DuckDB database
con = duckdb.connect()
# Populate data in memory
con.execute("CREATE TABLE users AS SELECT 1 AS id, 'Alice' AS name;")
con.execute(
"CREATE TABLE telemetry AS SELECT range AS id, random() AS metric FROM"
" range(1000);"
)
# Launches the interactive DuckPack IDE directly in your current terminal:
duckpack.explore(con)
# When you quit the TUI (Esc / q), Python resumes execution seamlessly!
print("Resuming pipeline execution...")
Jupyter Notebook & VS Code Pop-Out Terminal Support
Running terminal applications inside Jupyter notebooks (such as in VS Code Interactive, JupyterLab, or Jupyter Notebooks) usually fails with os error 6: No such device or address because notebooks lack an interactive TTY.
DuckPack solves this seamlessly:
- When you call
duckpack.explore(con)inside a notebook cell, DuckPack automatically spins up an ephemeral local Quack bridge on a free local port, attaches to your live in-memory connectioncon, and spawns a native graphical terminal emulator window (Ghostty, Foot, Kitty, WezTerm, Alacritty, GNOME Terminal, Konsole, Windows Terminalwt.exe, macOS Terminal.app / iTerm2). - You get the full interactive TUI IDE experience directly connected to your live in-memory notebook tables!
- When you exit the IDE window (
Esc/q), the temporary bridge shuts down and notebook execution continues. - In headless environments (CI / Docker without display), DuckPack falls back gracefully to printing a formatted schema overview directly into the notebook output cell.
import duckdb
import duckpack
con = duckdb.connect()
con.execute(
"CREATE TABLE metrics AS SELECT range AS id, random() AS val FROM"
" range(500);"
)
# Option A: Zero arguments (auto-resolves target, endpoint, and credentials from duckpack.toml / .env)
duckpack.explore()
# Option B: Pass live in-memory connection (auto-attaches external databases from duckpack.toml)
duckpack.explore(con)
# Option C: Switch environment profile directly in Python
duckpack.explore(env="staging")
# Optional controls:
# duckpack.explore(con, open_window=False) # Force in-cell formatted overview (headless mode)
# duckpack.explore(con, wait=False) # Run terminal asynchronously in background
2. Declarative Migrations in Pytest & Pipelines (apply)
Maintain a single declarative SQL project and automatically apply it to fresh in-memory test databases:
import duckdb
import duckpack
import pytest
@pytest.fixture
def db():
# Spin up an isolated in-memory test database
con = duckdb.connect()
# Apply all schemas, tables, views, and macros from your declarative project:
result = duckpack.apply(con, project_dir="./duckdb_project", auto_approve=True)
assert result.success
yield con
con.close()
def test_user_creation(db):
db.execute("INSERT INTO users (id, name) VALUES (42, 'Bob');")
count = db.execute("SELECT count(*) FROM users;").fetchone()[0]
assert count == 1
For interactive review before applying changes in your Python scripts or Jupyter notebooks, set auto_approve=False (or interactive=True). In Jupyter or VS Code, DuckPack automatically launches a connected native terminal window:
# Launch interactive TUI diff review screen before applying:
result = duckpack.apply(con, project_dir="./duckdb_project", auto_approve=False)
3. Pipeline Schema Drift Detection (diff)
Check if an analytical database matches your version-controlled SQL definitions before running ETL/ELT pipelines:
import duckdb
import duckpack
con = duckdb.connect("production.duckdb")
# Detect schema drift
diff = duckpack.diff(con, project_dir="./duckdb_project")
if diff.has_changes:
print(f"Schema drift detected ({diff.change_count} changes):")
for change in diff.items:
print(f" - {change}")
raise RuntimeError("Database schema does not match codebase!")
4. Multi-Database Catalog Targeting in Python
When working with DuckDB connections that attach multiple databases, use the database (or catalog) parameter to isolate migrations and drift checks to that specific catalog:
import duckdb
import duckpack
con = duckdb.connect()
# Attach an external analytics database
con.execute("ATTACH 'analytics.duckdb' AS analytics;")
# Target only 'analytics' (ignores tables in default/memory catalog)
diff = duckpack.diff(con, project_dir="./analytics_repo", database="analytics")
if diff.has_changes:
print(f"Pending changes for analytics: {diff.change_count}")
# Interactively review diff and apply to 'analytics'
# (Spawns a connected terminal pop-out in Jupyter / VS Code)
result = duckpack.apply(
con,
project_dir="./analytics_repo",
database="analytics",
auto_approve=False # or interactive=True
)
5. Python API Reference
import duckpack
Engine Version Properties
duckpack.__version__: str: The version of DuckPack (e.g."0.2.0").duckpack.__duckdb_version__: str: The embedded DuckDB engine version (e.g."1.2.0").
Functions
-
duckpack.explore(target=None, project_dir=".", quack_token=None, insecure=False, open_window=True, wait=True, database=None, catalog=None, env=None) -> NoneLaunches the interactive TUI IDE against a live connection (duckdb.DuckDBPyConnection), database URI (str), orNone(auto-resolves fromduckpack.tomland.env). When passing an existing in-memory connectioncon, automatically attaches configured external databases fromduckpack.toml. In Jupyter Notebooks or VS Code Dev Containers, renders an interactive card with a 1-click▶ Open DuckPack in VS Code Terminalaction and live background bridge. Passenvto switch environment profiles (e.g.env="staging"). -
duckpack.stop_server() -> boolStops any active background Quack session bridge started byduckpack.explore(con)in a notebook. -
duckpack.apply(target=None, project_dir=".", auto_approve=True, force_drop=False, interactive=False, database=None, catalog=None, env=None) -> ApplyResultComputes schema diffs and applies declarative migrations. In interactive mode (auto_approve=Falseorinteractive=True), opens the visual review TUI. Whentarget=None, auto-resolves database targets fromduckpack.toml. Returns anApplyResult. -
duckpack.diff(target=None, project_dir=".", database=None, catalog=None, env=None) -> DiffSummaryCompares declarative project state against target database or attached catalog without mutating data. Whentarget=None, auto-resolves fromduckpack.toml. Returns aDiffSummary. -
duckpack.compile(project_dir, out) -> NoneCompiles project SQL definitions into an immutable.duckpacksnapshot file. -
duckpack.build(project_dir=".") -> NoneValidates SQL syntax and dependencies against an in-memory Shadow DB. -
duckpack.init(project_dir=".") -> NoneScaffolds a new declarative database project directory.
Objects & Exceptions
ApplyResult: Has attributes.success: bool,.applied_count: int, and.items: list[str].DiffSummary: Has attributes.has_changes: bool,.change_count: int, and.items: list[str].- Exceptions:
duckpack.Error(base),duckpack.SchemaError,duckpack.ExecutionError.
CLI Python Management
Check and install the Python bindings directly from the standalone DuckPack CLI:
# Verify Python extension status in active environment
duckpack python status
# Install or upgrade duckpack in active environment via pip
duckpack python install --upgrade
🦆 Quack Remote Server Integration
DuckPack includes first-class integration with remote DuckDB instances running the Quack extension over HTTP/HTTPS.
# Explore a remote Quack server with authentication token
duckpack explore --db quack:localhost:9494 --quack-token <token>
(You can also set DUCKDB_QUACK_TOKEN=<token> in your environment).
Exploring Remote Quack Servers from CLI
When you connect DuckPack to a remote Quack server from the CLI:
duckpack explore --db quack:0.0.0.0:9494 --quack-token <token>
DuckPack establishes a dual-catalog session:
target_db [Active] (quack): The primary remote Quack database hosting remote tables, views, and persistent data.memory (duckdb): A fast, local client-side in-memory scratchpad database.
Dual Root Hierarchical Explorer
The Explorer pane automatically switches to multi-database mode, grouping assets under their respective root database folders:
- Navigate down to any table in
target_dbormemoryand pressqors(or press Enter) to generate catalog-qualified queries directly into your active query editor tab:-- Generated by pressing 'q' on a target_db table: SELECT * FROM target_db.remote_table LIMIT 500; -- Generated by pressing 'q' on a memory table: SELECT * FROM memory.local_scratchpad LIMIT 500;
Cross-Database Joins Across Remote and Local
Because DuckDB evaluates queries client-side across all attached catalogs, you can write federated joins combining remote Quack datasets with local client tables in a single query:
SELECT
rt.order_id,
rt.amount,
mem.customer_category
FROM target_db.orders rt
JOIN memory.customer_categories mem ON rt.customer_id = mem.customer_id;
Standard SELECT queries, aggregations, cross-database joins, and DML run natively across the connection without requiring any special annotations.
DuckDB v2.0 Native CONNECT Session Management
In DuckDB v2.0, the Quack remote protocol graduates to first-class connection sessions via the native CONNECT target_db; statement. When DuckPack attaches to a remote Quack server, it immediately establishes session context on the remote server:
ATTACH 'quack:analytics.company.com:443' AS target_db;
CONNECT target_db;
With CONNECT target_db; active:
- Zero-Friction Execution: All standard queries, DDL (
CREATE TABLE,CREATE SCHEMA), DML (INSERT,UPDATE,DELETE), CTEs, and session configuration commands execute directly on the remote server without manual wrappers. - Native Secrets & Settings:
CREATE SECRET (TYPE S3 ...)andSET variable = ...statements apply directly to the remote server session without needing special client-side redirection.
The -- @remote Query Directive (Sunset & Backwards Compatibility)
In DuckDB 1.x, session-scoped entities (such as secrets and configuration settings) were held in local client memory unless wrapped via -- @remote.
With DuckDB v2.0's native CONNECT architecture, -- @remote is sunsetted as a requirement. DuckPack maintains backwards-compatible support: if an existing script or query contains -- @remote, DuckPack strips the directive and executes the statement natively without errors.
| Statement Type | DuckDB v1.x (-- @remote) |
DuckDB v2.0 (CONNECT target_db) |
|---|---|---|
CREATE TABLE / CREATE VIEW / CREATE SECURE VIEW |
Standard SQL | Native server-side execution. |
SELECT / CTEs / DML |
Standard SQL | Native server-side execution (including CTE DML). |
CREATE SECRET (TYPE S3 ...) |
Required -- @remote |
Native server-side execution via CONNECT. |
SET variable = ... |
Required -- @remote |
Native server-side execution via CONNECT. |
INSTALL / LOAD |
Required -- @remote |
Native server-side execution via CONNECT. |
SSL & Non-TLS Options
DuckDB's Quack extension enforces HTTPS/SSL for remote hosts and uses plain HTTP for localhost and 127.0.0.1.
If you are running a local development container (e.g. bound to 0.0.0.0:9494 or a Docker network IP) without TLS:
duckpackautomatically detects0.0.0.0bindings and disables SSL out-of-the-box.- For other non-TLS endpoints, explicitly disable SSL using
--insecure(or--quack-disable-ssl), or setDUCKDB_QUACK_DISABLE_SSL=true:duckpack explore --db quack:10.0.0.5:9494 --quack-token <token> --insecure
📁 Declarative Project Structure
Directory Layout
Running duckpack init --project-dir my_project generates the standard declarative project scaffold:
my_project/
├── schemas/ # CREATE SCHEMA statements (supports nested schemas e.g. finance/reports.sql)
├── tables/ # CREATE TABLE statements (one table per .sql file; VARIANT types supported)
├── views/ # CREATE VIEW & CREATE SECURE VIEW statements (engine auto-forces OR REPLACE)
├── macros/ # CREATE MACRO statements (supports DuckDB 2.0 lambda x: ... syntax)
├── triggers/ # CREATE TRIGGER statements (auto-preserved during table copy-and-swap)
├── queries/ # Scratchpad queries, exports, and query history
├── seeds/ # Static CSVs or data seed files
├── scripts/
│ ├── pre-deploy/ # Raw SQL executed BEFORE migrations are applied
│ └── post-deploy/ # Raw SQL executed AFTER migrations are applied
├── duckpack.toml # Multi-environment targets configuration
├── .env # Environment variables for ${VAR} template substitution
└── .duckdbignore # Ignore patterns for tables/views
DuckDB v2.0 Authoring Guidelines
- Arbitrary Nested Schemas: Schemas can be nested to any depth (
CREATE SCHEMA finance.reports;). Table files can live in nested subdirectories (tables/finance/reports/q3.sql) or dot-named files (tables/finance.reports.q3.sql). DuckPack automatically resolves topological creation order (parents before children) and teardown order (children before parents). - First-Class
VARIANTColumns: Tables and views support nativeVARIANTtypes andvariant_*functions alongside JSON casts (::JSON::VARIANT). In-place type alterations (ALTER TABLE t ALTER c TYPE VARIANT) are applied without requiring table recreation. CREATE SECURE VIEW: Secure views are fully supported inviews/. When views are modified, DuckPack automatically emitsCREATE OR REPLACE SECURE VIEWto preserve view protection.- Double-Arrow /
lambdaMacro Syntax: In DuckDB 2.0, single-arrow lambdas (x -> x + 1) are deprecated. Write macros usinglambda x: x + 1or double-arrow syntax:CREATE MACRO core.double_all(arr) AS list_transform(arr, lambda x: x * 2);
- Automatic Trigger Preservation: DuckDB 2.0 cascades table drops to all attached triggers. DuckPack's declarative diff engine detects when a table requires a copy-and-swap migration and automatically re-emits
CREATE TRIGGERstatements immediately after the table swap, preventing trigger loss.
Configuration (duckpack.toml)
Define connection targets, remote Quack instances, and environment profiles without hardcoding sensitive credentials or database paths:
[project]
name = "analytics_warehouse"
version = "0.2.0"
[target]
default_db = "dev.duckdb"
database = "analytics" # Optional: default attached catalog name to target
# Or configure a default remote Quack target with structured host/port:
# host = "analytics.internal"
# port = 9494
# insecure = false
[env.dev]
db = "dev.duckdb"
[env.staging]
# Connect directly to a remote Quack server instance:
db = "quack:staging.company.internal:9494"
database = "analytics_stg"
insecure = true # Disable SSL for internal/self-signed deployments
[env.prod]
# Connect to production Quack or MotherDuck:
db = "quack:analytics.company.com:443"
database = "analytics"
token_env = "PROD_QUACK_TOKEN" # Look up token from PROD_QUACK_TOKEN in .env
Deploy, diff, or explore against any profile:
duckpack explore # Automatically connects using [target] settings
duckpack explore --env staging # Connects to staging Quack server with no flags needed
duckpack apply --env prod # Applies migrations to prod with secrets loaded from .env
Environment Variables & Credentials (.env)
1. Credential Safety (Zero Secrets in Shell History)
Never pass raw API tokens on the command line where they are saved into .bash_history or /proc/<pid>/cmdline. DuckPack automatically loads .env (or .env.<profile> when using --env <profile>) and checks for:
QUACK_TOKEN: Default authentication token for remote Quack servers.DUCKDB_QUACK_TOKEN: Standard DuckDB Quack token fallback.- Custom environment variable name defined via
token_env = "MY_TOKEN"induckpack.toml.
# .env (automatically ignored by git)
QUACK_TOKEN=your_secure_quack_token_here
PROD_QUACK_TOKEN=production_super_secret_token
2. SQL Template Interpolation
Write dynamic templates directly in your SQL files:
CREATE TABLE ${ENV}_customers_${REGION} (
id INT PRIMARY KEY,
name VARCHAR
);
DuckPack loads .env (or .env.<profile> when using --env <profile>) and interpolates variables via regex before compiling.
Ignoring Tables (.duckdbignore)
Specify glob patterns for tables or views that DuckPack should ignore during schema diffs:
# Ignore ephemeral tables and temp backups
temp_*
*_backup
scratch.*
📦 DuckPacks (.duckpack) for CI/CD
For production pipelines and remote servers, applying migrations over a live network connection can be slow or risky. Compile your project into an immutable, offline snapshot artifact:
duckpack compile --project-dir my_project --out release_v1.duckpack
How DuckPacks Work (Non-Destructively)
A .duckpack file is a pre-compiled DuckDB database containing your desired state with all environment variables resolved.
When you run apply using a DuckPack:
- Opens
release_v1.duckpack(Desired State). - Opens your live
prod.duckdb(Current State). - Calculates the Diff: Compares the two databases in memory.
- Applies Non-Destructively: Issues
ALTER TABLE,CREATE TABLE, andCREATE OR REPLACE VIEWstatements against the live database without dropping existing data.
Deploy to a remote server over SSH in a single step:
duckpack deploy --project-dir my_project --remote user@prod-server.internal --db /var/lib/duckdb/prod.duckdb --auto-install
NOTE
I've spent time as an educational 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
Metadata
Release files for duckpack 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| duckpack-0.2.0.tar.gz | 716.6 kB | With provenance | Details for duckpack-0.2.0.tar.gz |
Built distributions (wheels)
| File | Actions Reset | |||
|---|---|---|---|---|
| duckpack-0.2.0-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details for duckpack-0.2.0-cp310-abi3-win_amd64.whl |
| duckpack-0.2.0-cp310-abi3-manylinux_2_39_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.39+ x86-64 | Details for duckpack-0.2.0-cp310-abi3-manylinux_2_39_x86_64.whl |
| duckpack-0.2.0-cp310-abi3-manylinux_2_39_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.39+ ARM64 | Details for duckpack-0.2.0-cp310-abi3-manylinux_2_39_aarch64.whl |
| duckpack-0.2.0-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details for duckpack-0.2.0-cp310-abi3-macosx_11_0_arm64.whl |
| duckpack-0.2.0-cp310-abi3-macosx_10_15_x86_64.whl | CPython 3.10 | abi3 | macOS 10.15+ x86-64 | Details for duckpack-0.2.0-cp310-abi3-macosx_10_15_x86_64.whl |
Total release size: 100.0 MB
Release files / duckpack-0.2.0.tar.gz
| Download URL | duckpack-0.2.0.tar.gz |
|---|---|
| Size | 716.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ab9486198e6b882db511e292f7e930e3961bc9e9ae30733dfaf33b1a477d7313
|
|
BLAKE2b-256 checksum How to use checksums |
76ba38305811e8ecc0f0a71f838b9079049a1cf37eaf3a0fc0972c0c33ad2bd0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / duckpack-0.2.0-cp310-abi3-win_amd64.whl
| Download URL | duckpack-0.2.0-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 14.8 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
63660afccbc984b1c9c9778ae6cd42afdbd7e82493aec3d4b482ac02f5899a14
|
|
BLAKE2b-256 checksum How to use checksums |
cf8f2f2d0f6268c45a3bbe8f03e275d1874edeb1bff01ded95a90997cab85749
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / duckpack-0.2.0-cp310-abi3-manylinux_2_39_x86_64.whl
| Download URL | duckpack-0.2.0-cp310-abi3-manylinux_2_39_x86_64.whl |
|---|---|
| Size | 25.4 MB |
| Tags | CPython 3.10 Linux glibc 2.39+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
4b369cbd43363bf6ea16a80326809637784470eb76064e82c8daeb92b2bb583d
|
|
BLAKE2b-256 checksum How to use checksums |
ae78fc0b540bf9e439e951d08f56a7f4569c6f3153038481d571ab42ea9d753c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / duckpack-0.2.0-cp310-abi3-manylinux_2_39_aarch64.whl
| Download URL | duckpack-0.2.0-cp310-abi3-manylinux_2_39_aarch64.whl |
|---|---|
| Size | 19.7 MB |
| Tags | CPython 3.10 Linux glibc 2.39+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
891d84e06b13709cc9edbd333240b8b54530a3cb93f9a5021627d85326575816
|
|
BLAKE2b-256 checksum How to use checksums |
93f85d8664c71558ca088d0cc3698ca9c55b54f5d62140ab7ee62e8c2c6fc4c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / duckpack-0.2.0-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | duckpack-0.2.0-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 19.2 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
5be90a0df056886f277e8c1343c2e78a371f435dc9a788b8e5b1590ba5b8852f
|
|
BLAKE2b-256 checksum How to use checksums |
b3cbfe5c7ba60ec780f1d1971d9c0a618885edd38e3c4cb0e0b927bfdb3eb06f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / duckpack-0.2.0-cp310-abi3-macosx_10_15_x86_64.whl
| Download URL | duckpack-0.2.0-cp310-abi3-macosx_10_15_x86_64.whl |
|---|---|
| Size | 20.1 MB |
| Tags | CPython 3.10 abi3 macOS 10.15+ x86-64 |
|
SHA-256 checksum How to use checksums |
7dff66fa3cb1957436f15bc3482b573b8ae68ca7b12ef47ba91b7c32020ba2b1
|
|
BLAKE2b-256 checksum How to use checksums |
7e51fbf5605db6f337cb9404a13408616b1925772be633b15a81a75c0a12d572
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logSecurity for duckpack 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 6 files in this release have been uploaded with provenance metadata.
Attestation for duckpack-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.