{"id":50793286,"url":"https://github.com/nebkat/idftool","last_synced_at":"2026-06-12T12:31:46.191Z","repository":{"id":360262947,"uuid":"1249376501","full_name":"nebkat/idftool","owner":"nebkat","description":"Utility for flashing, provisioning, and interacting with Espressif SOCs running ESP-IDF","archived":false,"fork":false,"pushed_at":"2026-05-25T18:10:46.000Z","size":21,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-25T18:31:16.915Z","etag":null,"topics":["esp-idf","esp32","espressif"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/idftool/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nebkat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-25T16:25:37.000Z","updated_at":"2026-05-25T18:10:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nebkat/idftool","commit_stats":null,"previous_names":["nebkat/idftool"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/nebkat/idftool","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nebkat%2Fidftool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nebkat%2Fidftool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nebkat%2Fidftool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nebkat%2Fidftool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nebkat","download_url":"https://codeload.github.com/nebkat/idftool/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nebkat%2Fidftool/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34245217,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["esp-idf","esp32","espressif"],"created_at":"2026-06-12T12:31:45.475Z","updated_at":"2026-06-12T12:31:46.169Z","avatar_url":"https://github.com/nebkat.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# idftool\n\nA CLI tool built on top of [`esptool`](https://github.com/espressif/esptool)\nthat is ESP-IDF partition aware.\n\n## Why idftool?\n\n`esptool` is a generic tool for flashing Espressif modules that works with\narbitrary flash addresses. It does not take into the ESP-IDF partition\ntable or OTA mechanism, making it unduly difficult to perform simple tasks\nsuch as flashing a new firmware binary or pulling log data from a device -\nespecially when dealing with multiple devices/partition tables.\n\n`idftool` offers:\n\n- **Partition-name addressing.** Read, write, erase, or hex-dump a\n  partition by name (`nvs`, `ota_0`, `storage`, …) — and grab slices of it\n  with a `name[start:stop]` syntax.\n- **OTA slot management.** Inspect the active slot, switch slots, or roll\n  back to factory without hand-computing otadata offsets. `idftool list`\n  marks the running OTA partition right in the table.\n- **Improved safety features.** Writes are checked to ensure they do not\n  overflow the target partition. Firmware binaries are checked to ensure\n  compatibility with the chip being flashed.\n- **Reproducible multi-binary flashing.** `create-bundle` packs multiple\n  partition binaries into a single ZIP; optionally flashing a partition\n  table. `write-bundle` reflashes the lot in one command.\n\n## Installation\n\n### pipx (recommended)\n\n[pipx](https://pipx.pypa.io) installs idftool into an isolated environment and\nputs it on your `PATH` automatically:\n\n```bash\npipx install idftool\n```\n\nInstall pipx first if you don't have it:\n\n| Platform | Command |\n|----------|---------|\n| macOS | `brew install pipx` |\n| Windows | `winget install python.pipx` |\n| Linux / other | `pip install pipx` |\n\n### Binary\n\nIf you don't have Python, download the pre-built binary from the\n[Releases](https://github.com/nebkat/idftool/releases) page. Prefer the `-dir`\narchive over the single-file download — it starts instantly rather than extracting\nitself on each run.\n\n## At a glance\n\n```bash\n$ idftool devices\n/dev/cu.usbmodem1101 || USB JTAG/serial debug unit || USB VID:PID=303A:1001 SER=...\n\n$ idftool list\n| Name     | Type | Subtype  | Offset   | Size | App description |\n|----------|------|----------|----------|------|-----------------|\n| nvs      | data | nvs      | 0x9000   | 16K  |                 |\n| otadata  | data | ota (A)  | 0xd000   | 8K   |                 |\n| phy_init | data | phy      | 0xf000   | 4K   |                 |\n| ota_0    | app  | ota_0    | 0x10000  | 1M   | my-app v1.0.0   |\n| ota_1    | app  | ota_1    | 0x110000 | 1M   | my-app v1.1.0 * |\n| storage  | data | spiffs   | 0x210000 | 1M   |                 |\n\n# The trailing `*` marks the currently-active OTA app\n\n$ idftool ota build/my-app.bin\nWriting 'my-app v1.2.0' to partition 'ota_0'...\nSetting boot partition to 'ota_0'...\n\n$ idftool write nvs my-nvs.bin\nWriting file my-nvs.bin (size=0x4000) to partition nvs (offset=0x9000, size=0x4000)\n\n$ idftool set-boot ota_1\nSetting boot partition to 'ota_1'...\n```\n\n---\n\n## Command reference\n\n| Command | Description |\n|---------|-------------|\n| **Discovery** | |\n| [`devices`](#devices) | List serial ports with hardware IDs |\n| [`list`](#list) | Print the partition table |\n| **Partition I/O** | |\n| [`read`](#read) | Read a partition (or slice) into a file |\n| [`write`](#write) | Write one or more files to named partitions |\n| [`erase`](#erase) | Erase a partition (or slice) |\n| [`view`](#view) | Pretty-print a partition's contents |\n| **Firmware** | |\n| [`ota`](#ota) | Push an app to the next OTA slot and switch to it |\n| [`factory`](#factory) | Flash an app to the factory partition |\n| **Boot selection** | |\n| [`get-boot`](#get-boot) | Show the currently-active OTA slot |\n| [`set-boot`](#set-boot) | Force the next boot to a specific OTA partition |\n| [`clear-boot`](#clear-boot) | Erase otadata and let the bootloader fall back |\n| **Images** | |\n| [`create-image`](#create-image) | Merge partition binaries into a single flash image |\n| [`dump-image`](#dump-image) | Dump the entire flash to an image file |\n| [`write-image`](#write-image-alias-reflash) | Write a full flash image to the device |\n| **Bundles** | |\n| [`create-bundle`](#create-bundle) | Pack partition images into a ZIP bundle |\n| [`dump-bundle`](#dump-bundle) | Pack every partition from the device into a ZIP |\n| [`write-bundle`](#write-bundle) | Flash every binary in a bundle ZIP |\n| **NVS** | |\n| [`create-nvs`](#create-nvs) | Generate an NVS partition image from a CSV file |\n| [`write-nvs`](#write-nvs) | Generate an NVS image from CSV and flash it |\n| **Misc** | |\n| [`enter-bootloader`](#enter-bootloader) | Drop the chip into ROM bootloader mode |\n\n### Discovery\n\n#### `devices`\nList the serial ports the host can see, with their descriptions and USB\nhardware IDs.\n```text\nidftool devices\n```\n\n#### `list`\nPrint the device's partition table. With a connected ESP, idftool also\nreads the application descriptor of every app partition (project name,\nversion) and marks the currently-active OTA slot with a trailing `*`. The\nselected otadata copy is shown next to the otadata partition's subtype\n(`ota (A)`, `ota (B)`, or `ota (invalid)` when otadata is erased).\n```text\nidftool list\nidftool --partition-table-file partitions.csv list   # offline\n```\n\n### Partition I/O\n\n#### `read`\nRead a partition (or slice) into a file.\n```text\nidftool read nvs nvs.bin\nidftool read 'storage[-0x1000:]' tail.bin\n```\n\n#### `write`\nWrite one or more files to named partitions. Arguments come in\n`PARTITION FILENAME` pairs; you can repeat them to flash several\npartitions atomically.\n```text\nidftool write ota_0 build/app.bin storage build/spiffs.bin\n```\n\n#### `erase`\nErase a partition (or slice of one).\n```text\nidftool erase nvs\n```\n\n#### `view`\nPretty-print a partition's contents. Hex dump by default; pass `-s` for\nUTF-8 string mode and `-w` to tweak the dump width.\n```text\nidftool view nvs\nidftool view nvs -w 32\nidftool view nvs -s\n```\n\n### Firmware\n\n#### `ota`\nPush a new app image to the **next** OTA slot, then set it as the boot\nslot. idftool figures out which slot is next from otadata, writes the\nimage, and bumps the OTA sequence counter — exactly what an OTA update\nfrom the firmware would do, just over USB.\n```text\nidftool ota build/my-app.bin\n```\n\n#### `factory`\nWrite an app to the factory partition and erase otadata so the bootloader\nfalls back to factory on next boot. If the device has no factory\npartition, the image is written to `ota_0` instead.\n```text\nidftool factory build/my-app.bin\n```\n\n### Boot selection\n\n#### `get-boot`\nPrint which OTA slot the bootloader will run on the next reset, along\nwith the sequence number and OTA state.\n```text\nidftool get-boot\n```\n\n#### `set-boot`\nForce the next boot to a specific OTA partition by name (e.g. `ota_0`,\n`ota_1`).\n```text\nidftool set-boot ota_1\n```\n\n#### `clear-boot`\nErase the otadata partition. The bootloader's fallback then kicks in: if\na factory partition exists it boots factory, otherwise it boots `ota_0`.\nThe OTA app images themselves are left untouched.\n```text\nidftool clear-boot\n```\n\n### Images\n\nAn image is a single contiguous flash image — everything from the\nprimary bootloader through the partition table and partitions in one\nfile. Useful for archiving a known-good snapshot, recovering a bricked\ndevice, or feeding production programmers that can't speak the esptool\nprotocol.\n\n#### `create-image`\nCombine partition images into a single contiguous flash image, offline,\nfrom local files and a partition table.\n```text\nidftool --partition-table-file partitions.csv create-image \\\n  -o merged.img --flash-partition-table \\\n  ota_0 build/app.bin storage build/spiffs.bin\n```\n\n#### `dump-image`\nRead the entire flash to an image file. If no output filename is given,\nthe file is named `{chip}-{mac}-{timestamp}.img` (e.g.\n`esp32-s3-aabbccddeeff-20260522-143000.img`). Works even when the\non-device partition table is corrupted.\n```text\nidftool dump-image                 # auto-named\nidftool dump-image my-backup.img\n```\n\n#### `write-image` (alias: `reflash`)\nErase the entire flash and rewrite it from a flash image. The\ncounterpart of `dump-image`.\n```text\nidftool write-image build/full-flash.img\n```\n\n### Bundles\n\nA bundle is a plain ZIP file containing one `*.bin` per partition (named\nafter the partition) and, optionally, a `partition_table.csv`. Bundles\nare useful for hand-off between build and flash steps and for archiving a\nreproducible \"this is what shipped\" snapshot.\n\n#### `create-bundle`\nPack partition images into a bundle ZIP. Pass `--flash-partition-table`\nto embed the partition table CSV so `write-bundle` can also reflash it.\n```text\nidftool --partition-table-file partitions.csv create-bundle \\\n  -o release.zip --flash-partition-table \\\n  ota_0 build/app.bin storage build/spiffs.bin\n```\n\n#### `dump-bundle`\nRead every partition from the device and pack them into a bundle ZIP,\nalways including `partition_table.csv`. If no output filename is given,\nthe file is named `{chip}-{mac}-{timestamp}.zip`.\n```text\nidftool dump-bundle                  # auto-named\nidftool dump-bundle my-backup.zip\n```\n\n#### `write-bundle`\nFlash every binary in a bundle ZIP. If the bundle contains\n`partition_table.csv`, idftool uses it (and rewrites the on-device table\nto match) instead of reading the table from flash.\n```text\nidftool write-bundle release.zip\n```\n\n### NVS\n\nidftool can generate a binary NVS (Non-Volatile Storage) partition image\nfrom a CSV file, using the same format as ESP-IDF's\n[`nvs_partition_gen.py`](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/nvs_partition_gen.html).\n\nExample CSV:\n```csv\nkey,type,encoding,value\nstorage,namespace,,\ndevice_name,data,string,My Device\ndevice_id,data,u32,12345\napi_key,data,string,abc123def456\n```\n\n#### `create-nvs`\nGenerate an NVS partition image from a CSV file, offline. Requires either\n`--size` (explicit partition size) or `--partition` (look up the size from\nthe partition table — needs `--partition-table-file` or a device).\n```text\nidftool create-nvs nvs.csv -o nvs.bin --size 0x6000\nidftool --partition-table-file partitions.csv create-nvs nvs.csv -o nvs.bin --partition nvs\n```\n\n#### `write-nvs`\nGenerate an NVS partition image from a CSV file and flash it to the named\npartition on the device.\n```text\nidftool write-nvs nvs nvs.csv\n```\n\n### Misc\n\n#### `enter-bootloader`\nWait for a serial port to appear, then run the BOOT0+RESET dance to drop\nthe chip into the ROM bootloader (a.k.a. firmware download mode) — and\nexit immediately, leaving the device parked for whatever tool you want to\nhand it off to. The port path is polled at 50 ms intervals, and transient\nerrors (e.g. `termios.error: Device not configured` from a tty node that\nisn't fully settled) are retried silently.\n```text\nidftool -p /dev/cu.usbmodem1101 enter-bootloader\n```\nRequires `-p`/`--port`.\n\n--\n\n## Global options\n\nThese flags apply to every subcommand and go **before** the command name:\n\n| Flag | Purpose |\n|------|---------|\n| `-p`, `--port PATH` | Serial port device. If omitted, idftool auto-picks one. |\n| `-b`, `--baud N` | Serial baud rate (defaults to esptool's ROM baud, 115200). |\n| `--no-reset` | Skip the hard reset that normally happens after a command. |\n| `--partition-table-file PATH` | Use a CSV or binary partition table from disk instead of reading it off the device. |\n| `--partition-table-offset OFFSET` | Where to expect the partition table in flash (default `0x8000`). |\n| `--partition-table-size SIZE` | Size of the partition table region (default `0x1000`). |\n| `--primary-bootloader-offset OFFSET` | Primary bootloader offset, or a chip name like `esp32s3` to pick a default. Only needed when addressing the `bootloader` partition by name in **offline** mode (`--partition-table-file` with no device); auto-detected from a connected chip otherwise. |\n| `--recovery-bootloader-offset OFFSET` | Recovery bootloader offset; same scope as `--primary-bootloader-offset`. |\n\nThe commands `list`, `merge-bin`, and `create-bundle` will work **without**\na device when you supply `--partition-table-file`; everything else needs a\nconnected ESP.\n\n## Partition addressing\n\nWherever a command takes a `partition` argument you can pass:\n\n- A **name** from the partition table (`nvs`, `ota_0`, `storage`, …).\n- A **numeric address** that matches an existing partition's start\n  offset exactly — equivalent to looking the partition up by name, just\n  keyed on its address.\n- An **offset into a partition**: `name[offset]`. Negative values count\n  from the end. Sets the starting point for the operation. Accepted by\n  `write` and `merge-bin`.\n- A **slice of a partition**: `name[start:stop]`. Negative values count\n  from the end, and a `+N` stop is a length relative to `start`.\n  Accepted by `read`, `erase`, and `view`. Examples:\n  - `nvs[0:0x100]` — first 256 bytes of `nvs`\n  - `storage[-0x1000:]` — last 4 KiB of `storage`\n  - `ota_0[0x1000:+0x800]` — 2 KiB starting 4 KiB into `ota_0`\n\nAll numeric values in addresses, offsets, and sizes accept either\ndecimal (`4096`) or hex (`0x1000`).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnebkat%2Fidftool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnebkat%2Fidftool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnebkat%2Fidftool/lists"}