shedding
A terminal app for getting solid at Python by building small projects, one lesson at a time, without an AI writing your code.
┌ Lesson 11/29 ─────────────┐┌ solution.py ──────────────────────┐
│ # 11 · Grade book ││ def average(scores): │
│ ││ ... │
│ ## Goal ││ │
│ ... ││ │
│ ## Hints ││ │
│ Hint 1 of 3 ... ││ │
└───────────────────────────┘└───────────────────────────────────┘
┌ Results ── Tests │ Review ────────────────────────────────────┐
│ ✗ 2 failed, 9 passed │
│ ✓ average of three scores │
│ ✗ empty list averages to zero │
│ assert 0 == 0.0 ... │
└───────────────────────────────────────────────────────────────┘
F5 Run tests F1 Hint F2 Review F3 Prev F4 Next F9 Settings ^q Quit
Install and run
python -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/shedding # or: .venv/bin/python -m shedding
Options: --lesson N opens a specific lesson, --lessons PATH uses another lessons folder,
--db PATH uses another progress database. Progress, drafts and settings live in
~/.local/share/shedding/shedding.db.
Keys
| Key | Action |
|---|---|
| F5 | Run the hidden tests against the code in the editor |
| F1 | Reveal the next hint (they appear under the lesson text) |
| F2 | Request a code review (only after the tests pass, only if enabled) |
| F3 / F4 | Previous / next lesson (your draft is saved automatically) |
| F9 | Settings: review on/off, Ollama URL and model |
| Esc | Switch focus between the lesson pane and the editor |
| Ctrl+S | Save the draft now (it also autosaves a second after you stop typing) |
| Ctrl+P | Command palette: jump to any lesson, reset a lesson to its starter code |
| Ctrl+Q | Quit |
How lessons work
Each folder under shedding/lessons/ is one project: a README with the goal, concepts and exact
requirements, a starter.py that is loaded into the editor, hints revealed one at a time,
and pytest tests the app runs but never shows. Your code is written to a temporary folder as
solution.py and pytest runs there in a subprocess with a timeout, no stdin and resource
limits, so an infinite loop or a stray input() just shows up as a failure.
The 29 lessons ramp in two ways. The topics go from variables to a SQLite-backed CLI, and the scaffolding shrinks as you go:
- Lessons 01 to 04 are the basics, written as plain scripts: the starter holds given values, you compute the results, and the tests re-run your code with other values.
- Lessons 05 to 10 give you function stubs to fill in.
- Lessons 11 to 19 give you only a docstring; the README lists the required names and you write the signatures and pick your own helpers.
- Lessons 20 to 29 specify just the public surface. How you structure the program is yours to decide, and the tests only look at behaviour.
Reference solutions live in solutions/, which the app never reads. Don't look in there
while doing a lesson.
Code review (optional)
Off by default. Enable it in Settings (F9) and point it at a running Ollama
server with a model pulled (the default is qwen2.5-coder:7b). After your tests pass, F2 asks
the model for feedback. It returns a structured list of issues with line numbers and concepts
to look up; anything that looks like code is stripped before it reaches the screen. It will
not write a fix for you.
The snake, and skins
A pixel snake lives next to the results pane. It comments on what just happened (first pass, fewer failures than last run, the same failures again, a timeout), hands out a general Python tip when clicked or every few minutes, and after three runs without progress reveals the next hint on its own. Hide it with "Toggle mascot" in the command palette or in Settings.
Skins change the colour theme, the labels, and who the snake is:
| Skin | Snake | Flavour |
|---|---|---|
| Classic | Monty | Friendly python, plain labels |
| Metal Gear | Snake | Bandana, cigarette, codec calls from Otacon and the Colonel, missions instead of lessons |
The Metal Gear skin also retells every lesson: same concepts and the same tests one to one, but rations instead of pizzas, codec contacts instead of a contact book, and Mother Base GMP instead of a finance tracker. Switching skins swaps the lesson text, starter and tests, keeps your progress, and keeps a separate draft per skin.
Pick one in Settings (F9) or with "Skin: …" in the command palette. Adding a skin is one
entry in shedding/skins.py: a Textual theme, a labels table, pixel frames and a set of lines
per event.
Verifying lessons
.venv/bin/python scripts/verify_lessons.py # all lessons
.venv/bin/python scripts/verify_lessons.py 07 -v # one lesson, every check
.venv/bin/python -m pytest tests # the app's own tests
For every lesson the verifier checks that the files and metadata are valid, the reference
solution passes all tests, the starter fails, and both deliberately wrong solutions import
cleanly but fail at least one test. Anything else is reported as broken and CI fails.
See docs/authoring.md for how to add a lesson.
Metadata
Release files for shedding 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| shedding-0.1.0.tar.gz | 189.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| shedding-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 538.9 kB
Release files / shedding-0.1.0.tar.gz
| Download URL | shedding-0.1.0.tar.gz |
|---|---|
| Size | 189.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0b55a093389643b2a3766264ca6686ac284b704eafa75153a62fc9fa546222d2
|
|
BLAKE2b-256 checksum How to use checksums |
c218236084c4d884c49df305f8ce8dfcdc0af727f9ca59cab397079c713e4f73
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / shedding-0.1.0-py3-none-any.whl
| Download URL | shedding-0.1.0-py3-none-any.whl |
|---|---|
| Size | 349.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e0cbaa65fbdff4d73c632efb691f2ea93f347e32b9c30c0bec0144698757d69e
|
|
BLAKE2b-256 checksum How to use checksums |
59de5ff5e61b1eea705cedc0641b3c9d33c8abc2a9c9f57d4d21b32b0fd5a0db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|