Posts

  • CIDER 2.0: Sky is the Limit

    Two weeks ago I wrote that CIDER 2.0 was brewing. Today the brew is ready - CIDER 2.0 (“Terceira”)1 is officially out! I promised the release would follow the preview within a week or two if nothing serious surfaced, and for once in my life I’m actually on schedule.

    The preview post covered the big themes in detail - the transient menus, the call-graph browsers, cider-macrostep, the revamped tracing and enlighten, the ClojureScript improvements - so I won’t rehash all of that here. Instead I’ll focus on what changed between the preview and the release, and on the bigger picture of what CIDER 2.0 is actually about.

    What CIDER 2.0 is about

    Looking back at the (enormous) changelog, the release boils down to four themes:

    • Tackle some ambitious ideas that had been lying dormant for ages - inline macro stepping, rich (content-type) results, source-aware cross-referencing. Some of the issues closed by this release were filed the better part of a decade ago.
    • Polish the “understand your code” toolbox - the debugger, the macroexpansion facilities, tracing, enlighten, the stacktraces and the cross-references all got a serious amount of love.
    • Make the whole CIDER experience more consistent and discoverable - transient menus everywhere, one tree-view widget shared by all the browsers, and a naming cleanup that brought a bunch of stragglers in line.
    • Fix old annoyances - the friendly-session complexity that 1.22 started taming (remember the redisplay lag fix and default sessions?), the find-references gaps, the flaky SSH tunnels, the confused stdin handling.

    Notice what’s not on that list - a pile of shiny new features. There are a few genuinely new things in 2.0, of course, but the heart of this release is that most of CIDER’s important features got overhauled (tastefully, I hope) or made more robust and faster. After 14 years you accumulate a lot of good ideas with rough edges; 2.0 is me going over them with fine-grit sandpaper.

    What landed after the preview

    Quite a lot, as it turns out - the last two weeks were busy. The headliners:

    • Rich results are now on by default. Evaluate something that returns an image and it renders inline; a result that points to external content (a file, a URL) gets a [show content] button that fetches it only when you press it. HTML renders as formatted text, URLs are clickable. This works for regular C-x C-e-style evaluations too, not just in the REPL (configurable via cider-eval-rich-content-destination). Fun fact: content-type support was added way back in 0.17, disabled in 0.25 after it got a bit overzealous with the fetching, and the interactive-eval part was requested in 2018. Better late than never, right?
    • The transient story got finished. The debugger and the inspector now have menus of their own (? and m respectively), and many menus grew argument flags - pick a pretty-printer per invocation, set test selectors once and reuse them across runs, toggle the refresh modes, pass aliases at jack-in. As before, your muscle memory is safe - the menus only help when you pause.
    • There’s a new cider-doctor command that checks your Emacs setup and your active session for common problems (version mismatches, stale byte-code, leftover obsolete config) and produces a copy-pasteable report. My hope is that it will make “CIDER doesn’t work” bug reports a thing of the past - or at least give us something to look at when they arrive.
    • Pending evaluations now show an animated spinner overlay right at the form you’re evaluating, instead of a spinner in the mode-line of a REPL buffer you probably can’t even see.
    • The debugger got dusted off properly: quitting a debug session finally restores point to where you started - an issue filed in 2016 - the force-step-out key works again, and cider-nrepl 0.62 fixed a batch of instrumentation bugs (records surviving instrumentation, clear errors for forms too big to instrument, and a few crashes).
    • Stdin handling got a long overdue overhaul - input prompts are routed to the session that actually asked for input, cancelling a prompt now interrupts the evaluation (instead of quietly letting it continue), and C-c C-d sends EOF for code that reads until end of input.
    • Clicking a stack frame for a top-level anonymous function now jumps to the actual source instead of clojure.core/fn - a bug from 2020 - and ClojureScript frames render their ns/fn properly.
    • A big consistency pass over the options: the REPL history browser is now cider-history, the inline-result options became a coherent cider-eval-result-* family, and the six per-buffer auto-select options collapsed into a single cider-auto-select-buffer. Every old name keeps working as an obsolete alias, so nothing breaks.
    • And a long tail of robustness work - a slow memory leak on the eldoc/completion path, cider-classpath on Windows, formatting no longer corrupting multi-line strings, theme-aware colors for the nREPL message log, and plenty more of the same ilk.

    The documentation also got restructured to be more approachable - there’s a proper quickstart now, a keybindings reference page, dedicated pages on using CIDER alongside clojure-lsp and clojure-ts-mode, and a guide for full-stack Clojure + ClojureScript projects. The manual has grown organically for over a decade, and it showed; hopefully finding things is much easier now.

    Upgrading

    Despite the big scary version number, upgrading should be uneventful. All the renames ship with obsolete aliases, the transient menus preserve the classic keybindings, and the only removals are commands that had been no-ops for years. The one bit of muscle memory you may need to adjust: cider-macroexpand-all moved from C-c M-m to C-c M-m a, as C-c M-m is now a prefix for all the macroexpansion commands. If anything feels off after the upgrade, M-x cider-doctor is your friend.

    Fourteen years later

    CIDER 0.1 (well, nrepl.el 0.1) was released on July 10th, 2012 - fourteen years (and five days) ago.2 I’ve been reflecting on this a lot lately. Fourteen years is an eternity in our line of work - entire ecosystems have come and gone in that time - and yet here we are, still innovating, still improving, still moving forward. I dare say CIDER 2.0 is the strongest release in the project’s history, and it’s certainly the one I’ve enjoyed working on the most.3

    None of this would have been possible without the people and organizations who have supported the project over the years - everyone who contributed code, reported issues, wrote about CIDER, answered questions, or backed the project financially. A special thanks to Clojurists Together for their long-standing support, and to everyone who took the snapshot for a spin after the preview post and shared feedback - several rough edges got filed down because of you.

    So, go play with CIDER 2.0! Kick the tires, explore the menus, crack open some values in the inspector, step through a macro or two. And if CIDER makes your work a little nicer every day, consider supporting its future development

    • that’s what keeps CIDER and friends going.

    Where to from here? The sky is the limit. The REPL is the inspiration. The best is always yet to come…

    Keep hacking!

    1. Continuing the Azores naming streak started by 1.22 (“São Miguel”). “Terceira” literally means “the third” in Portuguese, which is a slightly confusing name for a 2.0 release, but naming things has never been my strong suit. 

    2. The full origin story is in CIDER Turns 10, if you’re curious how a prototype hacked on a flight to San Francisco ended up here. 

    3. That I can remember. My memory is not what it used to be. 

  • Lowering the Drawbridge

    Drawbridge 0.4 is out! If your reaction is “Draw-what now?”, I can’t really blame you - Drawbridge is easily the most obscure project in the nREPL stable, and it has spent most of its life in a state best described as “technically maintained”. I’ve set out to change that recently, and this post is both a release announcement and the story of a 14-year-old project that never quite lived up to its potential. Hopefully, until now.

    Read More
  • Clojurists Together Update: May and June 2026

    Some of you might know that Clojurists Together are supporting my work on nREPL, CIDER and friends this year. Normally I send them a bi-monthly progress report, but I saw some other people who got funding for their OSS work publish those reports as blog posts for the broader public and I thought to try this for a change.

    The past two months were super productive. I had a lot of inspiration during this period and I managed to tackle a lot of long-standing ideas and issues across the entire nREPL/CIDER ecosystem. Funnily enough, I also managed to grow the ecosystem with a couple of brand new projects, but more about those later.

    The big highlights from my perspective:

    • CIDER 1.22 is out
    • CIDER 2.0 is essentially ready and needs more user testing
    • Sayid is reborn
    • Two brand new projects saw the light of day: port and neat
    • Piggieback 0.7.0 is out (and Weasel got modernized while I was in the area)
    • clj-refactor and refactor-nrepl got some love as well

    Below you’ll find more details about the work I did, project by project.

    CIDER

    CIDER 1.22 (“São Miguel”) landed in mid-June, wrapping up the 1.x series. Its main features:

    • a registry for jack-in tools, so third parties can plug new build tools and Clojure dialects into cider-jack-in
    • a “default session” escape hatch from sesman’s project-based dispatch
    • keyword-argument versions of the low-level request APIs, alongside a proper decoupling of the nREPL client layer from CIDER’s UI

    It also fixed a long list of small annoyances: severe editor lag in unlinked buffers, several TRAMP and SSH tunnel problems, request id leaks, and a bunch of broken menu entries.

    Right after that I switched the development version to 2.0 and most of the planned work is already done. The headline items so far:

    That last one deserves a special mention: evaluation results that are images now render inline out of the box, and file/URL results offer their content on demand, six years after the feature had to be disabled over its safety problems. There was also a big cleanup pass: consolidated configuration options, the REPL history browser renamed to cider-history to end a long-standing naming clash, theme-aware faces instead of hardcoded colors, refreshed docs and a regenerated refcard. CIDER 2.0 is available from MELPA snapshots and I’d love for more people to take it for a spin before the final release.

    cider-nrepl

    Lots of cider-nrepl releases, driving the CIDER work above:

    • cider-nrepl 0.60.0 added the ops backing the new protocol exploration commands (cider/who-implements, cider/type-protocols, cider/protocols-with-method).
    • cider-nrepl 0.61.0 brought ClojureScript test support, a ClojureScript macroexpansion fix, formatting that honors the project’s cljfmt configuration, and a pprint backed by orchard.pp.
    • cider-nrepl 0.62.0-alpha1 and 0.62.0-alpha2 hardened the content-type and slurp middleware (URL scheme allowlist, size caps, graceful fetch errors) and cleaned up the response protocol, which is what made it safe to turn rich content on by default in CIDER 2.0.

    Along the way the project’s build was migrated from Leiningen to tools.deps, which required a new MrAnderson release (see the blog posts below).

    Orchard

    Orchard, the library that powers much of cider-nrepl’s functionality, kept pace:

    • Orchard 0.42.0 and Orchard 0.43.0 continued the inspector polish, added symbol classification to orchard.meta, a programmatic listener API for the tracer, and protocol/multimethod introspection in orchard.xref. The project also moved to tools.deps and its CI now covers JDK 26.

    Sayid

    Sayid, the omniscient Clojure debugger, had been dormant for years and I finally gave it the revival it deserved:

    • Sayid 0.2.0 was the big modernization pass: new mx.cider/sayid coordinates, a documented nREPL middleware API, a consolidated op surface (37 ops down to 26) and fixes for the most annoying Emacs client breakages.
    • Sayid 0.3.0 followed with usability work: no more frozen Emacs during the reload workflow, simpler query commands and help buffers generated from the keymaps.

    port

    port is a brand new project I started in May: a minimalist Clojure interactive programming environment for Emacs, built on prepl instead of nREPL. It went from nothing to three releases in the course of the month:

    • port 0.1.0
    • port 0.2.0
    • port 0.3.0, which added eldoc with active argument highlighting, a wire-level message log for debugging and a roughly 10x speedup in handling large prepl responses.

    I don’t have any particular plans for the future of this project - it was just something that I wanted to experiment with for a while. I see it as an interesting option for people looking for some middle ground between inf-clojure and CIDER.

    neat

    neat is the other new arrival: a small, language-agnostic nREPL client for Emacs. neat 0.1.0 has the essentials in place: a pure-elisp bencode codec, a comint-based REPL, and a source-buffer minor mode with eval, completion, eldoc, xref and doc lookup, tested against Clojure, Babashka and Basilisp. It’s early days, but it’s a nice testbed for exercising the nREPL protocol outside CIDER.

    This project also means I’ve dropped any plans to try to make CIDER a language-agnostic development environment. Going forward CIDER will focus only on Clojure-like languages, and everything else will be covered by neat.

    Piggieback and Weasel

    The nREPL org saw some ClojureScript-flavored action:

    • Piggieback 0.6.2 and Piggieback 0.7.0. The 0.7.0 release makes load-file evaluate the editor’s buffer contents instead of re-reading from disk, tears down ClojureScript REPLs when their sessions close (no more leaked Node processes) and surfaces ClojureScript status in the describe response.
    • Weasel 0.8.0 modernized the WebSocket REPL: the client now uses the platform’s native WebSocket, so it runs in any modern JavaScript runtime (browsers, Node 22+, Deno, Bun, workers), and the minimum requirements moved to Clojure/ClojureScript 1.12.

    I also backfilled proper GitHub releases for the historic tags of both projects, so their release history is finally browsable.

    Improving the ClojureScript support in CIDER has long been a major objective for me, and these small changes were some initial steps in that direction.

    refactor-nrepl and clj-refactor

    refactor-nrepl got three releases: 3.12.0, 3.13.0 and 3.14.0, the last one making the AST-based indexing much faster and more reliable. clj-refactor.el received a round of maintenance on master as well, and will get a new release after I wrap up the work on CIDER 2.0.

    I’m still pondering the future of both projects, as I plan to move the most useful refactor-nrepl features (those that don’t carry a lot of complexity) to CIDER and cider-nrepl eventually, and I’m not sure that the flagship AST-powered refactorings are very competitive these days (compared to clojure-lsp and static project-wide analysis a la clj-kondo in general).

    I’ll write a bit more about this and I’d certainly appreciate more feedback from the users of clj-refactor on the subject. It’s funny that I’ve been maintaining the project for ages, but I’ve never really used it (mostly due to its brittleness in the past). I think I managed to address some of the biggest problems recently, but perhaps this happened too late and the project has lost its relevance by now.

    Blog posts

    I wrote a few articles related to the work above:

    Wrapping up

    Big thanks to Clojurists Together, Nubank and the other organizations and people supporting my Clojure OSS work! I love you and none of this would have happened without you. Sadly, the amount of financial support my projects receive has eroded massively over the past 4 years and I’ve kind of lost hope that this negative trend will eventually be reversed. It was never easy to maintain many popular OSS projects, but the job certainly hasn’t got any easier or more rewarding in recent years…

    Overall, a super productive two months. Hopefully the next two are going to be just as productive, although I have to admit I’ve plucked most of the low-hanging fruit already. Then again, I’ve said this many times in the past, so one never knows…

  • Projectile 3.1

    Hot on the heels of Projectile 3.0 comes Projectile 3.1!

    Three days apart, yes. There’s a story there. A big chunk of what’s in 3.1 was originally meant for 3.0, but 3.0 was already turning into a monster of a release and I decided to cut it into two, so I’d actually be able to reason about each of them. So think of 3.1 less as “the next release” and more as “the second half of 3.0 that I was too scared to ship all at once”.

    Read More
  • Projectile 3.0

    Projectile 3.0 is finally out, and it’s a big one - easily the biggest release in years. There’s a nice reason for that: this year Projectile turns 15.1 It all started back in the summer of 2011, simply because I was frustrated that find-file-in-project didn’t work on Windows, and somehow that little anniversary made me want to shake things up and finally tackle a whole pile of changes I’d been putting off for ages. Some new features, some long-overdue spring cleaning, and a few things I’d wanted to remove for the better part of a decade.

    1. Give or take - I started Emacs Prelude the same year, so it’s always been a 

    Read More

Subscribe via RSS | View Older Posts