I have 14+ ESPHome devices and as my HA was running on Raspberry Pi 4, of course the updates were slow and painful. I moved it to my local mac, and I was maintaining a pair of shell scripts to upgrade and check firmware versions across all of them. It worked, but adding a new device meant editing the scripts manually. I rewrote it as a proper Go CLI that auto-discovers devices from your existing ESPHome YAML directory โ no separate device list to maintain. Sharing here in case others are managing larger fleets and hit the same friction.
Here is the link to github repo: https://github.com/gevgev/esp-tool
Works naturally with a git-managed ESPHome repo
My own setup: ESPHome YAML configs live in a dedicated GitHub repo, cloned both on my Mac and on the HA host. Editing happens locally in VS Code, changes get committed and pushed to GitHub, then pulled onto the HA instance before flashing. esp-tool sits inside that repo directory and discovers devices automatically from the same YAML files already there โ no separate config, no device list to maintain in parallel.
This means the tool fits into whatever git workflow you already have rather than adding a new one. If you're already version-controlling your ESPHome configs โ and if you're managing more than a handful of devices, you really should be โ esp-tool just works with that setup out of the box.
The only thing living outside git is the binary itself, which make install drops into the repo directory and a one-line .gitignore entry keeps out of version control.
What it does:
- Auto-discovers all devices by scanning your ESPHome YAML directory โ adding a new device YAML is all that's needed
- Parallel OTA upgrades with configurable concurrency, retry logic, and a colored summary table
- Firmware version check across all devices simultaneously
- Boot diagnostics โ detects prior crashes (hardware WDT, exceptions), bootloader age, chip rev, GPIO strapping conflicts, and more
--filterflag for targeting a subset of devices by name--dry-runto verify discovery and see exact commands before flashing anything- Zsh shell completion including device name completion scanned live from your YAML files
Install:
bash
git clone https://github.com/gevgev/esp-tool.git
cd esp-tool
make build
make install # drops the binary into your ESPHome YAML directory
Requires Go 1.21+ and esphome on your PATH.
Typical post-release workflow:
bash
pip3 install esphome --upgrade
./esp-tool versions # confirm all devices reachable
./esp-tool upgrade # flash everything in parallel
./esp-tool upgrade --filter bluetooth-proxy-9c866c # retry any failures
GitHub: GitHub - gevgev/esp-tool ยท GitHub
Tested against ESPHome 2024.11 / HA 2026.5. Still early โ bug reports and feedback very welcome. If you're running a larger fleet and have edge cases around substitution variable handling or unusual YAML structures, I'd especially love to hear about them.
Screenshot for upgrade command output:
In addition it has two useful commands diagnostics and versions commands with screenshots:
versionsโ fleet-wide firmware version check
Connects to each device's live log stream in parallel, grabs the reported ESPHome version from the boot output, and exits. No need to SSH into devices or check the HA UI one by one.
./esp-tool versions # check all devices
esp-tool versions --filter ocamera,widecamera # check a subset
esp-tool versions --timeout 20s # allow more time for slow devices
Prints a colored summary table โ green for reachable with version, red for unreachable. Useful as a quick sanity check before and after a bulk upgrade to confirm everything came back up on the expected firmware version.
diagnosticsโ boot health analysis across the fleet
This is the command I wish I'd had earlier. It connects to each device's live log stream in parallel, captures the initial boot dump, and analyses it for known problem patterns โ without you having to read through raw ESPHome logs manually for 14 devices.
./esp-tool diagnostics # check all devices
./esp-tool diagnostics --reboot # soft-reboot each device first, then capture fresh boot log
./esp-tool diagnostics --filter air-quality-external,aram-display --verbose
What it detects:
- Crash on previous boot โ hardware watchdog timer (WDT) resets, software exceptions, stack overflows. If a device has been silently crash-looping, this surfaces it immediately across the whole fleet in one pass
- Bootloader too old for OTA rollback โ flags devices that need a one-time USB flash to get a modern bootloader before OTA rollback will work safely
- Bootloader supports SRAM1 โ identifies devices where enabling the SRAM1 flag would give you an extra +40 KB of IRAM, useful if you're running close to memory limits
- Chip revision โฅ 3.0 โ flags devices where setting
minimum_chip_revisionin your YAML could reduce binary size- GPIO strapping pin conflicts โ detects when a GPIO you're using in your config overlaps with ESP32 hardware strapping pins, which can cause unpredictable boot behavior
- Multiple OTA platform configs merged โ catches a subtle ESPHome config issue where multiple OTA blocks are silently merged in ways that may not match your intent
The
--rebootflag is particularly useful after a bulk upgrade โ it soft-reboots each device and captures a clean boot log, so you're not reading stale pre-upgrade diagnostics. Combined with--verboseyou get the raw log lines alongside the parsed health table.A typical post-upgrade run looks like this:
./esp-tool upgrade # flash everything ./esp-tool diagnostics --reboot # reboot each device, confirm clean boot across the fleet
If you've ever spent 20 minutes grepping ESPHome logs trying to figure out why one device in your fleet keeps resetting โ this is the command that makes that a 12-second operation.


