The problem with (System/exit 0) is that it kills the whole JVM. The real question is how to programmatically exit just the current repl, and return to whatever function launched that repl.
Here is a convenient hack:
(clojure.main/repl
; Exit the repl whenever the user enters "exit" at the prompt.
:read (fn [request-prompt request-exit]
(let [form (clojure.main/repl-read request-prompt request-exit)]
(if (= 'exit form) request-exit form))))
clojure.main/repl repeatedly calls a a reader, by default repl-read, to get one form at a time. One of the arguments to the reader is a special sentinel object that the reader is supposed to return when there are no more forms to be read. The default reader, repl-read, returns the sentinel value only on EOF. At the repl-read prompt, you do not have access to the sentinel object, so you cannot return it to tell the evaluator that you have finished entering forms. By installing your own reader, you can check for a particular form -- e.g., the symbol exit -- and return the sentinel object whenever this form is read, thus indicating to the evaluator that you are ready to exit the repl, without actually killing the entire VM.