I think that is a much more interesting general question for all Silicon Labs modules with Zigbee NCP firmware instead of than building a custom firmware for a specific single device that is also niche + old.
“Zigbee Router mode” and “Join” command for Zigbee NCP in all zigpy radio radios would be both a good approach and useful for several reason, so if could manage to get that to work in bellows then you do not only remove the need for a custom firmware but it would possible be something that could be repurposed on all Silicon Labs modules and adapters shipping with Zigbee NCP (Coordinator) firmware, including all modern Zigbee Coordinaor adapters. If you achieve that then it could then be replicated in other popular zigpy radio libraries such as zigpy-znp.
In fact I posted that question as an open discussion to the zigpy/ZHA developers a few years ago here:
MattWestb also posted specific feature request about it to the bellows repository about the same time:
Anyway, zigpy developers have made it clear that the bellows CLI is deprecated and is no longer meant to be used on its own, as instead you are supposed to use bellows and other radio libraries indirectly via the CLI of zigpy-cli and/or the API of the main zigpy library. However, the CLI of some radio libraries like bellows and zigpy-znp was developeed on their own before zigpy-cli was created as a unified command line interface for zigpy radios and therefore the CLI of radio libraries like bellows and zigpy-znp may have several additional extra CLI command features that have not yet been implemented into zigpy-cli or the API zigpy library, so there is not full feature-parity, thus I think your best approach would be to submit a new feature request for “command ability to join Zigbee NCP device as Zigbee Router” (or similar) as an open issue for zigpy-znp or continue that discussion under the main zigpy repository. Again see:
Suggest you post a new feature request for “Zigbee Router mode” (and “Join” command) for zigpy-cli:
One possible real-world use-case scenario is having ZHA or zigpy-cli stand-alone join an existing Zigbee network for troubleshooting reasons, as a developer tool, that can be used to for example capture and verify Zigbee OTA firmware images (by sending OTA image request with the required image_id, hardware_id, etc., which is something that the deCONZ OTA plugin has the capability of doing). See:
and
Another directly related real-world use-case scenario is then having ZHA join the Zigbee network of existing Zigbee network does not even belong to a ZHA Zigbee Gateway instance but instead Zigbee2MQTT or a commercial Zigbee gateway/bridge/hub (like the IKEA Trådfri Gateway, Philips Hue Bridge, or the Samsung SmartThings Hub).
Yet another real-world use-case scenario is having two Home Assistant instances with the ZHA in the same home/house but only one of them acting as a Zigbee Gateway and having the optiuon to join the second as a Zigbee Router to the first node instead having to setup a new Zigbee network, (could possible even work in some kind of high-availability solution where both are always active that way and it is possible to fail-over to the other node by restoring ZHA backup). After all, a Zigbee Coordinator is technically more or less a Zigbee Router with the added role of security gatekeeper, holding the keys and allowing other devices to join the network or not.