{"id":28868230,"url":"https://github.com/project-chip/alchemy","last_synced_at":"2026-03-03T22:08:54.324Z","repository":{"id":246093337,"uuid":"819395593","full_name":"project-chip/alchemy","owner":"project-chip","description":"Alchemy is a command line tool for modifying and transforming Matter spec documents. ","archived":false,"fork":false,"pushed_at":"2026-02-25T22:28:20.000Z","size":47286,"stargazers_count":9,"open_issues_count":14,"forks_count":10,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-26T01:01:31.327Z","etag":null,"topics":["matter"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/project-chip.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-06-24T12:21:48.000Z","updated_at":"2026-02-04T19:04:25.000Z","dependencies_parsed_at":"2025-12-05T00:05:27.306Z","dependency_job_id":null,"html_url":"https://github.com/project-chip/alchemy","commit_stats":null,"previous_names":["project-chip/alchemy"],"tags_count":131,"template":false,"template_full_name":null,"purl":"pkg:github/project-chip/alchemy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/project-chip%2Falchemy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/project-chip%2Falchemy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/project-chip%2Falchemy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/project-chip%2Falchemy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/project-chip","download_url":"https://codeload.github.com/project-chip/alchemy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/project-chip%2Falchemy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30063469,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-03T18:21:05.932Z","status":"ssl_error","status_checked_at":"2026-03-03T18:20:59.341Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["matter"],"created_at":"2025-06-20T12:36:41.112Z","updated_at":"2026-03-03T22:08:54.314Z","avatar_url":"https://github.com/project-chip.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Alchemy\n\nAlchemy is a command line tool for modifying and transforming Matter spec documents.\n\u003cimg src=\"./alchemy.svg\" align=\"right\"/\u003e\n\nIt can:\n- Format your spec documents, aligning table cells, removing unneeded spacing, etc.\n- Disco-ball your spec documents, aligning them with Matter spec style guidelines\n- Generate ZAP XML files for clusters and device types\n- Generate Data Model XML files\n- Generate basic test plans for clusters\n- Present the Matter spec as a MySQL-compatible database to run queries against\n- Print English-language explanations of Matter conformance strings\n\n\u003cbr clear=\"right\"/\u003e\n\n## Installation\n\n### Prebuilt Binaries\n\nDownload the latest releases from the [GitHub release page](https://github.com/project-chip/alchemy/releases).\n\nThere are two builds for each architecture: plain and db. The db build includes the [DB Feature](#alchemy-db) below, but at the expense of a larger binary.\n\n### Build from source\n\nAlchemy is written in pure Go, so to build from source:\n\n1. Install Go 1.24 or greater\n2. Clone the alchemy repo\n3. In the root of the alchemy repo, run ```go build```\n\n## Commands\n\n### Common flags\n\n| Flag                                  | Default       | Description   |\t\n| :------------------------------------ |:-------------:| :-------------|\n| `--serial`          \t                | false         | Process Asciidoc files one-by-one instead of in parallel; slower\n| `--dry-run` `-d`                          | false         | Run all logic for the command, but do not write results to disk\n| `--patch`   \t                        | false         | Write a patch file for any changes to stdout\n| `--verbose` \t                        | false         | Display more verbose logging; best used with --serial\n| `--attribute=\"\u003cname of attribute\u003e\"` | empty string\t| Sets an attribute for Asciidoc processing, e.g. \"in-progress\".\u003cbr/\u003eThis parameter can be specified multiple times for different attributes \n\n\n### format\n\nFormat does not alter the content of the document, but does make it easier to read the source:\n\n- Aligns table cells so that table delimiters correctly line up with other cells in the same column\n- Removes extraneous spacing in tables and lists\n- Normalizes properties\n\n#### Examples\n\n| Flag                            | Default  | Description   |\t\n| :------------------------------ |:--------:| :-------------|\n| --wrap                          | none     | The number of characters to wrap lines without disrupting Asciidoc syntax |\n\nFormat a single document:\n\n```console\nalchemy format connectedhomeip-spec/src/app_clusters/Thermostat.adoc\n```\n\nFormat all documents in a directory:\n\n```console\nalchemy format connectedhomeip-spec/src/app_clusters/*.adoc\n```\n\nRecursively format all documents in the spec:\n\n```console\nalchemy format connectedhomeip-spec/src/\\*\\*/\\*.adoc\n```\n\nWord-wrap all documents in a directory to 120 characters:\n\n```console\nalchemy format connectedhomeip-spec/src/app_clusters/*.adoc --wrap=120\n```\n\n### disco\n\nDisco-ball is more aggressive than format, and attempts to rewrite the document to the disco-ball standard:\n\n- Everything format does\n- Rearranges the document into disco-ball order for clusters and device-types\n- Rearranges data types into bitmap, enum, struct order\n- Promotes inline data types into the Data Types section and creates references for them\n- Normalizes all references to the ref_PascalCase format\n- Adds missing columns to tables for each type of section\n- Reorders columns in tables to match disco ball order\n- Renames headers in columns to match disco ball header names\n- Re-formats access columns into disco ball order and spacing\n- Re-formats constraint columns to be more readable (e.g. an uint with the constraint \"0 to 60\" -\u003e \"max 60\", )\n- Fixes command directions to client (\u003c=/=\u003e) server format\n- Appends suffixes to sections when needed (e.g. \"XyzBitmap\" -\u003e \"XyzBitmap Type\" or \"MyField\" -\u003e \"MyField Field\")\n- Uppercases all hexadecimal numbers\n- Adds spaces after punctuation, when needed\n- Adds labels to anchors when missing\n- Removes extra spaces at the end of lines\n- Fixes common section naming mistakes\n\n| Flag                                 | Default                | Description   |\t\n| :----------------------------------- |:----------------------:| :-------------|\n| `--link-index-tables`                | false                  | Link table cells to child sections |\n| `--add-missing-columns`              | true                   | Add standard columns missing from tables |\n| `--reorder-columns`                  | true                   | Rearrange table columns into disco-ball order |\n| `--rename-table-headers`             | true                   | Rename table headers to disco-ball standard names |\n| `--format-access`                    | true                   | Reformat access columns in disco-ball order |\n| `--promote-data-types`               | true                   | Promote inline data types to Data Types section |\n| `--reorder-sections`                 | true                   | Reorder sections in disco-ball order |\n| `--normalize-table-options`          | true                   | Remove existing table options and replace\u003cbr/\u003ewith standard disco-ball options |\n| `--fix-command-direction`            | true                   | Normalize command directions |\n| `--append-subsection-types`          | true                   | Add missing suffixes to data type sections\u003cbr/\u003e(e.g. \"Bit\", \"Value\", \"Field\", etc.) |\n| `--uppercase-hex`                    | true                   | Uppercase hex values |\n| `--add-space-after-punctuation`      | true                   | Add missing space after punctuation |\n| `--remove-extra-spaces`              | true                   | Remove extraneous spaces |\n| `--normalize-feature-names`          | true                   | Normalize feature names to be compatible\u003cbr/\u003ewith downstream code generation |\n| `--disambiguate-conformance-choice`  | false                  | Ensure that each document only uses each\u003cbr/\u003econformance choice identifier once |\n| `--spec-root`                        | ./connectedhomeip-spec | The root of your clone of [the Matter Specification](https://github.com/CHIP-Specifications/connectedhomeip-spec/) |\n| `--wrap`                             | none                   | The number of characters to wrap lines\u003cbr/\u003ewithout disrupting Asciidoc syntax |\n\n#### Examples\n\nDisco-ball a single document:\n\n```console\nalchemy disco connectedhomeip-spec/src/app_clusters/Thermostat.adoc\n```\n\nDisco-ball the whole spec:\n\n```console\nalchemy disco --spec-root=./connectedhomeip-spec\n```\n\nDisco-ball a single document, but update any other documents if needed (e.g. rewriting a reference):\n\n```console\nalchemy disco --spec-root=./connectedhomeip-spec ./connectedhomeip-spec/src/app_clusters/Thermostat.adoc\n```\n\nDisco-ball a single document, wrapping the text at 120 characters and linking table entries to their associated sections:\n\n```console\nalchemy disco connectedhomeip-spec/src/app_clusters/Thermostat.adoc --wrap=120 --link-index-tables\n```\n\n### zap\n\nZAP generates zap-template XMLs from a spec, creating new XML files for provisional clusters, and amending existing XML files with\nchanges.\n\n| Flag                                       | Default                | Description   |\t\n| :----------------------------------------- |:----------------------:| :-------------|\n| `--spec-root`                              | ./connectedhomeip-spec | The root of your clone of [the Matter Specification](https://github.com/CHIP-Specifications/connectedhomeip-spec/) |\n| `--sdk-root`                               | ./connectedhomeip      | The root of your clone of [the Matter SDK](https://github.com/project-chip/connectedhomeip/) |\n| `--overwrite`                              | false                  | Overwrite existing XML files instead of amending them\n| `--force`                                  | false                  | Forces generation of XML files, even if there are parsing errors reading the spec\n| `--ignore-errored`                         | false                  | Generates XML files for all provided spec files that had no parsing errors\n| `--exclude=\u003cfile pattern\u003e`                 |                        | Ignores a pattern of file paths for generation; this attribute may be provided multiple times\n| `--provisional-policy=[none\\|loose\\|strict]` | none                   | Sets the provisional policy (see below)\n\n\u003e [!IMPORTANT]  \n\u003e ZAP generates the XML based on how the spec would render for the attributes provided. If you are attempting to generate the zap-template XML for a\n\u003e part of the spec that is hidden by an #ifdef by default, you will need to provide the necessary attributes to allow it to render.\n\u003e\n\u003e For example, if your cluster was included in the spec like so:\n\u003e\n\u003e ```\n\u003e ifdef::in-progress,my-cool-feature[]\n\u003e include::./MyAwesomeCluster.adoc[]\n\u003e endif::[]\n\u003e ```\n\u003e\n\u003e You would need to pass an `--attribute` flag for either `in-progress` or `my-cool-feature`:\n\u003e\n\u003e ```console\n\u003e alchemy zap --attribute=\"in-progress\"  --sdk-root=./connectedhomeip/ --spec-root=./connectedhomeip-spec/\n\u003e ```\n\n\u003e [!WARNING]  \n\u003e By default, Alchemy will refuse to generate XML for spec files with errors. If you receive the error `Alchemy was unable to proceed due to the following fatal errors in parsing the spec`,\n\u003e you can either:\n\u003e\n\u003e 1. Fix the error. This is the best route.\n\u003e 2. Use the `--exclude` flag to exclude the file that is failing to parse.\n\u003e 3. Use the `--ignore-errored` flag to automatically exclude any files that are failing to parse\n\u003e 4. Use the `--force` flag to cause Alchemy to ignore all errors and generate XML as best as it can. This is likely to cause issues later, and should be avoided if possible.\n\n\u003e [!NOTE]  \n\u003e By default, existing ZAP XML files will be amended by Alchemy, leaving ordering of elements, comments and unrecognized XML attributes in place. The overwrite flag allows regenerating the XML files from scratch.\n\n#### Generate ZAP files for a single cluster\n\n```console\nalchemy zap --attribute=\"in-progress\"  --sdk-root=./connectedhomeip/ --spec-root=./connectedhomeip-spec/ ./connectedhomeip-spec/src/app_clusters/Thermostat.adoc\n```\n\u003e [!NOTE]  \n\u003e Alchemy follows dependencies between clusters, so if the specified doc requires data types from other docs, it will also generate XML files for them as well. In the above case, Thermostat depends on an enumeration in OccupancySensor, so occupancy-sensing-cluster.xml will also be generated.\n\u003e\n\u003e If the targeted cluster references, directly or indirectly, one of the global data type files (e.g. global-structs.xml, global-enums.xml, etc.), the entire global data type file will be generated. This may pull in changes to global data types from other clusters.\n\n\n#### Provisional Policy\n\nThe provisional policy changes how Alchemy handles adding new data types to the XML files.\n\n##### None\n\nThe \"none\" policy causes Alchemy treat provisional data types the same way it did before these policies were introduced:\n\n1. Clusters/attributes with provisional conformance are written with the \"apiMaturity\" attribute set to \"provisional\"; clusters/attributes without provisional conformance have this attribute removed, if it already exists\n2. Structs which do not currently exist in the ZAP XML are written with \"apiMaturity\" set to \"provisional\"\n\n##### Loose\n\nThe \"loose\" policy causes Alchemy to write or clear apiMaturity attributes on the following data types:\n\n* Attributes\n* Bitmaps\n* Clusters\n* Commands\n* Enums\n* Events\n* Features\n* Structs\n* Fields on Commands, Events and Structs \n\nData types are considered provisional unless one of the following is true:\n\n1. The data type has a conformance column which does not have provisional conformance set\n2. The data type is referenced by a data type which is not provisional\n\n##### Strict\n\nThe \"strict\" policy has the same rules as the \"loose\" policy, except that it will refuse to add new data types to the generated XML if they are not provisional. \n\n### conformance\n\nConformance parses a provided conformance string and explains its meaning in plain English. It can also take a series of defined\nidentifiers and return whether the provided conformance would consider it mandatory, optional, etc.\n\n#### Examples\n\n```console\n$ alchemy conformance \"[LT | DF \u0026 CF]\"\ndescription: optional if (LT or (DF and CF))\n```\n\n```console\n$ alchemy conformance \"AB, [CD]\"\ndescription: mandatory if AB, otherwise optional if CD\n$ alchemy conformance \"AB, [CD]\" AB CD\ndescription: mandatory if AB, otherwise optional if CD\nconformance: Mandatory\n$ alchemy conformance \"AB, [CD]\" EF CD\ndescription: mandatory if AB, otherwise optional if CD\nconformance: Optional\n$ alchemy conformance \"AB, [CD]\" EF\ndescription: mandatory if AB, otherwise optional if CD\nconformance: Disallowed\n```\n\n### dm\n\nData Model generates the Data Model XML files from the spec.\n\n| Flag                       | Default                                 | Description   |\t\n| :------------------------- |:---------------------------------------:| :-------------|\n| `--spec-root`              | ./connectedhomeip-spec                  | The root of your clone of [the Matter Specification](https://github.com/CHIP-Specifications/connectedhomeip-spec/) |\n| `--dm-root`                | ./connectedhomeip/data_model/master     | The data model directory of your clone of [the Matter SDK](https://github.com/project-chip/connectedhomeip/) |\n| `--force`                  | false                                   | Forces generation of data model files, even if there are parsing errors reading the spec\n| `--ignore-errored`         | false                                   | Generates data model files for all provided spec files that had no parsing errors\n| `--exclude=\u003cfile pattern\u003e` |                                         | Ignores a pattern of file paths for generation; this attribute may be provided multiple times\n\n### testplan\n\nTestplan generates basic test plan adoc files from the spec.\n\n\n| Flag                       | Default                | Description   |\t\n| :------------------------- |:----------------------:| :-------------|\n| `--spec-root`              | ./connectedhomeip-spec | The root of your clone of [the Matter Specification](https://github.com/CHIP-Specifications/connectedhomeip-spec/) |\n| `--test-root`              | ./chip-test-plans      | The root of your clone of [the Matter test plans](https://github.com/CHIP-Specifications/chip-test-plans) |\n| `--overwrite`              | false                  | Overwrite existing test plan files instead of amending them\n\n\n\u003e [!NOTE]  \n\u003e By default, any existing test plan Asciidoc files will be ignored. The overwrite flag allows regenerating the test plan Asciidoc files from scratch; this will destroy any existing tests aside from basic validation of features, attributes, etc.\n\n### testscript\n\nTestplan generates a basic test script from the spec.\n\n| Flag                       | Default                | Description   |\t\n| :------------------------- |:----------------------:| :-------------|\n| `--spec-root`              | ./connectedhomeip-spec | The root of your clone of [the Matter Specification](https://github.com/CHIP-Specifications/connectedhomeip-spec/) |\n| `--template-root`          |                        | The root of your local template files; if not specified, Alchemy will use an internal copy|\n| `--overwrite`              | false                  | Overwrite existing test scripts files instead of amending them\n\n\n\u003e [!NOTE]  \n\u003e By default, any existing test script files will be ignored. The overwrite flag allows regenerating the test script files from scratch; this will destroy any existing tests aside from basic validation of features, attributes, etc.\n\n\n### alchemy-db\n\nAlchemy-db is provided as a separate binary. It loads up a set of spec docs or ZAP templates and exposes their contents as tables in a local MySQL server you can query.\n\n| Flag                       | Default                | Description   |\t\n| :------------------------- |:----------------------:| :-------------|\n| `--spec-root`              | ./connectedhomeip-spec | The root of your clone of [the Matter Specification](https://github.com/CHIP-Specifications/connectedhomeip-spec/) |\n| `--sdk-root`               | ./connectedhomeip      | The root of your clone of [the Matter SDK](https://github.com/project-chip/connectedhomeip/) |\n| `--address`                | localhost              | The address to bind the MySQL server to |\n| `--port`                   | 3306                   | The port to bind the MySQL server to |\n| `--raw`                    | false                  | Populates the tables with the raw text of the associated entities,\u003cbr/\u003e rather than parsing into an object model first |\n\n#### Building\n\nTo build `alchemy-db`:\n- In the root of the alchemy repo, run `go build -tags db -o alchemy-db .`.\n\n#### Examples\n\n##### Command line to launch, loading from specific paths\n\nTo launch `alchemy-db`:\n\n```console\nalchemy-db --sdk-root=./connectedhomeip/ --spec-root=./connectedhomeip-spec/\n```\n\nIt will then run as a daemon until terminated.\n\nTo query, use you favorite MySQL client. On the command line, for example:\n\n\n```console\nmysql -h 127.0.0.1 --skip-ssl MatterSpec\n```\n\nThe `--skip-ssl` is because `alchemy-db` runs locally without SSL certificates, as a debug tool, yet modern MySQL versions require SSL on the connection unless otherwise specified.\n\n##### Semantic tags used across multiple Namespaces\n```sql\nSELECT\n    t.name AS tag,\n    ns.name AS namespace,\n    d.path\nFROM\n    tag AS t\n    JOIN namespace AS ns ON t.namespace_id = ns.namespace_id\n    JOIN document AS d on ns.document_id = d.document_id\nWHERE\n    t.name IN \n    (\n        SELECT\n            name\n        FROM\n            tag\n        GROUP BY\n            name\n        HAVING\n            COUNT(*) \u003e 1\n    )\nORDER BY\n    t.name\n\n```\n\n##### Events with fields whose data types are enumerations with more than three values\n```sql\nWITH LargeEnums AS (\n    SELECT\n        enum_id,\n        name\n    FROM\n        enum\n    WHERE enum_id IN\n    (\n    SELECT \n        enum_id\n    FROM   \n        enum_value\n    GROUP BY enum_id\n    HAVING COUNT(*) \u003e 3\n    )\n) \nSELECT \n    c.name AS cluster_name, \n    e.name AS event_name\nFROM   \n    event AS e\n    JOIN cluster c ON e.cluster_id = c.id\nWHERE \n    event_id IN \n    (\n        SELECT \n            event_id\n        FROM   \n            event_field\n        WHERE \n            data_type IN \n        (SELECT NAME FROM LargeEnums)\n    );  \n```\n\n##### Export full list of semantic tags\n```sql\n\nSELECT\n    n.id AS namespace_id,\n    t.id AS tag_id,    \n    t.name AS tag_name,\n    n.name AS namespace_name,\n    d.name AS source_name\nFROM\n    tag AS t\nINNER JOIN\n    namespace AS n ON t.namespace_id = n.namespace_id\nINNER JOIN\n    document AS d ON n.document_id = d.document_id\nORDER BY\n    namespace_id ASC, tag_id ASC;\n```\n\nAn export as CSV of this query can be done directly like this:\n\n```console\nmysql -h 127.0.0.1 --skip-ssl --batch -e \"SELECT n.id AS namespace_id, t.id AS tag_id, t.name AS tag_name, n.name AS namespace_name, d.name AS source_name FROM tag AS t INNER JOIN namespace AS n ON t.namespace_id = n.namespace_id INNER JOIN document AS d ON n.document_id = d.document_id ORDER BY namespace_id ASC, tag_id ASC;\" MatterSpec | sed 's/\\t/,/g' \u003e namespaces.csv\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fproject-chip%2Falchemy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fproject-chip%2Falchemy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fproject-chip%2Falchemy/lists"}