Create a directory structure for your external component following ESPHome's convention: a Python __init__.py for the schema and code-generation hooks, a C++ .h file for the component class, and optionally a .cpp file
In __init__.py, define the CONFIG_SCHEMA using ESPHome's cv (config validation) helpers and implement to_code to generate the C++ instantiation call
Reference the external component in your device YAML under the external_components key, pointing to a local path or a GitHub repository URL with an optional ref
Declare an instance of your component in the YAML using the component's domain name as the key, providing the required configuration fields
Run esphome compile <device.yaml> to build; review compilation errors in the generated C++ in the .esphome/build directory
Flash with esphome upload <device.yaml> (OTA or USB) and monitor serial output with esphome logs <device.yaml>
Known gotchas
Custom components (raw C++ dropped in the config directory without a Python schema) were deprecated in early 2025; migrate to the external component pattern with a Python __init__.py to maintain compatibility with future ESPHome versions
The ref in external_components (branch or commit SHA) is pinned at the time of compilation; explicitly update it to pull in upstream fixes or new features
ESPHome's code generation relies on specific C++ patterns; using dynamic allocation (new/delete) or blocking calls in component constructors can cause boot loops or watchdog resets on ESP32/ESP8266
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp