Continuous integration: the harbour-master
Use hk check --all to run the ship's checks against a checkout. The harbour-master (CI) must bring aboard hk and every tool the configured steps call on, just as a sailor's own machine does.
One crew at the helm and for the harbour-master
As the song has it, the hook, the helm and the harbour-master all muster the self-same crew. Define a check hook that reuses yer linter mapping, the same lookouts ye post at the helm:
hooks {
["check"] { steps = linters }
}Then run:
hk validate
hk check --allNo hk install step is needed to call hk directly in CI. Keep check commands read-only, so a failing check, a squall, reports what needs to change. Mend the canvas with hk fix locally, review the changes, and commit them.
Provision the ship
With a committed mise.toml, these are the essential commands for the quartermaster in CI:
mise install
mise exec -- hk check --allIf yer linters are project dependencies, also run the package manager's install command and expose its executable directory to hk. The mise integration guide shows a Node.js example.
Pin tool versions in the project so local and CI runs sail by the same rules. Keep hk's Pkl package imports versioned as well.
Inspect only a branch's changes
A full check is the simplest baseline. For large ships, pick the files that differ between two references:
hk check --from-ref origin/main --to-ref HEADReplace origin/main with yer target branch, and make sure the checkout holds both references and enough history to compare them. Shallow clones may need an extra fetch.
Locally, hk check --pr picks the changes against the detected default branch. For the harbour-master, explicit references make the comparison easier to inspect.
Changed cargo is only a filter
Picking by reference chooses file paths; the commands still run against the cargo in the current checkout. It does not check out historical versions. A changed-file check also cannot work out every downstream effect of a change to shared configuration or a dependency.
Call up extra watches
Use profiles, the watches, for checks too costly to run on every commit:
["typecheck"] = (Builtins.tsc) {
profiles = List("slow")
}Call them up explicitly:
hk check --all --slow
hk check --all --profile ci --profile slowA step with more than one positive profile needs all of them. A profile named ci is a label ye enable yerself; do not rely on its name to call up that watch automatically.
Haul in useful diagnostics
hk check --all --no-fail-fast
hk check --all --plan --json
HK_TIMING_JSON=hk-timing.json hk check --all--no-fail-fast collects the failures from the remaining steps too. A plan, the passage plan, shows the selected steps without executing them. The timing file records total and per-step wall time; when all hands haul at once their times overlap, so don't add parallel step durations together as a total.
Use hk check --all --format jsonl for structured execution events, --sarif hk.sarif for normalized diagnostics, or --junit-xml hk.junit.xml to report each step as a JUnit test case for CI test-result viewers. See clockwork hands (coding agents) for command effects and exact file lists.
See troubleshooting for the ship's log levels and traces, and for inspecting the configuration.
