The cli/ directory is a Cargo workspace.
crates/hm/— thehmbinary (today's CLI body).crates/hm-exec/— theExecutionBackendtrait +LocalDockerBackend(in-process Docker DAG scheduler) +CloudBackend(submit+watch over the SDK). Thehmbinary renders the emittedBuildEventstream (viahm-render) and owns Ctrl-C; auth is injected (the crate takes a builtHarmontClient).crates/hm-render/—drive_stream: consumes anEventStreamand writes terminal/JSON output. No I/O beyond stdout.crates/hm-pipeline-ir/— pipeline IR schema (serde structs only, no runtime).crates/hm-util/— shared OS and filesystem utilities.crates/hm-plugin-protocol/— wire types (serde structs only).crates/hm-plugin-sdk/— authoring SDK for plugin writers. Runcargo buildfrom the workspace root. Build requires esbuild (npm ciincrates/hm-dsl-engine/harmont-ts/).
For cross-cutting doctrine see PRINCIPLES.md.
Both DSLs live inside crates/hm-dsl-engine/ so they ship with the crate:
crates/hm-dsl-engine/harmont-py/— theharmontPython package (pipeline DSL).crates/hm-dsl-engine/harmont-ts/— theharmontTypeScript package (pipeline DSL).
The toolchain helpers in crates/hm-dsl-engine/ (e.g.
harmont-py/harmont/_rust.py, harmont-ts/src/toolchains/rust.ts) are the
public authoring SDK. They have two downstream surfaces that drift silently
unless you update them in the same change. A toolchain change is not done until
all three agree:
-
hm inittemplates —crates/hm/src/commands/init_templates/<lang>.py, embedded into the binary viainclude_str!incrates/hm/src/commands/init.rs. When you change a toolchain's recommended entrypoint (e.g. Rust →rust.project().ci()), update the matching template so scaffolded projects use the current API. Roundtrip tests:crates/hm/tests/cmd_init.rs. -
Pipeline-SDK reference docs —
docs-site/content/docs/pipeline-sdk/reference/toolchains/<lang>.mdxare auto-generated from the Python docstrings inharmont-py(griffe →docs-site/scripts/extract-dsl-api.py→generate-dsl-docs.ts); they carry a "do not edit" header. So: (a) write/refresh the docstring on any method you add or change, then (b) regenerate from the simci repo root withmake docs-generate(DSL-only: rebuilddocs-site/dsl-api.jsonfromharmont-py, thencd docs-site && npx tsx scripts/generate-dsl-docs.ts && npx tsx scripts/check-dsl-pages.ts), and (c) commit the regenerated*.mdxin the simci (parent) repo alongside the gitlink bump.check-dsl-pages.tsguards that the committed pages match the docstrings.