Skip to main content

folder2uf2

What it does

Ships a CircuitPython project as one file, so customers copy once.

Install

pip install folder2uf2

Python 3.8 or newer, standard library only. No dependencies.

Three ways to ship

Output Goes onto Board must be
code.py CIRCUITPY running CircuitPython
.uf2 RPI-RP2, RP2350 in the UF2 bootloader
.bin flashed by esptool ESP32, any state

Self-extract: one file, no bootloader

Pack the project. Output must be code.py, the name CircuitPython runs.

folder2uf2 --self-extract -o code.py myproject/

What your customer does

1. drag code.py onto CIRCUITPY
2. CIRCUITPY disappears for about 4 seconds
3. board reboots with code.py, lib/ and assets in place

Works on every port, RP2 and ESP32 alike.

If it fails

The drive is handed back with an error. Nobody gets locked out.

How it works

storage.unsafe_disable_usb_drive() makes CIRCUITPY writable from code.py.

# payload rides in trailing comments, inflated one file at a time
# peak RAM is the largest single file, not the whole tree
# remount() cannot: MSC holds the block device lock while mounted

Limits

Needs CircuitPython installed already. CIRCUITPY vanishes while it runs.

zlib required: default wherever CIRCUITPY_FULL_BUILD is set
60KB incompressible single file verified on a 264KB RP2040

UF2, for RP2 boards

# filesystem only
folder2uf2 --board adafruit_metro_rp2350 -o fs.uf2 myproject/

# firmware and filesystem together
folder2uf2 --board adafruit_metro_rp2350 \
           --combine firmware.uf2 -o product.uf2 myproject/

# wipe residual data rather than writing only used sectors
folder2uf2 --board adafruit_metro_rp2350 --full -o fs.uf2 myproject/

# a board with no built-in profile
folder2uf2 --flash-offset 0x100000 --flash-size 0x1000000 \
           --family-id 0xe48bff59 -o fs.uf2 myproject/

folder2uf2 --list-boards

ESP32

tinyuf2 writes only ota_0, so ESP32 gets a raw image for esptool.

folder2uf2 --board esp32_16mb -o fs.bin myproject/
esptool --before no-reset --after no-reset write-flash 0x450000 fs.bin

Storage extend

Layouts differ, so read the table off your chip.

esptool --before no-reset --after no-reset read-flash 0x8000 0xc00 pt.bin
folder2uf2 --board esp32_16mb --partition-table pt.bin --storage-extend -o fs.bin src/
storage_extended = (_partition[0]->size < fatfs_bytes());
/* S3 16MB has that slot: 28032 sectors. S2 4MB does not: 1920. */

Download mode

One-shot: one esptool run per entry, then power cycle.

Bootloader

Install the tinyuf2 bootloader first, per your board's learn guide.

Browser instead of esptool

Takes a file and an offset, so customers need no Python.

https://adafruit.github.io/Adafruit_WebSerial_ESPTool/

How it was tested

Self-extract, three boards

RP2040 is the tight one.

Adafruit CircuitPython 10.3.0 on 2026-08-31; Adafruit Metro RP2040 with rp2040
Adafruit CircuitPython 10.3.0 on 2026-08-31; Adafruit Metro RP2350 with rp2350b
Adafruit CircuitPython 10.3.0 on 2026-08-31; Adafruit Metro ESP32S3 with ESP32S3

60144 bytes of source packed into 84356 bytes
assets.bin 60000 bytes incompressible, md5 matched
lib/mypkg/__init__.py created, nested dir
code.py replaced by the product, printed its marker

Drive returned unaided. All boards restored, identical.

What the RP2040 taught

Two MemoryErrors before it fit, both invisible on roomier chips.

"".join(chunks)        -> allocating 80037 bytes, failed
growing a bytearray    -> allocating 49680 bytes, failed
preallocate + memoryview -> fits

Combine, Metro RP2350

Before, then after one UF2 carrying the 10.3.0 release.

Adafruit CircuitPython 10.3.0-alpha.4 on 2026-07-23; Adafruit Metro RP2350 with rp2350b

Adafruit CircuitPython 10.3.0 on 2026-08-31; Adafruit Metro RP2350 with rp2350b
code.py output:
FOLDER2UF2-COMBINE-OK marker 8f3a21
lib import works

restored by a second combined UF2, 108 files identical

ESP32 image, Metro ESP32-S3

Partition table read from the chip, not assumed.

ffat  data fat  0x450000  0xBB0000  11968K
wrote 43520 bytes, hash verified
volume 28032 sectors, files intact

Safety

Firmware is untouched unless you pass --combine.

--self-extract writes only your files, leaving others alone
an ESP32 image sized wrong overflows, so read the table

Credit

Idea from jepler's archived mkfatimg. Thanks @todbot for the requests.

https://github.com/adafruit/circuitpython/issues/10074

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

folder2uf2-0.1.0.tar.gz (20.3 kB view details)

Uploaded Source

Built Distribution

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

folder2uf2-0.1.0-py3-none-any.whl (16.6 kB view details)

Uploaded Python 3

File details

Details for the file folder2uf2-0.1.0.tar.gz.

File metadata

  • Download URL: folder2uf2-0.1.0.tar.gz
  • Upload date:
  • Size: 20.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for folder2uf2-0.1.0.tar.gz
Algorithm Hash digest
SHA256 089d127fb04b051f4b386e8002172f93b20145336262706b87cd672703585d73
MD5 665a824ea40d4f811ea194048fd76876
BLAKE2b-256 1b6850d09c435aed6234ce98c92a939a7c0a63c6dfb8f900e6c6aaf86df19455

See more details on using hashes here.

File details

Details for the file folder2uf2-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: folder2uf2-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for folder2uf2-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 562f69c9d799f13eb0bddf28b6a72a3a97aa64e971a025aa3fe4b73c4c38be05
MD5 3d4a59acbe52e4dd2fd96b3b71f53227
BLAKE2b-256 2446773d820a352e92e3150c21f9c6faf5073f018e1f6d13e7dbb87c0d64d82f

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.1

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page