Claude Learner

Claude Code plugin GPL-3.0 · no build step

Quiz yourself on the code Claude just wrote.

Claude Learner pairs Claude Code hooks with a skill that asks you one question at the end of a turn — about the code you just shipped together, pitched at the level you set — and keeps a record of what you should work on.

Installs once at Claude Code user level, then active in every git repository you open, with no per-repo setup. The one thing it sends anywhere is a once-a-day, best-effort version check that reaches out to GitHub — it needs curl, and its absence is silent rather than an error.

the Stop hook's block reason
🎓 Learner (level: C, mode: granular,
   styles: auto, blanks: 2)
   — files: src/auth/session.ts
Invoke the `learner` skill, follow
references/hook-quiz.md for this mode.
Ask ONE question, then wait.
what Claude then asks you
🎓 Learner — src/auth/session.ts

You changed refreshSession() to delete
the old session row before inserting the
replacement. Why that order rather than
insert-then-delete, and what does a
caller see if the insert fails after the
delete has committed?
The problem

Code now arrives faster than understanding does.

Reviewing what an agent wrote is easy to skip and hard to do well — the diff is plausible, the tests are green, and the next task is already queued — so the honest answer to “do you know how this works?” drifts quietly from yes to nearly.

A question you have to answer before the turn ends is not skippable in the same way.

Learner spends one question of your attention at the end of a turn, while the code is still fresh, and writes down whatever you did not know so it can come back to it later — spaced repetition over the code you actually write.

Read it back any time with learner status.

What it actually looks like

Nothing below is a mock-up.

The trigger lines are the text hooks/learner-quiz.sh emits, the fill exercise cuts up a function from this project's own source, and the coach commands are the ones the usage page documents.

Granular

One question about one detail

When a turn ends and the session has edited at least one file inside the repository, the Stop hook blocks once. The trigger line is parameters, not the question — the protocol lives in the skill, so the hook never has an opinion about what a good question is. Claude reads the files, reads your open weak spots, and asks one question pitched at the level named.

Answer it and the turn continues. Say skip and it moves on without insisting. Either way what you did not know is recorded, and the next question prefers a weak spot that is still open.

Synthesis

One question about the shape of the work

Every fourth question by default, the hook switches mode and widens the file list: a granular question sees the edits since the last question, a synthesis question sees every file the session has touched — each list capped, at 20 files and 40 files respectively, so the trigger line itself never grows unbounded on a very large session.

the same hook, in synthesis mode
🎓 Learner — this session

Trace what happens between a request
arriving with an expired access token and
its caller getting a fresh one. Which of
the three files you touched owns each
step, and why does the rotation live in
tokens.ts rather than in session.ts?
Coach mode BETA

You write, Claude challenges

The other two invert: Claude writes and quizzes you afterwards. Coach mode has you write, while Claude watches your working tree and comes back when you pause with one to three socratic questions sized by the diff, up to three findings anchored file:line, and up to two leads — never a patch.

While it is on, Claude is denied write access to your source outside the globs you hand it, and reviews arrive when you pause typing by default. It needs an interactive session: the watcher is a Monitor, which does not exist in claude -p. Read the whole regime.

the three commands
learner coach on
learner coach delegate 'src/**/repository/**'
learner coach review
Fill exercise

The style that tells you whether you understood the code.

Claude picks one short function among the files you just edited, memorises the correct version from git, then cuts holes in the real file on disk and asks you to fill them in. Here is learner_synthesis_n from this project's own hooks/learner-config.sh — it turns the synthesisFrequency word into the number of questions between synthesis questions.

before — hooks/learner-config.sh
learner_synthesis_n() {
  case "${1:-}" in
    off)   printf '0' ;;
    rare)  printf '8' ;;
    often) printf '2' ;;
    *)     printf '4' ;;
  esac
}
after — the same file, two holes cut
learner_synthesis_n() {
  case "${1:-}" in
    off)   printf '0' ;;
    // LEARNER-TODO: the two named cadences
    // LEARNER-TODO: the fallback arm
  esac
}

This is not a preview pane: it is your file, saved to disk, and your editor will show it changed. Claude names the file and the function, asks you to write the missing code in the file, and then waits. It will not fill them in for you. When you are done — or you say skip — it compares what you wrote against the version it memorised, gives you a couple of lines of feedback, restores a correct implementation, and runs a focused check that the file is valid again.

Two things worth knowing before you let it do that. The marker is the same literal string in every language, // LEARNER-TODO, so in a language where // does not start a comment — shell, as above — the file does not merely have a gap in it: it does not run until the exercise is finished. And the exercise edits your real source, not a copy. Both of those are why the guardrail exists — read it before you install.

Get started

Two commands, then it is on everywhere.

Claude Code manages updates itself. Prefer apt, Homebrew, a clone, or a curl one-liner? They are all on the install page.

install
claude plugin marketplace add Tykok/learning-with-claude
claude plugin install learner@learning-with-claude

Next: Install — what Learner needs, and the ways in.