What is the preferred way to add a pre-commit hook to re-frame project?


I am new to Clojure, and mostly I am familiar with the JS ecosystem. In my projects, I find Prettier very convenient. When there are several developers, it is convenient to introduce pre-commit hook with Prettier, linters, testing and else. I’ve discovered zprint as an alternative to Prettier in the Clojure world in the following thread: How to best integrate zprint as pre-commit hook?. Unfortunately, there is no answer to its central question: how to introduce a pre-commit hook?

There is always an option to introduce .git/hooks/pre-commit. Still, in projects, I use lint-staged combined with husky, it allows me to work only with staged files. But this is a JavaScript way, what is a Clojure way or if there is one, a re-frame way?

You could just use these tools and set them up to run zprint or cljfmt.

But I don’t see what these tools help with to be honest. Git hooks are pretty easy. Just edit the pre-commit shell script sample to call zprint or do whatever you want. If you wanted to go all Clojure, you could make the script a joker or babashka script. Heck, even go for ClojureScript or Clojure, but those will both add some start time latency to the hook.

1 Like

Thank you @didibus! I’ll, therefore, use familiar tools. Yes, pre-commit hooks are not the most complicated topic that I’ve encountered, but additional tooling helps to act easily only on the changed files or on partially added ones.

After some time spent, I have a pre-commit configuration that works fine for me. I decided to use husky with lint-staged, which I configure in package.json.
In project.clj I’ve added the following to install zprint and use it from lein:

(defproject my-project "0.1.0-SNAPSHOT"
  ; Use zprint.
  :dependencies [
                 ; ...
                 [zprint "0.5.3"]]

  ; Make it run by CLI command: lein zprint.
  :plugins [
            ; ...
            [lein-zprint "0.5.3"]]

  ; Configure zprint.
  :zprint {:old? false :style :respect-nl}
  ; ...

Also, I’ve added some configuration to prevent zprint from creating new files and to keeping the additional linebreak.

Unfortunately clj-kondo is not available as lein plugin, but I can use it as Node.js package. Here is my package.json configuration:

  "devDependencies": {
    "husky": "^3.1.0",
    "lint-staged": "^10.0.0-beta.14",
    "clj-kondo": "^2019.11.23"
  "scripts": {
    "format": "lein zprint",
    "lint": "clj-kondo --lint"
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
  "lint-staged": {
    "*.{clj,cljs}": [
      "npm run format",
      "npm run lint"

Both zprint and clj-kondo are availaible as a native CLI executable as well. Did you try using those instead of their lein or Node counterpart? The benefit is that they’d run much faster, the downside is that if you have members developing on different platform (win, mac, linux), you need a way to select the correct binary.

1 Like

Do they imply pre-installation on developers’ machines or they can be installed like the project development dependencies on initial installation of the dependencies?

From a quick look at clj-kondo’s docs, you should be able to run on any machine with Docker:

1 Like

There’s no install needed, it’s a self contained binary. But the binary has to find its way on their machine somehow, either through a download, or a script. I guess you could consider that an install. Lein can’t pull it down for you.

You can find download links here: https://github.com/borkdude/clj-kondo/releases/tag/v2020.01.10
And here: https://github.com/kkinnear/zprint/releases/tag/0.5.3

Though it looks like zprint doesn’t have a windows binary.

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.