CLI

Run go build ./cmd/iceberg from the root of this repository to build the CLI executable, alternately you can run go install github.com/apache/iceberg-go/cmd/iceberg to install it to the bin directory of your GOPATH.

The iceberg CLI usage is very similar to pyiceberg CLI.
You can pass the catalog URI with the --uri argument.

Connecting to a catalog

Start a local REST catalog (the default --catalog type):

docker pull apache/iceberg-rest-fixture:latest
docker run -p 8181:8181 apache/iceberg-rest-fixture:latest

and run the iceberg CLI pointing to the REST API server:

 ./iceberg --uri http://0.0.0.0:8181 list
┌─────┐
| IDs |
| --- |
└─────┘

Catalog connection flags are global and apply to every subcommand:

FlagDescription
--catalogCatalog type: rest (default), glue, hive, hadoop
--uriCatalog URI (REST/Hive)
--warehouseWarehouse location
--credentialCredentials for the catalog
--tokenOAuth token (skips OAuth flow)
--scopeOAuth scope (default catalog)
--catalog-nameCatalog name to load from config file (default default)
--configPath to a config file

To avoid passing flags every time, define a config file at ~/.iceberg-go.yaml:

default-catalog: default
catalog:
  default:
    type: rest
    uri: http://localhost:8181
    warehouse: s3://my-warehouse

Flags on the command line override values from the config file.

Output format

All commands accept --output text (default, human-readable) or --output json (machine-readable, suitable for piping into jq or scripts).

Catalog and namespace commands

Create namespace

./iceberg --uri http://0.0.0.0:8181 create namespace taxitrips

List namespaces

 ./iceberg --uri http://0.0.0.0:8181 list
┌───────────┐
| IDs       |
| --------- |
| taxitrips |
└───────────┘

Create table

Note: only the identity transform is supported for --partition-spec at this moment.

# Create a simple table with REST catalog and Minio
./iceberg create table default.table-1 \
        --properties write.format.default=parquet \
        --partition-spec foo \
        --sort-order foo:desc:nulls-last \
        --schema '[{"id":1,"name":"foo","type":"string","required":false},{"id":2,"name":"bar","type":"int","required":true}]' \
        --catalog rest \
        --uri http://localhost:8181
Table default.table-1 created successfully

# Describe the newly created table
./iceberg describe --catalog rest --uri http://localhost:8181 default.table-1
Table format version | 2
Metadata location    | s3://warehouse/default/table-1/metadata/00000-f0ccaadd-d988-482e-99da-3a37870288fe.metadata.json
Table UUID           | 33fa3fac-e638-4335-a085-343c6d9e7de5
Last updated         | 1753133512562
Sort Order           | 1: [
                     | 1 desc nulls-last
                     | ]
Partition Spec       | [
                     |  1000: foo: identity(1)
                     | ]

Current Schema, id=0
├──1: foo: optional string
└──2: bar: required int

Current Snapshot |

Snapshots

Properties
key                             | value
-----------------------------------------
write.format.default            | parquet
write.parquet.compression-codec | zstd

Inspecting tables

info — single-screen summary

iceberg info my_db.events

Reports format version, location, current snapshot, schema, partition spec, sort order, snapshot count, ref count, and property count for a table.

snapshots — snapshot history

iceberg snapshots my_db.events

Lists all snapshots with timestamp, parent snapshot, operation (append, overwrite, delete, replace), and added/deleted data file counts.

refs — branches and tags

iceberg refs my_db.events
iceberg refs --type branch my_db.events
iceberg refs --type tag    my_db.events

Lists snapshot refs along with their retention settings (max-ref-age, max-snapshot-age, min-snapshots-to-keep).

partition-stats — partition statistics files

iceberg partition-stats my_db.events                          # current snapshot
iceberg partition-stats --snapshot-id 7234981023498 my_db.events
iceberg partition-stats --all my_db.events                    # all snapshots

schema --show-defaults

iceberg schema --show-defaults my_db.events

Prints the schema and surfaces each field's initial-default and write-default — useful when debugging schema-evolution behavior.

Snapshot maintenance

expire-snapshots

Drop old snapshots so their unreferenced data files become eligible for cleanup.

FlagDescription
--older-than DURATIONExpire snapshots older than the given duration (7d, 168h)
--retain-last NAlways keep at least N snapshots, regardless of age
--dry-runList what would be expired without committing
--yesSkip the confirmation prompt
# Preview
iceberg expire-snapshots --older-than 7d --dry-run my_db.events

# Commit, retaining at least 5 snapshots
iceberg expire-snapshots --older-than 7d --retain-last 5 my_db.events

clean-orphan-files

Remove data files in the table location that are not referenced by any snapshot's manifests (e.g. left behind by failed writes).

FlagDescription
--older-than DURATIONOnly consider files older than this (default 72h, gives in-flight writes time to finish)
--location PATHScan a different directory (e.g. an old warehouse path after migration)
--dry-runList orphan files without deleting
--yesSkip the confirmation prompt
iceberg clean-orphan-files --dry-run my_db.events
iceberg clean-orphan-files --older-than 5d my_db.events
iceberg clean-orphan-files --location s3://old-warehouse/my_db/events my_db.events

Rollback

Reset the current snapshot pointer to a previous snapshot. The target must be an ancestor of the current snapshot.

FlagDescription
--snapshot-id IDSnapshot to roll back to (required)
--yesSkip the confirmation prompt
iceberg rollback --snapshot-id 6891234567890 my_db.events

Format upgrade

Upgrade the table format version (metadata-only operation; no data files are rewritten). Refuses downgrades and same-version "upgrades".

FlagDescription
--dry-runShow what would change without committing
--yesSkip the confirmation prompt
iceberg upgrade --dry-run my_db.events 2
iceberg upgrade my_db.events 2

Branches and tags

branch create

iceberg branch create my_db.events ml-experiment-v3
FlagDescription
--snapshot-id IDSnapshot the branch points at (default: current snapshot)
--max-ref-age DURATIONBranch itself expires after this age
--max-snapshot-age DURATIONSnapshots on the branch older than this can be expired
--min-snapshots-to-keep NAlways retain at least N snapshots on the branch
--yesSkip the confirmation prompt
iceberg branch create \
  --snapshot-id 7234981023498 \
  --max-ref-age 30d \
  --max-snapshot-age 7d \
  --min-snapshots-to-keep 10 \
  my_db.events audit-2026-q2

tag create

iceberg tag create my_db.events pre-migration-v4
FlagDescription
--snapshot-id IDSnapshot the tag points at (default: current snapshot)
--max-ref-age DURATIONTag is auto-cleaned after this age
--yesSkip the confirmation prompt
iceberg tag create \
  --snapshot-id 7234981023498 \
  --max-ref-age 90d \
  my_db.events monthly-backup-may

Automation

Two flags make these commands safe to run from cron jobs or CI:

  • --yes skips the interactive prompt. Without it in a non-interactive environment, the CLI exits with stdin is not a terminal: use --yes to confirm in non-interactive mode rather than hanging.
  • --output json emits structured output that can be consumed by jq and downstream tooling.

Daily maintenance over every table in a namespace:

#!/bin/bash
TABLES=$(iceberg list my_db --output json | jq -r '.identifiers[].name')
for table in $TABLES; do
  iceberg expire-snapshots --older-than 7d --retain-last 3 --yes \
    --output json "my_db.$table"
  iceberg clean-orphan-files --older-than 3d --yes \
    --output json "my_db.$table"
done

Tag tables before a deploy:

iceberg tag create --yes my_db.events "pre-deploy-$VERSION"
iceberg tag create --yes my_db.users  "pre-deploy-$VERSION"

Audit-only report (no commits):

iceberg expire-snapshots --older-than 7d --dry-run --output json my_db.events \
  | jq '{table, would_expire: .expired_snapshot_count}'

Safety features

Every write command has multiple layers of protection:

  • --dry-run — shows the would-be effect without committing. Look for [DRY RUN] in text output or "dry_run": true in JSON.
  • --yes — required to skip the prompt; without it, non-interactive shells get an explicit error rather than hanging.
  • TTY detection — interactive prompts are only shown when stdout is a terminal.
  • Ancestor validationrollback rejects target snapshots that are not in the current branch's history.
  • Version checkupgrade refuses same-version or downgrade requests.