CIDER 1.22: Sao Miguel

Table of Contents

1. What shipped

CIDER 1.22 "Sao Miguel" (2026-06-16) is a technical-debt release. Batsov calls it "one of the most important CIDER releases in recent memory." Three structural fixes that change daily experience:

  1. Editor responsiveness. Buffer lag when no REPL is connected is gone. Expensive classpath scanning replaced with cheaper alternatives (#3933).
  2. Default sessions. cider-set-default-session bypasses project-based dispatch and pins a specific REPL. Directly useful when running multiple REPLs – a :repl alias for site tools alongside a :test alias for verification.
  3. nREPL decoupling. Transport layer separated from CIDER-specific UI handlers (#3892), closing #1099 (open since 2017). Two spin-offs: Port (prepl client) and Neat (language-agnostic nREPL client).

Other: faster cider-connect completions (#3888), a cider-repl-history-doctor for unbalanced parens, TRAMP improvements for SSH tunneling (#3885–7), and let-go (Go-hosted Clojure) as a valid nREPL runtime (#3926).

Emacs 30.2 org-mode with CIDER 1.22 — Clojure src blocks with inline evaluation results and nyan-mode

2. Version matrix

Component Before After
Emacs 30.1 30.2
CIDER 1.20.0 1.22.2
cider-nrepl 0.58.0 0.59.0
nREPL 1.3.1 1.7.0
Clojure 1.12.0 1.12.0 (unchanged)
Java 21.0.4 21.0.8

The nREPL jump from 1.3 to 1.7 is the largest gap. Running the old middleware against the new client produces a mismatch warning:

WARNING: CIDER 1.22.2 requires cider-nrepl 0.59.0, but you're currently using
cider-nrepl 0.58.0. The version mismatch might break some functionality!

After bumping deps.edn and upgrading the Emacs package, the warning disappears and docstrings resolve cleanly.

3. The harness

Goal: prove 1.22 drives our testing REPL without touching the everyday Emacs config. Two pieces, both in the repo:

  • elisp/cider-1.22.elemacs -Q-loadable. Installs CIDER from MELPA Stable into an isolated package-user-dir (/tmp/cider-1.22-elpa) so it never perturbs ~/.emacs.d/elpa. On cider-connected-hook it sync-evals our workhorse forms via cider-nrepl-sync-request:eval and appends value/err to a log.
  • The testing nREPL: clojure -M:repl:test -m nrepl.cmdline on port 42527 – the :repl + :test aliases together, i.e. the exact dep set the test suite runs under.
# window 0: the testing nREPL
clojure -M:repl:test -m nrepl.cmdline --bind 127.0.0.1 --port 42527 \
  --middleware '["cider.nrepl/cider-middleware"]'
# window 1: a clean Emacs that installs + drives 1.22
emacs -Q -nw -l elisp/cider-1.22.el

4. Version negotiation

The one real finding. Run it twice, and the version line is the whole story:

;; Phase 1 -- deps.edn pinned cider-nrepl 0.58.0 / nrepl 1.3.1
;; CIDER 1.22.2 (Sao Miguel), nREPL 1.3.1
WARNING: CIDER 1.22.2 requires cider-nrepl 0.59.0, but you're currently
using cider-nrepl 0.58.0.

;; Phase 2 -- deps.edn bumped to cider-nrepl 0.59.0 / nrepl 1.7.0
;; CIDER 1.22.2 (Sao Miguel), nREPL 1.7.0
;; (no warning)

The action item: bump deps.edn :repl.

:repl {:extra-deps {nrepl/nrepl           {:mvn/version "1.7.0"}
                    cider/cider-nrepl     {:mvn/version "0.59.0"}}}

After the bump and an nREPL restart, the banner reports nREPL 1.7.0 and the mismatch warning is gone. gmake nrepl and the nexus REPL inherit the bump (both run the :repl alias).

5. Smoke results

Namespace Result
pocket-es.date (date-math window) "2026-06-18" "2026-06-11" "2026-06-18"
wal-sh.tools.transform (rev thread) "FLAG{r3v3rs1bl3}"
wal-sh.files-to-prompt (new port) 8
pocket-es.cli (search doc_count) 699

1.22 commands resolved: cider-set-default-session and cider-repl-history-doctor are both fboundp. Docstrings render for both standard library and project namespaces.

6. Literate verification

Executable blocks evaluated via C-c C-c through the CIDER nREPL connection. Results appear inline as #+RESULTS: – the org document is both the spec and the test harness.

(str "Clojure " (clojure-version) ", Java " (System/getProperty "java.version"))
(require '[pocket-es.cli :as cli])
(let [idx (cli/load-index "site/static/search-index.json")]
  {:doc-count (:doc_count (:_cluster idx))
   :top-hits (mapv :_id (cli/search idx "cider clojure repl" :size 3))})
(require '[pocket-es.date :as d])
(let [t (d/today-iso)]
  {:today t
   :week-ago (d/resolve-bound "now-1w" t)
   :range (str "[" (d/resolve-bound "now-1w" t) " TO " t "]")})
(require '[wal-sh.tools.transform.core :as tx])
(-> (tx/thread "d3d31566a7b63326879575a5a7b623d4c6478465f4c61355"
               (tx/str->steps "reverse hex:d base64:d rot13"))
    last :value)

7. Gotchas

  1. tmux session names eat dots. tmux new-session -s cider-1.22 silently becomes cider-1_22. send-keys -t cider-1.22 then parses as "session cider-1, pane 22" – "can't find pane: 22." Name sessions without dots.
  2. require + expression in one eval prints two value frames. The sync-eval log shows nil8 (the require's nil then the real 8). Split the require into its own eval for a clean single value.
  3. Multiple Emacs installs shadow each other. FreeBSD has builds at ~/opt/emacs-{28,29,30}-amd64-freebsd/bin/emacs. Use explicit paths – which emacs may resolve an older install. On macOS, brew install emacs upgraded 30.1 to 30.2 at /opt/homebrew/opt/emacs/bin/emacs but the PATH shadow stayed at 30.1.

8. What this means for the REPL-driven series

The wal.sh stack uses CIDER as the driver for three workflows:

  • elisp/cider-demo.el – driven REPL confirming pocket-es search, tool cores, and date-math.
  • elisp/cider-annotations.el – driven REPL for annotations and the verification layer.
  • The clj-repl tmux session – long-running nREPL for ad-hoc site queries (log analysis, sitemap cross-referencing, org parsing).

Default sessions solve the multi-REPL dispatch problem: when both drivers have jacked in, cider-set-default-session makes routing explicit instead of relying on project-based heuristics.

The nREPL decoupling means the transport layer evolves independently of the Emacs UI. nREPL server upgrades on the FreeBSD host no longer risk breaking the Emacs client.

Verified on FreeBSD 15.0 (Emacs 30.2, Xvfb headless) and macOS (Apple Silicon, Emacs 30.2 GUI). The harness is platform-neutral: emacs -Q -nw + a CLI nREPL. The only variance is the Emacs binary path.

9. References