Faceberg
Bridge HuggingFace datasets with Apache Iceberg tables — no data copying, just metadata.
Faceberg maps HuggingFace datasets to Apache Iceberg tables. Your catalog metadata lives on HuggingFace Spaces (or Buckets) with an auto-deployed REST API, and any Iceberg-compatible query engine can access the data.
[!NOTE] Faceberg is early-stage, alpha-quality software — APIs and CLI flags may still evolve between releases. See CHANGELOG.md for what's landed so far.
Installation
pip install faceberg
Requires Python 3.10+. The REST catalog server (faceberg serve) is included by default.
Prerequisites
Get a token from HuggingFace Settings and export it:
export HF_TOKEN=your_huggingface_token
The token is only required for remote catalogs (user/repo, hf://...). Local catalogs (plain paths) don't need one.
Quick Start
# Create a catalog on HuggingFace Hub (deploys a Space with a REST API)
faceberg user/mycatalog init
# Add datasets — table identifier is inferred (org.repo) unless --table is given
faceberg user/mycatalog add stanfordnlp/imdb
faceberg user/mycatalog add openai/gsm8k --config main
# List what's in the catalog
faceberg user/mycatalog list
# Query with interactive DuckDB shell
faceberg user/mycatalog quack
SELECT label, substr(text, 1, 100) as preview
FROM faceberg.stanfordnlp.imdb
LIMIT 10;
CLI Reference
Every command follows the same shape: faceberg <catalog-uri> <command> [args], where <catalog-uri> is one of:
| URI form | Backend |
|---|---|
org/repo or hf://datasets/org/repo |
HuggingFace dataset repo (Space auto-deployed) |
hf://spaces/org/repo |
HuggingFace Space |
hf://buckets/org/repo |
HuggingFace Bucket (S3-like, no git history) |
./path or /abs/path |
Local filesystem catalog |
| Command | Description |
|---|---|
init [config.yml] |
Create the catalog. Auto-discovers ./faceberg.yml if no path is given; --sync populates tables immediately. |
add <dataset> |
Add a HuggingFace dataset as a table. --table ns.table sets an explicit identifier, --config selects a dataset config. |
sync [table] |
Re-check datasets for new revisions and update Iceberg metadata. Omit table to sync everything; --tree-view shows progress as a tree. |
list |
List all namespaces/tables in the catalog. |
info <table> |
Show a table's schema, partitioning, and metadata location. |
scan <table> |
Read and print sample rows. --limit/-n controls row count (default 5). |
remove <identifier> |
Drop a table (ns.table) or an empty namespace. --yes skips the confirmation prompt. |
serve |
Start an Iceberg REST catalog server. --host, --port (default 8181), --reload, --prefix. |
quack |
Open an interactive DuckDB shell with the catalog pre-attached. --endpoint overrides auto-detection. |
Run faceberg <uri> <command> --help for full flag details and examples on any command.
faceberg.yml
Catalogs are described by a faceberg.yml config that tracks dataset-to-table mappings:
default:
imdb:
type: dataset
repo: stanfordnlp/imdb
config: plain_text
gsm8k:
type: dataset
repo: openai/gsm8k
config: main
faceberg init tables.yml bootstraps a catalog from a file like this in one shot; faceberg sync re-reads it and updates any table whose source dataset revision changed.
Local Catalogs
For development, testing, or CI, point the CLI at a filesystem path instead of a HuggingFace URI — no token needed:
faceberg ./mycatalog init
faceberg ./mycatalog add stanfordnlp/imdb --config plain_text
faceberg ./mycatalog serve --port 8181 # in one terminal
faceberg ./mycatalog quack # in another
See Local Catalogs for the on-disk layout and testing patterns.
HuggingFace Buckets
Catalog metadata can also live in a HuggingFace Bucket (hf://buckets/org/name) instead of a Space — an S3-like storage backend with no git history, useful for catalogs that don't need a hosted REST endpoint:
faceberg hf://buckets/user/mycatalog init
faceberg hf://buckets/user/mycatalog add stanfordnlp/imdb
How It Works
HuggingFace Hub
┌─────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────────────┐ ┌─────────────────────────┐ │
│ │ HF Datasets │ │ HF Spaces (Catalog) │ │
│ │ (Original Parquet) │◄───│ • Iceberg metadata │ │
│ │ │ │ • REST API endpoint │ │
│ │ stanfordnlp/imdb/ │ │ • faceberg.yml │ │
│ │ └── *.parquet │ │ │ │
│ └─────────────────────┘ └───────────┬─────────────┘ │
│ │ │
└─────────────────────────────────────────┼───────────────┘
│ Iceberg REST API
▼
┌─────────────────────────┐
│ Query Engines │
│ DuckDB, Pandas, Spark │
└─────────────────────────┘
No data is copied — only metadata is created. Query with DuckDB, PyIceberg, Spark, or any Iceberg-compatible tool.
Python API
import os
from faceberg import catalog
cat = catalog("user/mycatalog", hf_token=os.environ.get("HF_TOKEN"))
table = cat.load_table("stanfordnlp.imdb")
df = table.scan(limit=100).to_pandas()
The catalog object exposes the usual Iceberg operations:
| Method | Description |
|---|---|
init(config) |
Initialize catalog storage, optionally with a Config |
config() |
Load the catalog's faceberg.yml configuration |
add_dataset(identifier, repo, config) |
Add a HuggingFace dataset as an Iceberg table |
sync_dataset(identifier) / sync_datasets() |
Sync one or all datasets (update if source changed) |
load_table(identifier) |
Load a table for querying |
list_tables(namespace) / list_namespaces() |
Enumerate tables / namespaces |
drop_table(identifier) / drop_namespace(identifier) |
Remove a table or empty namespace |
table_exists(identifier) |
Check if a table exists |
Pandas integration
import pandas as pd
df = pd.read_iceberg(
table_identifier="stanfordnlp.imdb",
catalog_name="faceberg",
catalog_properties={"type": "rest", "uri": "https://user-mycatalog.hf.space"},
columns=["text", "label"],
limit=10,
)
See Pandas Integration for the local-catalog variant and more examples.
Share Your Catalog
Your catalog is accessible to anyone via the REST API:
import duckdb
conn = duckdb.connect()
conn.execute("INSTALL iceberg; LOAD iceberg")
conn.execute("""
ATTACH 'https://user-mycatalog.hf.space' AS cat (
TYPE ICEBERG,
ENDPOINT 'https://user-mycatalog.hf.space',
AUTHORIZATION_TYPE 'none'
)
""")
result = conn.execute("SELECT * FROM cat.stanfordnlp.imdb LIMIT 5").fetchdf()
To make your catalog private, set the underlying HuggingFace Space/dataset/Bucket to private.
Documentation
- Getting Started — Full quickstart guide
- Local Catalogs — Use local catalogs for development
- Buckets — Store catalog metadata in HF Buckets
- DuckDB Integration — Advanced SQL queries
- Pandas Integration — Load into DataFrames
- Architecture — How Faceberg maps datasets to Iceberg metadata
Development
git clone https://github.com/kszucs/faceberg
cd faceberg
pip install -e '.[dev]'
Common tasks are wired up via just (see the justfile):
just test # run the test suite (pytest faceberg/tests/)
just cov # run tests with coverage
just format # format code with ruff
just check # lint + format check
just build # build distribution packages
Docs are written in Quarto (docs/*.qmd) and published to https://faceberg.kszucs.dev/.
License
Apache 2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file faceberg-0.4.0.tar.gz.
File metadata
- Download URL: faceberg-0.4.0.tar.gz
- Upload date:
- Size: 88.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c0c6ceabb6079e17a978f8958830e570891fe8d48927b0ecd62583983d10462
|
|
| MD5 |
ca1512ab24428df15e201e88fc067cc6
|
|
| BLAKE2b-256 |
5bd108eae9998241fb949cc36b5f4ff7d90382dd9301ee886d694cb893a640b2
|
Provenance
The following attestation bundles were made for faceberg-0.4.0.tar.gz:
Publisher:
main.yml on huggingface/faceberg
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
faceberg-0.4.0.tar.gz -
Subject digest:
9c0c6ceabb6079e17a978f8958830e570891fe8d48927b0ecd62583983d10462 - Sigstore transparency entry: 2137407914
- Sigstore integration time:
-
Permalink:
huggingface/faceberg@d9082bbdbe990de25eb97844d7a539394829e9b9 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/huggingface
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
main.yml@d9082bbdbe990de25eb97844d7a539394829e9b9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file faceberg-0.4.0-py3-none-any.whl.
File metadata
- Download URL: faceberg-0.4.0-py3-none-any.whl
- Upload date:
- Size: 96.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
edccf897f4b221c014285f200cda9e608b0704c47adac8bbc7de48e4d4c2bd00
|
|
| MD5 |
6bb0c1f57a111a6639118b16e69df447
|
|
| BLAKE2b-256 |
96da1d840a379e57f491c48678e04e861244791f4659a91511bdc072644cabea
|
Provenance
The following attestation bundles were made for faceberg-0.4.0-py3-none-any.whl:
Publisher:
main.yml on huggingface/faceberg
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
faceberg-0.4.0-py3-none-any.whl -
Subject digest:
edccf897f4b221c014285f200cda9e608b0704c47adac8bbc7de48e4d4c2bd00 - Sigstore transparency entry: 2137408043
- Sigstore integration time:
-
Permalink:
huggingface/faceberg@d9082bbdbe990de25eb97844d7a539394829e9b9 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/huggingface
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
main.yml@d9082bbdbe990de25eb97844d7a539394829e9b9 -
Trigger Event:
push
-
Statement type: