hoks
v0.1.22
Published
> Amazingly simple Git hooks library, packed with great defaults.
Readme
hoks
Amazingly simple Git hooks library, packed with great defaults.
- Get up and running with one command
- Automatic setup of config file (TS, JS, JSON, package.json)
- Simple configuration
- Great pre-configured defaults (branch validation, commit validation, staged commands, etc)
- Support for custom hooks
Install
Install with the following commands. Run hoks --init on config updates to apply the changes.
# install
npm install hoks
# init typescript config file
npx hoks --init
# update hooks whenever a change has occurred to the config
npx hoks --initSupported flags:
--json- use JSON config file--javascript- use JS config file--package- use package.json config file
Setup
To ensure all developers always have the correct Git hooks, add the following to your project's package.json:
"scripts": {
"postinstall": "hoks --init"
}This will automatically set up the hooks after every install. Note: The hoks --init command will automatically skip running in CI environments (when the CI environment variable is set).
Uninstall
Either remove hooks in .git/hooks/ manually or run the following command:
npx hoks --cleanExample
import { defineConfig } from "hoks";
export default defineConfig({
installOnLockChange: true,
commitMessage: {
pattern: "^ID-[0-9]+: .+",
message: pc => pc.red("Commit message must look like this ID-<number>: <message>"),
},
preCommit: ["npm run test"],
staged: {
"*": "npm run format",
"*.{ts,js}": "npm run lint",
},
preventCommit: ["main", "master", "develop"],
});API Reference
Install on lock change
Install dependencies on lock file change. Uses git-install-hook under the hood. Installs automatically by default, but can be a prompt. Will run on branch change and after a merge.
- type:
boolean | object - default:
false - command:
installOnLockChange - hooks:
post-checkout,post-merge
{
"installOnLockChange": {
"prompt": true,
"installation": "show",
"noText": false
}
}- prompt:
boolean- prompt before installing - installation:
show | hide | spinner- show or hide the installation output - noText:
boolean- hide the text
Branch name
Validate branch name.
- type:
boolean | object - default:
false - command:
branchName - hooks:
pre-commit
{
"branchName": {
"pattern": "^feature/.+",
"message": "Branch name must start with 'feature/'"
}
}- pattern:
string- regex pattern - message:
string | function- error message
The error message can be a string or a function that returns a string. It gets the pc object as parameter. This is piccocolors and can be used to style the text.
{
"branchName": {
"pattern": "^feature/.+",
"message": pc => pc.red("Branch name must start with 'feature/'")
}
}Commit message
Validate commit message. Will run on commit-msg hook. If staged is enabled, it will run before the staged commands by moving the staged commands to the commit-msg hook.
- type:
boolean | object - default:
false - command:
commitMessage - hooks:
commit-msg
{
"commitMessage": {
"pattern": "^ID-[0-9]+: .+",
"message": "Branch must look like this ID-<number>: <message>"
}
}- pattern:
string- regex pattern - message:
string | function- error message
The error message can be a string or a function that returns a string. It gets the pc object as parameter. This is piccocolors and can be used to style the text.
{
"commitMessage": {
"pattern": "^ID-[0-9]+: .+",
"message": pc => pc.red("Branch must look like this ID-<number>: <message>")
}
}Staged
Run commands on staged files. Defaults to run on pre-commit, but will run on commit-msg if any feature that checks the commit message is enabled (commitMessage or enforceConventionalCommits). This is because the validation needs to run before running the commands.
- type:
false | object - default:
false - command:
staged - hooks:
pre-commit,commit-msg
{
"staged": {
"*": "npm run format",
"*.{ts,js}": "npm run lint"
}
}The key is a minimatch pattern. The value is a command to run. If no / is used in the name, it will match the file name even if it is in a subdirectory. If / is used, it will match the whole path.
Prevent commit
Prevent commits on certain branches.
- type:
false | string | string[] - default:
false - command:
preventCommit - hooks:
pre-commit
{
"preventCommit": ["main", "master", "develop"]
}Sync before push
Sync (pull) before push. Will not sync if force push.
- type:
boolean - default:
false - command:
syncBeforePush - hooks:
pre-push
{
"syncBeforePush": false
}Enforce conventional commits
Enforce conventional commits. If staged is enabled, it will run before the staged commands by moving the staged commands to the commit-msg hook.
- type:
boolean - default:
false - command:
enforceConventionalCommits - hooks:
commit-msg
{
"enforceConventionalCommits": true
}No todos
Prevent commits with TODOs in comments.
- type:
boolean - default:
false - command:
noTodos - hooks:
pre-commit
{
"noTodos": true
}Test changed
Run tests on changed files. Supports for jest and vitest.
- type:
boolean - default:
false - command:
testChanged - hooks:
pre-commit
{
"testChanged": true
}Include
Control when hooks run by specifying an include field. This field takes an array of folder paths (relative to the repo root). If set, hooks will only run if any staged file is within one of the specified folders. Matching is performed using grep (regular expressions), not glob patterns. Only folders can be specified—file or glob patterns are not supported. If not set, hooks always run (default behavior).
- type:
string[] - default: not set (hooks always run)
- command:
include - hooks: all
{
"include": ["apps/web", "src/features"] // Only folders, uses grep for matching
}- If any staged file is within a folder listed in
include, the hook runs as normal. - If no staged files are within the specified folders, the hook is skipped for that commit.
- If
includeis not set, hooks always run (legacy/default behavior).
Use cases:
- Speed up hooks in monorepos by only running checks for relevant folders.
- Prevent unnecessary hook runs for unrelated changes.
Custom hooks
Any custom hook can be added. For example, the pre-commit hook can be added using camelCase preCommit as key and commands as value. This works for any valid hook.
- type:
false | string | string[] - default:
false
{
"preCommit": ["npm run test"]
}