canton-devkit ships through complementary channels:
- DPM component (primary) — installed via
dpm install package. - Standalone Go binary (additional) — direct download / install.
- Package-manager convenience — a Homebrew tap wraps the same standalone binary for macOS and Linux workflows.
All release artifacts are produced by the same release workflow
(.github/workflows/release.yml)
from the same Go source. The DPM component and Homebrew formula both wrap
the standalone binary for their respective ecosystems.
Tagged releases (v*) publish per-platform standalone artifacts to
GitHub Releases:
| File | Platform |
|---|---|
canton-devkit_<version>_linux_amd64.tar.gz |
Linux x86_64 |
canton-devkit_<version>_darwin_arm64.tar.gz |
macOS Apple Silicon |
canton-devkit_<version>_windows_amd64.zip |
Windows x86_64 |
SHA256SUMS |
GNU sha256sum --check-compatible manifest |
Each tarball/zip contains the binary, LICENSE, and README.md. Verify
before unpacking:
sha256sum --check SHA256SUMS
tar -xzf canton-devkit_v0.7.0_linux_amd64.tar.gz
./canton-devkit localnet --helpFor macOS arm64 and Linux amd64, a scripted installer is also available:
curl -fsSL https://raw.githubusercontent.com/bitdynamics-ab/canton-devkit/main/install.sh | shVersion-string asymmetry: the standalone archive filenames keep the
vprefix (canton-devkit_v0.7.0_linux_amd64.tar.gz), matching the git tag, while the DPM/OCI tag strips it (ghcr.io/bitdynamics-ab/canton-devkit:0.7.0) because DPM requires a bare-semver tag. Same release, two conventions — chosen to match each ecosystem's norm.
The DPM component is published to GitHub Container Registry on every
tagged release at ghcr.io/bitdynamics-ab/canton-devkit:<version>.
dpm install package reads the component references from the project's
daml.yaml. Remove sdk-version and declare the SDK packages plus the
DevKit component, then install:
# daml.yaml
#sdk-version: <your-sdk-version>
components:
- canton-open-source:<your-sdk-version>
- codegen:<your-sdk-version>
- damlc:<your-sdk-version>
- daml-new:<your-sdk-version>
- daml-script:<your-sdk-version>
- upgrade-check:<your-sdk-version>
- scribe:<your-sdk-version>
- daml-shell:<your-sdk-version>
- oci://ghcr.io/bitdynamics-ab/canton-devkit:<version>dpm install package
dpm localnet --helpReplace <your-sdk-version> with the Canton/Daml release you are
targeting. <version> for the DevKit OCI tag follows semver (no v
prefix); tag latest points at the most recently published final
(non-pre-release) release.
The component registers a single top-level command localnet that
delegates the rest of the DevKit CLI surface to the binary's own argv
parser. See packaging/component.yaml.tmpl.
DPM does NOT pass the registered command name into the binary's argv —
only exec-args + user args reach it. exec-args: ["--via-dpm", "localnet"] is therefore required: the localnet arg makes the binary
dispatch into its localnet subtree regardless of how DPM invoked the
component, and the leading --via-dpm marker tells the binary it was
launched by DPM. A contract test (TestRunIsArgvOnly) locks this
invariant.
The manifest lives as a template with a @@BINARY_PATH@@ token: the
release workflow substitutes bin/canton-devkit on Unix platforms and
bin/canton-devkit.exe on Windows. DPM does NOT auto-append .exe
on Windows — empirically verified against DPM 1.0.16, which fails
manifest validation with stat <path>: no such file or directory when
the path doesn't include the extension.
DPM components register top-level commands into a flat namespace shared
with DPM builtins and every other component. DevKit deliberately
registers only localnet to:
- Avoid collisions with DPM builtins (
install,publish,versions,bootstrap, …) or with future first-party components. - Keep the DPM surface minimal —
dpm localnet up,dpm localnet dar upload,dpm localnet contracts ls, etc. nest naturally.
All DevKit subcommands live inside the binary's own Cobra tree, not in the DPM manifest.
Before pushing a release-affecting change, validate the manifest end-to-end against a real DPM CLI:
# 1. Build a host-platform binary into the expected layout.
mkdir -p /tmp/cdk-component/bin
go build -o /tmp/cdk-component/bin/canton-devkit ./cmd/canton-devkit
# 2. Render the manifest from the template for this platform.
sed "s|@@BINARY_PATH@@|bin/canton-devkit|" \
packaging/component.yaml.tmpl > /tmp/cdk-component/component.yaml
cp LICENSE /tmp/cdk-component/LICENSE
# 3. Run dpm publish --dry-run; it validates the manifest schema and
# reports the OCI layout that would be pushed.
dpm publish component oci://localhost:5000/canton-devkit:0.0.1-dryrun \
--dry-run \
--platform darwin/arm64=/tmp/cdk-component✅ Component manifest is valid confirms the manifest schema. The
release workflow runs the same --dry-run validation on every run
(tag pushes and manual dispatches); the real publish happens only on
v* tags.
Today's integrity story is SHA-256 checksums (SHA256SUMS, verifiable
with sha256sum --check) plus the immutability of the GHCR OCI digest.
The CI pipeline also pins every GitHub Action and the DPM CLI tarball by
SHA.
Known limitation: the release artifacts are not yet
cryptographically signed. There are no cosign/Sigstore
signatures on SHA256SUMS or on the OCI artifact, so consumers can
verify integrity (the bytes match the checksum) but not provenance
(the bytes were produced by the project's release pipeline). Keyless
cosign signing plus a published verification step is a planned
hardening item.