Swirl.jl - Interactive Julia Learning in the REPL 🌀

Swirl.jl now supports multi-step code questions and full Markdown rendering! :cyclone:

Swirl.jl has just been updated with two major improvements:

:sparkles: Multi-step questions: you can now design exercises that require multiple code lines, with separate hints for each step. Perfect for walking learners through multi-part problems or short coding tasks.

:memo: Markdown rendering everywhere: lessons, questions, hints, and menus are now displayed with Markdown formatting, making everything cleaner and easier to read directly in the REPL.

The built-in Julia Basics course has been adapted to use these new features.
You can check it out in action here

Thanks for the great suggestion!
You can check out my latest post. I hope you’ll like the result.

There wasn’t really a strong reason those fields had to be String; I had chosen that early on because the classic runner simply used println everywhere. Now, Swirl.jl fully supports Markdown.MD in REPL mode, so lessons, questions and hints are all nicely rendered.

I love this idea! Running Swirl in a ttyd container is brilliant. The REPL likely exits because ttyd isn’t fully interactive yet, I guess(?) Could you try swirl(use_repl_mode=:classic) for now and see how it goes?

Hey @Alex_Tantos,

I was thinking some more about Swirl.jl today and was curious: are you thinking about attending JuliaCon 2026 in Meinz? I am wondering if having some in-person hacking sessions could be fun.

Moreover, and perhaps a bit selfishly, over in JuliaHealth world we are beginning to start thinking about the JuliaHealth 2026 Mini-Symposium – I am thinking there may be some neat applications where Swirl.jl could be used for teaching/highlighting package use cases and crucially: workflows! :thinking:

At any rate, hope all is well and thanks for the work here!

~ tcp :deciduous_tree:

Thanks so much for the message, really appreciated @TheCedarPrince .

Regarding JuliaCon 2026 in Mainz: it will mostly depend on whether I manage to put together our own minisymposium and secure the logistics around that. I’ll need to think about it a bit more, but if I do attend, then absolutely. Sitting down for some in-person hacking sessions would be a lot of fun.

About the JuliaHealth minisymposium: happy to hear that Swirl.jl came to mind in that context. About the “workflows” part: if I understand correctly, you’re referring to using Swirl to guide users through complete usage paths of JuliaHealth packages, not just individual functions, but the full sequence of steps that make up a typical workflow. If that is the case, that actually aligns very well with what I’m doing on the language-data side too: many linguistic and corpus-analysis tasks also follow multi-step pipelines (loading data, preprocessing, applying models or statistical functions, visualizing, interpreting)
If there’s interest in having a presentation or demo on how Swirl can support workflow-oriented teaching for JuliaHealth packages, I’d definitely be open to discussing it. It could actually fit quite naturally with the kind of step-by-step REPL-based interaction Swirl encourages.

Let me know what ideas you have in mind. I’d love to explore them. Feel free to DM me anytime if that’s easier.

After some back-and-forth and much cleaner code with less Claude Sonnet intervention this time, we’ve now merged a PR where questions transition from symbol-based to type-based dispatch.

Previously, questions were created using symbol-based dispatch:

Question("What is 2+2?", :code, 4, "Add the numbers")
Question("Welcome!", :message, nothing)
Question("Pick one:", :multiple_choice, 2, "hint", ["A", "B", "C"])

Now, we use explicit typed constructors:

CodeQ(text="What is 2+2?", answer=4, hint="Add the numbers")
MessageQ(text="Welcome!")
ChoiceQ(text="Pick one:", choices=["A", "B", "C"], answer=2, hint="hint")

New Question Types

The refactoring also introduces new question types:

  • CodeQ - Single-step code questions (replaces :code)
  • MultistepCodeQ - Multi-step code questions with step-by-step guidance
  • MessageQ - Display-only messages (replaces :message)
  • ChoiceQ - Single-choice questions (replaces :multiple_choice)
  • MultipleChoiceQ - Multiple-selection questions
  • StringQ - String matching with regex support
  • NumericQ - Numeric answers with range checking

Example: Multi-Step Code Questions

MultistepCodeQ(
                text=md"**Good**! Bindings let you reuse values. Now create a binding `y` with the value `5`, then add `x` and `y` together.",
                answer=15,
                hint="",
                steps=[
                    md"Create a binding `y` with value `5`.",
                    md"Add `x` and `y` together."
                ],
                step_hints=[
                    md"Type: `y = 5`
Bindings let you refer to values for later use.",
                    md"Type: `x + y`
Remember: `x` is still `10` from the previous question!"
                ],
                setup="x = 10"
            )

Also, a few new features and changes were adopted that improve the experience such as the <- in progress and the <- just completed indicators.

UPDATE: The README.md has just been updated.
UPDATE2: Here is a short new yt demo of the current state of the UI.