Liking cljdoc? Tell your friends :D

Monkey Build

Utility lib for building Clojure libs/apps using Clojure CLI.

I have provided this because although the CLI and related tools provide everything I need, I found myself copy/pasting the same code over and over. So I decided to create this opinionated lib. It does some assumptions regarding the way the code is structured, which libs you use, etc...

Consider it a "batteries included" library for Clojure CLI.


Clojars Project CircleCI

Include the library in your deps.edn file, and then you can call it as a function, using the -X parameter. For example, to add an alias to run all unit tests using Kaocha, add this:

  {:extra-deps {com.monkeyprojects/build {:mvn/version "0.1.0-SNAPSHOT"}}
   :exec-fn monkey.test/all}}

To run the tests, just execute:

clojure -X:test

Available Commands

These commands are available to use in exec-fn:

  • monkey.test/all: run all unit tests
  • monkey.test/watch: run unit tests continuously and watch for changes
  • monkey.test/junit: run all unit tests and output to junit.xml
  • monkey.test/coverage: runs unit tests with cloverage
  • monkey.test/lint: runs the cli-kondo linter on the src dirs (but you can override this).
  • deletes the target/classes dir
  • build jar file
  • install the jar locally
  • combines jar and install
  • creates an uberjar file
  • deploys to Clojars

Since this is just Clojure code, you are of course completely free to call these functions from your own build code. All they require is a single parameter, containing the arguments passed in (see below).

When building a jar or uberjar, the clean function is invoked to ensure no unnecessary or stale class files are added to the jar file.


In order to build a jar, or deploy, some extra exec-args are needed:

  • :jar: the path to the jar file
  • :version: the version to include in the pom.xml
  • :lib: the name to deploy the library as (in case of deployment).
  • :scm (optional): add additional SCM info to the pom file.

You can also customize the junit.xml output file by adding an :output parameter. The test functions essentially just call the Kaocha code, so if you want more customization, either specify it in the tests.edn file, or call the functions directly from your own build code. As I said, this is an opinionated lib, mostly created for my own purposes.


Sometimes it's easier to get the version from an environment variable, or you have some custom calculation system. For this, Monkey Build also supports two additional arguments, instead of :version:

  • :version-env: reads the version string directly from an environment variable
  • :version-fn: resolves the fully qualified function symbol, and invokes it without arguments

Although, in most cases it's easiest to just pass the version argument on the command line:

clj -X:jar:install :version '"1.0'"


The test commands use Kaocha, so in order to do some additional configuration, you can create a tests.edn file in the project root. Sometimes, however, you want some deviating configuration depending on the situation. For example, when doing TDD, you'll want to watch your code, and in that case you may want to skip any slow tests. In that case, you can pass in extra configuration in the exec-args, like so:

  {:exec-fn monkey.test/watch
   :exec-args {:kaocha.filter/skip-meta [:slow]}}}}

When watching, the exec-args are passed directly to Kaocha, so all config options that Kaocha supports can be specified here.


For coverage calculation the default args from Cloverage are being applied, with the exception of junit?, which is enabled by default. You can override them by specifying them in the exec-args map.

Apart from that, there is one required parameter, the ns-regex vector. It should be a list of strings that contain all the namespaces that should be instrumented. Example deps.edn fragment:

  {:exec-fn monkey.test/coverage
   :exec-args {:ns-regex ["my.lib.ns.*"]}}}}


In order to to static code analysis, you can run the lint command. By default it analyzes the src directory, but you can override this by specifying an argument:

  {:exec-fn monkey.test/lint
   :exec-args {:dirs ["src" "test"]}}}}

Or, on the command line:

clj -X:lint :dirs '["src" "test"]'


Copyright (c) 2023 by Monkey Projects BV.

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close