That seems like a tall order, though a worthwhile one.
You of course need a way to create a repl with visibility into the dynamic context from which it's created, which implies representing dynamic context in a way that's convenient for inspection.
If you want dynamic editing and recovery features similar to those of CL and Smalltalk systems, you'll also need the dynamic context to be represented in a way that permits mutation, which is a little awkward, considering Clojure's understandable preference for immutability and thread safety.
If you want to be able to restart from a user-selected stack frame, then you need something that serves the same purpose as Common Lisp's conditions and restarts, or Smalltalk's activation records. Maybe you could borrow the design of the Common Lisp condition system.
If you want to be able to handle dynamic redefinition gracefully, then you need something like Common Lisp's and Smalltalk's ability to automatically find and update live instances of a redefined type, which in turn requires system-level features for tracking changes to the type definitions of arbitrary instances, and a facility for automatically reinitializing them on-demand (which in turn requires the very breakloop features that you're building, because sometimes reinitialization requires user input).
This set of features is kind of a ball of hair that is hard to get right by bolting it on after the language is designed. The Julia folks have been struggling with it for years now. They work well in Common Lisp and Smalltalk, but I think that's because the languages were designed around these kinds of features from the start. Language support for them in Common Lisp, for instance, is written into the ANSI standard.
Also, of course, if the system can reinitialize live instances, then they can't really be immutable or thread safe--at least not from the point of view of the development environment, because it has to be able to mutate them as-needed. Maybe they can still be immutable from Clojure's point of view, but that implies that the development environment is not bound by the same rules as the language that it implements.
That's doable, of course. No law of nature requires that the development environment obey the same rules as the language that it implements. For example, Leibniz, the development environment for the Newton version of Dylan, was written in Common Lisp.
Of course, that meant that those of use who wanted to modify and extend Leibniz had to know Common Lisp as well as Dylan. But that's not so different from the situation with Clojure and Java.