Usage
The three shapes a question can take, and what you can ask Learner for directly.
The three question styles
code- What a specific changed function does.
architecture(aliasarchi)- Which module, directory or layer the code lives in, and why that is where it belongs.
fill- The interactive exercise above: holes cut in the real file, filled in by you.
questionStyles takes either "auto", the default, or a
subset of those three. "auto" varies the format from one question to the
next, picking whichever fits what changed. Naming a subset restricts it — set it to
["code"] and no exercise will ever touch a file; set it to
["fill"] if writing code back is the only feedback you trust.
There is no setting for the language of the questions. Claude mirrors whatever you are writing in the conversation.
On demand
Everything above happens on its own, once per turn. The same learner
skill also answers when you ask it directly — invoke it as
learner <subcommand>:
learner quiz [base-ref] [count]- Q&A over the current branch diff, right now, instead of waiting for the
Stophook — optionally against a named base ref, for a chosen number of questions. learner status- Read-only: your level, plus what to improve — the record the lede above promises, read back to you on request. No quiz, no write.
learner improve [topic]- Coaches one weak spot — named, or the most open one on record — to mastery.
learner export [notion-page-url]- Pushes the recap into a Notion database — one row per competency theme, with a learning level derived from your session history. Needs the Notion connector; the parent page URL is asked for once, on the first export, and remembered after that.
learner sync push/pull [gist]/status/use <gist>- Carries your learning record between machines through a private gist. See Sync below.
learner events import- Backfills
events.jsonl, the append-only log the Learner IDE extensions read, from yourrecap.mdSession history — a one-time catch-up for history recorded before the log existed. Ordinary quiz and coach sessions write to it on their own; safe to run more than once. learner update- Checks the remote version and, if it is newer, re-runs the installer pinned to it. Safe to run any time — a no-op when you are already current.
learner config [key=value …]- Views or edits settings.
learner config project …scopes the edit to the current repository instead of the global default; with no arguments it prints your current settings. learner off/learner on- Silences or restores the automatic quiz in the current repository. See Turning it off for what that writes and why.
learner pilot …- Forwards the rest of the line to the separate, opt-in
pilotskill — a delegation-habit score read from your sessions themselves, off by default. Reachable directly too, as plainpilot …. learner help- Prints its subcommand and parameter reference, then stops.
Coach mode — you write, Claude challenges
The regime above has Claude write the code and quiz you afterwards. Coach mode inverts
it: you write the code, and Claude watches your working tree and comes back after you pause
typing with one to three socratic questions, up to three findings anchored file:line,
and up to two leads — never a patch. Your level drives both what the
challenge attacks and the register it is written in.
learner coach on/learner coach off- Turns the coach regime on or off in this repository. Off is the default — a dev who
never runs this sees no change. Once on, Claude is denied write access to
your source: a
PreToolUsehook refuses anyWrite,EditorNotebookEditoutside the slice you delegate below, and hands back a copy-pasteable glob in the refusal. learner coach delegate <glob> …- Lets Claude write inside the given globs for this session, e.g.
learner coach delegate 'src/**/repository/**'— the layer that looks the same in every project, leaving you the service and the business logic.learner coach delegate noneclears it. learner coach review [base-ref]- Runs one coach review right now, off-cadence, instead of waiting for the watcher.
A review fires when you pause typing: the watcher polls your working tree
every coachPollSeconds, and once it has seen coachQuietPolls
consecutive quiet polls with at least coachMinLines changed since the last
review, it fires — floored by coachCooldownMinutes so a run of short pauses does
not turn into a run of interruptions, and forced anyway past
coachMaxWaitMinutes so a long uninterrupted stretch doesn't wait for the day's
end to get a review. Zero changes for coachIdleMinutes and the watcher stops
itself and asks whether you want to continue. See Configuration for
the seven coach* keys that tune all of this.
A review is sized by the diff it is reviewing, not fixed in advance: a small change gets
one question — the challenge — and nothing else; a larger one may add a question about a
third-party library actually in play, and, past a size threshold, a question about how the
change is split across files. One or two questions arrive together, in the same message; only
when a review earns all three are they asked one at a time — say there are
three, ask the first, wait for your answer, then the next, never all three stacked in one
message. Alongside the questions, the review may open with a one-line
confirmation of a genuinely good decision it found in the diff (silence otherwise — an empty
compliment teaches nothing), and it closes with findings anchored file:line and
leads for what comes next. Once you answer, Claude teaches: the concept, the pitfall, the
parameters that matter — never a patch, never a snippet built from your own code.
Both regimes feed the same record: Claude quizzes you on what it wrote, the coach
challenges you on what you wrote, and learner status sees all of it.
Coach mode needs an interactive Claude Code session: the watcher runs as
a Monitor, which does not exist in claude -p, in a subagent, or in
a cloud session. The write refusal above still applies everywhere, because it is an ordinary
hook — so a non-interactive session with coach mode on gets the denials without ever
receiving a review. When the watcher cannot be armed there, the UserPromptSubmit
check says so once, rather than leaving you to guess why no review ever arrives.
Pilot — a delegation score, read from the transcript
Pilot is a separate, opt-in skill, off by default
(pilotEnabled: false), that scores how much of the thinking on a task you
handed to Claude versus did yourself. It never asks you a question to produce that
score — everything it reports comes from the sessions you already had, read straight from
the transcript, never from a prompt written to test you.
Four axes, each scored 0–4 per session and rolled into a 0–100 rolling index:
direction- Did you set the target and the constraints, or ask for "something that works"?
verification- Did you read what came back — evidenced by naming something concrete from it: a function, a line, a branch of the logic?
contradiction- Did you ever object, correct, or ask why?
writing- Did you write any of the code yourself? Exact when the session's coach tally covers everything a plain git diff still finds in the working tree; estimated from that diff otherwise — including under coach mode itself, on the block a watcher cycle never got to measure, since a tally alone is a lower bound, not a guaranteed total, and git alone cannot say who typed what beyond it; and, for a session held outside any git repository at all, not scored rather than guessed at zero — a dash, not a low score.
The three axes above (not writing, which never gates it) settle into one
of six profiles once each has enough assessable sessions behind it — Pilot,
Co-pilot, Observer, Backseat, Cargo,
Passenger — but no profile is named off two or three sessions: until the
floor is met, the dashboard shows the axes it does have and says so instead of guessing.
Pilot measures a habit, not you: it is not a measure of intelligence and not a measure of cognitive health. A score is a model reading a transcript against a written rubric, the same instrument that scores the exercises above — a defensible signal about a pattern in how a task got delegated, not a clinical or cognitive claim about the person who delegated it.
Once a day, if sessions are waiting, a subagent judges them against the rubric and
writes the result to your dashboard — never inside the session being judged. Every axis
score carries one supporting quote from the transcript; a score with no quote to show for
it is recorded as not-assessable, never as a zero. Once a week (pilotCadenceDays
by default), Claude opens a weekly brief after answering your first
request of that session, never instead of it: the facts with no adjectives, one question
about what pushed you there that week, one mechanism from the advice corpus that matches
your weakest axis, and one counter-manoeuvre negotiated with an expiry — never two live
manoeuvres at once, never a lecture, and "not now" defers it without penalty.
pilot(bare)- Renders the dashboard: index per axis, profile (once there is enough data), and the active manoeuvre, if any.
pilot on/pilot off- Prints the privacy paragraph below in full, then flips
pilotEnabled. Reachable aslearner pilot ontoo. pilot brief- Runs the weekly brief right now, off-cadence.
pilot score- Drains the scoring queue right now, off-cadence.
pilot why <date>- Shows the quotes behind that row's scores.
pilot forget [--all|--before <date>]- Purges stored quotes — every one, or every one before a date.
Privacy — read this before turning it on. Pilot reads every prompt you have typed, in every repository, including ones where the automatic quiz above is switched off — that is exactly why it defaults to off and stays opt-in rather than a setting you would stumble into. Everything stays local: the transcript is referenced by path and never copied, and the judgement that turns a session into scores runs in a subagent on this machine — nothing about it leaves that Claude Code itself was not already sending.
- Contained.
disabledPathsis honoured exactly as it is for the quiz, so a repository listed there is never read for Pilot either. - Reversible. The quotes kept as evidence are capped at 200
characters each, and
pilot forget --allpurges every one of them, any time.
Sync — carry your record between machines
learner sync moves your learning record — memory.md,
recap.md and the global learner.json — between machines through
one private GitHub gist. It is the only path that ever sends the record off the machine, and
it is manual only: no hook pushes anything, on any machine; nothing leaves
until you type it.
learner sync push- Snapshots the local record to the gist. The first push asks before creating it, and
creates it
--secret. A secret gist is unlisted, not access-controlled: anyone who has the URL can read it, without a GitHub account — it carries your repo names, file names and the wording of your weak spots, pluspushedFrom(themachine_nameplugin option, if set),learner.json'sdisabledPaths(absolute local paths) andevents.jsonl(the text of every question you were asked and each repo's absolute path), so treat the link like a password. learner sync pull [gist-url]- Backs up the local record first, to
${CLAUDE_CONFIG_DIR:-$HOME/.claude}/learner/backups/<timestamp>/, then three-way mergesmemory.md— a line you deleted here because you mastered it stays deleted, even if the other side still has it — unions theSession historytable, and lets Claude merge the theme sections. Name a gist URL the first time you pull on a new machine; after that it is remembered. learner sync status- Read-only: the gist URL, when you last pushed and pulled, and what is not pushed yet.
learner sync use <gist-url>- Repoints this machine at a different gist — for a dev who already has one from another machine.
learner export (Notion) is unaffected by any of this: it stays the
human-readable view of your record, not a restore path. The gist carries the raw state, and
needs gh and a GitHub token you hand over — a fine-grained token with only the
Gists permission: the github_token plugin option (stored in your system
keychain), or LEARNER_GITHUB_TOKEN for a curl, Homebrew or apt install. Learner
never reads the credential gh auth login stored. Worth making a habit:
learner sync push before you switch machines, so the record you left behind is
the one you pick back up.
Agent salvo — questions while the subagents work
When Claude hands work to subagents, the main conversation would otherwise go quiet. It owes you a short burst instead, once per dispatched agent: two questions — about the delegation itself, the branch diff, the code those agents are about to touch, or an open weak spot — then one fill-in exercise cut in your own code. Three agents dispatched at once earn three salvos, served one per turn as you answer. The moment the last agent returns, the unserved ones are dropped: the queue never trails into work that has resumed.
The exercise is cut by a dedicated agent launched while you answer the questions, so it is
ready when you get to it. You will see it start with a description beginning
learner-prep: — that prefix is a contract, not a label: the salvo deliberately
does not count its own preparation agent as an agent to quiz you about.
In coach mode the salvo is questions only. Cutting the exercise needs a write, and
coach-gate.sh denies it — the barrier is not weakened for the learner's
convenience.
One limitation, stated where you will hit it: if your client runs subagents synchronously, the salvo lands just after the result instead of during the wait. The questions are still asked; only the overlap is lost. No hook fires when a subagent starts, so there is no mechanism that does better.
learner config agentSalvo=false- Turns the salvo off. On is the default: it costs nothing in a session that dispatches no agent.
learner config agentSalvoQuestions=1- Questions per salvo, before the exercise.
0means exercise only. learner config agentSalvoFill=false- Questions only, no exercise.
Next: Configuration — every setting Learner reads.