# clj-refactor.el: Clojure refactoring commands inside Emacs

> clj-refactor.el is a GPL 3.0 licensed CIDER extension that adds refactoring commands to Emacs, from adding a missing libspec to renaming a symbol across a live project. The judgement is that the package is careful about its own limits, because the README spends as much space on what the AST based commands cannot do as on what they can, and the split between the local commands and the nREPL backed ones is the design decision that matters.

**clojure-emacs/clj-refactor.el** — A CIDER extension that provides powerful commands for refactoring Clojure code.

- Repository: https://github.com/clojure-emacs/clj-refactor.el
- Stars: 785 · Forks: 109
- Language: Emacs Lisp
- License: GPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/clojure-emacs-clj-refactor-el

## A refactoring layer that sits between clojure-mode and CIDER

clj-refactor.el is a CIDER extension, and the README frames it precisely as a complement rather than a replacement. The refactoring that clojure-mode and CIDER already provide is the baseline, and this package adds to it.

Installation goes through package.el, which the README calls highly recommended, and the package is on MELPA and on MELPA Stable:

```
M-x package-install clj-refactor
```

One extra dependency matters here, and it is conditional. If you use IDO, you get better completions if you also install ido-completing-read+, and the README adds that users of other completion frameworks should check that their framework can take over completing-read automatically. That is a small detail with a disproportionate effect on how the package feels in daily use.

The package covers the range of Clojure refactoring work you would otherwise do by hand, from adding a missing libspec and adding a declaration or an import to cleaning a namespace, through the pure text transformations such as cycling a coll, cycling an if, converting a coll, expanding a let, destructuring keys and promoting a private function, to the structural ones such as extracting a function, finding usages and renaming a symbol.

The examples directory in the repository holds animated demonstrations of these commands, one GIF per operation.

## Setup is one hook, one minor mode and one keybinding prefix

The recommended setup is a single function that gets attached to the mode hooks. The snippet in the README is the whole configuration:

```emacs-lisp
(require 'clj-refactor)

(defun my-clojure-mode-hook ()
    (clj-refactor-mode 1)
    (yas-minor-mode 1) ; for adding require/use/import statements
    ;; This choice of keybinding leaves cider-macroexpand-1 unbound
    (cljr-add-keybindings-with-prefix "C-c C-m"))

(add-hook 'clojure-mode-hook #'my-clojure-mode-hook)
```

Three things are happening there. clj-refactor-mode turns the package on for the buffer. yas-minor-mode is enabled because the commands that add a require, a use or an import need a snippet expansion to place the new form. And cljr-add-keybindings-with-prefix binds the whole command set under one prefix, C-c C-m in this case, with the comment noting that this particular prefix leaves cider-macroexpand-1 unbound.

If you use clojure-ts-mode, which the README says is fully supported by CIDER, you attach the same hook to that mode as well or instead:

```emacs-lisp
(add-hook 'clojure-ts-mode-hook #'my-clojure-mode-hook)
```

The prefix choice is the part to think about, because it is the difference between a refactoring command being one keystroke away and being something you look up.

## The middleware decides which commands you actually get

The package has two layers, and the boundary between them is set by a piece of server side middleware.

The local commands are pure Emacs Lisp text transformations and they always work. The advanced ones need the refactor-nrepl middleware, and the README is clear that most users never have to think about it, because from version 2.2.0 onwards the middleware is injected automatically when cider-jack-in is used. The consequence is stated plainly: profiles.clj or profile.boot do not need to be modified for that use case.

The manual case is a standalone REPL or an embedded nREPL server, where the dependency has to be added by hand, either in the project.clj or in the :user profile at ~/.lein/profiles.clj:

```clojure
:plugins [[refactor-nrepl "3.14.0"]
          [cider/cider-nrepl "0.62.1"]]
```

If you do configure middleware yourself, the name to use is refactor-nrepl.middleware/wrap-refactor. The README explains the design difference from cider-nrepl, which defines many middleware with a handful of related operations each, while refactor-nrepl defines a single middleware that houses all of the operations it provides.

That single middleware is where the AST work happens, and it is why the next section is about evaluating code.

## The compatibility table is the upgrade planning tool

The README carries a compatibility table with five columns, and it is the first thing to read before upgrading anything in the Clojure toolchain, because this package sits between three moving parts.

The rows pair a clj-refactor version with a refactor-nrepl version, a CIDER version, a Clojure version and a Java version. The 2.4.0 row pairs with refactor-nrepl 2.4.0, CIDER 0.17 and 0.18, Clojure 1.7 and Java 8. The 2.5.0 row pairs with refactor-nrepl 2.5.0, CIDER 0.24, Clojure 1.8 and Java 8. The 3.0.0 and later row pairs with refactor-nrepl 3.0.0 and later, CIDER 1.0, Clojure 1.9 and Java 11. The current row, 4.0.0 and later, pairs with refactor-nrepl 3.x with 3.13.0 or newer recommended, CIDER 2.0 and later, Clojure 1.10 and later and Java 8.

The Java requirement moving to 11 at the 3.0.0 line and back to 8 at the 4.0.0 line is the kind of detail that breaks a build on an older JDK, and the same table also pins Emacs, since clj-refactor 4.0.0 and later require Emacs 28.1 or newer.

The release history matches the table. Version 4.0.0 was published on 2026-07-16, and the last push to the repository was on 2026-09-15.

## The AST commands evaluate your code, and the package tells you so

This is the section a careful reader should not skip, and the README gives it a heading of its own.

The analyzer that refactor-nrepl uses is tools.analyzer, and it needs to evaluate the code in order to build the AST the refactorings work with. The README spells out the consequence: if evaluating your code causes side effects, writing files, opening connections to servers or modifying databases, then performing certain refactoring functions on your code does that too.

The default behaviour is a warning. It appears when an AST dependent feature is invoked, and the README offers the setting cljr-warn-on-eval to silence it, which in turn allows cljr-eagerly-build-asts-on-startup to take effect and build ASTs for all namespaces when the REPL starts. If that eager behaviour is not what you want, set cljr-eagerly-build-asts-on-startup to nil.

The list of AST dependent features is given explicitly, so you can tell which commands carry the risk: find usages, rename symbol, extract function, inline symbol, rename file or dir, change function signature and promote function.

There is also cljr-ignore-analyzer-errors, which the README says to set to t so that commands skip a namespace that cannot be analysed instead of aborting, with the advice to reserve it for read-only commands like find usages.

## What the AST commands cannot do, and what to use instead

The README devotes a section to expectations, on the grounds that knowing them in advance saves a lot of head-scratching. The list is specific enough to be the deciding factor for some projects.

The commands need a live, connected REPL with your project on the classpath, so they cannot be used before the project starts. They do not work on code that does not compile, whether the problem is a missing dependency, a load-order issue or a namespace you are halfway through editing, and the failure is an unable to build an AST error. They do not support ClojureScript, and in a .cljc file only the :clj branch is analysed. The first invocation can be slow on a large project, since much of it may have to be loaded. And macro-generated code is only approximated, so occurrences that appear only after macroexpansion can be missed.

The README then names the alternative, which is the sentence to pay attention to if any of those limits hit you. If you need static analysis, ClojureScript support, or refactoring without a running REPL, the recommendation is to consider clojure-lsp alongside CIDER.

So the two tools are complementary rather than competing, and the choice depends on whether your project is a running JVM application that you can evaluate safely or a ClojureScript codebase that has to be analysed statically.

## Two-letter shortcuts, a transient menu and an Eldev test suite

Every function in the package has a two-letter mnemonic shortcut, and the example given is rs for cljr-rename-symbol, called after the prefix choice in the setup, so C-c C-m rs.

When a shortcut is not remembered, the answer is a menu rather than a lookup table. M-x clj-refactor-menu opens it, and hh under the prefix does the same. It is a transient menu, so it groups every command by category, it shows the keys as you go, which makes it a way to learn the shortcuts rather than only to find them, and its Options section toggles common settings for the current session.

The development setup is Eldev, and the Makefile is small. make lint runs eldev lint, make compile runs eldev with the byte-compilation warnings treated as errors, and make test runs the test suite under the same harness. The default goal runs all three in order, and a comment at the top of the file shows how to point Eldev at a different Emacs than your default one through the ELDEV_EMACS variable.

The repository also holds feature/ and features/ directories, a doc/ directory, a ROADMAP.md, a markdownlint configuration and a .dir-locals.el, and an extensive changelog is kept in CHANGELOG.md.

## Conclusion

clj-refactor.el fits a Clojure developer already working in Emacs with CIDER and a real REPL, because the commands are wired into the same editing loop as the rest of the toolchain and the AST based ones can rename and extract across a project that is actually running. It is the wrong choice if your project is ClojureScript, since the analysis is limited to the clj branch of cljc files, and it is the wrong choice if you want refactoring without a REPL, because the advanced commands evaluate your namespaces and need a live connection with the project on the classpath. Before you rely on it, check the version row for your Clojure, CIDER and Java combination in the compatibility table, run the commands on a scratch project first, and if the analysis warnings get in the way, set cljr-warn-on-eval to nil only for a project you know is safe to evaluate.

## FAQ

### How do I install clj-refactor.el in Emacs?

Install it through package.el, which the README recommends, with M-x package-install clj-refactor from MELPA or MELPA Stable. Then require clj-refactor, enable clj-refactor-mode in your Clojure mode hook, and bind the commands with cljr-add-keybindings-with-prefix.

### What does refactor-nrepl provide and do I need to install it?

The middleware provides the nREPL operations the advanced refactorings run on. From version 2.2.0 onwards it is injected automatically with cider-jack-in, so profiles.clj needs no change, but a standalone or embedded nREPL server needs the dependency added manually to project.clj or to the :user profile in ~/.lein/profiles.clj.

### Can clj-refactor.el handle ClojureScript?

No. The AST based features do not support ClojureScript and only analyse the :clj branch of .cljc files. The README recommends clojure-lsp alongside CIDER if you need static analysis, ClojureScript support, or refactoring without a running REPL.

### Why does clj-refactor warn me before renaming a symbol?

The analyzer behind the AST based commands has to evaluate your namespaces to build the AST, so evaluating code with side effects means the refactoring has those side effects too. Set cljr-warn-on-eval to nil to silence the warning, and set cljr-eagerly-build-asts-on-startup to nil if you do not want the ASTs built at REPL start.

## Sources

- [clojure-emacs/clj-refactor.el on GitHub](https://github.com/clojure-emacs/clj-refactor.el)
- [Issues](https://github.com/clojure-emacs/clj-refactor.el/issues)
- [License: GPL-3.0](https://github.com/clojure-emacs/clj-refactor.el/blob/master/LICENSE)
- [README](https://github.com/clojure-emacs/clj-refactor.el/blob/master/README.md)
- [Releases](https://github.com/clojure-emacs/clj-refactor.el/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/clojure-emacs-clj-refactor-el
