Skip to main content

Duckle

Local-first ETL/ELT pipelines that run on DuckDB. Python builds the plan, DuckDB moves the rows. Your data never leaves the machine.

PyPI License GitHub

Build your first pipeline

Paste this into Claude Code, Cursor, or Codex. The agent does the rest.

Run uvx duckle quickstart to build my first pipeline and run it

Nothing to install first. The agent fetches Duckle and the DuckDB engine on demand, runs a real pipeline, and shows you the rows.

Prefer to drive it yourself:

uvx duckle quickstart      # no install
pip install duckle         # or install it
Terminal: uvx duckle quickstart scaffolds sample data and a pipeline, runs it, and prints the resulting rows

quickstart scaffolds sample data and a pipeline, runs it, and shows you the rows. One command from nothing to a result, because the engine comes with it: a ~20 MB native binary plus the DuckDB CLI. No JVM, no Docker, no server, no account.


Or install it

Terminal: pip install duckle brings the DuckDB engine, then a job.py using the Python API reads a CSV, filters, derives a column and writes Parquet

Where uvx is for trying it, pip is for keeping it: a persistent duckle command, duckle-mcp for agents, and import duckle in Python.

No data passes through Python

Every method appends a node to a pipeline graph. Nothing executes until .run(), and then the whole graph is handed to the engine, compiled to SQL, and executed inside DuckDB.

That is the difference from a dataframe library: a billion-row job costs what the SQL costs, because it is SQL. There is no interpreter in the data path, and no to_pandas() escape hatch quietly pulling rows into memory.

import duckle
from duckle import col

(duckle.read_csv("orders.csv")
    .where(col.amount >= 20)
    .derive(total="round(amount * 1.2, 2)", tag="f'{region}-{id}'")
    .write_parquet("out.parquet")
    .run())

Python expressions, compiled to SQL

amount * 1.2, f'{a}-{b}', x if c else y, name.strip().upper() and email is None are translated to vectorized DuckDB SQL at plan time:

.derive(band="'high' if amount > 50 else 'low'")
# CASE WHEN ("amount" > 50) THEN 'high' ELSE 'low' END

An expression with no exact SQL equivalent is rejected with the construct named, never quietly executed somewhere slower. Comprehensions, lambda, indexing and eval are refused by name.

Prefer editor completion over strings? col builds the same tree with real operators, and fragments are reusable:

eu_only = col.region.isin(["EU", "UK"])
p.where(eu_only & (col.amount >= 20))

See exactly what will run, before it runs:

p.explain()   # prints the compiled SQL, one block per stage

360+ components, not 10 file formats

Component ids map onto attribute paths, so anything in the catalog is reachable:

duckle.src.salesforce(object="Account", authMode="clientCredentials")
duckle.xf.geo.reproject(geomColumn="geom", targetCrs="EPSG:3857")
duckle.snk.salesforce.bulk(operation="upsert", externalIdField="Ext__c")

104 sources, 66 sinks and 138 transforms: Postgres, MySQL, Oracle, SQL Server, Snowflake, Databricks, Teradata, SAP OData, Salesforce (including Bulk API 2.0), Kafka, WebSocket, S3, SFTP, IMAP, LanceDB and more.

duckle.component_ids(contains="salesforce")
duckle.describe("snk.salesforce.bulk")   # settings, and which ones the engine ignores

A CI gate that needs no engine

Terminal: duckle validate reports one failing and one passing pipeline, then exits 1

duckle validate compiles every pipeline without opening a source or writing a sink, so it needs no DuckDB, no credentials and no network. Exit codes are stable and safe to gate on:

code meaning
0 clean
1 a real finding: a pipeline failed, or did not compile
2 the runner could not start: bad usage, missing engine
duckle validate --json          # machine-readable, for a build step
duckle --pipeline my.json       # run one

Note: validate does not yet catch every missing required property, so a clean validate is not proof that a run will succeed.

Agent-ready, with nothing installed

Terminal: adding duckle as an MCP server via uvx, then an agent discovering Salesforce connectors, reading a component schema, creating a pipeline that compiles, and running it

The same package is an MCP server, so an AI agent gets a governed way to work with data instead of a shell. Point Claude Code, Claude Desktop or Cursor at it:

{ "mcpServers": { "duckle": { "command": "uvx", "args": ["duckle", "mcp"] } } }

Or in Claude Code:

claude mcp add duckle -- uvx duckle mcp

That is the whole setup. No pip install, no PATH, no engine to configure: uv fetches the package and the DuckDB engine into a throwaway environment and the server finds it there. If you did pip install duckle, "command": "duckle", "args": ["mcp"] works the same way.

19 tools, including list_components, get_component_schema, create_pipeline, validate_pipeline, run_pipeline, pipeline_lineage, trust_report and schema_drift.

What that buys over letting an agent write a script: it can discover a real connector rather than guess one, compile-check a pipeline before anything executes, run it, and get column-level lineage back. validate_pipeline opens no source and writes no sink, so an agent can check its work without touching your data. The pipeline it produces is the same JSON your desktop canvas opens, so you can inspect what it built.

Code and canvas are the same file

Pipelines are the same JSON the Duckle desktop studio reads. A pipeline written in Python opens on the canvas, and one drawn on the canvas runs from Python:

p.save("pipelines/orders.json")          # opens in the studio
duckle.from_json("pipelines/orders.json").run()

Install notes

duckle depends on duckdb-cli, published by the DuckDB Foundation, so the engine arrives with the install and works offline. To pin your own build instead, set DUCKLE_DUCKDB_BIN.

Wheels ship for Linux, macOS and Windows on x86-64 and arm64. The wheel carries a compiled Rust binary and is Python-version independent (py3-none-<platform>).


Apache-2.0  ·  GitHub  ·  duckle.org  ·  Issues

Release files for duckle 0.7.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for duckle 0.7.3
File
duckle-0.7.3-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
duckle-0.7.3-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
duckle-0.7.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
duckle-0.7.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
duckle-0.7.3-py3-none-macosx_11_0_x86_64.whl Python 3 none macOS 11.0+ x86-64 Details
duckle-0.7.3-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 173.1 MB

Release files / duckle-0.7.3-py3-none-win_arm64.whl

Download URL duckle-0.7.3-py3-none-win_arm64.whl
Size 28.7 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
aad9a13bb81396b8f87d56e41b8121666f85699e73027cdfcbee66017aecd305
BLAKE2b-256 checksum
How to use checksums
fd0c9179152562ed6d4d7989f890bcbf232dfa39ad8c4dacf964f8ee31f1fc2d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 16, 2026.

Transparency log

Release files / duckle-0.7.3-py3-none-win_amd64.whl

Download URL duckle-0.7.3-py3-none-win_amd64.whl
Size 30.2 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
4945cb86b80307ec74df347f2eefa59f69c6dd558e6ff0b7534d085567686f59
BLAKE2b-256 checksum
How to use checksums
fae04fee7ae710c674a36bed6262fb76c3c684a7e1336b5f4a85f7b72acff22a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 16, 2026.

Transparency log

Release files / duckle-0.7.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL duckle-0.7.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 30.5 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
eda06b7d6e6a18943f252f24e4f731aed12f338b94b558cefb2132c8f7b40fbf
BLAKE2b-256 checksum
How to use checksums
8c1c1b684e92ce123e7542768c60bc18d4d4d9a73e12689d8478484a41e1918e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 16, 2026.

Transparency log

Release files / duckle-0.7.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL duckle-0.7.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 29.0 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
d8d339bd34d8fa3dc708717309418747e42c1cf3f588f7f787a540102c6e66c0
BLAKE2b-256 checksum
How to use checksums
16738c7a5860d1c9c098e5f72300acb1be9d21e5aa01516e9732849b22eee85c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 16, 2026.

Transparency log

Release files / duckle-0.7.3-py3-none-macosx_11_0_x86_64.whl

Download URL duckle-0.7.3-py3-none-macosx_11_0_x86_64.whl
Size 27.9 MB
Tags Python 3 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
f0a9d355ce6e408082ff2fbe2dfcf896104ddd31b992ad5c35f5880e8816e7f7
BLAKE2b-256 checksum
How to use checksums
011a61ad2b648d7348bf00f5a4b465c99b60faa67a3d71cd23569239380bdf64
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 16, 2026.

Transparency log

Release files / duckle-0.7.3-py3-none-macosx_11_0_arm64.whl

Download URL duckle-0.7.3-py3-none-macosx_11_0_arm64.whl
Size 26.8 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a9bf402f2f5deac20672a7bca4ff4eda1a161fb103272ca754113d1ebf89101a
BLAKE2b-256 checksum
How to use checksums
c820265635cacba143e44886456b6152e232ab3dc71851d1eeb8f94d05a48f6c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.7.3 This release

6 release files

0.7.2

6 release files

0.7.1

6 release files

0.5.11

6 release files

0.5.10

6 release files

0.5.9

6 release files

0.5.8

6 release files

0.5.7

6 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page