The Clojure runtime now has the ability to start a socket server at initialization based on system properties. One expected use for this is serving a socket-based REPL, but it also has many other potential uses for dynamically adding server capability to existing programs without code changes.

A socket server will be started for each JVM system property like "clojure.server.<server-name>". The value for this property is an edn map representing the configuration of the socket server with the following properties:

server-daemon - defaults to true, socket server thread doesn’t block exit

address - host or address, defaults to loopback

port - positive integer, required

accept - namespaced symbol of function to invoke on socket accept, required

args - sequential collection of args to pass to accept

bind-err - defaults to true, binds *err* to socket out stream

client-daemon - defaults to true, socket client thread doesn’t block exit

Additionally, there is a repl function provided that is slightly customized for use with the socket server in clojure.core.server/repl.

Following is an example of starting a socket server with a repl listener. This can be added to any existing Clojure program to allow it to accept external REPL clients via a local connection to port 5555.

-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"

An example client you can use to connect to this socket repl is telnet:

$ telnet 127.0.0.1 5555 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. user=> (println "hello") hello

You can instruct the server to close the client socket repl session by using the special command :repl/quit :

user=> :repl/quit Connection closed by foreign host.