CLI reference
halyard
A deploy CLI that builds, signs and ships a release, then keeps the previous one
warm so a rollback is one command and not a rebuild. Run deploy locally, promote a build with promote, and step
back with rollback.
01
Installation
Before you start
- Node 18 or later for the
npxroute. The Homebrew formula bundles its own runtime. - A project with component files to scan;
deploydefaults to the current directory.
Terminal
$ brew install halyard # verify the install $ halyard --version
Terminal
# no install step; runs the latest version each time $ npx halyard deploy
02
Commands
Every command accepts an optional path argument; it defaults to the current directory.
deploy [path]
Builds, signs and uploads the artifact, then runs the 31 preflight checks against it. Stops before the traffic switch, so a failed check costs you a build and nothing else.
promote [build]
Switches traffic to a build that already passed preflight, and keeps the outgoing one warm. Defaults to the most recent passing build.
rollback
Sends traffic back to the warm build. No rebuild, no registry round trip — the previous release is still running.
03
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
| --env <name> | string | staging | Which environment to act on. Anything other than staging has to exist in the config already; halyard will not create production for you. |
| --keep-warm <n> | number | 1 | How many superseded releases stay running after a promote. rollback can only reach a build that is still warm. |
| --skip <check> | string[] | — | Skip a named preflight check. Repeatable, written into the release record, and refused for the four signing checks. |
| --format <type> | string | pretty | Output format: pretty, json, or junit. Use json to pipe the release record into other tooling. |
04
Configuration
Drop a halyard.config.json in your project root to set defaults for every command. Flags on the command line always win.
halyard.config.json
{ "environments": { "staging": { "keepWarm": 1 }, "production": { "keepWarm": 2, "promote": "manual" } }, "preflight": { "healthcheck": "/readyz", "timeout": "90s", "skip": ["bundle-size"] }, "signing": { "key": "env:HALYARD_SIGNING_KEY" }, "notify": "deploys" }
05
Example output
A deploy to production where two preflight checks fail, so traffic never moves.
Terminal
$ halyard deploy --env production build 4f21c9e · signed · uploaded in 38s preflight: 31 checks runtime fail healthcheck /readyz answered 503 for 90s (timeout) warn cold-start p95 1.9s, up from 0.7s on the live build config fail env-drift STRIPE_WEBHOOK_SECRET set live, missing here ✖ 2 checks failed, 1 warning · 28 passed traffic unchanged · v1.0.2 still live · build kept for 24h
Nothing was promoted, so there is nothing to roll back. Fix the two failures and run the
same command again; --skip cold-start silences the warning and is written
into the release record, so a later reader can see it was a choice.
06
Exit codes
Every command returns one of three codes; script against these rather than parsing stdout.
| Code | Meaning | Description |
|---|---|---|
| 0 | Released | Every preflight check passed and traffic is on the new build. rollback can still reach the previous one. |
| 1 | Preflight failed | One or more checks failed, so traffic never moved. CI should fail the job on this and leave the live release alone. |
| 2 | Configuration error | An invalid halyard.config.json, an unknown --env, or a signing key that cannot be read. |