Skip to main content

Local, folder-driven Dagster CSV transformation engine with hot-folder sensors, AI-assisted pipeline creation, and Tkinter configuration UI.

Project description

ETLai

A local, AI-assisted CSV transformation engine built on Dagster. Install it, scaffold a project, and let Claude Code create new pipelines for you.

Install

pip install ETLai

Requires Python 3.10+ and Tkinter (ships with most Python installations).

Quick start

etlai init ~/my-etl
cd ~/my-etl
etlai sync
etlai run

This starts a Dagster dev server at http://localhost:3000. Enable sensors in the UI, then drop CSV files into pipelines/<name>/inbox/.

Commands

Command Purpose
etlai init <dir> Scaffold a new project with example pipelines
etlai sync Validate manifests, create folders, prompt for path: ask
etlai run Start the Dagster dev server
etlai list Show all registered pipelines

How it works

Each pipeline is defined by a manifest (pipelines/<name>/manifest.yaml) that wires together:

  • Atom — a reusable, domain-agnostic transformation (execute(params_json) -> result_json)
  • Form — a first-run Tkinter UI that collects user config (or passthrough for no-UI pipelines)
  • Sensor — watches the inbox folder for stable files
inbox/ → sensor (stability check) → staging/ → job runs
                                      ├→ processed/ + output/     (success)
                                      └→ rejected/ + *.error.txt  (failure)

Config is saved to config.json after first run. Subsequent runs are fully automated. Delete config.json to force reconfiguration.

Shipped atoms

Atom Input Description
vlookup 2 CSV Left join on specified columns with dtype validation
groupby 1 CSV Group by column with count, sorted descending
mock_generate 1+ CSV Generate synthetic data from file headers using Faker

Shipped forms

Form Description
vlookup_column_picker Join column + output column multi-select with dtype validation
groupby_picker Single column selection
passthrough No UI — reads config.json and passes it to atom

Example manifest

name: vlookup_rollnumber
atom: vlookup
form: vlookup_column_picker
min_files: 2
path: ask                     # prompts for folder location during etlai sync

Composite pipelines

Chain multiple atoms in sequence:

name: vlookup_then_groupby
min_files: 2
steps:
  - atom: vlookup
    form: vlookup_column_picker
  - atom: groupby
    form: groupby_picker

Output of each step becomes input to the next.

Custom data paths

Each pipeline can store its data anywhere. Set path in the manifest:

  • path: asketlai sync opens a folder picker dialog
  • path: /absolute/path — uses that path directly
  • Omitted — defaults to pipelines/<name>/ inside the project

Adding new pipelines with Claude Code

Open your project in Claude Code. The scaffolded CLAUDE.md teaches it how to:

  1. Create atoms in atoms/ (or reuse shipped ones)
  2. Create forms in forms/ (or use passthrough with a pre-written config.json)
  3. Write a manifest.yaml in pipelines/<name>/
  4. Run etlai sync to validate and create folders

For no-UI pipelines, Claude Code writes config.json directly with the business logic (e.g. {"group_column": "religion"}).

Resolution order

  • Atoms: ./atoms/<name>.pyetlai.atoms.<name> (package)
  • Forms: ./forms/<name>.pyetlai.forms.<name> (package)

User files take precedence over shipped ones.

Project structure after etlai init

my-etl/
  etlai.yaml              ← pipelines_root config
  dagster.yaml            ← auto-generated storage config
  definitions.py          ← 3-line auto-loader
  CLAUDE.md               ← instructions for Claude Code
  atoms/                  ← custom atoms (AI-generated)
  forms/                  ← custom forms (AI-generated)
  pipelines/
    <name>/
      manifest.yaml       ← wiring: atom + form + min_files + path
      config.json         ← saved config (always here, even if path points elsewhere)
      inbox/              ← drop files here (or at custom path location)
      staging/            ← in-flight processing
      processed/          ← successfully processed source files
      rejected/           ← failed files + .error.txt
      output/             ← transformation results

Development

git clone <repo>
pip install -e .
etlai init /tmp/test-project
cd /tmp/test-project
etlai run

No automated tests or linter configured yet.

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

etlai-0.2.2.tar.gz (19.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

etlai-0.2.2-py3-none-any.whl (25.7 kB view details)

Uploaded Python 3

File details

Details for the file etlai-0.2.2.tar.gz.

File metadata

  • Download URL: etlai-0.2.2.tar.gz
  • Upload date:
  • Size: 19.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for etlai-0.2.2.tar.gz
Algorithm Hash digest
SHA256 ab539e11fcc28127f560026072cd19e56517c2b6bf643aefccbe9cec91d02c88
MD5 0af19f281d679713a26756f3286cf8e6
BLAKE2b-256 a9265187fcc2ec333207b42fec0931b87cfe5f9defef18cf63769f2ce59a25ab

See more details on using hashes here.

File details

Details for the file etlai-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: etlai-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 25.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for etlai-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c122a539d6ff4a5d9710934d3093e6623253e02152727870f96fa7bfd7d1c56e
MD5 9fcfe83f2129b342ce52517f3a60a1c5
BLAKE2b-256 8cd664337b8fdbb343129633eaaff159ce47f44486ce7101982f760ea3775959

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page