Python Gym: Practicing the Part the Agents Do Now

Agents write most of my Python now, and my own fluency had slipped. Reading and judging code was fine; writing it from a blank file was slower than it used to be. Python Gym is the practice studio I built to get it back. The one rule is that I write every line. The editor has completion and hover docs, the standard library is fair game, and an AI coach answers when asked, but nothing writes the solution for me, and every bit of help gets recorded against the attempt it touched.

A Map Instead of a Syllabus
The curriculum is a tech tree of 85 skills in nine branches: Python fluency, algorithms, engineering, the standard library, data and text, advanced Python, ML practice, interview problems and system design. Behind them sit 630 challenges and 102 code review drills. Prerequisites run left to right and suggest a path, but nothing is locked, so if you already know heaps you can go straight to them.

Each skill has an evidence state of Unseen, Learning, Independent or Retained, and the rules for moving between them are deliberately strict. One passing check without help makes a skill Independent. Retained needs more: independent work on three different days, across at least two problem families so that close variations don't count twice, an explanation in your own words, a pass on an unlabeled mixed checkpoint where you have to recognize the technique without the topic name, and a first check at least seven days after you last touched the skill. The six pips under each box on the map are those requirements. No percentages and no streaks, because a passing test and a month of retained ability are different things, and the app tries not to blur them.
Tests That Time Your Code
The Interview problems branch is the NeetCode 250, the same algorithms as that well-known list, rewritten with original wording, examples and tests. Their tests check speed as well as correctness. A hidden scaling test times one call at growing input sizes and stops at the first call over 0.3 seconds, then reports how fast the time grew.

The ratio is what matters, so the test works on any machine: going from n = 1,000 to 4,000 took 13 times longer, which is quadratic. Before checking, you can say what complexity you expect, and the chart's caption compares your guess with the measurement. The tests can reject a whole complexity class, quadratic where n log n is expected or exponential where polynomial is, but they can't tell O(n) from O(n log n) reliably, so the reflection prompt and the coach take that distinction up afterwards.
Passed interview problems come back for a re-solve from blank starter code after roughly 1, 3, 7, 14 and 30 days. A clean re-solve moves a problem up the ladder; any help in that session, or a miss, brings it back the next day.
Reading Code You Didn't Write
If agents write the first draft, the skill that matters most is spotting what's wrong with plausible code, so there are two kinds of review drill. Each is built from a realistic defect that passes every visible example. In a repair drill the buggy code starts in the editor and you fix it. In a find-the-input drill you can't touch the code at all: you write arguments that make it break its contract, and the grader runs them against both the code under review and a correct implementation.

Help That Gets Recorded
Coaching comes in two phases. Before you pass, you can open authored hints or ask the AI for a question or a nudge; it won't name the insight outright, and asking marks the attempt as assisted. After a saved full pass, the coach will discuss your solution, alternatives and complexity, and you can open the reference. Mixed checkpoints have no coach at all, since their point is an unassisted measurement. For interview problems the coach also gets the author's notes on the key insight and common pitfalls, plus your last few failed checks, which makes its hints much more specific.
Help is recorded before it's shown, so a failed save can't erase it, and the journal keeps every attempt with its code, its test results and the help it had.
Where the Python Runs
Your code runs in Python 3.14 compiled to WebAssembly (Pyodide) in a browser worker, in a fresh interpreter for every run, with NumPy and real asyncio available for the ML practice branch. Stop ends a runaway loop by terminating the worker. The studio started as a local app on my Mac with a FastAPI and SQLite backend, reachable from my other devices over Tailscale. It now also runs as a web app with Google sign-in and Firestore, and it installs on a phone and works offline: the Python runtime, the curriculum and every exercise's tests are cached on the device, and offline work merges with the other devices' saves when the connection comes back.
There's more around the edges: a system design branch with estimation drills and design write-ups that the coach reviews against a rubric, flashcards with Anki export, and an offline standard-library reference that the coach cites. The site is private to my account for now.
The curriculum took most of the work. Every exercise has a reference solution and at least one realistic wrong version, the kind of bug a person or an agent writes (an off-by-one, < for <=, a truthiness test that drops 0), and the tests are checked to reject each one. Where a realistic bug still gets through, it's logged as a known gap, because fixing it changes the grading and needs a new exercise version.