Integrating cider-nrepl into Your Tool
This section is aimed at people building editor plugins and other nREPL
clients on top of cider-nrepl. It complements the generated
ops reference (which documents the request/response
keys of every op) with the things that aren’t visible there - conventions,
cross-cutting behaviors and the multi-message protocols of the more complex
middleware:
Op Naming
Historically all cider-nrepl ops had plain names like complete or
test-var-query. Those names live in a flat namespace shared with nREPL
itself and every other middleware, so newer ops are namespaced with a
cider/ prefix (cider/complete, cider/test-var-query), and the old
names are kept as deprecated aliases.
New client code should always use the cider/-prefixed names. The
deprecated aliases won’t be removed lightly (see
Compatibility), but they no longer appear in new
functionality - some recent ops (e.g. cider/tap-subscribe,
cider/get-state) have no unprefixed alias at all.
Discovering Capabilities
Don’t assume a particular cider-nrepl version - probe for it:
-
nREPL’s built-in
describeop returns the full op list; check for the ops you need. With:verbose? "true"it also returns each op’s documented request/response keys (that’s what the ops reference is generated from). -
The
cider-versionop returns cider-nrepl’s own version map.
Because cider-nrepl’s middleware is loaded lazily (see Understanding the Internals), the first use of an op may take noticeably longer than subsequent ones - budget your timeouts accordingly.
ClojureScript Sessions
Many ops are ClojureScript-aware and transparently operate on the cljs
compiler environment when the session is a ClojureScript REPL (via
Piggieback or shadow-cljs). Ops that only make sense on the JVM reply with a
clojure-only status in a ClojureScript session, so your client can show a
meaningful message instead of confusing JVM results. Handle that status
generically and you’re covered for all of them.
Bypassing the Middleware
Any message carrying a truthy inhibit-cider-middleware key skips all of
cider-nrepl’s middleware and is handled as if only stock nREPL were present.
This is occasionally useful for tooling-internal evals that shouldn’t
trigger side effects like state tracking or debugger instrumentation.
Printing
cider-nrepl requires nREPL 1.0+ and builds on nREPL’s print middleware.
Ops that return printed values (eval and friends, but also e.g. the
debugger and the test ops) accept the standard
nrepl.middleware.print/* options (print, quota, stream?, …);
see the nREPL documentation
for details.
Errors
cider-nrepl wraps its handlers in a "safe transport": if an op’s handler
throws, the client receives a response with an error status (typically
<op-name>-error) and exception details instead of silence. Your client
should still apply timeouts, but it doesn’t need to guard against requests
that never complete simply because a handler blew up.