OTA firmware images, metadata, and CLI tools for Zigbee devices, used by zigpy-based applications like Home Assistant's ZHA.
You don't need to use this repository directly. OTA updates are automatically available through:
- Home Assistant ZHA integration - Updates appear automatically in the UI (requires Home Assistant Core 2026.1.0 or later)
- zigpy-based applications - Any application using zigpy can consume these updates
Note: Firmware marked as [disabled] or [stale] is not installable. It's retained for historic and changelog purposes only.
Click to expand
By default, only stable firmware is available, which is highly recommended for most users.
To opt into pre-release firmware, add this to your Home Assistant configuration:
zha:
zigpy_config:
ota:
extra_providers:
- type: zigpy_ota
channel: beta # or 'dev' for bleeding edge (unstable, not recommended)
override_previous: trueUse the GitHub issue form to submit OTA images - this is the recommended and easiest method:
- Go to: https://github.com/zigpy/zigpy-ota/issues/new/choose
- Select one of two options:
- "Submit OTA (URL)" - Provide a download URL to the OTA file
- "Submit OTA (File Upload)" - Upload the OTA file directly (must be zipped first)
- Fill out the form with:
- Title: Use format
Add Manufacturer Device vX.X.X - OTA image URL or upload zipped OTA file (depending on which form)
- How to handle existing images (required dropdown):
- Keep all existing images
- Keep existing images and set
min_current_file_versionto highest existing version
- Manufacturer name (optional, for display purposes)
- Release notes (optional but recommended)
- Optional metadata (model names, version constraints, hardware versions, etc.)
- Checklist items (at least confirm the file format)
- Title: Use format
Important: Submit one issue per OTA image. Multiple versions should be separate issues.
What happens next:
- For trusted submitters, an automated PR is created immediately
- For other submitters, a maintainer will review your issue and add the
ota-createlabel to trigger PR creation
If you need to make changes to your submission, edit the original issue and ask a maintainer to add the ota-resubmit label to update the PR.
Tip: You can also submit older firmware versions (e.g., factory-installed firmware) so that ZHA displays "up-to-date" instead of "unknown" for devices already running the latest available firmware.
For updates to existing images (e.g., adding min_current_file_version or model_names to an existing image), you can submit a PR directly:
- Fork the repository
- Edit the
.yamlfile in theimages/directory - Submit a pull request with your changes
See the YAML Metadata Format section below.
To disable or revert an existing firmware update, submit a PR using one of these methods:
- Disable the image (preferred) - Add
disabled: trueto the YAML metadata file to exclude it from the index without deleting the files. - Revert the commit - If the firmware was recently added, create a PR that reverts the commit which added the update
- Manual deletion - Delete both the OTA file (
.zigbeeor.ota) and its corresponding YAML metadata file (.yaml) from theimages/directory, then submit a PR with those changes
For options 2 and 3, both the OTA binary and YAML metadata file must be removed together to fully remove a firmware update from the index. Use deletion only if the firmware bricks devices.
Note: The repository generally retains all firmware images for historic purposes.
Zigpy always prefers newer firmware versions, so older images are only used when they have constraints (like min_current_file_version or model_names) that make them more specific to certain devices.
You can check the firmware index to see if an image is marked as [stale] or [disabled]. These are not installed by zigpy/ZHA.
- OTA images are submitted via GitHub issues
- Automated PRs are created and reviewed
- Once merged to
dev, thedev/folder on therelease/filesbranch is automatically updated with the latest index files - Images are immediately available for testing from the dev channel
- For stable/beta releases, maintainers create a GitHub release. Index files are attached as release assets and mirrored to the corresponding folder on the
release/filesbranch - zigpy and Home Assistant automatically consume the index from the appropriate channel
- stable - Production releases for end users
- beta - Pre-release testing versions
- dev - Latest development builds from the
devbranch
Images are included in channels based on their channel YAML field:
- No
channelfield (default): included in stable, beta, and dev channel: beta: included in beta and dev onlychannel: dev: included in dev only
Index file naming (GitHub release assets):
- Stable releases:
zigpy_v1_ota.json,z2m_v1_ota.json, andmarkdown_v1.md - Beta releases:
zigpy_v1_ota_beta.json,z2m_v1_ota_beta.json, andmarkdown_v1_beta.md
Recommended: Discover the URL dynamically via version files on the release/version branch:
https://raw.githubusercontent.com/zigpy/zigpy-ota/release/version/{stable,beta,dev}.json
Index files are also mirrored to the release/files branch organized by channel (stable/, beta/, dev/), where all folders use the same filenames (zigpy_v1_ota.json, z2m_v1_ota.json, markdown_v1.md).
After an image is merged to the dev branch, the updated index is immediately available for testing at:
https://raw.githubusercontent.com/zigpy/zigpy-ota/release/files/dev/zigpy_v1_ota.json
Direct access for all channels (not preferred):
https://raw.githubusercontent.com/zigpy/zigpy-ota/release/files/{stable,beta,dev}/zigpy_v1_ota.json
Example: To use the stable Zigbee2MQTT index, add this to your Z2M configuration:
ota:
zigbee_ota_override_index_location: https://raw.githubusercontent.com/zigpy/zigpy-ota/release/files/stable/z2m_v1_ota.jsonThe YAML metadata file must have the same name as the OTA file with .yaml appended.
(e.g., firmware_name.ota → firmware_name.ota.yaml).
OTA files are automatically renamed to a standardized format based on their metadata: <manufacturer_id>-<image_type>-<file_version>_<hash>.ota (hash is first 6 chars of SHA3-256). The original filename is preserved in the source_file_name field.
This renaming is done automatically when submitting a new OTA image via the issue form. In the future, CLI tools will also be added to rename files locally.
For images stored in this repository:
# OTA metadata
file_name: 100B-010C-01001A02_abc123.ota
source_file_name: original_firmware.zigbee
source_url: https://manufacturer.com/original_firmware.zigbee
# Optional fields:
release_notes: |-
- Bug fixes
- New features
manufacturer_names: [Manufacturer A, Manufacturer B]
model_names: [Model X, Model Y]
min_current_file_version: 100
max_current_file_version: 200
min_hardware_version: 5
max_hardware_version: 10
specificity: 3
channel: betafile_name: The standardized filename in the repository (auto-generated from OTA metadata)source_file_name: The original filename from the source (preserved for reference)
manufacturer_names- List of manufacturer name strings for device matchingmodel_names- List of model name strings for device matchingmin_current_file_version- Minimum current firmware version for update eligibilitymax_current_file_version- Maximum current firmware version for update eligibilitymin_hardware_version- Minimum hardware version compatibilitymax_hardware_version- Maximum hardware version compatibilityspecificity- Priority level when multiple images match (higher = more specific)channel- Release channel (omit for stable which appears in all channels;betaappears in beta and dev;devappears only in dev)
Note on multi-step upgrades: Due to how zigpy's firmware matching algorithm works, it's typically sufficient to set min_current_file_version on the newer image to require a previous upgrade first.
Zigpy automatically prioritizes and prefers more specific images based on the device's current firmware version, so max_current_file_version constraints are usually not needed.
For the generated Z2M index, maxFileVersion is automatically computed from min_current_file_version constraints of newer images.
Click to expand
# Clone the repository
git clone https://github.com/zigpy/zigpy-ota.git
cd zigpy-ota
# Run setup script (creates venv, installs dependencies, sets up pre-commit)
script/setup
# Activate the virtual environment
source .venv/bin/activate
# Or manually:
# uv sync
# pre-commit install# Run all tests
pytest
# Update snapshots after intentional changes
pytest --snapshot-update
# Run specific test file
pytest tests/test_prepare_pr.py
# Run with coverage
pytest --cov=zigpy_ota --cov-report=html# Run all pre-commit hooks
pre-commit run --all-files
# Type checking
mypy zigpy_ota
# Linting and formatting
ruff check zigpy_ota
ruff format zigpy_ota# Generate index from images
zigpy-ota generate-index --format zigpy # zigpy JSON (default)
zigpy-ota generate-index --format z2m # Zigbee2MQTT JSON
zigpy-ota generate-index --format markdown # Human-readable markdown
# Parse a GitHub issue submission
zigpy-ota parse-issue issue.md
# Prepare PR from issue (download OTA, create YAML, generate PR markdown)
zigpy-ota prepare-pr issue.md --output-pr-markdown pr.md
# Generate stub YAML metadata for an OTA file
zigpy-ota generate-stub-metadata firmware.ota
# Rename OTA files to standardized format (updates YAML too)
zigpy-ota rename-ota-files --dry-run # preview
zigpy-ota rename-ota-files # apply
# Generate fake OTA image for testing
zigpy-ota generate-fake-ota output.ota --manufacturer-id 0x100B --image-type 0x010C --file-version 0x00000001
# Replace real OTA files with fake ones (for tests)
zigpy-ota replace-with-fake-ota tests/data/ota_files/*.otaThe generate-index command has validation flags (all default to strict/fail):
# Strict validation (recommended for CI/CD)
zigpy-ota generate-index
# Development mode flags:
--allow-missing-yaml # Allow OTA images without corresponding YAML metadata
--allow-missing-ota # Allow YAML files without corresponding OTA binary
--allow-inconsistent-yaml # Allow third-party YAML with local OTA files present
--allow-filename-mismatch # Allow YAML file_name field not matching filename
--allow-invalid-yaml # Allow YAML files that fail to parse
--allow-collisions # Allow duplicate images (same ID/type/version)
# Download and validate third-party/remote hosted images (not for CI/CD)
--validate-third-partySee CLAUDE.md for detailed developer documentation.
The zigpy-ota software code is licensed under GPL-3.0 (GNU General Public License v3.0). See LICENSE file.
Important: Binary firmware image files in this repository are third-party content from their respective manufacturers and are NOT covered by the GPL license. These firmware files remain under their original copyright and licensing terms as set by their manufacturers. Users must comply with applicable manufacturer terms when using these firmware files.
For questions or discussions, see GitHub Discussions.