Add lefthook for linting and testing hooks, and optional pre-commit hook via local (#7)

* unbreak package lock

* lint

* add lefthook for prepush test and lint hook

* attempt at exiting 0 if we made a change in lint

* fix lint

* add fail text

* pre-commit test

* adjust autofix

* add lefthook example

* fix comment
This commit is contained in:
Paul Carleton 2025-11-04 14:50:17 +00:00 • committed by GitHub
commit 44a2732b53
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 207 additions and 1 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
node_modules
results/
lefthook-local.yml

View file

@ -0,0 +1,10 @@
# Optional local lefthook configuration
# To enable this:
# cp lefthook-local.example.yml lefthook-local.yml
# Uncomment to add pre-commit hook for automatic linting on staged files:
pre-commit:
commands:
lint:
run: npm run lint:fix {staged_files}
stage_fixed: true

39
lefthook.yml Normal file
View file

@ -0,0 +1,39 @@
# lefthook.yml
# Configuration reference: https://lefthook.dev/configuration/
assert_lefthook_installed: true
output:
- meta # Print lefthook version
- summary # Print summary block (successful and failed steps)
- empty_summary # Print summary heading when there are no steps to run
- success # Print successful steps
- failure # Print failed steps printing
- execution # Print any execution logs (but prints if the execution failed)
- execution_out # Print execution output (but still prints failed commands output)
- execution_info # Print `EXECUTE > ...` logging
- skips # Print "skip" (i.e. no files matched)
pre-push:
follow: true
parallel: true
jobs:
- name: 'Code Formatting'
run: npm run lint:fix_check
stage_fixed: true
fail_text: |
💡 To catch linting issues earlier, enable the pre-commit hook:
cp lefthook-local.example.yml lefthook-local.yml
- name: 'Test'
run: npm run test
post-checkout:
jobs:
- name: 'Install Dependencies'
run: npm install
post-merge:
jobs:
- name: 'Install Dependencies'
run: npm install

154
package-lock.json generated
View file

@ -10,6 +10,7 @@
"dependencies": {
"@modelcontextprotocol/sdk": "^1.20.1",
"express": "^5.1.0",
"lefthook": "^2.0.2",
"zod": "^3.25.76"
},
"devDependencies": {
@ -57,6 +58,7 @@
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@ -4856,6 +4858,158 @@
"node": ">=6"
}
},
"node_modules/lefthook": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook/-/lefthook-2.0.2.tgz",
"integrity": "sha512-2lrSva53G604ZWjK5kHYvDdwb5GzbhciIPWhebv0A8ceveqSsnG2JgVEt+DnhOPZ4VfNcXvt3/ohFBPNpuAlVw==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"lefthook": "bin/index.js"
},
"optionalDependencies": {
"lefthook-darwin-arm64": "2.0.2",
"lefthook-darwin-x64": "2.0.2",
"lefthook-freebsd-arm64": "2.0.2",
"lefthook-freebsd-x64": "2.0.2",
"lefthook-linux-arm64": "2.0.2",
"lefthook-linux-x64": "2.0.2",
"lefthook-openbsd-arm64": "2.0.2",
"lefthook-openbsd-x64": "2.0.2",
"lefthook-windows-arm64": "2.0.2",
"lefthook-windows-x64": "2.0.2"
}
},
"node_modules/lefthook-darwin-arm64": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-2.0.2.tgz",
"integrity": "sha512-x/4AOinpMS2abZyA/krDd50cRPZit/6P670Z1mJjfS0+fPZkFw7AXpjxroiN0rgglg78vD7BwcA5331z4YZa5g==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/lefthook-darwin-x64": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-2.0.2.tgz",
"integrity": "sha512-MSb8XZBfmlNvCpuLiQqrJS+sPiSEAyuoHOMZOHjlceYqO0leVVw9YfePVcb4Vi/PqOYngTdJk83MmYvqhsSNTQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/lefthook-freebsd-arm64": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-2.0.2.tgz",
"integrity": "sha512-gewPsUPc3J/n2/RrhHLS9jtL3qK4HcTED25vfExhvFRW3eT1SDYaBbXnUUmB8SE0zE8Bl6AfEdT2zzZcPbOFuA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/lefthook-freebsd-x64": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-2.0.2.tgz",
"integrity": "sha512-fsLlaChiKAWiSavQO2LXPR8Z9OcBnyMDvmkIlXC0lG3SjBb9xbVdBdDVlcrsUyDCs5YstmGYHuzw6DfJYpAE1g==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/lefthook-linux-arm64": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-2.0.2.tgz",
"integrity": "sha512-vNl3HiZud9T2nGHMngvLw3hSJgutjlN/Lzf5/5jKt/2IIuyd9L3UYktWC9HLUb03Zukr7jeaxG3+VxdAohQwAw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/lefthook-linux-x64": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-2.0.2.tgz",
"integrity": "sha512-0ghHMPu4fixIieS8V2k2yZHvcFd9pP0q+sIAIaWo8x7ce/AOQIXFCPHGPAOc8/wi5uVtfyEvCnhxIDKf+lHA2A==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/lefthook-openbsd-arm64": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-2.0.2.tgz",
"integrity": "sha512-qfXnDM8jffut9rylvi3T+HOqlNRkFYqIDUXeVXlY7dmwCW4u2K46p0W4M3BmAVUeL/MRxBRnjze//Yy6aCbGQw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"openbsd"
]
},
"node_modules/lefthook-openbsd-x64": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-2.0.2.tgz",
"integrity": "sha512-RXqR0FiDTwsQv1X3QVsuBFneWeNXS+tmPFIX8F6Wz9yDPHF8+vBnkWCju6HdkTVTY71Ba5HbYGKEVDvscJkU7Q==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"openbsd"
]
},
"node_modules/lefthook-windows-arm64": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-2.0.2.tgz",
"integrity": "sha512-KfLKhiUPHP9Aea+9D7or2hgL9wtKEV+GHpx7LBg82ZhCXkAml6rop7mWsBgL80xPYLqMahKolZGO+8z5H6W4HQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/lefthook-windows-x64": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-2.0.2.tgz",
"integrity": "sha512-TdysWxGRNtuRg5bN6Uj00tZJIsHTrF/7FavoR5rp1sq21QJhJi36M4I3UVlmOKAUCKhibAIAauZWmX7yaW3eHA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",

View file

@ -6,7 +6,8 @@
"start": "tsx src/runner.ts",
"test": "jest",
"lint": "eslint src/ && prettier --check .",
"lint:fix": "eslint src/ --fix && prettier --write ."
"lint:fix": "eslint src/ --fix && prettier --write .",
"lint:fix_check": "npm run lint:fix && git diff --exit-code --quiet"
},
"devDependencies": {
"@eslint/js": "^9.8.0",
@ -24,6 +25,7 @@
"dependencies": {
"@modelcontextprotocol/sdk": "^1.20.1",
"express": "^5.1.0",
"lefthook": "^2.0.2",
"zod": "^3.25.76"
}
}