Swirl.jl - Interactive Julia Learning in the REPL 🌀

[ANN] Swirl.jl - Interactive Julia Learning in the REPL :cyclone:

Hi everyone! :waving_hand:

I’m really happy to introduce Swirl.jl, an interactive platform that teaches Julia programming right inside the REPL. It’s inspired by the excellent swirl package for R, which has helped thousands of people get started with R programming.

Why Swirl.jl?

When I was learning R, swirl made the experience engaging and accessible; you could learn by doing, right in your console, with immediate feedback. I wanted to bring that same experience to Julia.

swirl for R has been a tremendous success in lowering the barrier to entry for R learners and I hope Swirl.jl can play a similar role in helping more people adopt Julia.

What is Swirl.jl?

Swirl.jl is an interactive tutorial system that runs entirely in the REPL and there are no external tools needed. You type Julia code, get instant feedback, and learn by doing.

After trying it out, feel free to give it a :star: on GitHub!

Quick Demo

julia> using Swirl

julia> swirl()

============================================================
| Welcome to Swirl for Julia! 🌀
============================================================

Available courses:
  1. Julia Basics

Select a course: 1

Lessons in Julia Basics:
  1. [ ] Basic Math and Variables
  2. [ ] Types and Functions  
  3. [ ] Vectors and Arrays

Select a lesson: 1

--- Question 1 of 7 ---

Let's begin! Julia can be used as a calculator. Try adding 5 + 3.

julia> 5 + 3
8
✓ Correct!

--- Question 2 of 7 ---

Now try multiplication. What is 7 * 6?

julia> hint
💡 Hint: In Julia, multiplication uses the asterisk symbol: *
Type: 7 * 6

julia> 7 * 6
42
✓ Correct!

How It Works

Everything happens in the REPL:

  1. Real Code Execution: Your code runs in the actual Main module, so variables persist between questions and you can use any Julia features or packages
  2. Intelligent Evaluation: The system evaluates your expressions and checks if they produce the expected result, not just exact string matching
  3. Natural Interaction: You can explore and experiment - multi-step questions work naturally. For example, you can enter multiple commands on a single line by separating them with ; (e.g., define a variable and then use it in the same line).
  4. Smart Hints: When you type hint, you get detailed -and hopefully educational- explanations, not just “type this.”
  5. Auto-Save Progress: Your progress is automatically saved after each question, so you can stop and resume anytime even after ending the current REPL session.

Technical Details

Under the hood:

  • Questions are evaluated using Core.eval(Main, ...) so your code runs in the same environment as your REPL
  • The parser handles multi-statement code (semicolon-separated) and checks only the final result
  • Progress is serialized to ~/.swirl_julia/progress/ for persistence
  • The system supports different question types: messages, code evaluation, and multiple choice

Features

:sparkles: Interactive Learning - Type real Julia code, get immediate feedback
:books: Structured Lessons - Work through well-designed courses
:floppy_disk: Auto-Save Progress - Never lose your place
:light_bulb: Smart Hints - Detailed help when you’re stuck
:bullseye: Multiple Question Types - Mix of explanations, code, and quizzes
:package: Custom Courses - Install courses from GitHub, URLs, or local directories
:counterclockwise_arrows_button: Flexible Navigation - Easy menus with back/exit commands
:video_game: Progress Management - Reset and retake lessons anytime

Current Status

The package includes a Julia Basics course covering:

  • Basic Math and Variables
  • Types and Functions
  • Vectors and Arrays

:rocket: Call for Contributors!

This is where I need your help!

The current course is quite minimal, just 3 lessons with a handful of questions each to demonstrate the system. The current built-in course is quite basic, just enough to showcase what the system can do. It would be exciting to see the Julia community help expand it into something comprehensive for Julia beginners. Even adding a few more questions to existing lessons or creating new lessons on basic topics would be incredibly valuable!

Each lesson (should) include(s) carefully crafted questions with detailed, educational hints.

Immediate needs:

  • More questions for the existing Julia Basics lessons
  • New lessons on basic Julia topics (e.g., loops, conditionals, strings, dictionaries, etc.)
  • Better coverage of fundamental concepts (e.g., types and type composition)
  • More diverse examples and exercises

Longer-term vision:
Besides adding new lessons to the Julia Basics course, Swirl.jl can also host new, independent courses. Imagine having new courses on:

  • Julia for Python/R/MATLAB users
  • DataFrames.jl and data wrangling
  • Plotting (Plots.jl, Makie.jl)
  • Statistics and machine learning
  • Package development

How to Contribute

The system is designed to make course creation straightforward. A course is just a Julia file that organizes lessons, each made up of individual questions:

Course(
    "Course Name",
    "Description",
    [
        Lesson("Lesson 1", "Learn X", [
            Question("Try 1+1", :code, 2, "Type: 1+1"),
            # ... more questions
        ])
    ]
)

I’ve included templates for creating courses and lessons in the repository to help you get started. You can:

  • Create entirely new courses
  • Expand the existing Julia Basics course
  • Improve hints and questions
  • Add advanced topics

Installation

using Pkg
Pkg.add(url="https://github.com/atantos/Swirl.jl")

Then just:

using Swirl
swirl()

Learn More

:open_book: GitHub Repository: github.com/atantos/Swirl.jl
:page_facing_up: README: Full documentation and examples

Why This Matters

Learning programming should be interactive and engaging. Just as swirl helped make R more accessible, I hope Swirl.jl can help more people discover and learn Julia.

The REPL is Julia’s superpower. It’s fast, interactive and it’s where we do our work. Why not make it a powerful learning environment too?

A personal motivation: I’m particularly interested in helping people from the Humanities learn Julia. Interactive tools like Swirl.jl can help them build confidence with the language and then, hopefully, discover powerful packages for their work such as the recently created TextAssociations.jl package for calculating n-gram associations in texts/corpora, which will be submitted to the Julia registry soon. Making Julia accessible is essential for expanding its adoption in the Humanities and the Social Sciences, especially among people with non-traditional programming backgrounds.

A note on development: Swirl.jl was developed with significant assistance from Claude 4.5, which made the development process incredibly productive.


TL;DR: Interactive Julia tutorials in your REPL, inspired by R’s swirl. Currently includes one short course (Julia Basics) and welcomes community contributions to expand content and help more people learn Julia!

41 Likes

Amazing! :heart_hands:

2 Likes

Out of curiosity, was AI involved in the creation of this package/port?

Yes, that’s right. I touched on it near the end of the post.

Amazing… you developed it in the 2 days from my ping on your old topic ??

I wonder (not actually sure) if it would be better to check if the answer is the expected expression rather than generating the expected result.

2 Likes

The idea and the structure were already there and the types too, from when I first posted about it back in 2023. I just never had the time to actually sit down and work on it. But when you pinged me, I thought, this really should be completed at some point… well, now or never! :slightly_smiling_face: I should also mention that Claude really helped speed things up over the past two days.

As for your concern, I think it’s actually addressed by the REPL-based flow suggested in issue #4 just a couple of hours ago raised by @BeastyBlacksmith.

With that approach, we’d be checking the state of Main when the user submits their code, rather than having Swirl evaluate it directly. For example, according to @BeastyBlacksmith we could use validators like:

function(mod::Module = Main)
    isdefined(mod, :x) && mod.x == 10
end

For cases where we do want to enforce a specific approach (e.g., “use the range operator”), we can make that explicit both in the question text and in the validator logic.

It’s not implemented yet, but I think the idea has real potential. I’d suggest joining the discussion in the issue below. Does this address your concern?

2 Likes

First, I want to emphasize how fantastic of an effort this is. I downloaded the package, tried it out, and it works fantastically:

This is exactly something I was so excited about year’s ago being: GitHub - caseykneale/JuliaTutor.jl: Learn Julia from the REPL. The author, Casey Kneale, used to be quite prolific in the Julia ecosystem but I haven’t seen him around in nearly 4/5 years (oye, I am getting old). There may be some ideas there you could adapt to your work in Swirl.jl?

That said, bridging social sciences/humanities into Julia is such a fantastic endeavor. As someone who works in the biostats, public health, and census data worlds, R is the de facto tool of choice. I’ve been quietly exploring options on how to bridge worlds, but this seems like such a wonderful idea, Alex.

I hope you do not mind, but I would like to share some general thoughts as I found this extremely exciting and would like to share this excitement with some other folks.

Some Feedback

Interface UI/UX

I love the TUI design so far. It does the things learning tools like this should do – it’s fun, quick, easy, and gets you doing the things you will be doing. Not artificial pseudocode but the literal methods you would use when starting out or working through tutorials. That said, I have some feedback:

  • Could we use the Julia REPL per use the actual julia REPL · Issue #4 · atantos/Swirl.jl · GitHub ? This keeps syntax coloring and could be used to display more visual information to the learner.
  • Could you clear the terminal between each question?
  • Per the work of @FedeClaudi in Term.jl, you may be able to deliver even more panache to the learner and help guide them along.
  • Could you update the REPL display to label questions/sections? Something like:
╭ Section 1: Basic Math and Variables 
├ Question 1/8: Adding Two Numbers
│ 	
╰ julia>

Or like:

╭ Question 1/8: Adding Two Numbers
╰ julia>

For the UX design:

  • Could you somehow remind the user the available Swirl.jl specific commands that are available to them? Like the ‘hint’ or other commands?
  • Maybe for fun, an optional success noise? Like via Beep.jl?

Design Thoughts

On the design, I like the caching methods and where that is going. Some additional suggestions:

  • Did you consider using BaseDirs.jl by @tecosaur ? I think this would be a helpful and useful way to systematically path information from Swirl.jl to achieve maximum best practices.
  • If a learner does not answer a question correctly, could the Question object have a hint field that a course creator could write custom hints for?

Wish List Ideas

These are just some wish list thoughts looking through this all:

  • I would like an easy way to create Swirl.jl lessons to walk future contributors or users of my tools in JuliaHealth. How can I make a custom lesson that does not live in Swirl.jl but in another package that I could save the lesson in? Extensions could help perhaps – maybe a standard interface of swirl() and then a dispatch that allows one to say something like swirl(lessons = :juliahealth) or something like that?
  • It would be nice to have set-up and tear-down such that if someone wants to create directories, files, or what have you, these could be temporary directories that could be deleted when the lesson is over. Especially with data-driven tutorials vis a vis DataDeps.jl or DrWatson.jl.
  • Lesson on interacting with errors via InteractiveErrors.jl by @mike ?

Note on AI

This is exactly how I dreamed LLMs could be used. This is such a great use case of GenAI and I deeply appreciate the disclosure of its use. I wanted to mention that as I think you did that really great here.


As I mentioned, my enthusiasm for this work here is quite high! I hope you’ll forgive this lengthy message without much action on my side, but I deeply resonate with this effort. While I am time-constrained, I am more than glad to follow-up and share thoughts here. Keep up the excellent, excellent work.

~ tcp :deciduous_tree:

P.S. Some other packages that may be helpful:

  • TerminalPager.jl – native Julia pager (maybe for questions that are long and include a lot of info?)
  • JLFzf.jl – fuzzy finder via fzf
1 Like

I’m pretty confident something like this could be done, from my work around the REPL.

Yes, \e[H\e[2J for starters. There’s more that could be done with ANSI sequences too.

This can be done, but getting it to work well would be a little tricky: depending on how much repetition is tollerable.

This would be very difficult, however status information around the REPL prompt would be viable.

It would be great to add reminders like “hint” after X (configurable per-lesson) many REPL interactions without progressing the problem.

:heart:


This reminds me of some work I started a while back on an interactive version of the Emacs tutorial for Doom. Sample:

I made a format so that Doom modules could define their own tutorials. I imagine Swirl.jl could do something similar with packages/package extensions.

2 Likes

This is very cool. I remember starting to learn R with zero understanding of programming or computers through Swirl and a Coursera course (both from Johns Hopkins Biostatistics).

1 Like

Thank you so much for the kind words and for taking the time to try out Swirl.jl! I’m really glad to hear it’s working well for you. I really appreciate you pointing me to JuliaTutor.jl. I wasn’t aware of that project! I will definitely take a look and explore what concepts might translate well to Swirl.jl. It’s a bit bittersweet to hear about projects and contributors who’ve moved on from the ecosystem. Hopefully Swirl.jl can carry forward some of that interactive learning spirit and maybe even bring a few of those ideas back into active use.

It really means a lot to hear this perspective from someone working directly in those fields. As someone coming from a different background, I sometimes wonder if efforts like this will actually resonate with the communities that could benefit most from Julia’s capabilities. Hearing from someone actively working in biostats, public health, and census data that this approach feels valuable is incredibly encouraging and helps validate that this bridge-building work is worth pursuing.

Not at all. I’m really glad it sparked that kind of excitement; that’s exactly what I was hoping for.

This is fantastic feedback. Thank you! I will compile a list of potential features out of these bullet points that you pointed throughout your useful post and I’ll open GitHub issues to track each suggestion/design thought/idea so anyone can follow along, discuss about them and contribute to their implementation.

Just touching on this point for now. I’m about to add REPL support shortly and will revisit this soon.

I’m really glad that came through, and it’s great to know it aligns with how you envisioned LLMs being used. I completely share that mindset.

I completely understand, I’m quite time-constrained myself too! Hopefully, little by little, as more of us find bits of time to contribute or share thoughts, the project can evolve and help more new people get started with Julia.

1 Like

Really helpful and targeted feedback. Thanks!

I will definitely look at your package!

Impressive!

We could really use your help on that! A setup like what you did for Doom modules is definitely worth considering for package-specific tutorials.

1 Like

I’ve always thought Swirl was a brilliant idea for R users. I actually shared a similar entry experience to R myself.