ducktail
tail -f for DuckLake tables.
Watch inserts, deletes, and updates flow through a DuckLake table in real time, powered by DuckLake's built-in CDC.
$ ducktail tail orders -C meta.duckdb
+ id=1 name=Alice amount=100.0
+ id=2 name=Bob amount=50.0
- id=2 name=Bob amount=50.0
Δ amount: 100.0 → 150.0
Install
pip install ducktail # or: uv add ducktail
Requires Python 3.12+ and DuckDB 1.4+ (ducklake extension loads automatically).
Usage
Basic
ducktail tail TABLE -C CONNECTION
# DuckDB metadata catalog
ducktail tail events -C meta.duckdb -d /data
# Postgres metadata catalog
ducktail tail events -C "postgres:dbname=ducklake host=localhost user=ducklake password=ducklake"
Interactive mode
Full-screen TUI with color-coded rows (green inserts, red deletes, yellow updates):
ducktail tail events -C meta.duckdb -m interactive
Filter what you see
# Only specific columns
ducktail tail events -C meta.duckdb -col status -col amount
# Server-side filter (pushed into the CDC query)
ducktail tail events -C meta.duckdb -f "amount > 100"
# Faster polling
ducktail tail events -C meta.duckdb -i 0.5
Compose with Unix tools
Pager mode (the default) writes one line per change to stdout, so it plays nicely with the usual suspects:
# Inserts only
ducktail tail orders -C meta.duckdb | grep '^\+'
# Deletes only
ducktail tail orders -C meta.duckdb | grep '^\-'
# Count changes per second
ducktail tail orders -C meta.duckdb | pv -l > /dev/null
Options
ducktail tail [OPTIONS] TABLE_NAME
| Option | Short | Default | Description |
|---|---|---|---|
TABLE_NAME |
(required) | Table to tail | |
--connection |
-C |
(required) | Catalog connection string |
--catalog |
-c |
lake |
Catalog name |
--data-path |
-d |
. |
Path to DuckLake data files |
--namespace |
-n |
main |
Table namespace |
--interval |
-i |
1.0 |
Poll interval (seconds) |
--columns |
-col |
(all) | Columns to show (repeat for multiple) |
--filter |
-f |
(none) | CDC filter expression |
--mode |
-m |
pager |
pager or interactive |
Change symbols
| Symbol | Color | Meaning |
|---|---|---|
+ |
Green | Row inserted |
- |
Red | Row deleted |
Δ |
Yellow | Row updated — shows column: old → new for each changed field |
Try the demo
The repo includes a Docker-based demo that stands up a Postgres metadata catalog and a producer that streams a mix of inserts, deletes, and updates.
# Terminal 1 — infrastructure + producer
just demo-up
just demo-producer
# Terminal 2 — watch it happen
just demo-tail # pager mode
just demo-tail-interactive # or interactive mode
# Cleanup
just demo-down
Development
Requires flox and Docker (for integration tests and demo).
flox activate
just sync # install deps
just test # unit tests
just ci # format + lint + typecheck + unit tests
| Recipe | What it does |
|---|---|
just sync |
Install dependencies |
just fmt |
Format code |
just lint |
Lint |
just typecheck |
mypy strict |
just test |
Unit tests |
just test-integration |
Integration tests |
just test-all |
Both |
just ci |
fmt-check + lint + typecheck + test |
License
Apache License 2.0
Metadata
Release files for ducktail 1.0.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ducktail-1.0.4.tar.gz | 680.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ducktail-1.0.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 694.1 kB
Release files / ducktail-1.0.4.tar.gz
| Download URL | ducktail-1.0.4.tar.gz |
|---|---|
| Size | 680.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
79fecb01a01992f6ab45a1ac6a707b4b26bd00102d5a84302d1806397105968c
|
|
BLAKE2b-256 checksum How to use checksums |
3652d4bff80b5bbf754451af64b42b4c8c3a112fd580c94645948c828ce3473d
|
| 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 Aug 13, 2026.
Transparency logRelease files / ducktail-1.0.4-py3-none-any.whl
| Download URL | ducktail-1.0.4-py3-none-any.whl |
|---|---|
| Size | 13.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d7ab59b00b5d8403832791f22eaf4da99373f033647c140e2183103ffa16c0ef
|
|
BLAKE2b-256 checksum How to use checksums |
34294a91784b0cb69b3904151b3079b82065f5fcd2b8f0090d9fe39e34c7bef8
|
| 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 Aug 13, 2026.
Transparency log