zigbee-herdsman-converters: the device knowledge layer under Zigbee2MQTT
Collection of device converters to be used with zigbee-herdsman
At a glance
- What is it?
- zigbee-herdsman-converters is a TypeScript library of per-device converters that tell Zigbee2MQTT what a specific piece of hardware actually is, which is where most of the pain of a Zigbee mesh lives. It suits anyone building on zigbee-herdsman or contributing a device, and it is a fast-moving package whose major versions arrive with breaking changes.
- Who is it for?
- zigbee-herdsman-converters fits anyone who runs a Zigbee mesh and needs a specific device to behave correctly, because the converter is where the mapping from a manufacturer's proprietary cluster to a standard one lives, and because contributing a new device is a contained piece of work with a documented pull request checklist.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What a converter actually is
The package is described as a collection of device converters to be used with zigbee-herdsman, and that description is accurate but undersells why the collection exists.
Zigbee is a standard, and the devices that people actually buy are not standard. A manufacturer will take the standard clusters, extend them, rename the attributes, use a different endpoint layout, and ship firmware that does not quite behave like the specification. A bulb that reports brightness in a proprietary cluster, a sensor that sends a manufacturer specific payload, a switch that reports a different attribute set depending on its firmware version. The Zigbee2MQTT documentation for supporting new devices exists precisely because this is where the work is.
A converter is the code that translates one device's real behaviour into the shape the rest of the system expects. The README's breaking changes list shows the two directions. A `fromZigbee` converter takes a message received from the device and produces a normalized message, and a `toZigbee` converter takes a command and produces the bytes to send back. There is also a `postProcessConvertedFromZigbeeMessage` step, which since version 18.0.0 has to be called after a fromZigbee conversion, and it exists to apply calibration and precision, since a cheap sensor reports 23.4 degrees and the converter decides whether that means 23.4 or 23.0.
The collection is large and it is the reason this package exists as a shared dependency. Every consumer of zigbee-herdsman who wants a particular device to work needs the same converter code, so it is maintained in one place and published.
The project is MIT licensed, the primary language is TypeScript, and the repository is not archived with the last push on 2026-10-19.
A rolling major version number, and what that does to your dependencies
The release history is the most important practical fact about this package, and it deserves close attention.
The current version is 26.119.0, and the recent releases are 26.117.1, 26.118.0 and 26.119.0 within the first two weeks of October 2026. So the major version is 26 and the minor number is in the hundreds, which tells you this package releases very often and that the minor number is a running counter rather than a feature number.
The README carries a list of breaking changes by major version, and it is long. 25.0.0 changed the `onEvent` api, added a `device` argument to `postProcessConvertedFromZigbeeMessage`, and changed how `rawData` is provided to `Fz.Message.meta`. 24.0.0 changed how `definition.exposes` is called, so `definition.exposes(undefined, undefined)` is no longer possible and `definition.exposes({isDummyDevice: true}, {})` should be used instead. 23.0.0 requires a `Publish` to be passed to toZigbee converters. 22.0.0 renamed `addDefinition` to `addExternalDefinition` and stopped exposing all `definitions` from an import.
Going further back, 21.0.0 had various breaking changes listed in the changelog, 20.0.0 allowed a toZigbee converter to define no `key` at all, in which case it is used for any key, and 19.0.0 removed legacy extend.
Two older entries are worth noting because they show the shape of the API evolving. 17.0.0 made various methods in `index.ts` async and returning a `Promise`, and 15.0.0 changed the OTA methods, with `isUpdateAvailable` returning an object such as `{available: true, currentFileVersion: 120, otaFileVersion: 125}` instead of a boolean, and `updateToLatest` returning a number, the fileVersion of the new OTA, instead of void.
So the pattern is clear. The major version moves with a breaking change and the minor number counts releases. If you depend on this package directly, you want to pin it and read the changelog, because a floating range will pull in a new major at some point and your code will stop compiling.
Contributing a device, and the three commands that gate a pull request
The contribution path is unusually well specified, which makes sense for a project that takes device support from many contributors.
The documentation points to the Zigbee2MQTT guide on how to support new devices, and then gives a pull request checklist. There are two ways to work on it. GitHub Codespaces lets you create a pull request with a fully setup editor, right from your web browser, which removes the local environment setup as a barrier for a first-time contributor.
Or you work locally. The prerequisites are:
npm install -g pnpm
pnpm install --frozen-lockfileThe frozen lockfile flag matters, because it makes the install reproducible and it is what the continuous integration will do, so a lockfile that drifts from the manifest is caught before the pull request rather than during it.
And then the gate, which is the part to read carefully:
pnpm run check --fix
pnpm run build
pnpm testIf any of those commands finish with an error your PR won't pass the tests and will likely be rejected. The `check` script is `biome check --error-on-warnings`, and the `--fix` flag applies the fixes automatically, which is the difference between a contributor having to learn the formatter's rules and the formatter just doing it. The build is `tsc && node dist/indexer.js`, and the test is `vitest run` with its own config file.
That `dist/indexer.js` step in the build is worth noticing. The build is not just a compile, it also runs an indexer that produces `models-index.json`, and the clean script removes `coverage`, `dist`, `tsconfig.tsbuildinfo` and `models-index.json` together. So the package generates a searchable index of the device models as part of building, which is what lets a large collection of converters be browsable rather than a wall of files.
The package shape, and what it depends on
The manifest is small and its shape tells you what this package is and is not.
The runtime dependencies are three: `iconv-lite` at ^0.7.3, `semver` at ^7.8.5, and `zigbee-herdsman` at ^11.1.0. The last one is the interesting one, because it means this is a companion library that sits on top of the Zigbee stack rather than a standalone application. The other two are there for practical reasons, since some devices report text in a non UTF-8 encoding, and since firmware version strings need comparing to decide which converter to use.
That last point is a real design pressure in Zigbee. The same model number from a manufacturer can ship with different firmware that uses different attributes, so the converter set often has to be selected by firmware version, and `semver` is what makes that comparison possible.
The exports map shows how the package is meant to be consumed. The main entry is `dist/index.js` with types at `dist/index.d.ts`, and there are wildcard subpath exports for `./converters/*` and `./devices/*`, so you can import a single converter file directly rather than pulling in the whole collection. That matters for a package this size, where a targeted import is the difference between a fast start and a slow one.
The build tooling is modern and consistent. Biome handles both checking and formatting, with the config in `biome.json`, vitest handles the tests, and there is a `bench` script running `vitest bench` for benchmarks, which is what you would want on a hot path that converts every incoming message. The `prepack` script runs clean and then build, so what gets published is always freshly built, and `prepare` runs husky to install the git hooks.
There is also a `pnpm-workspace.yaml` in the published files list, which is unusual, and it suggests the repository is set up as a workspace even though the published artifact is a single package.
The repository has a `CODEOWNERS` file and a `release-please-manifest.json` with a `release-please-config.json` beside it, so releases are automated with release-please. There is an `AI_POLICY.md` at the top level and an `AGENTS.md`, plus a `.claude/` directory and a `.devcontainer/`, which together tell you the project has made an explicit decision about how automated contributions are handled.
Where this package stops being the answer
The limits here are worth stating plainly, and they come from the same source as the value.
The first is that it is not a Zigbee stack. It is a knowledge base that plugs into zigbee-herdsman, which is a separate package, and behind that sits the radio and the mesh. If you are not running a Zigbee mesh, none of this applies, and there is no CLI here to browse your devices, no UI, no configuration file. It is a library.
The second is that the converters are device specific by nature, so the coverage is uneven. Some devices have a converter that works well, some have one that was contributed quickly and handles only the common case, and some have no converter at all, in which case the device appears in the system with generic attributes that do not match its real capabilities. The upside of the model is that each device is individually correct rather than generically wrong. The downside is that the quality of your Zigbee experience depends on whether somebody cared about your particular switch.
The third is the breaking change rate, which is the practical cost of a project maintained at this pace. The major version moves on a regular cadence, and the README lists what changed each time. That is normal for a project where the API is still finding its shape, and it is why a direct consumer should pin carefully. If you are writing against it directly, you are effectively accepting a moving API.
The fourth is that the platform is constrained. The engines field declares Node `^22.2.0 || ^24 || <=26.2`, and the package manager is pinned to pnpm 12.3.4, so an older Node or a different package manager is not a supported configuration. For a library that sits inside a larger stack that is already Node 22 based, that is a non-issue. For a standalone script on an older runtime, it is a blocker.
The alternative approaches are worth naming. The Zigbee2MQTT project itself is the usual way to consume this, since it is the application that turns a mesh into MQTT topics, and the converters are the part that makes the devices work. Writing your own converter is entirely reasonable for a device nothing else supports, which is why the contribution guide is as detailed as it is. And for a mesh you control entirely, using a manufacturer's own gateway and its software avoids the problem of heterogeneous device behaviour altogether, at the cost of giving up the open data model.
Editorial conclusion
zigbee-herdsman-converters fits anyone who runs a Zigbee mesh and needs a specific device to behave correctly, because the converter is where the mapping from a manufacturer's proprietary cluster to a standard one lives, and because contributing a new device is a contained piece of work with a documented pull request checklist. Skip it if you are not using zigbee-herdsman, since it is a companion library rather than a standalone tool, and be careful with pinning, because the project documents breaking changes in nearly every major version, with the current release at 26.119.0 and the last push on 2026-10-19. Before you upgrade, read the breaking changes list in the README, and note that Node must be `^22.2.0 || ^24 || <=26.2` and the package manager is pnpm 12.3.4.
Frequently asked questions
What is zigbee-herdsman-converters used for?
It is a collection of device converters to be used with zigbee-herdsman. A fromZigbee converter normalizes messages received from a device, a toZigbee converter turns commands into device bytes, and postProcessConvertedFromZigbeeMessage applies calibration and precision.
How do I contribute a new Zigbee device?
Follow the Zigbee2MQTT guide on supporting new devices, then either use a GitHub Codespace or work locally with pnpm installed and `pnpm install --frozen-lockfile`. Before submitting, run `pnpm run check --fix`, `pnpm run build` and `pnpm test`, since a failure in any of them means the pull request will not pass.
How often does zigbee-herdsman-converters release?
Very often, and the version number reflects it: the current release is 26.119.0, with 26.117.1, 26.118.0 and 26.119.0 all released in the first two weeks of October 2026. The major version moves when there is a breaking change.
What breaking changes did zigbee-herdsman-converters 25.0.0 introduce?
The onEvent api changed, a `device` argument was added to postProcessConvertedFromZigbeeMessage, and `rawData` now needs to be provided to `Fz.Message.meta`. Earlier majors changed the exposes call, required a Publish for toZigbee converters, renamed addDefinition to addExternalDefinition and removed legacy extend.
What are the runtime requirements for zigbee-herdsman-converters?
Node `^22.2.0 || ^24 || <=26.2` and pnpm 12.3.4 as the package manager. The runtime dependencies are iconv-lite, semver and zigbee-herdsman itself, and the licence is MIT.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/koenkk-zigbee-herdsman-converters)Was this useful?