ZAP XML Generation from Spec to SDK (Alchemy)
This skill provides comprehensive instructions, scenarios, and commands for
generating and amending ZAP template XML files (.xml) in the Matter SDK
repository (connectedhomeip) from Matter specification AsciiDoc documents
(.adoc) using Alchemy (alchemy zap).
1. Overview & Tool Setup
Alchemy is the canonical command-line tool for transforming Matter specification
documents into code-generation artifacts. When invoked with the zap
subcommand, Alchemy parses the AsciiDoc data model definitions and translates
them into the ZAP XML files located in the Matter SDK under
src/app/zap-templates/zcl/data-model/chip/.
1.1 Obtaining & Building Alchemy in alchemy Folder
Always clone and build Alchemy inside its own dedicated alchemy folder (for
example, as a sibling directory ../alchemy), rather than inside the
connectedhomeip repository:
# Clone and build inside a dedicated alchemy folder alongside your SDK/Spec clones
git clone https://github.com/project-chip/alchemy.git ../alchemy
cd ../alchemy
go build -o alchemy .
Alternatively, prebuilt binaries can be downloaded directly from the Alchemy GitHub releases page.
1.2 Standard Repository Paths & Execution Context
When executing commands, assume you are running from inside the root directory
of the Matter SDK repository (connectedhomeip) and invoking the binary built
in the alchemy folder (../alchemy/alchemy, or alchemy if installed to your
$PATH):
cd <path_to_connectedhomeip>
../alchemy/alchemy zap --sdk-root=. --spec-root=../connectedhomeip-spec [options] [spec_doc_paths...]
- Current Working Directory (
CWD):connectedhomeip(.) - Alchemy Binary Location:
../alchemy/alchemy(built inalchemyfolder) - SDK Root (
--sdk-root):.(the current working directory) - Specification Root (
--spec-root):../connectedhomeip-spec(assuming a sibling clone ofconnectedhomeip-spec) - Output Location in SDK:
src/app/zap-templates/zcl/data-model/chip/
2. Core Generation Scenarios
2.1 Scenario 1: Amending an Existing Cluster (-cluster.xml)
Use Case: You modified, added, or removed attributes, commands, events, or
data types in an existing cluster AsciiDoc file
(connectedhomeip-spec/src/app_clusters/<ClusterName>.adoc) and need to update
its corresponding XML in the SDK (<cluster-name>-cluster.xml).
alchemy zap --sdk-root=. --spec-root=../connectedhomeip-spec ../connectedhomeip-spec/src/app_clusters/Thermostat.adoc
Key Behaviors & Gotchas:
- Amending by Default: Alchemy reads the existing XML file and amends it. It preserves element order, existing comments, and unrecognized XML attributes while injecting or updating spec entities.
- Automatic Dependency Tracking: If the target cluster relies on data
types (structs, bitmaps, enums) defined in other cluster docs or global data
types (
global-structs.xml,global-enums.xml), Alchemy automatically generates/amends those dependency XMLs as well. - Index & List Updates: Alchemy automatically registers any updates in
src/app/zap-templates/zcl/data-model/chip/clusters.xmlandsrc/app/zap-templates/zcl/zcl.json.
2.2 Scenario 2: Generating XML for a New / Provisional Cluster
Use Case: A new cluster AsciiDoc document was introduced in
connectedhomeip-spec and does not yet have an XML template in the SDK.
alchemy zap --sdk-root=. --spec-root=../connectedhomeip-spec ../connectedhomeip-spec/src/app_clusters/NewAwesomeCluster.adoc
Key Behaviors:
- Alchemy detects that
<cluster-name>-cluster.xmldoes not exist and creates a new XML file from scratch with standard XML headers and copyright/license comments. - The new cluster is automatically added to
clusters.xml,zcl.json, and provisional index files (provisional.xml/index.xmlas applicable).
2.3 Scenario 3: Generating XML for Features Behind Conditional #ifdef Attributes
Use Case: A cluster, attribute, or feature in the specification is wrapped
in an AsciiDoc ifdef block (e.g., guarded by in-progress or a specific
feature flag like my-cool-feature).
ifdef::in-progress,my-cool-feature[]
include::./MyAwesomeCluster.adoc[]
endif::[]
Command:
alchemy zap --attribute="in-progress" --attribute="my-cool-feature" --sdk-root=. --spec-root=../connectedhomeip-spec ../connectedhomeip-spec/src/app_clusters/MyAwesomeCluster.adoc
[!IMPORTANT] > Why
--attributeis Mandatory: Alchemy generates ZAP XML strictly based on what renders in the AsciiDoc document during processing. If a feature or cluster is hidden by anifdef::in-progress[]condition and you do not pass--attribute="in-progress", Alchemy will treat those entities as non-existent and will omit or delete them from the generated XML!
2.4 Scenario 4: Applying Provisional API Maturity Policies (--provisional-policy)
Use Case: Controlling how apiMaturity="provisional" XML attributes are
assigned to generated data types (Clusters, Attributes, Commands, Enums,
Structs, Bitmaps, Events) depending on their draft status in the specification.
alchemy zap --provisional-policy=loose --sdk-root=. --spec-root=../connectedhomeip-spec ../connectedhomeip-spec/src/app_clusters/Thermostat.adoc
Available Policies:
none(Default):- Clusters and attributes with provisional conformance in the spec are
written with
apiMaturity="provisional". - If they do not have provisional conformance,
apiMaturityis removed if it previously existed. - Structs that do not currently exist in the ZAP XML are written with
apiMaturity="provisional".
- Clusters and attributes with provisional conformance in the spec are
written with
loose:- Writes or clears
apiMaturity="provisional"on all entity types (Attributes, Bitmaps, Clusters, Commands, Enums, Events, Features, Structs, and Fields). - Entities are considered provisional unless they have a non-provisional conformance column OR are referenced by a non-provisional data type.
- Writes or clears
strict:- Follows the same rules as
loose, but refuses to add new data types to the generated XML if they are not provisional in the spec. Use this policy when enforcing strict API stability gates.
- Follows the same rules as
2.5 Scenario 5: Updating Device Types and Namespaces
Use Case: You modified Device Type definitions
(connectedhomeip-spec/src/device_types/*.adoc) or Namespace definitions
(connectedhomeip-spec/src/namespaces/*.adoc).
[!WARNING] > Device Types Support Limitation: Note that automatic generation and patching of
device-types.xmlfrom AsciiDoc documents is currently not fully supported in Alchemy. While the command exists and attempts basic patching, output may be incomplete or experimental. Always manually inspect and verify any changes todevice-types.xml.
# Update Device Types (experimental / not fully supported - modifies device-types.xml)
alchemy zap --sdk-root=. --spec-root=../connectedhomeip-spec ../connectedhomeip-spec/src/device_types/*.adoc
# Update Namespaces (modifies src/app/zap-templates/zcl/data-model/chip/namespaces.xml)
alchemy zap --sdk-root=. --spec-root=../connectedhomeip-spec ../connectedhomeip-spec/src/namespaces/*.adoc
Key Behaviors:
- Namespace
.adocfiles map collectively tonamespaces.xml. - Device type
.adocfiles map collectively todevice-types.xml(configurator/deviceTypeelements), but note the partial support limitation above.
2.6 Scenario 6: Whole-Spec and Batch Processing
Use Case: Regenerating or updating ZAP XMLs across the entire specification (e.g., during major SDK-Spec synchronizations).
alchemy zap --sdk-root=. --spec-root=../connectedhomeip-spec
(When no specific .adoc files are passed, Alchemy parses all documents
discovered in --spec-root and updates all corresponding SDK XML files).
3. Error Mitigation & Validation Scenarios
If the specification has syntax errors or missing dependencies, Alchemy will
halt with a fatal error:
Alchemy was unable to proceed due to the following fatal errors in parsing the spec
Use the following strategies based on your workflow needs:
3.1 Exclude Specific Errored Files (--exclude)
If a few unrelated spec documents fail to parse while you are generating XMLs for a different cluster, exclude the broken paths:
alchemy zap --sdk-root=. --spec-root=../connectedhomeip-spec --exclude="*/BrokenCluster.adoc" ../connectedhomeip-spec/src/app_clusters/*.adoc
(The --exclude flag supports glob patterns and can be passed multiple
times).
3.2 Automatically Ignore Errored Files (--ignore-errored)
To automatically skip any spec file that encounters parsing errors while generating XML for all valid files:
alchemy zap --ignore-errored --sdk-root=. --spec-root=../connectedhomeip-spec ../connectedhomeip-spec/src/app_clusters/*.adoc
3.3 Force Generation Despite Errors (--force)
Forces Alchemy to generate XML files on a best-effort basis even when parsing errors occur:
alchemy zap --force --sdk-root=. --spec-root=../connectedhomeip-spec ../connectedhomeip-spec/src/app_clusters/*.adoc
[!WARNING] Use
--forceonly as a last resort for local debugging. Best-effort generation from partially parsed AsciiDoc files can produce incomplete or corrupted XML structures. Always prefer fixing the underlying specification error or using--exclude.
4. Preview & Verification Scenarios
4.1 Dry Run (--dry-run / -d)
Run all AsciiDoc parsing, dependency resolution, and XML rendering logic without writing any files to disk. Useful for verifying that your spec changes parse cleanly:
alchemy zap --dry-run --sdk-root=. --spec-root=../connectedhomeip-spec ../connectedhomeip-spec/src/app_clusters/Thermostat.adoc
4.2 Patch Output (--patch / -p)
Generate a unified diff (.patch) to stdout showing the exact XML additions,
modifications, and deletions without modifying the SDK directly:
alchemy zap --patch --sdk-root=. --spec-root=../connectedhomeip-spec ../connectedhomeip-spec/src/app_clusters/Thermostat.adoc > zap_changes.patch
5. Summary Cheatsheet
| Flag | Default | Description |
|---|---|---|
--spec-root |
../connectedhomeip-spec |
Root path to the clone of the Matter Specification repository (../connectedhomeip-spec when in SDK) |
--sdk-root |
. |
Root path to the clone of the Matter SDK repository (. when inside connectedhomeip) |
--attribute="<name>" |
"" |
Sets an AsciiDoc attribute (#ifdef) so guarded sections render (e.g., "in-progress") |
--provisional-policy |
none |
Policy (none, loose, strict) for assigning apiMaturity="provisional" attributes |
--exclude=<pattern> |
"" |
Glob pattern of spec files to ignore during processing (can be repeated) |
--ignore-errored |
false |
Automatically skip spec documents that encounter parsing errors |
--force |
false |
Force XML generation even if spec parsing errors occur |
--dry-run / -d |
false |
Execute all generation logic without saving changes to disk |
--patch / -p |
false |
Write unified diffs of XML changes to stdout instead of modifying files |