Dataset-centric CLI toolkit for exploring, compiling, transforming, and diffing tabular data
Project description
TabCaddy
TabCaddy is a dataset-centric CLI for tabular data engineering workflows. It helps you move from raw files to reproducible dataset operations without leaving the terminal.
Use it to:
- profile files and folders quickly
- inspect sample rows before modeling
- detect schema drift and dominant schema groups
- compile heterogeneous raw data into a reusable Parquet dataset
- scaffold and run Python transforms
- diff dataset versions at metadata, statistics, or full levels
- merge incoming drops into an archive with conflict-aware validation
TabCaddy works with single files, directory trees, and compiled TabCaddy datasets.
Installation
Requirements:
- Python 3.11+
Install with pip:
pip install tabcaddy
Install as a standalone CLI with uv:
uv tool install tabcaddy
Add to a project environment with uv:
uv add tabcaddy
Supported Sources
.csv.feather.arrow.parquet- folders containing supported files
- compiled datasets created by
tabcaddy compile
Command Map
summary: profile counts, schemas, stats, and warningshead: preview rows from files, folders, or compiled datasetsschema: inspect schema groups and drift-focused schema diagnosticscompile: materialize a selected schema into a compiled Parquet datasetscaffold-transform: generate a transform starter from observed schemastransform: apply Python transforms to file, folder, or compiled inputsdiff: compare files/folders/compiled datasetsmerge: combine source data into a target with validation and conflict rules
Quick Start
Typical curation flow (inspect, clean, compile):
tabcaddy summary data/
tabcaddy head data/ --n 5
tabcaddy schema data/
tabcaddy scaffold-transform data/
tabcaddy transform data/ transform_template.py cleaned_data/
tabcaddy compile cleaned_data/ --interactive
Typical incremental ingest flow (clean, merge, compile):
tabcaddy scaffold-transform incoming/
tabcaddy transform incoming/ transform_template.py incoming_cleaned/
tabcaddy merge incoming_cleaned/ archive/ --out merged_archive --on id
tabcaddy compile merged_archive/ --interactive
Note: compiling before transforming is still useful when you want to lock onto one schema first, or when the transform input is already a compiled dataset.
Command Reference
summary
tabcaddy summary <source> [--profile quick|standard|deep]
Best default entry point for understanding a source.
quick: counts onlystandard: metadata, schema overview, lightweight statistics, and warningsdeep: adds histograms, uniqueness estimates, and column hashes
Example:
tabcaddy summary data/ --profile deep
head
tabcaddy head <source> [--n N] [--showmeta]
Previews rows without loading the full dataset into a notebook.
- file input: first
Nrows - compiled dataset input: first
Nrows from compiled Parquet data - folder input: first row from each of the first
Nfiles
Use --showmeta to include metadata columns in output.
schema
tabcaddy schema <source>
Focused schema analysis for schema groups, type changes, and non-dominant files. This command always uses quick schema analysis and does not take --profile.
compile
tabcaddy compile <folder> [--output compiled_dataset] [--schema N] [--interactive]
Compiles a folder into a standardized Parquet-backed dataset.
- use
--schema Nto choose a schema directly - use
--interactiveto inspect detected schemas and select one at the prompt - files from non-selected schemas are skipped and reported
scaffold-transform
tabcaddy scaffold-transform <source> [--output transform_template.py]
Generates a Python transform scaffold based on observed schemas.
transform
tabcaddy transform <input> <transform.py> [output_path] [--workers N]
Applies a Python transform to a file, folder, or compiled dataset.
- if
output_pathis omitted, TabCaddy creates one by appending_transformed - compiled input produces compiled output with refreshed
metadata.jsonanddata/
Supported signatures:
def transform(df):
return df
def transform(df, context):
return df
context fields:
file_namefile_pathschemametadata.row_countmetadata.schema_hash
diff
tabcaddy diff <left> <right> [--level metadata|statistics|full]
Supported comparisons:
- file vs file
- folder vs folder
- file vs folder (either side)
- compiled dataset vs compiled dataset
Unsupported combinations (for example file vs compiled dataset) are rejected.
For file-vs-folder comparisons, matching is filename-based across the folder tree:
- no match:
missing - one unique exact-content match:
unmodified - one filename match with content change:
modified - multiple candidates:
ambiguous
Levels:
metadata: high-level file and dataset changesstatistics: metadata plus column-stat changesfull: metadata, schema, and statistics changes
merge
tabcaddy merge <source> <target> (--out <path> | --inplace) [--on COLUMN ...] [--strategy append|upsert] [--schema-evolution strict|allow-additive] [--ignore-filetype] [--dry]
Merges source rows into matching target files and preserves the target layout.
Use --dry to preview matched and unmatched files, output destinations, schema issues, casts, and expected conflicts without writing output.
Core rules:
- supports file-to-file, file-to-folder, and folder-to-folder merges
- folder-to-file merge is not supported
- provide exactly one of
--outor--inplace - compiled datasets are rejected (merge does not rebuild compiled metadata)
- folder matching is by relative path
Strategy and keys:
- default
append: keeps target rows and appends source rows not already present upsert: requires--onand replaces matching target keys with source rows--onis optional in append mode, but enables conflict-aware duplicate-key validation
Schema behavior:
- default
strict: identical column layout required allow-additive: union columns (target order first, then source-only), fill missing values with nullsallow-additiveis not supported with--ignore-filetypein v1
File type behavior:
- when both source and target are files, file types must match unless
--ignore-filetypeis set - with
--ignore-filetype, matching ignores extension and uses relative path plus stem - ambiguous ignore-filetype matches fail fast before any write
- dtype mismatches are rejected unless a valid CSV-to-binary cast is possible under ignore-filetype mode
Output and safety:
- file-to-file merge requires
--outto point to a file - folder-to-folder merge requires
--outdirectory or--inplace - non-inplace folder merge carries unmatched target files into output unchanged
- non-inplace merge does not overwrite existing output files
- folder merges are transactional; inplace writes use atomic replacement per destination
Examples:
# Preview a merge plan
tabcaddy merge incoming/ archive/ --out merged_archive/ --on customer_id --dry
# Append mode (default)
tabcaddy merge incoming/ archive/ --out merged_archive/ --strategy append
# Upsert mode
tabcaddy merge incoming/ archive/ --out merged_archive/ --strategy upsert --on customer_id
Help
Show all commands:
tabcaddy --help
Show command-specific help:
tabcaddy summary --help
tabcaddy schema --help
tabcaddy scaffold-transform --help
tabcaddy head --help
tabcaddy compile --help
tabcaddy transform --help
tabcaddy diff --help
tabcaddy merge --help
Project details
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 tabcaddy-0.1.6.tar.gz.
File metadata
- Download URL: tabcaddy-0.1.6.tar.gz
- Upload date:
- Size: 169.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
249317e5f1249f8db3fdd1e58dba1129df6c2bfdf1e32df8b87a1c2a535875ef
|
|
| MD5 |
410b8c9f0c45bb463f4f7e83f9500816
|
|
| BLAKE2b-256 |
f67f48b93a89b19c4db09636e44938b9718fcedda58232585da6f9c6b4aaf583
|
File details
Details for the file tabcaddy-0.1.6-py3-none-any.whl.
File metadata
- Download URL: tabcaddy-0.1.6-py3-none-any.whl
- Upload date:
- Size: 64.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c08c486f3b0d1302866ddd5a46b824d054ec3de7d6402b7c97ad2d106547b8cc
|
|
| MD5 |
9486df8cb3a1b8fc8ef3842bb080ce27
|
|
| BLAKE2b-256 |
12582249340b0604417192377e5205b9791f34fe7c43b2ae0c4141f5f5645e94
|