docs: cover undocumented Indigo state-ID and plugin-host rules#41
Conversation
Five small additions to the plugin-dev concepts documenting rules I
hit while building a Zigbee2MQTT bridge plugin (capture-all dynamic
states). All come from real LowLevelBadParameterError or
AttributeError failures with no upstream documentation.
concepts/devices.md
+ State ID naming rules — must be camelCase ASCII, no underscores
(despite XML allowing them), no non-ASCII letters. Includes a
snake_case -> camelCase sanitiser and a strict validator.
+ Reserved state names — don't shadow native device properties; in
particular `batteryLevel` silently routes writes to the native
int property instead of Custom States. Use `battery` (Integer).
+ Dynamic state declaration — three subtle rules for plugins
overriding getDeviceStateList():
1. The parent's list is a LIVE reference; mutating it
permanently corrupts subsequent reads (must shallow-copy).
2. dev.pluginProps keys via replacePluginPropsOnServer cannot
start with underscore (distinct from self.pluginPrefs).
3. Roll back pluginProps on stateListOrDisplay failure to
avoid a sticky bad-key state.
+ deviceUpdated self-loop guard — when a plugin uses
subscribeToChanges() AND writes its own device states, the guard
must check pluginId (not id) at the top of deviceUpdated.
concepts/events.md
+ Common-mistake section warning that `indigo.server.fireEvent()`
and `self.triggerEvent()` both look correct but raise
AttributeError. Use the triggerStartProcessing /
triggerStopProcessing lifecycle plus
indigo.trigger.execute(trigger_object).
concepts/actions.md
+ uiPath="..." attribute — must be PascalCase with no spaces;
spaces cause NSInternalInconsistencyException in the Indigo
client (confirmed 2026-04-30).
+ Calling other plugins' actions — Pushover (action ID is "send",
not "sendPushover"; msg* prop names; priority is a string) and
Email+ (use indigo.server.sendEmailTo() directly; executeAction
"sendEmail" silently drops the props dict during cross-plugin
serialization).
concepts/plugin-preferences.md
+ Counter-warning that the existing "prefix hidden prefs with
underscore" advice applies to self.pluginPrefs ONLY — device-
level dev.pluginProps keys cannot start with `_` (writes via
replacePluginPropsOnServer are XML-validated and reject them).
troubleshooting/common-issues.md
+ LowLevelBadParameterError section linking back to the
state-ID rules in concepts/devices.md, since the error message
doesn't identify which key is bad.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
✅ Files skipped from review due to trivial changes (3)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughDocumentation and manifest updates: action uiPath and cross-plugin execution, event trigger lifecycle, device state naming and dynamic-state rules, plugin vs device prop underscore rules, troubleshooting XML serialization errors, and manifest version bumps. ChangesPlugin Development Documentation Updates
Possibly Related PRs
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
docs/plugin-dev/concepts/actions.md (1)
337-338: ⚡ Quick winUse
Plugincapitalization consistently for Indigo Plugin references in this new section.Several added lines use lowercase “plugin/plugins” while describing Indigo Plugin concepts (e.g., action grouping and cross-Plugin calls). Please normalize these to
Pluginfor guideline consistency.As per coding guidelines, "Use 'Plugin' (capitalized) when referring to Indigo plugins (the tools this project helps build)".
Also applies to: 360-364, 357-358
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/plugin-dev/concepts/actions.md` around lines 337 - 338, Update capitalization for Indigo Plugin references in this section: change all occurrences of "plugin" or "plugins" to "Plugin" when referring to Indigo Plugin concepts (e.g., in sentences describing uiPath on <Action> and <MenuItem>, action grouping, and cross-Plugin calls). Search for the tokens uiPath, <Action>, <MenuItem>, and any mentions of "action grouping" or "cross-Plugin calls" within the added lines (around the new section) and normalize the wording to use "Plugin" consistently.docs/plugin-dev/concepts/devices.md (1)
300-301: ⚡ Quick winNormalize Indigo terminology to
Plugincapitalization in the newly added prose.The added sections refer to Indigo Plugin concepts using lowercase “plugin” in a few places. Update those instances to
Pluginto match repository terminology rules and avoid ambiguity.As per coding guidelines, "Use 'Plugin' (capitalized) when referring to Indigo plugins (the tools this project helps build)".
Also applies to: 345-346, 422-423
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/plugin-dev/concepts/devices.md` around lines 300 - 301, Update the new prose instances where "plugin" is used in lowercase to the repository-standard capitalization "Plugin" (e.g., phrases like "Indigo plugin", "plugin host", or any reference to the tools this project helps build) so they read "Indigo Plugin" and "Plugin host" as appropriate; locate these occurrences in the added sections around the discussion of custom state IDs and change "plugin" -> "Plugin" consistently (also adjust the other occurrences noted in the same added content).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@docs/plugin-dev/concepts/actions.md`:
- Around line 337-338: Update capitalization for Indigo Plugin references in
this section: change all occurrences of "plugin" or "plugins" to "Plugin" when
referring to Indigo Plugin concepts (e.g., in sentences describing uiPath on
<Action> and <MenuItem>, action grouping, and cross-Plugin calls). Search for
the tokens uiPath, <Action>, <MenuItem>, and any mentions of "action grouping"
or "cross-Plugin calls" within the added lines (around the new section) and
normalize the wording to use "Plugin" consistently.
In `@docs/plugin-dev/concepts/devices.md`:
- Around line 300-301: Update the new prose instances where "plugin" is used in
lowercase to the repository-standard capitalization "Plugin" (e.g., phrases like
"Indigo plugin", "plugin host", or any reference to the tools this project helps
build) so they read "Indigo Plugin" and "Plugin host" as appropriate; locate
these occurrences in the added sections around the discussion of custom state
IDs and change "plugin" -> "Plugin" consistently (also adjust the other
occurrences noted in the same added content).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 3145b9b3-f868-4a26-9d60-c1c3173f7b6b
📒 Files selected for processing (5)
docs/plugin-dev/concepts/actions.mddocs/plugin-dev/concepts/devices.mddocs/plugin-dev/concepts/events.mddocs/plugin-dev/concepts/plugin-preferences.mddocs/plugin-dev/troubleshooting/common-issues.md
…ferences Per repo style guideline: 'Plugin' (capitalized) when referring to Indigo plugins (the tools this project helps build). Normalised in the new sections of actions.md, devices.md, and plugin-preferences.md.
|
Thanks for the review @coderabbitai! Capitalisation normalised across the new sections (actions.md, devices.md, plugin-preferences.md) — pushed in 9d03c7a. |
|
Tip For best results, initiate chat on the files or code changes.
If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! |
|
Cracking PR — really good catch on each of these. Most of it is exactly the kind of "the SDK doesn't tell you" knowledge worth landing. Going to suggest pulling the Pushover + Email+ sections though, for one reason: this repo intentionally stays at the SDK/IOM concept level, and once we start documenting third-party plugins' action IDs and prop names we're on the hook for keeping them in sync as those plugins evolve. The next person reading them won't know whether the table was verified yesterday or 18 months ago. For your own use, those notes are gold in The cross-plugin pattern you've documented (the general shape of Everything else is great and I'd take it as-is:
One mechanical thing: branch needs a rebase + bump to 1.9.5 — just merged some other docs work into main as 1.9.4, so version-check is failing. Trivial. Thanks for putting this together — saves the next plugin author a real amount of time. |
- Replace the Pushover/Email+ specific examples with a generic "calling another plugin's actions" warning. Avoids committing this repo to tracking third-party plugins' action IDs and prop names as they evolve. The general shape (read the target's Actions.xml, prefer direct server APIs when one exists) is what's actually transferable. - Bump plugin.json and marketplace.json to 1.9.5 so version-check passes now that 1.9.4 has landed on main. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Thanks — totally fair call on the third-party plugin specifics. Pulled the Pushover and Email+ blocks and replaced them with a generic "calling another plugin's actions" note: read the target's Actions.xml for the action ID and prop names rather than guessing, and prefer a direct server API (like Also rebased onto main and bumped to 1.9.5 so version-check passes. |
Summary
Five small additions to the plugin-dev concepts documenting Indigo plugin-host rules I hit while building a capture-all Zigbee2MQTT bridge plugin (importing every MQTT field as a dynamic Indigo state). All come from real
LowLevelBadParameterErrororAttributeErrorfailures that have no upstream documentation — and the error messages don't identify which key/method is at fault, so each one cost meaningful debug time.These are additions and clarifications only — no existing content removed.
What's added
concepts/devices.md(+143 lines)batteryLevelsilently routesupdateStateOnServerwrites to the native int property instead of Custom States, with no error. Usebattery(Integer) instead.getDeviceStateList():list(...).dev.pluginPropskeys viareplacePluginPropsOnServercannot start with underscore (distinct fromself.pluginPrefs).stateListOrDisplayfailure so a single bad key doesn't permanently poison the device record.deviceUpdatedself-loop guard — when a plugin usessubscribeToChanges()AND writes its own device states, the guard must checkpluginId(notid) at the top ofdeviceUpdated. Per-id checks don't prevent cross-device A→B→A loops.concepts/events.md(+40 lines)indigo.server.fireEvent("eventId")andself.triggerEvent("eventId", ...)both look correct but raiseAttributeError— neither exists onPluginBase/ServerInfo. Documents the correct pattern withtriggerStartProcessing/triggerStopProcessinglifecycle storing trigger objects, plusindigo.trigger.execute(trigger_object).concepts/actions.md(+71 lines)uiPathattribute — must be PascalCase with no spaces; spaces causeNSInternalInconsistencyExceptioncrash in the Indigo client (confirmed 2026-04-30).io.thechad.indigoplugin.pushover): action ID is\"send\"(not\"sendPushover\"— does not exist); prop namesmsgTitle/msgBody/msgUser/msgPriority/msgSound; priority is a string.com.indigodomo.email): useindigo.server.sendEmailTo()directly; callingexecuteAction(\"sendEmail\", props=...)silently drops the props dict during cross-plugin serialization, email never sends.concepts/plugin-preferences.md(+24 lines)self.pluginPrefsonly — device-leveldev.pluginPropskeys cannot start with_(writes viareplacePluginPropsOnServerare XML-validated and reject them). Updates the Best Practices line to call out the distinction.troubleshooting/common-issues.md(+14 lines)LowLevelBadParameterError -- illegal XML tag name charactersection linking back to the state-ID rules inconcepts/devices.md, since the error message doesn't identify which key is bad.Why these matter
Each rule below caused a real, hard-to-diagnose failure during the Z2M bridge work. Indigo's error messages and SDK don't mention any of them:
illegal XML tag name characteron otherwise-valid Python identifiersgetDeviceStateListreturns LIVE referencedev.pluginPropsrejects_-prefixed keysreplacePluginPropsOnServer, no indication that the key is the issueself.triggerEventdoesn't existWorth saving the next person the same debugging cycle.
Test plan
concepts/devices.mdanchor links work (#state-id-naming-rules-undocumented-but-strictfrom the troubleshooting cross-link)Notes
clives-rules-from-2026-05on Highsteads/indigo-claude-plugin (fork)🤖 Generated with Claude Code
Summary by CodeRabbit