Minimal idiomatic starter projects, each wired up to a Harmont CI pipeline. Every example lives in its own subdirectory with a .hm/pipeline.py you can read, copy, and run via hm run <slug>.
| Example | Toolchain | Pipeline |
|---|---|---|
| react | npm + Vite + Vitest + ESLint | hm.js.project(...) |
| nextjs | npm + Jest + ESLint | hm.js.project(...) |
| typescript | tsc + Vitest + ESLint | hm.js.project(...) |
| bun | Bun + tsc + bun:test + ESLint | hm.js.project(runtime="bun") |
| rust | cargo + clippy + rustfmt | hm.rust(...) |
| python-uv | uv + pytest + ruff + mypy | hm.python(...) |
| go | go build/test/vet/fmt | hm.go(...) |
| c | CMake + CTest + clang-format | hm.cmake(lang="c") |
| cpp | CMake + CTest + clang-format | hm.cmake(lang="cpp") |
| zig | zig build/test/fmt | hm.zig(version="0.13.0") |
- Install the Harmont CLI (
cli/in this repo, orcargo install harmont-clionce published). cd examples/<lang>and runhm run ci. The CLI uses the project's.hm/pipeline.pyand executes each step in a local Docker container (the default backend), sharing caches across runs. Use--backend cloudto submit the run to Harmont Cloud instead.
Every pipeline runs on the default ubuntu:24.04 base (set a per-step image= to override) and the apt-base / language-install steps are cached forever — only the action leaves (test, lint, etc.) re-run after a code change.
The shape every pipeline shares: a single @hm.target() builds the toolchain object once; the @hm.pipeline("ci") body returns a tuple of leaves (build, test, lint). Each leaf forks off the shared install step, so adding a fifth check costs you the action — never the install.