Get started

Your first .em.hcl model

Install the CLI, write a small model, validate it, and render it locally.

1 · Install the CLI

Use Go 1.25 or newer to install emhcl for your user account. You can also use a release archive.

Option A: install with Go

go install github.com/event-modeling-hcl/eventmodeling-hcl/cmd/emhcl@v0.9.0

Go writes the executable to GOBIN. If GOBIN is unset, Go writes it to $(go env GOPATH)/bin. Add that directory to your PATH. Then you can run emhcl from any directory:

export PATH="$(go env GOPATH)/bin:$PATH" emhcl version

Option B: download a release

curl -LO https://github.com/event-modeling-hcl/eventmodeling-hcl/releases/download/v0.9.0/emhcl_0.9.0_linux_amd64.tar.gz curl -LO https://github.com/event-modeling-hcl/eventmodeling-hcl/releases/download/v0.9.0/checksums.txt grep ' emhcl_0.9.0_linux_amd64.tar.gz$' checksums.txt | sha256sum -c - tar -xzf emhcl_0.9.0_linux_amd64.tar.gz

Replace linux_amd64 with darwin_amd64, darwin_arm64, linux_arm64, windows_amd64, or windows_arm64 as needed. The Windows archives are .zip files, not .tar.gz. If you have GitHub CLI 2.49.0 or newer, make sure that this repository's release workflow produced the archive:

gh attestation verify emhcl_0.9.0_linux_amd64.tar.gz --repo event-modeling-hcl/eventmodeling-hcl

Option C: build from source

git clone https://github.com/event-modeling-hcl/eventmodeling-hcl.git cd eventmodeling-hcl go build -o emhcl ./cmd/emhcl

Make sure that the command runs:

emhcl version

2 · Write your first model

Save this model as pet.em.hcl. It is the same minimal model that this site uses throughout. It has one bounded context, one Event, and one State Change workflow:

bounded_context "pet_management" { title = "Pet Management" aggregate "pet" { } field_type "pet_id" { type = "Int" id_attribute = true example = 5 } event "pet_added" { title = "Pet Added" aggregate = aggregate.pet field "pet_id" { } } } state_change "add_pet" { title = "Add Pet" screen "add_pet_form" { title = "Add Pet Form" to = [command.add_pet_command] } command "add_pet_command" { title = "Add Pet" aggregate = aggregate.pet_management.pet fields = [field_type.pet_management.pet_id] to = [event.pet_management.pet_added] } }

3 · Validate it

emhcl validate pet.em.hcl

If the document is valid, the command prints:

pet.em.hcl valid

The command prints diagnostics like file:line:column: Severity EMxxx: message for errors and warnings. See the quality page to learn which diagnostics are hard errors and which are warnings to review.

4 · Render the canvas

emhcl diagram pet.em.hcl -o pet.html wrote pet.html

pet.html is one self-contained file. It has no external dependencies and needs no build step. Open it in a browser.

To render again each time you save the file, run emhcl serve pet.em.hcl. Then open the URL that it prints.

If one file becomes too large to read, split whole top-level blocks into a folder of .em.hcl files. The validate, diagram, serve, and export commands accept the folder path. Format each member file with emhcl fmt -w. The formatter refuses a folder. See Folder models.

For a folder model, serve reloads when you add, remove, rename, or edit a member file. Diagnostics name the file that needs attention.

In the browser playground, use file tabs to add, rename, or remove files. All tabs form one model. Select a diagnostic to open its file.

Optional: publish the diagram

The model and the rendered canvas are files. You can commit them beside the code and host the canvas with GitHub or GitLab Pages:

git add pet.em.hcl pet.html git commit -m "Add pet-registration event model" git push

Because the model is in the repository, you can version and review it with the code.

A coding agent can draft, validate, fix, and render a model before human review. See Using .em.hcl with coding agents.