Workspace tooling for Gleam monorepos.Derived from gleam.toml.
Run tasks across your Gleam packages, inspect their dependencies, and manage changelogs, versions, and publishing from one binary.
$curl --proto '=https' --tlsv1.2 -LsSf https://github.com/tylerbutler/trellis/releases/latest/download/trellis-gleam-installer.sh | shlat_core (1.2.0)
lat_mid (0.5.0)
└─ lat_core
lat_cli (0.3.1)
├─ lat_core
└─ lat_mid
package_a (0.0.0)
└─ lat_cliThe glue this replaces.
The lattice inventory records the bash loops, YAML blocks, and duplicated configuration below. Each row is workspace information that was maintained by hand.
| Where it lives | What's maintained by hand | What can drift |
|---|---|---|
justfile | The package list, in topological order, as a space-separated string | A new package is silently excluded from every recipe |
justfile | ~15 near-identical for pkg in … bash loops | Copy-paste drift between recipes; strictly serial execution |
.changie.yaml | One config block per package: label, key, changelog path, version regex | A forgotten block means a package can't be versioned or released |
publish.yml | A hand-written mirror of the path_dependency graph | Nothing verifies it when a package gains a dependency |
release.yml | 25 lines of inline sed/grep patching locked versions | Untestable regex logic living inside CI YAML |
Trellis derives the information behind each row from gleam.toml, a file format the ecosystem already uses.
Configure nothing that can be derived.
Verify anything that must be duplicated.
# The table's presence marks the workspace root.# Every key is optional — members auto-discover from git.[tools.trellis]members = ["packages/*", "examples/*"]# Exclusions are scoped by task. `@release` covers changelog,# versioning, tagging, publishing, and release CI.exclude = { docs = ["examples/*"], "@release" = ["examples/*"] }
[tools.trellis.tasks.lint]command = "gleam run -m glinter"
[tools.trellis.publish]exact_tag_format = "{name}-v{version}"From that, trellis computes:
- The member set and its topological order. New packages join every command the moment their directory matches a glob.
- Change impact.
--since origin/mainmaps a diff to owning packages, plus the reverse-dependency closure. Only test what a PR touched. - Publish order and path-dep rewrites. Dependencies publish first, and path references become Hex versions automatically.
- A tag per releasable package, plus a
doctorthat fails loudly when anything drifts.
Opinionated, but modular.
Trellis has one way of doing each job: TOML change fragments, a tag per package, bumps derived from fragment kinds. But the jobs are independent, and nothing requires the piece above it, so you adopt a layer at a time and keep whatever already works.
Just the task runner
run,exec,list, andgraphneed no configuration at all, because members are auto-discovered from git. Your changelog tool and CI stay untouched.Add changelogs and versioning
Fragments,
version plan, andversion applymanage bumps and changelogs without trellis owning your release workflow, or any CI at all.Add publishing
tagandpublishpush to Hex in dependency order, from your own scripts or workflows.The full pipeline
ci,changelog check, andrelease prturn GitHub Actions workflows into thin triggers around trellis commands.
One workspace. Different task sets.
Examples, benchmarks, and internal tools can remain workspace members for builds, tests, and graphing without needing generated docs or a release on Hex.
exclude gives each built-in or custom task its own member-path globs. The reserved @release key covers changelogs, versioning, tags, publishing, and release CI.
| Member | build / test | docs | release |
|---|---|---|---|
packages/* | included | included | included |
examples/* | included | excluded | excluded |
lat_core hex
lat_mid hex
lat_cli hexpackage_a — the examples/ member — still appears in trellis list, graph, exec, and tasks that do not exclude it. Only the configured task sets change.One binary across the lifecycle.
The same tool runs locally and in CI. Commands work from anywhere in the workspace, since the root is found by walking up, like git or cargo.
Run tasks across packages
Build, test, and run custom tasks in dependency order. Select the packages affected by a change, locally or in CI.
Read the task-running guide →Plan versions and changelogs
Record changes as TOML fragments. Review the version plan before applying package bumps and generated changelogs.
Read the versioning guide →Automate release workflows
Generate GitHub Actions matrices, check changelog coverage, and open release pull requests from the same workspace model.
Read the CI recipes →
Checks for drift.
Some things can't be derived: locked versions, changelogs, tags, toolchain pins. For those, trellis doctor checks the invariants that remain explicit and exits non-zero when one breaks.
checked: member globs resolve and every package has a parseable gleam.toml
checked: path dependencies stay inside the workspace; graph is acyclic
checked: task exclusion globs match members; no package depends on one unavailable at its release lifecycle
checked: tag format produces a unique tag per releasable package
checked: manifest.toml locked versions match workspace-internal gleam.toml versions
checked: each releasable package's version is not behind its CHANGELOG
checked: unreleased changelog fragments parse and reference valid packages, kinds, and categories
checked: [tools.trellis] has no unrecognized keys
checked: packages agree on the external dependencies they share
checked: gleam on PATH matches the .tool-versions pin (advisory)
ok: 4 package(s) (1 workspace, 0 git_only, 3 hex), 0 warning(s)Install a prebuilt binary.
Trellis has no runtime dependencies and includes SLSA build provenance. Its shell installer typically completes in about a second in CI.
- Shell (Linux, macOS)
$curl --proto '=https' --tlsv1.2 -LsSf https://github.com/tylerbutler/trellis/releases/latest/download/trellis-gleam-installer.sh | sh- Homebrew
$brew install tylerbutler/tap/trellis- mise / asdf (pin it in .tool-versions)
$mise use "github:tylerbutler/trellis@1.0.0"- From source
$cargo install --git https://github.com/tylerbutler/trellis
Windows installer and pinned-version URLs are on thereleases page. From there, trellis doctor works immediately, with no setup. Run trellis init only when you want to configure something; the configuration guide covers what it writes.