agentskills.codes
HO

homey-app-dev

Homey (Athom) app development with SDK v3 — manifest/compose structure, drivers, capabilities, flow cards, Node.js runtime constraints, CLI commands, validation and publishing. Use when working on this Homey app (drivers, capabilities, flows, app.json, .homeycompose) or any Homey apps SDK question.

Install

mkdir -p .claude/skills/homey-app-dev && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/16688" && unzip -o skill.zip -d .claude/skills/homey-app-dev && rm skill.zip

Installs to .claude/skills/homey-app-dev

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Homey (Athom) app development with SDK v3 — manifest/compose structure, drivers, capabilities, flow cards, Node.js runtime constraints, CLI commands, validation and publishing. Use when working on this Homey app (drivers, capabilities, flows, app.json, .homeycompose) or any Homey apps SDK question.
299 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)

About this skill

Homey App Development (SDK v3)

Authoritative documentation — fetch it, don't guess

Homey publishes the full Apps SDK documentation in machine-readable form:

When unsure about a manifest field, capability, or SDK API, fetch the relevant page instead of relying on memory. Key pages: the-basics/app/manifest.md, the-basics/devices/capabilities.md, the-basics/flow.md, the-basics/devices/energy.md, advanced/homey-compose.md, app-store/guidelines.md.

Runtime and compatibility model

  • Apps declare "sdk": 3 and a "compatibility" semver range of supported Homey firmware versions (not hardware models). Minimum allowed is ">=5.0.0".
  • All Homey hardware still receiving firmware updates — including Homey Pro (Early 2016/2018/2019) — runs the latest firmware. Supporting older hardware means supporting the firmware range, and thereby its Node.js version:
PlatformFirmwareNode.js
Homey Pro (2016–2019)< 7.4.012
Homey Pro (2016–2019)7.4.0 – 12.8.x16
All platforms>= 12.9.022
  • Consequence: pick the TypeScript target and @types/node major to match the lowest Node version implied by the app's compatibility. This app declares ">=12.2.0", so the floor is Node 16 (older 2016–2019 hubs on firmware 12.2–12.8): keep @types/node at ^16 and the compile target at ES2021, even though tooling runs on newer Node.
  • Apps are plain Node.js (CommonJS by default; ESM possible), entry point app.js/app.ts, running sandboxed on the hub itself.

Project structure (Homey Compose)

app.json is generated — never edit it by hand. Sources live in:

  • .homeycompose/app.json — id, version, compatibility, sdk, brandColor, category, name/description (i18n objects), permissions, author, contributors.
  • .homeycompose/capabilities/<name>.json — custom (non-system) capabilities: type (boolean/number/string/enum), title, getable/setable, uiComponent, enum values with translated titles.
  • drivers/<driver>/driver.compose.json — driver class, capabilities list, energy object, pair views, images.
  • drivers/<driver>/driver.flow.compose.json — flow cards scoped to the driver: triggers, conditions, actions, each with translated title/hint, optional args and tokens.
  • drivers/<driver>/driver.settings.compose.json — device settings shown in the mobile app.
  • .homeycompose/flow/ — app-level (non-device) flow cards, if any.
  • locales/<lang>.json — app-wide translations referenced as { "en": ..., "no": ... } objects.

Regenerate app.json with npx homey app build (or any run/validate command, which composes first). After changing any compose file, rebuild and commit the regenerated app.json alongside the sources.

Translations: this app maintains en, no, nl, sv, de. Every new user-visible string (capability titles, enum values, flow card titles/hints, tokens) needs all five.

Devices, capabilities, flows — core patterns

  • Driver.onInit registers flow cards: this.homey.flow.getDeviceTriggerCard(id), getConditionCard(id).registerRunListener(...), getActionCard(id).registerRunListener(...). A trigger card declared in compose but never fetched+triggered from code silently does nothing.
  • Device.onInit registers capability listeners (registerCapabilityListener('onoff', ...)) for setable capabilities and starts polling/subscriptions.
  • Update state with setCapabilityValue(cap, value) (returns a promise — attach .catch(this.error)).
  • Adding/removing capabilities on existing devices requires addCapability/removeCapability migration in onInit — capabilities in the manifest only apply to newly paired devices.
  • Enum capability values are string IDs; adding new enum values to an existing capability is backward compatible, removing/renaming breaks users' flows.
  • energy objects (per driver or device class evcharger, cumulative, etc.) power the Homey Energy tab — see the-basics/devices/energy.md.
  • Device class changes (e.g. to evcharger) need a setClass migration in onInit.
  • Multiple picker capabilities (undocumented, verified empirically July 2026 on the iOS app): the device view shows ONE picker widget with a dropdown menu to switch between picker capabilities. The menu lists them in capability order, but the DEFAULT selection is the LAST picker capability in the device's capability order — so put the picker you want as default last among the pickers. Not sticky: the app recomputes the default every time the device view opens. Order changes on existing devices require a capability rebuild (remove+re-add all in the new order) in onInit, since set-based change detection won't fire.

CLI (npx homey ...)

  • homey app validate — manifest validation; --level=publish for the App Store bar (this repo's target).
  • homey app build — compose + TypeScript compile. The CLI requires tsconfig.json outDir to be ./.homeybuild.
  • homey app run — run on a hub in dev mode with live console; homey app install — install without console.
  • homey app publish — push to the App Store (asks to bump version; pre-release versions not allowed).
  • homey app version patch|minor|major — bump version in .homeycompose/app.json + app.json.
  • homey app driver create, homey app flow create, homey app driver flow create — scaffolding.
  • First use: homey login.

Publishing checklist

  1. npm run build (tsc) and npm run lint pass.
  2. npx homey app validate --level=publish passes.
  3. Version bumped (compose + app.json in sync; package.json version kept matching by convention).
  4. Changelog: .homeychangelog.json if present; App Store “What’s new” text on publish.
  5. Review App Store guidelines (app-store/guidelines.md) for naming, images, and description rules.

This repository's specifics

  • myenergi cloud API client lives in the myenergi-api npm package (same author); device data models (Zappi, Eddi, Harvi) come from there. Zappi status combines pilot state (pst) with device state (sta) — see drivers/zappi/device.ts getChargerStatusText.
  • Data flows: app.ts polls the myenergi cloud per hub credential → drivers relay via registered callbacks → devices update capabilities in dataUpdated.
  • Energy values from the myenergi API history endpoints are in joules (watt-seconds); instantaneous values are watts.

Search skills

Search the agent skills registry