Getting under way
Rig hk on a Git repository ye already sail, then set the same linters to work when ye commit, when ye work locally, and when CI (the harbour-master) runs.
Bringing hk aboard
Pick one way to bring hk aboard:
mise use hkbrew install hkcargo install hk --lockedMake sure hk came aboard and answers:
hk --versionPrebuilt binaries are also waiting at GitHub releases. By default hk reads its charts with the built-in pklr evaluator, so ye do not need to install the Pkl CLI.
Rigging the ship
From the root of yer repository, have hk draw up a configuration:
hk inithk spots yer tools from the project's files and writes hk.pkl, the ship's charts. Read over its steps before ye run them. To pick the tools and hooks yerself, use hk init --interactive. hk searches recursively, through every directory, for the source files that give a tool away, honouring ignore rules and never following symlinks; .gitignore applies inside Git repositories, and .ignore works outside Git too. .NET manifest globs and configuration indicators are only looked for at the root, so a nested workspace is not activated behind yer back.
When hk init --mise is used, hk merges into an existing mise.toml only the entries it lacks: hk if it's missing, and pre-commit when there's none. The quartermaster's existing pins, comments, tools, and tasks are all kept as ye left them. --force governs hk.pkl and does not reset mise.toml. hk inspects only literal local task includes; an included flat pre-commit task stops it adding a duplicate. An include that is unknown, remote, dynamic, missing, unreadable, or malformed stops the insertion, and hk sings out a warning.
Muster yer lookouts
Builtins, the standing crew, configure commands; they do not install the tools those commands invoke. Bring the linters ye chose aboard with yer project's package manager or mise, and make sure hk can find them on PATH.
Rig the hooks
Choose the scope that fits how ye sail:
| Scope | Command | What it does |
|---|---|---|
| The whole fleet (all repositories), Git 2.54+ | hk install --global | Rig it once in yer user Git config; ships without an hk configuration are skipped |
| This ship (the current repository) | hk install | Rig the hooks this project defines; works with older Git versions too |
On Git 2.54+, hk uses Git's configuration-based hooks. On older Git, rigging a single ship (a per-repository install) writes script shims. Use hk install --legacy to ask for shims outright.
If hk is already rigged across the fleet (installed globally), hk install skips the local installation and clears away stale local hk hooks. --force-local overrides that, but combining local and global hooks can cause duplicate runs: the pipe may call all hands twice over.
The quartermaster's tools in Git hooks
On Git 2.54+, the recommended course is hk install --global --mise, which launches hooks through mise x. The installer writes down where mise lives, so mise must be on PATH while ye install, but Git does not need it on its runtime PATH. For an installation scoped to one repository, on any supported Git version, use hk install --mise; this local launcher does need mise on Git's runtime PATH.
Commit hk.pkl so all yer shipmates sail by the same charts. Installing the hooks is local to each developer's machine or clone.
To take an installation down, use hk uninstall or hk uninstall --global. The install reference lists every option.
Yer first charts
This complete example puts Prettier, ESLint, and Ruff to work. Bring those tools aboard and configure them first, or swap them for builtins that suit yer project.
amends "package://github.com/jdx/hk/releases/download/v2.4.0/hk@2.4.0#/Config.pkl"
import "package://github.com/jdx/hk/releases/download/v2.4.0/hk@2.4.0#/Builtins.pkl"
steps {
["prettier"] = Builtins.prettier
["eslint"] = Builtins.eslint
["ruff"] = Builtins.ruff
}The amends line loads hk's configuration schema. Builtins supplies reusable step definitions: the standing crew. Top-level steps is the recommended place to start: from it hk creates check, fix, and pre-commit hooks that share these steps, so all three muster the self-same crew.
With these charts, pre-commit fixes the staged files while yer unstaged work is stowed in the hold. check inspects yer working tree, and fix applies fixes to it. A step whose file patterns match none of the selected files is skipped.
Top-level steps is optional, matey. Ye can instead define steps only inside explicit hooks, giving each pipe its own hands, or use explicit hooks to customize the shared setup. See hook defaults.
Make sure the charts are sound without sending any linters aloft:
hk validateChecking the cargo and mending the canvas
hk check # Check modified files
hk fix # Apply available fixes
hk check --all # Check all files, useful for CI
hk check src/main.ts # Check a specific file
hk check --step eslintWith the charts above, the modified files include the staged, unstaged, and untracked ones: cargo loaded aboard, cargo left on the dock, and cargo Git doesn't track yet. --all selects the tracked files plus eligible untracked ones; ignore rules and exclusions still apply. Hook settings and flags can change which files are selected.
Check commands should be read-only: lookouts look, they don't touch. Fix commands may edit files, and some findings need mending by hand. hk fix leaves its fixes unstaged by default; use hk fix --stage to stage them. The default pre-commit hook stages its fixes. Review git diff and git diff --cached to see what the sailmakers changed.
Read the passage plan
Use the passage plan to see which steps and files hk selects:
hk check --plan
hk check --why eslint
hk check --all --plan --jsonThese commands do not execute the hook's steps; no hand goes aloft. See troubleshooting if a step is missing or behaves strangely.
Calling all hands: running hooks
Once the hooks are rigged, Git sounds the pipe for each configured hook by itself. Ye can also sound it directly:
hk run pre-commitA hook run by hand does everything the hook is configured to do: fixes, staging, and stashing included. To inspect it first, use hk run pre-commit --plan.
Where to sail next
- Git hooks and stowing the hold: take command of automatic fixes and partial commits.
- Continuous integration, the harbour-master: check a full repository or a branch.
- Ships in bottles, the configuration examples: start from a JavaScript, Python, or monorepo setup.
- The ship's charts, configuration: customize steps, profiles (the watches), and local overrides.
Heave away, haul away, and ye're bound away for the main!
