nREPL Clients
Most of the time, you will connect to an nREPL server using an existing library/client/tool. Bellow is a listing of many such clients.
Some of these clients will only work with Clojure nREPL servers, while others are built with language-agnosticism and can connect to nREPL servers written in any language. |
Command-line Clients
-
grenchman (command-line nREPL client written in OCaml, works with non-Clojure servers)
-
REPL-y (command-line client for nREPL)
-
rep (A single-shot nREPL client designed for shell invocation.)
-
shevek (A command-line nREPL client written in Fennel, works with non-Clojure servers)
-
Parle (A command-line nREPL client using node.js written in ClojureScript)
Both Leiningen and Boot use internally REPL-y, as their command-line nREPL client. |
Editors/IDEs
-
CIDER (Clojure Interactive Development Environment that Rocks for Emacs)
-
Cursive (Clojure IDE/plugin for IntelliJ Idea)
-
Counterclockwise (Clojure IDE/plugin for Eclipse)
-
monroe (nREPL client for Emacs, works with non-Clojure servers)
-
miracle (fork of
monroe
targeting Arcadia) -
fireplace.vim (Clojure + nREPL support for vim)
-
Conjure (Clojure(Script) plugin for Neovim)
-
vim-iced (Clojure Interactive Development Environment for Vim8/Neovim)
-
Acid.nvim (Asynchronous Clojure Interactive Development for Neovim)
-
Chrorine (Atom plugin for Clojure Development)
-
Proto REPL (Clojure development environment and REPL for Atom)
-
Calva (Clojure & ClojureScript support for VS Code)
-
Tutkain (Clojure plugin for Sublime Text)
If your preferred Clojure development environment supports nREPL, you’re in luck. Just use it or connect to an existing nREPL endpoint and start hacking.
Most Clojure editors/IDEs can start an nREPL server themselves and connect
to it automatically (e.g. CIDER would do this when you’re using the
cider-jack-in family of commands), so you’ll rarely need to start a server
externally for local development purposes.
|
Libraries
-
node-nrepl-client (An nREPL client for programmatic use from node.js written in Javascript)
-
nrepl-python-client (nREPL client library for Python)
-
R-nREPL (nREPL client for R)
Other Clients
-
clojupyter (Jupyter notebooks for Clojure)
Using the built-in client
nREPL ships with a very simple command-line client that you can use for some basic interactions with the server. The following command will start an nREPL server and connect with it using the built-in client.
$ clj -Sdeps '{:deps {nrepl {:mvn/version "0.9.0"}}}' -m nrepl.cmdline --interactive
nREPL server started on port 59403 on host 127.0.0.1 - nrepl://127.0.0.1:59403
nREPL 0.9.0
Clojure 1.9.0
Java HotSpot(TM) 64-Bit Server VM 10.0.1+10
user=> (+ 1 2)
3
If you want to connect to a server that’s already running you can do it like this:
$ clj -Sdeps '{:deps {nrepl {:mvn/version "0.9.0"}}}' -m nrepl.cmdline --connect --host host --port port
nREPL 0.9.0
Clojure 1.9.0
Java HotSpot(TM) 64-Bit Server VM 10.0.1+10
user=> (+ 1 2)
3
The built in client does not support the tty transport. Use nc
or telnet
instead.
Most users, however, are advised to use REPL-y or their favourite editor instead for optimal results.
Talking to an nREPL endpoint programmatically
If you want to connect to an nREPL server using the default transport, something like this will work:
=> (require '[nrepl.core :as nrepl])
nil
=> (with-open [conn (nrepl/connect :port 59258)]
(-> (nrepl/client conn 1000) ; message receive timeout required
(nrepl/message {:op "eval" :code "(+ 2 3)"})
nrepl/response-values))
If your nREPL server is running on a different machine or listening on a specific
address different than the default one, you can use the :host
keyword in the
connect
function to specify which address to connect to. E.g., to
connect to a nREPL server listening on address 172.18.0.5 and port 4001:
=> (with-open [conn (nrepl/connect :host "172.18.0.5" :port 4001)]
(-> (nrepl/client conn 1000) ; message receive timeout required
(nrepl/message {:op "eval" :code "(+ 2 3)"})
nrepl/response-values))
response-values
will return only the values of evaluated expressions, read
from their (by default) pr
-encoded representations via read
. You can see
the full content of message responses easily:
=> (with-open [conn (nrepl/connect :port 59258)]
(-> (nrepl/client conn 1000)
(nrepl/message {:op "eval" :code "(time (reduce + (range 1e6)))"})
doall ;; `message` and `client-session` all return lazy seqs
pprint))
nil
({:out "\"Elapsed time: 68.032 msecs\"\n",
:session "2ba81681-5093-4262-81c5-edddad573201",
:id "3124d886-7a5d-4c1e-9fc3-2946b1b3cfaa"}
{:ns "user",
:value "499999500000",
:session "2ba81681-5093-4262-81c5-edddad573201",
:id "3124d886-7a5d-4c1e-9fc3-2946b1b3cfaa"}
{:status ["done"],
:session "2ba81681-5093-4262-81c5-edddad573201",
:id "3124d886-7a5d-4c1e-9fc3-2946b1b3cfaa"})
Each message must contain at least an :op
(or "op"
) slot, which specifies
the "type" of the operation to be performed. The operations supported by an
nREPL endpoint are determined by the handlers and middleware stack used when
starting that endpoint; the default middleware stack (described below) supports
a particular set of operations, detailed here.