Depending on what the lifecycle of your application is, whether you want to be
able to easily restart the server, etc., you might want to put the value
start-server returns into an atom or somesuch. Anyway, once your app is
running an nREPL server, you can connect to it from a tool like Leiningen or
Counterclockwise or Reply, or from another Clojure process:

Server options

tty

http

implementing your own transport / handler(s)

Building nREPL

Releases are available from Maven
Central, and SNAPSHOT builds from master's HEAD are automatically deployed to
Sonatype's OSS repository (see this
for how to configure Leiningen or Maven to use OSS-snapshots), so building nREPL
shouldn't ever be necessary. That said:

Clone the repo

Make sure you have maven installed

Run the maven build; run either:

mvn package: This will produce an nREPL jar file in the target
directory, and run all tests against Clojure 1.2.0.

mvn verify: This does the same, but also runs the tests with
other Clojure "profiles" (currently v1.1.0 and v1.1.0 + clojure-contrib).

Need Help?

Ping cemerick on freenode irc or twitter.

Why nREPL?

nREPL has been designed with the aim of ensuring that it satisfies the
requirements of both application developers (in support of activities ranging
from interactive remote debugging and experimentation in development
contexts through to more advanced use cases such as updating deployed
applications) as well as toolmakers (providing a standard way to connect to and
introspect running environments as a way of informing user interfaces of all
kinds, including "standard" interactive, text-based REPLs).

The network protocol used is simple, depending neither
on JVM or Clojure specifics, thereby allowing (encouraging?) the development
of non-Clojure REPL clients. The REPLs operational semantics are such
that essentially any future non-JVM Clojure implementations should be able to
implement it, with allowances for hosts that lack the concurrency primitives to
support e.g. asynchronous evaluation, interrupts, etc.

For more information about the motivation, architecture, use cases, and
discussion related to nREPL, see the see the original design notes, available
here,
and the notes and
discussion
around its recent redesign.

Design

nREPL largely consists of three abstractions: handlers, middleware, and
transports. These are largely analogous to the handlers, middleware, and
adapters of Ring, though there are some
important semantic differences, especially around transports.

Handlers

nREPL is fundamentally message-oriented, where a message is a map of key/value
pairs. Handlers are functions accept a single incoming message as an argument,
and should return a truthy value indicating whether or not the provided message
was processed. An nREPL server is started with a single handler function, which
will be used to process messages for the lifetime of the server.

(This is because the most prevalent operation — evaluation
of Clojure code — is fundamentally asynchronous.)

Messages are guaranteed to contain the following slots:

:transport The transport that should be used to send all
responses precipitated by a given message.

:op The operation to perform; roughly, the type of message

Depending on its :op, a message might be required to contain other slots, and
might optionally contain others. Each request should contain a unique
:id.

Responses are also messages, maps of key/value pairs, the content of which
depend entirely upon the type of message for which the responses are produced.
Every request must provoke at least one and potentially many response messages,
each of which should contain an :id slot echoing that of the provoking
request. Once a handler has completely processed a message, a response
containing a :status of :done must be sent. Some operations necessitate
that additional responses related to the processing of a request are sent after
a :done:status is reported (e.g. delivering content written to *out* by
evaluated code that started a future).

Other statuses are possible, depending upon the semantics of the :op being
handled; in particular, if the message is malformed or incomplete for a
particular :op, then a response with an :error:status should be sent,
potentially with additional information about the nature of the problem.

It is possible for an nREPL server to send messages to a client that
are not a direct response to a request (e.g. streaming content written to
System/out might be started/stopped by requests, but messages containing such
content can't be considered responses to those requests).

If the handler being used by an nREPL server returns a logically false value
(indicating that a message's :op was unrecognized), then the the server will
respond with a message containing a :status of "unknown-op".

Generally, the handler that is provided as the :handler to
clojure.tools.nrepl.server/start-server is built up as a result of composing
multiple pieces of middleware.

Middleware

Middleware are higher-order functions that compose additional functionality
onto or around a handler. For example, some middleware that handles a "time?":op by replying with the local time on the server:

A little silly, perhaps, but you should get the idea. Nearly all of the same
patterns and expectations associated with Ring middleware should be applicable
to nREPL middleware.

It is recommended that (constantly false) always be the base handler; this
ensures that unhandled messages will always yield a logically false return
value. For example, nREPL's default handler is constructed like so in the
clojure.tools.nrepl.server namespace:

This combination — when paired with a suitably-capable client — aims to match
and exceed the functionality offered by the standard Clojure REPL. Please see
the documentation for each of those middleware functions for details as to what
they expect in requests, and what they emit for responses.

On the other hand, a Transport implementation suitable for exposing nREPL over
plain-text sockets (clojure.tools.nrepl.transport/tty) is only usable by the
server. Its only purpose is to enable the use of simpler/less capable tools
(e.g. telnet et al.) to connect to an nREPL backend, so there's little reason
to support client usage in such a scenario. Simiarly, an HTTP Transport
(taking the form of a Ring handler) would expect clients to connect via e.g.
curl, a browser, or a Javascript-powered HTTP console.

Change Log

0.2.0:

Top-to-bottom redesign

0.0.6:

Never released; initial prototype of "rich content" support that (in part)
helped motivate a re-examination of the underlying protocol and design.