# Swirl.jl - Interactive Julia Learning in the REPL 🌀

**URL:** <https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705>\
**Category:** Package Announcements\
**Tags:** announcement, repl, tutorials, teaching\
**Created:** [November 6, 2025, 10:25am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705 "2025-11-06T10:25:15Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [November 6, 2025, 10:25am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/1 "2025-11-06T10:25:15Z")

</div>

# [ANN] Swirl.jl - Interactive Julia Learning in the REPL 🌀

Hi everyone! 👋

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](https://swirlstats.com/), 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 ⭐ on GitHub!

### Quick Demo

```julia
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

✨ **Interactive Learning** - Type real Julia code, get immediate feedback  
📚 **Structured Lessons** - Work through well-designed courses  
💾 **Auto-Save Progress** - Never lose your place  
💡 **Smart Hints** - Detailed help when you’re stuck  
🎯 **Multiple Question Types** - Mix of explanations, code, and quizzes  
📦 **Custom Courses** - Install courses from GitHub, URLs, or local directories  
🔄 **Flexible Navigation** - Easy menus with back/exit commands  
🎮 **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

## 🚀 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:

```julia
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

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

```

Then just:

```julia
using Swirl
swirl()

```

## Learn More

📖 **GitHub Repository** : [github.com/atantos/Swirl.jl](https://github.com/atantos/Swirl.jl)  
📄 **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](https://github.com/atantos/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!

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [November 6, 2025, 10:44am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/2 "2025-11-06T10:44:57Z")

</div>

Amazing! 🫶

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [November 6, 2025, 11:48am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/3 "2025-11-06T11:48:57Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [November 6, 2025, 11:52am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/4 "2025-11-06T11:52:07Z")

</div>

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

> [@Alex\_Tantos](#):
>
> **A note on development** : **Swirl.jl** was developed with significant assistance from Claude 4.5, which made the development process incredibly productive.

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [November 6, 2025, 8:23pm UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/5 "2025-11-06T20:23:05Z")

</div>

Amazing… you developed it in the 2 days from [my ping on your old topic](https://discourse.julialang.org/t/swirl-for-julia/86987/4) ??

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.

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [November 6, 2025, 8:48pm UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/6 "2025-11-06T20:48:13Z")

</div>

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!_ 🙂 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](https://github.com/atantos/Swirl.jl/issues/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:

```julia-auto
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](https://github.com/atantos/Swirl.jl/issues/4). Does this address your concern?

---

<div class="post-metadata">

**Author:** ![TheCedarPrince](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thecedarprince/32/17323_2.png) [@TheCedarPrince](https://discourse.julialang.org/u/TheCedarPrince)\
**Post date:** [November 7, 2025, 12:41am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/7 "2025-11-07T00:41:44Z")

</div>

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

 ![image](https://global.discourse-cdn.com/julialang/original/3X/8/1/81445bad651982bc7daa58e9e978435b120cb2b5.png)

This is exactly something I was so excited about year’s ago being: [GitHub - caseykneale/JuliaTutor.jl: Learn Julia from the REPL.](https://github.com/caseykneale/JuliaTutor.jl) 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](https://github.com/atantos/Swirl.jl/issues/4) ? 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:

```julia-repl
╭ Section 1: Basic Math and Variables 
├ Question 1/8: Adding Two Numbers
│ 	
╰ julia>

```

Or like:

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

```

- Is it possible to display a lesson outline? Something like this on the left hand side of the REPL (helpful reference: [https://woertergarten.medium.com/a-history-of-outliners-397b29840592](https://woertergarten.medium.com/a-history-of-outliners-397b29840592))

 ![image](https://global.discourse-cdn.com/julialang/original/3X/d/3/d31e500ee50046614718cc3df2a36a0814b13d15.png)

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 🌳

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

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [November 7, 2025, 2:43am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/8 "2025-11-07T02:43:02Z")

</div>

> [@TheCedarPrince](#):
>
> - Could we use the Julia REPL per [use the actual julia REPL · Issue #4 · atantos/Swirl.jl · GitHub](https://github.com/atantos/Swirl.jl/issues/4) ? This keeps syntax coloring and could be used to display more visual information to the learner.

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

> [@TheCedarPrince](#):
>
> - Could you clear the terminal between each question?

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

> [@TheCedarPrince](#):
>
> - Could you update the REPL display to label questions/sections? Something like:

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

> [@TheCedarPrince](#):
>
> Something like this on the left hand side of the REPL

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

> [@TheCedarPrince](#):
>
> Could you somehow remind the user the available [Swirl.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/Swirl) specific commands that are available to them? Like the ‘hint’ or other commands?

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

> [@TheCedarPrince](#):
>
> I think this would be a helpful and useful way to systematically path information from [Swirl.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/Swirl) to achieve maximum best practices.

❤

* * *

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

 ![image](https://global.discourse-cdn.com/julialang/original/3X/1/1/114829f3e717e577765989467efd691681ec2431.png)

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.

---

<div class="post-metadata">

**Author:** ![eteppo](https://avatars.discourse-cdn.com/v4/letter/e/90db22/32.png) [@eteppo](https://discourse.julialang.org/u/eteppo)\
**Post date:** [November 7, 2025, 11:40am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/9 "2025-11-07T11:40:09Z")

</div>

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).

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [November 7, 2025, 3:42pm UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/10 "2025-11-07T15:42:26Z")

</div>

> [@TheCedarPrince](#):
>
> This is exactly something I was so excited about year’s ago being: [GitHub - caseykneale/JuliaTutor.jl: Learn Julia from the REPL.](https://github.com/caseykneale/JuliaTutor.jl) 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](https://juliaregistries.github.io/General/packages/redirect_to_repo/Swirl)?

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.

> [@TheCedarPrince](#):
>
> 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.

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.

> [@TheCedarPrince](#):
>
> 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.

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.

> [@TheCedarPrince](#):
>
> Could we use the Julia REPL per [use the actual julia REPL · Issue #4 · atantos/Swirl.jl · GitHub](https://github.com/atantos/Swirl.jl/issues/4) ? This keeps syntax coloring and could be used to display more visual information to the learner.

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

> [@TheCedarPrince](#):
>
> 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.

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.

> [@TheCedarPrince](#):
>
> 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.

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.

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [November 7, 2025, 3:49pm UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/11 "2025-11-07T15:49:54Z")

</div>

Really helpful and targeted feedback. Thanks!

> [@tecosaur](#):
>
> ❤

I will definitely look at your package!

> [@tecosaur](#):
>
> This reminds me of some work I started a while back on an interactive version of the Emacs tutorial for Doom. Sample:

Impressive!

> [@tecosaur](#):
>
> I made a format so that Doom modules could define their own tutorials. I imagine [Swirl.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/Swirl) could do something similar with packages/package extensions.

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.

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [November 7, 2025, 3:52pm UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/12 "2025-11-07T15:52:39Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [November 8, 2025, 9:49am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/13 "2025-11-08T09:49:15Z")

</div>

Hi everyone

Swirl now supports a **fully interactive REPL mode** powered by [ReplMaker.jl](https://github.com/MasonProtter/ReplMaker.jl), while still keeping the **classic mode** for backward compatibility.

This makes Julia learning experiences smoother and more immersive right from your REPL.  
Below is a quick summary of what changed.

## TL;DR

- `swirl()` now runs in a **ReplMaker-powered interactive REPL** by default and can accept a keyword `use_repl_mode` to allow for setting either a **ReplMaker-powered interactive REPL** or a **classic readline mode**.
- Several functions were **removed from the public API** (breaking change).
- The **parser and progress system** were simplified.
- The **classic mode** remains available for backward compatibility.

_Here is a short **[demo video](https://youtu.be/_gOWw0_fi-E)** showing the new REPL mode in action!_

It walks through lesson selection, answering questions, and how to switch between modes. In the video, I intentionally inject a few user errors to showcase how Swirl responds. I missed to demonstrate navigationwhile responding to questions using

```julia-auto
hint → show detailed hint
skip → skip current question
restart → restart lesson
menu → return to menu
exit → exit swirl mode

```

but I guess you can see all the details in the [PR description](https://github.com/atantos/Swirl.jl/pull/5) i just opened.

---

<div class="post-metadata">

**Author:** ![TheLateKronos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thelatekronos/32/12824_2.png) [@TheLateKronos](https://discourse.julialang.org/u/TheLateKronos)\
**Post date:** [November 8, 2025, 11:00pm UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/14 "2025-11-08T23:00:28Z")

</div>

From the screenshots, it looks like the user inputs a number to select an entry from a menu. If that is correct, then TerminalMenus.jl might provide a much smoother interface.

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [November 9, 2025, 7:40am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/15 "2025-11-09T07:40:34Z")

</div>

Having a peek at the package source code, I’m awfully tempted to try a tweaked approach 😅

_slaps hand: bad Timothy, don’t start doing another thing._

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [November 9, 2025, 9:08am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/16 "2025-11-09T09:08:11Z")

</div>

Haha, I know that feeling @tecosaur , the eternal struggle not to start another side project 😅  
Your reaction might just be the push I needed. looks like it’s time to merge the REPL-support PR (probably later tonight or tomorrow).  
Even with two unrelated talks to prepare this month, I somehow found myself working on Swirl anyway 😄

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [November 9, 2025, 9:50am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/17 "2025-11-09T09:50:41Z")

</div>

That’s a great point. And yes, right now it’s number-based. I’ll definitely take a look at `TerminalMenus.jl`; it seems like a great match for Swirl’s menu navigation once the REPL mode is fully merged.

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [November 10, 2025, 12:32pm UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/18 "2025-11-10T12:32:24Z")

</div>

Until now, **Swirl for Julia** worked in a classic readline-based mode.  
The latest update introduces **REPL-based interaction** , powered by **ReplMaker.jl** , meaning you can now enter Swirl lessons directly inside your REPL in `swirl\> mode with syntax highlighting, persistent variables, and smooth transitions between questions.

The **README.md** has been updated accordingly, and you can now experience exactly what’s shown in the short YouTube demo I shared in my earlier post.

By default, Swirl.jl comes with a **“Julia Basics”** course consisting of three lessons (six questions each):

- **Basic Math and Bindings**
- **Types and Functions**
- **Vectors and Arrays**

Of course, you can also create your own custom courses. Two template files are included to make that process easy.

Before expanding further, though, I’d really appreciate hearing your thoughts on what topics or exercises should be part of the _Julia Basics_ course.

I know there are already plenty of learning resources out there, but this format feels quite different; more hands-on and interactive than traditional video tutorials or static exercises. Platforms like DataCamp used to offer something similar (with code and questions embedded directly in the console), typically around 15 questions per lesson (if I am right, am I?). I’m curious what you think would be a good balance here and I also feel that the **hints** could be improved to guide learners more effectively.

On the technical side, the next step is to support **multi-step questions** or questions that can be written across multiple lines.  
At the moment, users need to join multi-step commands with a semicolon (`;`), which can be a bit of a hurdle for beginners.

If you’ve used platforms like _swirl_ in R or other interactive learning tools, I’d love to hear what worked well (or didn’t) and what you think could make Swirl.jl a better learning experience for new Julia users. 💡

---

<div class="post-metadata">

**Author:** ![tobydriscoll](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobydriscoll/32/1843_2.png) [@tobydriscoll](https://discourse.julialang.org/u/tobydriscoll)\
**Post date:** [November 11, 2025, 3:31pm UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/19 "2025-11-11T15:31:17Z")

</div>

Cool idea! Is there a reason that the instructions have to be converted to String type? I’d love to use Markdown.MD objects to display function names and code snippets more clearly, for example.

---

<div class="post-metadata">

**Author:** ![ctessum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ctessum/32/19444_2.png) [@ctessum](https://discourse.julialang.org/u/ctessum)\
**Post date:** [November 12, 2025, 1:55am UTC](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705/20 "2025-11-12T01:55:47Z")

</div>

This is really cool! I tried putting it in a docker container with ttyd to allow students to do the exercises without needing to install julia first:

```Dockerfile
FROM julia:latest

# Install dependencies and download ttyd
RUN apt-get update && \
    apt-get install -y --no-install-recommends wget ca-certificates libwebsockets-dev libjson-c5 libssl3 bash && \
    wget -O /usr/local/bin/ttyd \
      https://github.com/tsl0922/ttyd/releases/download/1.7.7/ttyd.x86_64 && \
    chmod +x /usr/local/bin/ttyd && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

# Create a non-root user with writable home
RUN useradd -m juliauser
USER juliauser
WORKDIR /home/juliauser

RUN /usr/local/julia/bin/julia -e "using Pkg; Pkg.add(url=\"https://github.com/atantos/Swirl.jl\"); using Swirl"

# Expose the port
EXPOSE 7681

# Launch ttyd with an interactive shell running Julia
ENTRYPOINT ["ttyd", "-W", "--port", "7681", "/usr/local/julia/bin/julia"]

```

However, in ttyd, the swirl repl starts up but then exits again right away:

```julia
julia> using Swirl

julia> swirl()
REPL mode Swirl initialized. Press ) to enter and backspace to exit.

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

🌀 Type ')' to enter Swirl mode!
   (Press backspace anytime to exit Swirl mode)

Available courses:
  1. Julia Basics
 -1. Exit Swirl

💡 Select a course (enter number):

julia> 1
1

```

[Next page](https://discourse.julialang.org/t/swirl-jl-interactive-julia-learning-in-the-repl/133705.md?page=2)
