icepickExperimental
A small, experimental Rust CLI and library that commits Parquet files to Apache Iceberg tables and runs compaction and snapshot cleanup through a REST catalog, aimed at Cloudflare’s R2 Data Catalog (now Basin Catalog) and Amazon S3 Tables, with no JVM.
- What it is
- Table formats,Lakehouse catalogs
- Type
- Open source
- Made by
- Clay Smith
- License
- Apache 2.0
- Status
- Experimental. It describes itself as an experimental, append-only client.
- Facts checked
- 11 October 2026
What it is
icepick is one binary (cargo install icepick --features cli) that talks to an Iceberg REST catalog with just two inputs, a catalog URL and a bearer token. It reads the catalog’s /v1/config for the prefix, then asks the catalog’s /credentials endpoint for short-lived storage keys for each table. icepick commit takes a glob of Parquet files, checks that they all match the first file’s schema, uploads local files to the table’s location and registers them in one snapshot, skipping files already in the table. icepick compact bin-packs small files into larger ones (by default files under 128 MB into 256 MB outputs, in groups of at least 3), icepick snapshot cleanup expires snapshots older than N days while keeping the last N and anything a branch or tag points to, and icepick table scan --filter shows how many files partition pruning would skip. commit, compact and snapshot cleanup each take --dry-run to print the plan first.
Clay Smith started it in November 2025 because the official iceberg-rust library didn’t compile to WebAssembly and most Iceberg tooling needs a JVM. Four days in, it replaced iceberg-rust with its own implementation of the Iceberg REST protocol; it now writes manifests itself with apache-avro and reaches storage through opendal. The README says its R2 catalog code is WebAssembly-compatible, for use in Cloudflare Workers, while S3 Tables needs the AWS SDK and runs only on native platforms; in 0.4.1 the CLI itself only takes a URL and token, so S3 Tables is reachable only from the Rust library. It describes itself as an experimental, append-only client. The latest release is 0.4.1 (19 January 2026), and the repository has had no commits since that day.
Why teams pick it
- No JVM, Spark or Python: one native binary commits files, compacts and expires snapshots, which suits cron jobs and CI
- Registers Parquet files that already exist, without rewriting them, and skips files already in the table, so reruns are safe
- Needs only a catalog URL and token; in a test for this page the same binary worked against a local Lakekeeper 0.14 catalog with MinIO, because it relies only on the standard config and credentials endpoints
- Snapshot cleanup never expires the current snapshot or one a branch or tag points to, and only removes snapshots that are both older than the age limit and outside the last N
Watch out for
- A one-person experiment: version 0.4.1, a few hundred downloads, no commits since January 2026, and docs that have drifted from the code (the README’s
--limitflag andICEPICK_CATALOG_ARNsetting don’t exist in the 0.4.1 CLI, and the changelog describes a 0.5.0 that was never published) - In a test for this page, 0.4.1’s
compactcouldn’t read Snappy-compressed Parquet, because itsparquetdependency is built without compression codecs, and on uncompressed files it left the six original files live next to the merged one, so readers saw 120 rows instead of 60 - Append-only, and strict about inputs: no deletes or updates, and
commitrejects Parquet files whose columns lack Iceberg field ids, which a plain PyArrow write doesn’t add - In a test for this page,
commit --create --partitioncreated a partitioned table but registered the files with no partition values, so filters pruned nothing
Alternatives
What all table formats have in common →
Apache HudiOpen sourceA table format built for upserts and incremental pulls, with record-level indexes and built-in table services.
Apache IcebergOpen sourceThe most widely supported open table format: snapshots of data files, tracked by a tree of metadata and swapped in atomically through a catalog.
LanceOpen sourceA file and table format for AI data: columnar like Parquet, but fast at fetching single rows, with vector and full-text indexes, versions and room for images and video.How it fits with other technologies
What icepick uses
- icepickcommits to and maintains tables inApache Iceberg
- icepickcommits and compacts tables throughCloudflare Basin Catalog
- icepickmanages tables, from its library, inAmazon S3 Tables
- icepickregisters and compacts files inApache Parquet
- icepickreads and writes storage throughApache OpenDAL
- icepickis written inRust
Register local Parquet files as a new Iceberg table, then plan a compaction · bash
cargo install icepick --version 0.4.1 --features cli --locked
# For Basin Catalog: https://catalog.cloudflarestorage.com/<account-id>/<bucket>
# Run here against a local Lakekeeper 0.14 catalog (warehouse "catalog") on MinIO
export ICEPICK_CATALOG_URL=http://localhost:28181/catalog
export ICEPICK_TOKEN=dummy # a Cloudflare API token on Basin
icepick namespace create web
# Namespace 'web' created successfully.
# Six uncompressed files written by PyArrow, with PARQUET:field_id on each column
icepick commit 'raw/*.parquet' --namespace web --table clicks --create
# Found 6 Parquet files
# Detected local files - will upload to table storage
# Schema from: raw/part-0.parquet
# Created table: web.clicks
# Uploading 6 local files...
# part-0.parquet -> s3://lake/01a12e09-.../data/part-0_b5acfe29-....parquet
# ...
# Upload complete
# Files: 6 committed, 0 skipped
# Rows: 60
icepick compact web.clicks --dry-run
# Partition: (unpartitioned)
# Input: 6 files, 5.7 kiB (avg 974 B /file)
# Output: ~1 files (target 5.7 kiB)
# Dry run complete. Remove --dry-run to execute.
icepick snapshot list web.clicks # one append snapshot, current, on mainSee it in a real stack
No architecture uses icepick yet. Drop it into the playground and wire it up yourself.Open playground →Where it came from2025–2026
By 2025 teams could get a managed Iceberg catalog without running servers, such as Amazon S3 Tables or Cloudflare’s R2 Data Catalog, which entered public beta in April 2025. Most Iceberg tools, icepick’s README notes, are built for JVM environments, and the official Rust library, iceberg-rust, couldn’t be compiled to WebAssembly, so it couldn’t run inside a Cloudflare Worker.
Clay Smith began the project on 15 November 2025 as hello-world-iceberg, a test of iceberg-rust against S3 Tables, and renamed it icepick. That first day the commit history records an S3 Tables incompatibility finding and a switch from iceberg-catalog-rest to a minimal hand-written client; on 19 November “Standalone implementation of Iceberg REST” removed iceberg-rust altogether. 0.1.0 went to crates.io on 17 November 2025.
December’s 0.3.0 added registration of existing Parquet files with Hive-style partition values read from their paths. In January 2026 a reworked CLI arrived with partition pruning, bin-pack compaction, snapshot cleanup and the commit command, and 0.4.1 shipped on 19 January 2026.
Why it’s built this way
- Its own REST client instead of
iceberg-rust - The 0.4.0 changelog notes that
iceberg-rust0.7.0 couldn’t build for WebAssembly because of its Tokio dependency, which blocked the main goal of running in Cloudflare Workers. - Only a catalog URL and a token
- The CLI rework made everything else, the prefix and the storage credentials, come from the catalog’s own config and credentials endpoints, so pointing it at R2 or another REST catalog takes two settings.
- Register files rather than write rows
- The developer guide pitches it for Parquet files that already sit in object storage: they become an Iceberg table without being rewritten, and files already registered are skipped.
- Bearer tokens for R2, SigV4 only on native builds
- R2’s catalog takes a Cloudflare API token, which works from WebAssembly. S3 Tables needs SigV4 signing and the AWS SDK, which doesn’t compile to WebAssembly, so that path is native-only.
Timeline
- 2025
Clay Smith starts
hello-world-icebergon 15 November and renames it icepick - 2025
Replaces
iceberg-rustwith a standalone REST client on 19 November - 2025
0.3.0 adds registration of existing Parquet files in December
- 2026
0.4.1 brings the CLI with commit, compaction and snapshot cleanup on 19 January
- GitHub: smithclay/icepick commit history (November 2025 to January 2026)
- GitHub: icepick PR #3, Standalone implementation of Iceberg REST (19 November 2025)
- GitHub: icepick PR #5, register_data_files for existing Parquet files (December 2025)
- GitHub: icepick PR #8, simplified REST catalog CLI with partition pruning and compaction (January 2026)
- GitHub: icepick CHANGELOG (rename from hello-world-iceberg, iceberg-rust WASM limitation)
- crates.io: icepick versions (0.1.0 November 2025 to 0.4.1 January 2026)
- Cloudflare blog: R2 Data Catalog public beta (April 2025)
Sources10 · facts checked 11 October 2026
- GitHub: smithclay/icepick README (commands, R2 and S3 Tables setup, WASM notes)
- GitHub: icepick DEVELOPER.md (library usage, generic REST catalog, registering files)
- GitHub: icepick Cargo.toml 0.4.1 (“Experimental Rust client”, `parquet` with only the `arrow` feature, `opendal`)
- GitHub: icepick REST client (config and credentials endpoints, warehouse from URL)
- GitHub: icepick compact command (defaults: 256 MB target, 128 MB max input, 3 files per group)
- GitHub: icepick CLI options (catalog URL and token only)
- GitHub: icepick PR #10, snapshot cleanup (retention rules, defaults)
- GitHub: icepick CHANGELOG
- GitHub: smithclay/icepick repository (description: append-only Rust Iceberg client)
- crates.io: icepick (versions and downloads)