Local Filesystem Files Python Docs | dltHub
Load CSV, Parquet and JSONL files from Local Filesystem with dlt's filesystem source and your coding agent: credentials, the reader for each format, and incremental loading by modification date.
Last updated:
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt. dlt's filesystem source lists the files behind a bucket_url, and a reader turns each one into rows: CSV, Parquet and JSONL out of the box, anything else with a few lines of your own. See the dlt filesystem source docs for the full reference.
Local Filesystem at a glance
| dlt source | filesystem (from dlt.sources.filesystem import filesystem, read_csv) |
bucket_url | file:///absolute/path/to/files |
| Extra | none — dlt[hub] is enough |
| Credentials | none |
| Readers | read_csv, read_parquet, read_jsonl, read_csv_duckdb |
How do I connect to Local Filesystem?
Point dlt at the folder in .dlt/config.toml. Nothing here is a secret, so config.toml is the right file:
# .dlt/config.toml [sources.filesystem] bucket_url = "file:///absolute/path/to/files"
No credentials: dlt reads the folder directly. A plain absolute path works as well as the file:// form, including Windows paths such as C:\data\files.
dlt reads these files automatically at runtime — never hardcode credentials in your pipeline script. For production environments, see setting up credentials with dlt for environment variable and vault-based options.
Which files can I load from Local Filesystem?
filesystem() only lists files: it yields one item per file (name, path, size and modification_date), not rows. To get rows you pipe it into a reader, a dlt transformer resource: filesystem(...) | read_csv(). dlt ships one reader per common format; for anything else you write your own @dlt.transformer.
| Format | Reader | Needs |
|---|---|---|
| CSV | read_csv() | pandas |
| CSV, large files | read_csv_duckdb() | duckdb |
| Parquet | read_parquet() | pyarrow |
| JSONL | read_jsonl() | — |
| Anything else | your own @dlt.transformer | the parser of your choice |
file_glob selects the files: *.csv for one folder, **/*.csv for every folder below bucket_url. Give the reader a name with .with_name("orders"); that is the table the rows land in.
How do I set up and run the pipeline?
Set up a virtual environment and install dlt:
uv init uv add "dlt[hub,duckdb]" pandas
1. Install the dlt AI harness:
uv run dlthub ai init --agent <your-agent> # <agent>: claude | cursor | codex
This installs project rules, a secrets management skill, appropriate ignore files, and configures the dlt MCP server for your agent. Learn more →
2. Install the filesystem-pipeline toolkit:
uv run dlthub ai toolkit install filesystem-pipeline
This loads the skills and context about dlt the agent uses to scaffold, run and tune the pipeline safely. The agent uses MCP tools to inspect credentials — it never needs to read your secrets.toml directly. Learn more →
3. Start LLM-assisted coding:
Use /create-filesystem-pipeline to load the CSV files in my Local Filesystem folder into DuckDB.
The filesystem-pipeline toolkit takes over from here — it asks for the bucket_url, file format and glob, confirms the plan, scaffolds a single-table pipeline, and runs it on one file before loading everything.
4. Run the pipeline:
uv run python filesystem_pipeline.py
If everything is configured correctly, you'll see output like this:
Pipeline local_filesystem_pipeline load step completed in 0.26 seconds 1 load package(s) were loaded to destination duckdb and into dataset local_filesystem_data The duckdb destination used duckdb:/local_filesystem_pipeline.duckdb location to store data Load package 1749667187.541553 is LOADED and contains no failed jobs
Inspect your pipeline and data:
uv run dlthub show
This opens the Pipeline Dashboard where you can verify pipeline state, load metrics, schema (tables, columns, types), and query the loaded data directly.
Python pipeline example
This example loads the CSV files below bucket_url into DuckDB as one orders table. Replace the glob and the table name with your own:
import dlt from dlt.sources.filesystem import filesystem, read_csv def load_files() -> None: files = filesystem(file_glob="**/*.csv") orders = (files | read_csv()).with_name("orders") pipeline = dlt.pipeline( pipeline_name="local_filesystem_pipeline", destination="duckdb", dataset_name="local_filesystem_data", ) load_info = pipeline.run(orders, write_disposition="replace") print(load_info) if __name__ == "__main__": load_files()
bucket_url and the credentials are not passed in the code: filesystem() reads them from [sources.filesystem] in .dlt/config.toml and .dlt/secrets.toml.
Load only new files:
Reading the whole folder on every run is rarely what you want. Pass an incremental on modification_date and dlt skips every file it has already loaded; the rows of new files are appended:
files = filesystem( file_glob="**/*.csv", incremental=dlt.sources.incremental("modification_date"), ) orders = (files | read_csv()).with_name("orders") load_info = pipeline.run(orders)
If rows inside a file change too, add a primary key and merge: orders.apply_hints(primary_key="id", write_disposition="merge"). The toolkit's /add-incremental-loading skill sets this up for you. See incremental loading.
How do I make it fast?
Reading fewer files beats reading them faster, so set up the incremental above first. After that, the levers are the format, the reader and the glob:
| Symptom | Fix |
|---|---|
| CSV parsing is slow | read_csv_duckdb() is faster and lighter than pandas; land Parquet if you control the format |
| A file does not fit in memory | Lower the reader's chunk size: read_csv(chunksize=10000), read_parquet(chunksize=1000) |
| Many remote files read one by one | filesystem(files_per_page=10) plus .parallelize() on the reader |
| Listing the whole folder is slow | Narrow file_glob to the folders and extensions you need |
The toolkit's /optimize-filesystem-performance skill measures where time goes and applies these one at a time. See the filesystem source reference.
How do I query the loaded data?
After a run, pipeline.dataset() holds the loaded tables. A Relation is a query on that dataset, either a whole table or a SQL string, and reading it gives you the data as a Pandas DataFrame, a PyArrow table or Python tuples. Nothing is read until you ask for it.
import dlt pipeline = dlt.pipeline("local_filesystem_pipeline") # Step 1: Get the dataset from the pipeline dataset = pipeline.dataset() # Step 2: Get a Relation, either a whole table... orders = dataset.table("orders") # ...or any SQL query against DuckDB recent = dataset("SELECT * FROM orders ORDER BY updated_at DESC LIMIT 100") # Step 3: Read the data df = orders.df() # or orders.df(chunk_size=50) for a large table arrow_table = recent.arrow() # a PyArrow Table rows = recent.fetchall() # a list of Python tuples
The columns are the ones in your files; dataset.row_counts().df() lists every table with its row count. Your agent can run the same queries through the MCP server's execute_sql_query tool, and uv run dlthub show opens the Pipeline Dashboard with the schema, load metrics and a query box. See access loaded data in Python and exploring it in marimo notebooks.
What destinations can I load Local Filesystem data to?
dlt supports loading into any of these destinations — only the destination parameter changes:
| Destination | Example value |
|---|---|
| DuckDB (local, default) | "duckdb" |
| PostgreSQL | "postgres" |
| BigQuery | "bigquery" |
| Snowflake | "snowflake" |
| Redshift | "redshift" |
| Databricks | "databricks" |
| Filesystem (S3, GCS, Azure) | "filesystem" |
Change the destination in dlt.pipeline(destination="snowflake") and add credentials in .dlt/secrets.toml. See the full destinations list.
Next steps
Continue your data engineering journey with the other toolkits of the dltHub AI harness:
data-exploration— Build custom notebooks, charts, and dashboards for deeper analysis with marimo notebooks.dlthub-platform— Deploy, schedule, and monitor your pipeline in production.
uv run dlthub ai toolkit install data-exploration uv run dlthub ai toolkit install dlthub-platform
Was this page helpful?
Community Hub
Need more dlt context for Local Filesystem?
Request dlt skills, commands, AGENT.md files, and AI-native context.
Available Pipelines
Local Filesystem to Amazon S3
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: Amazon S3
Local Filesystem to Azure Blob Storage
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: Azure Blob Storage
Local Filesystem to Azure Synapse Analytics
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: Azure Synapse Analytics
Local Filesystem to BigQuery
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: BigQuery
Local Filesystem to Databricks
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: Databricks
Local Filesystem to DuckDB
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: DuckDB
Local Filesystem to Google Cloud Storage
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: Google Cloud Storage
Local Filesystem to Local Filesystem
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: Local Filesystem
Local Filesystem to Microsoft SQL Server
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: Microsoft SQL Server
Local Filesystem to PostgreSQL
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: PostgreSQL
Local Filesystem to Snowflake
Load CSV, Parquet and JSONL files from a local directory or mounted drive with dlt
Destination: Snowflake