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.
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.
🎓 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?
- 1skill, invoked by the hooks
- 15POSIX
shhook files - 0build steps
- jqthe only hard dependency
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.
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.
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.
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.
🎓 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?
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.
learner coach on
learner coach delegate 'src/**/repository/**'
learner coach review
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.
hooks/learner-config.shlearner_synthesis_n() {
case "${1:-}" in
off) printf '0' ;;
rare) printf '8' ;;
often) printf '2' ;;
*) printf '4' ;;
esac
}
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.
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.
claude plugin marketplace add Tykok/learning-with-claude
claude plugin install learner@learning-with-claude
Next: Install — what Learner needs, and the ways in.