nREPL 0.9 is out! We’ve been working on it for over a year, but we finally got where we wanted to be.

The highlight of the release is undoubtedly the support for Unix file sockets, which are a secure and fast alternative to TCP sockets for local development. This feature was on the books for a very long time, but it became viable only recently when Java 16 added support for Unix sockets.1 If you’re stuck with an older version of Java we’ve got you covered as well - just add junixsocket as a dependency and nREPL will pick it up automatically. With tools.deps you can do something like:

{
;; ...
:aliases {:nREPL
          {:extra-deps
           ;; UNIX domain socket support was added in 0.9.0
           {nrepl/nrepl {:mvn/version "0.9.0"}
            com.kohlschutter.junixsocket/junixsocket-core {:mvn/version "2.3.2"}}}}
}

Afterwards you can start nREPL like this:

$ clj -M:nREPL -m nrepl.cmdline --socket nrepl-socket

CIDER has already added experimental support for Unix sockets and I hope that other nREPL clients will follow suit soon.2 The changes necessary to clients are tiny, as only the connection mechanism changes, everything else stays exactly the same as with TCP sockets. The magic happens in nrepl.socket, which serves as a compatibility layer for java.io and java.nio.

If you’re not familiar with Unix sockets you might be wondering if this is something that is relevant for you. I’ll try to explain the impact of Unix sockets here briefly:

  • UNIX domain sockets know that they’re running locally, so they can avoid some checks and operations (like routing), which makes them faster and lighter than TCP/IP sockets.
  • You can’t accidentally start an nREPL server that’s listening on a public address and allows external parties to execute any code on your computer.
  • Security/access is enforced via file permissions.
  • For clients it’s easier to start a server and connect to it, because they don’t have to deal with a random port that they have to figure out once the server starts. E.g. cider-jack-in can just select some socket name based on the current project and connect to it immediately.
  • They are not supported on Windows. No surprise here given their name, right?3

In practice all of this means that Unix sockets are generally a better option for local development than TCP sockets. You’re free to keep using TCP sockets, though, and they will always be the default in nREPL.

The 0.9 release also brings a bunch of small improvements and bug-fixes. One more thing - now it’s possible to use nREPL with GraalVM native images. Read the release notes for all the details.

As usual, here I’ll thank all the people who contributed to the release in one way or another. You rock and you show why the Clojure community is so awesome! Another round of special thanks goes to Clojurists Together and Cognitect, the main patrons of my open-source Clojure work!

What’s next? Time will tell. It seems that nREPL is feature-complete at this point and that we’ve made good on all the promises we made several years ago when nREPL’s development moved away from Clojure Contrib. Other than polishing the existing functionality, the nREPL protocol specification and the documentation there’s nothing major I want to tackle at this point. Perhaps it’s time for a 1.0 release?

In parentheses we trust!

  1. Remember that nREPL can’t have any runtime dependencies, so we’re limitted to what’s available in the JDK and Clojure. 

  2. See https://github.com/clojure-emacs/cider/pull/3088 for more details. 

  3. It was pointed out to me that these days Windows actually supports Unix sockets! See https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ for more details.