Skip to main content

Custom integrations

Integrations do not have to live in the core tree. ApexOS loads custom integrations from a custom_components package inside the user's configuration directory. The configuration directory is inserted at the front of sys.path, so custom_components/ there is importable as a regular Python package.

<config_dir>/
└── custom_components/
└── my_integration/
├── __init__.py
├── manifest.json # must include "version"!
├── config_flow.py
├── sensor.py
├── strings.json
└── translations/

How loading works

  • At startup the loader scans every directory inside custom_components/ and resolves each one that contains a valid integration (apexos/loader.py, _get_custom_components).
  • Custom integrations are looked up before built-in ones — a custom integration whose domain matches a built-in integration shadows it. The manifest validator emits a warning for such collisions ("Domain collides with built-in core integration"), so only do this deliberately.
  • Custom integrations are not loaded in recovery mode or safe mode.
  • Loading any custom integration logs a notice that the component has not been tested by ApexOS and may cause stability problems — this is expected and purely informational for users.
  • A small denylist of known-broken custom integrations (BLOCKED_CUSTOM_INTEGRATIONS in apexos/loader.py) is blocked below a known good version.

The version key is mandatory

Unlike built-in integrations, a custom integration's manifest.json must contain a version key. The loader refuses to load it otherwise:

The custom integration '<domain>' does not have a version key in the manifest file and was blocked from loading.

The version must be parseable as CalVer, SemVer, SimpleVer, BuildVer, or PEP 440 — an invalid value blocks loading just as a missing one does.

Custom manifests also differ from core manifests in these ways (full details in the manifest reference):

  • documentation must be an https URL pointing at your own docs — not the core documentation site.
  • issue_tracker (URL) is available and recommended.
  • import_executor (bool) is available.

How users install a custom integration

  1. Locate the ApexOS configuration directory.
  2. Create the custom_components directory next to the main configuration file if it does not exist yet.
  3. Copy the integration directory (the one containing manifest.json) into it, so the path is custom_components/<domain>/manifest.json.
  4. Restart ApexOS. If the integration has "config_flow": true, it can then be added from the integrations UI; discovery keys (zeroconf, dhcp, usb, …) work for custom integrations too.

Python requirements listed in the manifest's requirements key are installed automatically into the deps directory of the configuration directory when the integration is first set up.

Validating a custom integration

You can run the same validator the core uses against your integration directory:

python -m script.apexfest --integration-path /path/to/custom_components/<domain>

This checks the manifest schema (including the custom-specific version and documentation rules), key ordering, translations, services, and more.