Shared configurations for managing pre-commit and pre-push git hooks using hk.
If you have a repository where a configuration was already set up using hk, you can simply run:
hk install --miseIf hk is not installed yet, you should be able to install it, including required tools, using mise (mise install).
The command will install the git hooks defined in the configuration in your local repository. With this set up, the defined hooks will be executed automatically on the respective git actions (e.g. pre-commit, pre-push). Usually this consists of running checks like code formatting, linting, or running tests.
By convention, we set up a check in GitHub Actions that runs the checks for all files on a pull request.
Sometimes it may be required to run checks or fixes manually on all files, for example when changing the configuration of the hooks or then first introducing the checks.
You can run the checks manually using:
hk check --allYou can run fixes manually using:
hk fix --allIt can be that hk uses an outdated configuration because of its internal caching mechanism.
In this case you can clear the cache using:
hk cache clearThis may not help in all cases, especially when using remote configurations.
You can try to run pkl directly to see if the configuration is as expected:
pkl eval hk.pklIf the configuration is not as expected it may be that the remote file is cached by pkl.
It is unclear though how to clear the pkl cache in this case, solution is usually to change the URL (e.g. by using a different tag or commit hash).
As a prerequisite for all setups with hk we set up a mise configuration. First, make sure you have mise installed.
Create a mise.toml file in the root of your repository or extend the existing one and add the tools hk and pkl.
You can do this using the following command:
mise use --pin hk pklThe respective section in the mise.toml file should look like this:
[tools]
hk = "<version>"
pkl = "<version>"Currently the configuration requires to explicitly configure the pkl CLI to be used as backend, since the PKL support built into hk does not support all language features required for our configuration:
[env]
# explicitly use pkl CLI instead of pklr library because the latter does not support all language features needed
HK_PKL_BACKEND = "pkl"If experimental features are enabled in your mise setup, you can add an enter and postinstall hook to automatically install the git hooks after running mise install:
[hooks]
enter = "mise x -- hk install --mise"
postinstall = "mise x -- hk install --mise"Create a file hk.pkl in the root of your repository.
You have the option to
- use a pre-defined shared configuration from this repository (see
configs/folder) - reuse shared pre-defined linter configurations from this repository (see
Shared.pkl) - define your own configuration from scratch
For the last option please refer to the hk documentation.
Depending on your configuration it is important to also add the required tools (e.g. actionlint, prettier, etc.) to your mise.toml file.
Reference a released version as a Pkl package (recommended). Package archives are served from the GitHub release CDN, avoiding the rate limiting that applies to raw GitHub URLs:
amends "package://github.com/wetransform/hk-config/releases/download/v<version>/hk-config@<version>#/configs/Default.pkl"Replace <version> with the desired release version, e.g. 2.4.0 (note: the
v prefix appears in the path segment but not in the hk-config@<version>
package coordinate). Package archives are attached to every release from the
one that introduced packaging onward; earlier tags have no archive (use the
raw-URL form below for those).
To reference a branch or specific commit (for example, to test changes before a release), use a raw GitHub URL instead — branches have no package archive:
amends "https://raw.githubusercontent.com/wetransform/hk-config/refs/heads/<branch>/configs/Default.pkl"To pin an older tag that predates package publishing, use refs/tags/<tag> in place of refs/heads/<branch>.
Example content of hk.pkl reusing shared linter configurations:
amends "package://github.com/wetransform/hk-config/releases/download/v<version>/hk-config@<version>#/Config.pkl"
import "package://github.com/wetransform/hk-config/releases/download/v<version>/hk-config@<version>#/Builtins.pkl"
import "package://github.com/wetransform/hk-config/releases/download/v<version>/hk-config@<version>#/Shared.pkl"
local linters = new Mapping<String, Step> {
// use shared linters from Shared.pkl
["prettier"] = Shared.prettier
["pkl"] = Shared.pkl
["actionlint"] = Shared.actionlint
}
hooks {
["pre-commit"] {
fix = true // automatically modify files with available linter fixes
stash = "git" // stashes unstaged changes while running fix steps
steps = linters
}
// instead of pre-commit, you can instead define pre-push hooks
["pre-push"] {
steps = linters
}
// "fix" and "check" are special steps for `hk fix` and `hk check` commands
["fix"] {
fix = true
steps = linters
}
["check"] {
steps = linters
}
}You can also reuse the function that creates the hooks mapping to avoid boilerplate code:
amends "package://github.com/wetransform/hk-config/releases/download/v<version>/hk-config@<version>#/Config.pkl"
import "package://github.com/wetransform/hk-config/releases/download/v<version>/hk-config@<version>#/Shared.pkl"
import "package://github.com/wetransform/hk-config/releases/download/v<version>/hk-config@<version>#/Model.pkl"
import "package://github.com/wetransform/hk-config/releases/download/v<version>/hk-config@<version>#/Functions.pkl"
local linters = new Mapping<String, Model.Step> {
// use shared linters from Shared.pkl
["prettier"] = Shared.prettier
["pkl"] = Shared.pkl
["actionlint"] = Shared.actionlint
}
hooks = Functions.defaultHooks(true, linters)To pin a branch or commit instead of a release, use the
https://raw.githubusercontent.com/wetransform/hk-config/refs/heads/<branch>/…
form shown above.