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

7 Likes

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.

1 Like

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?

21 posts were split to a new topic: Reliability of AI coding tools

A post was merged into an existing topic: Reliability of AI coding tools

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:

1 Like

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.

3 Likes