TL;DR: If you teach Python, then you should check out course-setup (https://pypi.org/project/course-setup/) at PyPI!
I’ve been teaching Python and Pandas for many years. And while I started my teaching career like many other instructors, with slides, I quickly discovered that it was better for my students — and for me! — to replace them with live coding.
Every day I start teaching, I open a new Jupyter or Marimo notebook, and I type. I type the day’s agenda. I type the code that I want to demonstrate, and then do it right there, in front of people. I type the instructions for each exercise we’re going to use. I type explanatory notes. If people have questions, I type those, along with my answers.
In other words, every day’s notebook contains a combination of documentation, demonstration, explanation, and exercise solutions. That combination is unique to the group I’m teaching. If we get sidetracked with someone’s question, that’s OK — I include whatever I can in each day’s notebook.
Teaching in this way raises some issues. Among the biggest: If I’m working on my own computer, then how can someone see the notebook that I’m writing? Obviously, I could scroll my screen up and down, but that’s frustrating for everyone, especially when we’re doing an exercise.
I was thus delighted to learn, years ago, about “gitautopush” (https://pypi.org/project/gitautopush/), a simple PyPI project that takes a local Git repository and monitors it for any changes. When something changes, it commits those changes to Git and then pushes them to a remote repository. The fact that GitHub renders Jupyter notebooks into HTML made this a perfect solution for me.
For years, then, my setup has been:
- Create a new directory
- Make that directory into a Git repo
- Connect the repo to GitHub
- Create a Jupyter notebook in that repo
- Run “gitautopush” in another terminal window
- When I’m done with the course, make the repo private and move it to an archive directory
This worked fine for many years, but it took about 10 minutes of prep before each class. I finally realized that this was silly: I’m a programmer, and shouldn’t I be automating repetitive tasks that take a long time?
That’s where course-setup started. I wrote two Python programs that would let me create a new course (doing all of the setup tasks I mentioned above) or retire an existing one. Did it do everything I wanted? No, but it was good enough.
Once I started to use uv, I turned these programs into uv tools, always available in my shell. I made some additional progress with course-setup, but most of my thoughts about improvements stayed on the back burner.
And then? I started to use Claude Code. I decided to see just how far I could improve course-setup with Claude Code — and to be honest, the improvements were beyond my wildest dreams:
- I tightened up the code a lot, adding oodles of automated tests and type hints. This is actually a must when using Claude Code; it reduces the chances of things going off the rails completely.
- I added a bunch of options, including a configuration file, giving sensible defaults but also allowing me to customize the precise type of notebook (Jupyter or Marimo), the package dependencies, and even what files I’ll want included.
- I made it possible to create a new notebook for each day of a multi-day class, whether the class is spread over days or weeks. I made it possible to start on a day other than today (for those rare occasions when I prepare things in advance), to skip the weekend, and even to take the Israeli weekend into account, teaching on Sunday and not on Friday.
- I improved the retire-course script, so that it can handle multiple retirements at once — and added an unretire-course script, for when I accidentally retire the wrong course.
- I typically create a zipfile from each day’s course. I added the archive-course utility to do that, giving me a zipfile for each day that I can easily e-mail to the course participants
- It supports MacOS, Windows, and Linux, with the configuration file in the platform-appropriate directory.
It’s hard to exaggerate how much of this work was done by Claude Code. I supervised, checked things, added new functionality, pushed back on a number of things it suggested, and am ultimately responsible. But really, the code itself was largely written by Claude, often using a number of agents working in parallel, and I couldn’t be happier with the result. I’ve included the CLAUDE.md file in the GitHub repo, if you’re interested in learning from it and/or using it.
This suite of utilities is now available on PyPI as “course-setup” (https://pypi.org/project/course-setup/). It includes a ton of functionality, and I’m always looking to improve it — so tell me how, or send a PR my way at https://github.com/reuven/course-setup!
