$ make install
This section is dedicated to people who’re hacking on nREPL itself (e.g. to fix bugs or to enhance existing functionality).
There are generally two approaches to hacking on nREPL - you can either make some changes, build a new server
and run it locally to test your changes (e.g. via clj) or you can hack on nREPL in the classic
interactive Lisp manner and just make some changes and test them directly from a running (n)REPL.
Building nREPL locally is a very simple process:
Clone the repo
Make sure you have Clojure CLI installed
Run the build:
$ make install
That installs nREPL as version 99.99 into your local Maven repository
(set PROJECT_VERSION to pick another one), so afterwards you can simply
do something like:
$ clj -Sdeps '{:deps {nrepl/nrepl {:mvn/version "99.99"}}}' -M -m nrepl.cmdline --interactive
Now you can start playing with the server you’ve built.
| The reason why nREPL needs a native agent is explained here. |
Native binaries of libnrepl JVMTI agent are built on CI and then copied into the res/ directory manually, so to do regular nREPL builds you don’t have to recompile native code. However, if you want to experiment with the agent yourself, then you can rebuild the native library for your current platform like this:
$ cd libnrepl/
$ make all
The Makefile will use the default C compiler for your OS (GCC on Linux, Clang on
MacOS). You will also need JAVA_HOME environment variable to be pointing at
the JDK installation. After the binary is built, copy it from libnrepl/build/
directory into res/ and restart the REPL. The new binary will be picked up
automatically.
As nREPL is fundamental to the development workflows of many people it might be unclear how exactly you can hack on it, while at the same time you’re already running an nREPL server, powering the REPL in which you’re doing the hacking.
Developing nREPL while connected to nREPL is a classic example of eating your own dog food.
The development process is actually pretty simple - you just need to connect to nREPL as you’d normally would (e.g. by using CIDER, vim-iced or Calva), make some changes and test them by starting new nREPL instances from the REPL and connecting to them to see how they are behaving.
In practice it might not be convenient to spin many nREPL connections
from your editor, so a combination of nrepl.server/start-server and
nrepl.core/connect is a very good alternative.
;; first we have to start a new server
=> (require '[nrepl.server :refer [start-server stop-server]])
nil
=> (def server (start-server :port 7888))
='user/server
=> (require '[nrepl.core :as nrepl])
nil
;; now you can connect to the server and send it some messages
=> (with-open [conn (nrepl/connect :port 7888)]
(-> (nrepl/client conn 1000) ; message receive timeout required
(nrepl/message {:op "eval" :code "(+ 2 3)"})
nrepl/response-values))
;; when you're done with a server you can stop it
=> (stop-server server)
| You don’t really need an nREPL-powered REPL for this workflow. It’s going to work in exactly the same manner regardless of the REPL you’re using. |
See the Makefile for the list of available tasks.
The primary way to run tests is using Kaocha. The following command runs the test suite on latest configured Clojure version:
$ make test
The following command is useful while actively working on the codebase:
$ clojure -M:dev:test --watch --skip-meta :slow
as it will re-run tests on changes, but also skip a handful of slower tests.
For ease of use/consistency with other nREPL projects, tests are run on CI environments using Make, with the command:
$ make test
Our CI build enforces consistent indentation in all source files using cljfmt. You can run it
locally using:
$ make cljfmt
You can have cljfmt fix indentation problems like this:
$ clojure -M:cljfmt fix
Our CI build enforces some lint checks via Eastwood. You can run it
locally using:
$ make eastwood
If you’ve made any changes to the built-in middleware descriptors you can regenerate their documentation using:
$ make docs
| This section is relevant only to nREPL maintainers with push access to the repository. |
Here’s the process for cutting a new release (e.g. version 1.6.0):
Update CHANGELOG.md — rename the master (unreleased) section to
the new version and date (e.g. 1.6.0 (2026-02-26)), and add a fresh
master (unreleased) section above it.
In doc/antora.yml, set version to the major.minor version, quoted
(e.g. "1.6" for a 1.6.0 or 1.6.1 release; unquoted, YAML reads 2.0 as
the number 2). Do not include the patch number. Set nrepl-version under
asciidoc.attributes to the full version, so the manual’s snippets pin the
release. make deploy refuses a release tag whose docs version is still ~,
since a tag can’t be fixed after the fact.
Commit and tag:
$ git commit -am "Release 1.6.0"
$ git tag v1.6.0
Reset version in doc/antora.yml back to ~ and commit:
$ git commit -am "Begin next development iteration"
Push the commits and tag:
$ git push origin master --tags
The rest is automated:
Clojars deploy — pushing the tag triggers a CircleCI deploy job
(after tests and lint pass) that publishes the artifact to
Clojars. The version is derived from
the tag name. The tag must match v<major>.<minor>.<patch> (with an
optional -alpha<N>, -beta<N> or -rc<N> suffix).
GitHub Release — a GitHub Actions workflow creates a GitHub Release
whose notes are the version’s section of CHANGELOG.md.
Pushing a tag like v1.6.0-SNAPSHOT runs the same pipeline, tests
included, and deploys a snapshot to Clojars. That’s a cheap way to
exercise the whole release path before tagging the real thing.
|
Can you improve this documentation? These fine people already did:
Bozhidar Batsov, Oleksandr Yakushev, ikappaki, Shen Tian, p4v4n, Michael Griffiths & Dominic MonroeEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |