Learn as your AI coding assistant builds.
You can outsource your thinking, but you can't outsource your understanding.
vibe-learn watches what Claude Code, GitHub Copilot CLI, Codex, OpenCode, Grok Build, or Cursor does during a session and helps you understand what was built, why, and how β without changing how you work.
Every file write, edit, and command is logged locally. /learn explains it, /digest reports on it, /quiz checks you actually understood it β and a small knowledge ledger brings shaky concepts back until they stick. Offline, bash + jq, no API keys.
New here? Follow the Getting Started guide for a step-by-step first session walkthrough.
Inside Claude Code:
/plugin marketplace add gkaria/vibe-learn
/plugin install vibe-learn@vibe-learn
That registers the hooks and adds /vibe-learn:learn, /vibe-learn:digest, /vibe-learn:quiz, and /vibe-learn:explain. Updates arrive with /plugin update vibe-learn@vibe-learn. Requires jq β brew install jq / apt-get install jq.
GitHub Copilot CLI, Codex, OpenCode, Grok Build, Cursor β or Claude Code without the plugin system
curl -fsSL https://raw.githubusercontent.com/gkaria/vibe-learn/main/scripts/setup.sh | bashInstalls to ~/.vibe-learn/, creates the vibe-learn CLI, and registers hooks globally for every AI assistant detected on your machine. If the Claude Code plugin is already enabled, the installer skips Claude hook registration so events are not logged twice. GitHub Copilot CLI is detected via the copilot binary, ~/.copilot, or COPILOT_HOME. To update: re-run the same command. Latest release: v0.10.0.
After every AI response that touches files or runs commands, vibe-learn:
- Appends every action to
.vibe-learn/session-log.jsonl - Writes a pause summary to
.vibe-learn/pause-summary.txt - Injects that summary into your assistant's context at the start of the next session (Claude Code and GitHub Copilot CLI)
- Regenerates the session briefing in the background
The summary looks like this (the last line switches to /vibe-learn:β¦ under the plugin install):
βΈ vibe-learn β what just happened:
Goal: add JWT auth middleware
β¦ Created src/middleware/auth.ts
β¦ Edited src/routes/user.ts
β¦ Ran: npm install jsonwebtoken
/learn [question] Β· /digest Β· /quiz Β· /explain [file|topic] Β· vibe-learn briefing Β· vibe-learn audio-prep
/learn β explain what just happened
/learn why did we add middleware? β answer a specific question
/digest β full structured session report
/quiz β check your understanding of this session
/quiz review β re-quiz concepts that are shaky or due again
/explain [file|topic] β guided code tour of what was touched
With the plugin install the same commands are namespaced: /vibe-learn:learn, /vibe-learn:digest, /vibe-learn:quiz, /vibe-learn:explain.
Use /learn
Use /learn why did we add middleware?
Use /digest
Use /quiz
Use /quiz review
Use /explain src/middleware/auth.ts
Use vibe-learn to learn what happened.
Copilot CLI loads these as Agent Skills from .github/skills/ (project) or ${COPILOT_HOME:-~/.copilot}/skills/ (personal). They are skill references inside a prompt, not new built-in interactive commands; typing a bare /learn is not guaranteed to dispatch like Claude Code's custom slash commands. Project hooks live in .github/hooks/ and need the folder trusted before they run.
Use vibe-learn to learn what happened.
Use vibe-learn to answer: why did we install bcrypt?
Use vibe-learn to create a digest.
Use vibe-learn to quiz me on this session.
Use vibe-learn to explain src/middleware/auth.ts.
/learn
/learn why did we add middleware?
/digest
/quiz
/explain src/middleware/auth.ts
/learn
/learn why did we add middleware?
/digest
/quiz
/explain src/middleware/auth.ts
/vibe-learn
Use vibe-learn to learn what happened.
/learn
/learn why did we add middleware?
/digest
/quiz
/explain src/middleware/auth.ts
/vibe-learn
Cursor ships these as skills (.cursor/skills/), so plain requests like "what did we just build?" also route to the vibe-learn skill.
Continuing the JWT session from above:
/learn β a plain-language recap, grounded in the actual log:
π What just happened:
β’ Added JWT auth middleware (src/middleware/auth.ts) β every request to a
protected route now passes a token check before reaching the handler
β’ Wired it into the user routes (src/routes/user.ts), so /profile and
/settings require a valid token
β’ Installed jsonwebtoken to sign and verify tokens
β’ Pattern worth knowing: middleware ordering β auth runs before the route
handlers, so handlers can safely assume req.user exists
/digest β the structured session report:
## π Session Digest
### What Was Built
JWT authentication for the user routes: a reusable auth middleware that
verifies tokens and attaches the decoded user to the request.
### Key Decisions
- Middleware over per-route checks β one enforcement point, no duplication
- jsonwebtoken over hand-rolling β battle-tested signing and expiry handling
### Patterns Used
- Express middleware chaining and ordering
- Fail-closed auth (reject first, then continue)
### Things to Study
- [ ] How JWT expiry and refresh interact
- [ ] What happens to routes registered before the auth middleware
- [ ] (carried over from Jul 2) Environment-based config for secrets
/quiz β one question at a time, graded against what actually happened:
Question 1 of 3: The auth check lives in middleware instead of inside each
route handler. What does that buy us β and what's the risk when someone
adds a new route later?
> no repeated checks in every handler, and new routes are protected
automatically?
Right on the first half β one enforcement point, no duplication. One nuance
you missed: routes are only protected if they're registered *after* the
middleware. A new route mounted above app.use(auth) skips the check
entirely. That ordering is the thing to remember.
Question 2 of 3: ...
After the last question you get a recap, and the results are recorded:
Solid: jwt-verification, fail-closed-auth
Revisit: express-middleware-ordering β you had the what, not the when
β 3 concepts recorded to the knowledge ledger
That recording is the ledger at work β next session, /learn will nudge you if middleware ordering comes up again, and /quiz review will re-ask until it's solid.
/explain src/middleware/auth.ts β a guided tour when you want to actually read the code:
Entry point β src/middleware/auth.ts:8 exports `requireAuth`, mounted in
src/routes/user.ts:4 with app.use(requireAuth) before any route.
The spine
1. auth.ts:10 reads the Authorization header and strips "Bearer " β the
only place the raw token is touched
2. auth.ts:14 jwt.verify(token, secret) β throws on bad signature *or*
expiry, which is why there's a single catch below
3. auth.ts:19 req.user = payload β every handler after this can assume it
4. auth.ts:22 next() β only reached on success; failure returns 401 first
The edges β user.ts:4 must stay above the routes; a route mounted earlier
skips the check entirely. auth.ts:14 has no clock-skew tolerance.
Connections β user.ts (/profile, /settings) and, after this session,
nothing else. Adding a new protected router means mounting it below line 4.
You marked express-middleware-ordering shaky on July 11 β this is the code
behind it. Want me to quiz you on this, or save it to Obsidian?
Reading a digest feels like learning; answering questions proves it. /quiz asks 3β5 recall questions grounded in what actually happened this session β "why did we install bcrypt?", "which files would you touch to add another adapter?" β one at a time, then tells you what you got right and what you missed.
Results go into .vibe-learn/knowledge.json, a small cross-session knowledge ledger. Concepts you answered shakily come back: /quiz review re-quizzes anything shaky or unreviewed for two weeks, /learn gives you a one-line heads-up when a shaky concept resurfaces in a new session, and /digest's "Things to Study" accumulates across sessions instead of resetting.
The ledger is updated only by the learning commands (via scripts/knowledge.sh) β never by hooks, never over the network.
vibe-learn recap # this week, to stdout
vibe-learn recap --days=30 # wider window
vibe-learn recap --save # also writes .vibe-learn/recaps/<date>-recap.mdA markdown rollup built from the ledger, the session logs, and any saved digests β what you confirmed solid, what's still shaky, what you met but haven't been quizzed on, plus days active and files touched. Made to paste into a standup note, a learning journal, or a post:
# What I learned this week β my-api
2026-07-05 β 2026-07-11
**3 active day(s) Β· 7 prompt(s) Β· 14 file(s) touched Β· 22 command(s) run Β· quizzed on 2 day(s)**
## Confirmed solid (2)
- JWT verification β quizzed 2026-07-11
- Fail-closed auth β quizzed 2026-07-11
## Still shaky β revisit (1)
- Express middleware ordering β quizzed 2026-07-11: you had the what, not the when
## Met this week, not quizzed yet (1)
- Repository pattern β seen in 2 session(s), not quizzed yet
## Next
/quiz review β re-ask the shaky ones until they stick.
After each session a local HTML briefing is auto-generated. Open it any time:
vibe-learn briefing # regenerate and show pathPlugin-only install? The vibe-learn CLI is on the Bash tool's PATH inside Claude Code, so just ask Claude to run vibe-learn briefing. To have it in your own shell too, run the curl installer above β it adds the CLI and skips the duplicate hooks.
The briefing includes: maintainer brief (what changed / why it matters / inspect first / what could break), session timeline with filter buttons, file tour with colour-coded area badges, command log with failure highlighting, syntax-highlighted diff, a study queue, and a NotebookLM-ready source pack. When .vibe-learn/knowledge.json exists, the study queue leads with your shaky concepts, the page gains a Knowledge State section, the source pack gains a "Your knowledge state" table, and the audio prompt asks NotebookLM to dwell on what you've struggled with.
No server, no build step, no external assets β just a static HTML file that opens directly from disk.
Every session briefing also produces a markdown source pack at .vibe-learn/briefing/exports/<session>-notebooklm-pack.md. This is a structured document containing the session summary, timeline, file list, commands, and diff excerpt β formatted for upload to NotebookLM.
To prepare the upload in one step:
vibe-learn audio-prepThis:
- Finds the latest pack in
.vibe-learn/briefing/exports/ - Copies the file path to your clipboard
- Opens NotebookLM in your browser
- Opens the exports folder in Finder
- Prints the audio prompt to paste when NotebookLM asks to customise the overview
The audio prompt tells NotebookLM to produce a maintainer-focused overview β what changed, why it matters, what to inspect first, what could break β pitched at someone who owns and needs to support the codebase. Upload the pack as a source, generate an Audio Overview, and listen on your commute.
| Assistant | How vibe-learn integrates |
|---|---|
| Claude Code | Plugin (/plugin install vibe-learn@vibe-learn) or JSON hooks in settings.json; native /learn, /digest, /quiz, and /explain slash commands |
| GitHub Copilot CLI | Native JSON hooks in .github/hooks/ or ~/.copilot/hooks/; /learn, /digest, /quiz, /explain, and vibe-learn project/personal skills |
| Codex App/CLI | Inline TOML hooks in config.toml, global vibe-learn skill, prompt-file fallbacks |
| OpenCode | JavaScript plugin in .opencode/plugins/, native /learn, /digest, /quiz, and /explain commands |
| Grok Build | JSON hooks in ${GROK_HOME:-~/.grok}/hooks/vibe-learn.json, native /learn, /digest, /quiz, /explain, and a /vibe-learn skill |
| Cursor | hooks.json entries pointing at one shim (.cursor/hooks/vibe-learn.sh), plus /learn, /digest, /quiz, /explain, and vibe-learn skills in .cursor/skills/ |
Auto-detected on install. To target one: --assistant=claude-code, --assistant=copilot-cli, --assistant=codex, --assistant=opencode, --assistant=grok, or --assistant=cursor.
Project Grok hooks stay inert until the folder is trusted (/hooks-trust or grok --trust). If Claude Code vibe-learn is also installed, Grok may run both hook sets; set [compat.claude] hooks = false in ~/.grok/config.toml to avoid double-logging.
Cursor project hooks (.cursor/hooks.json) run once the workspace is trusted. Cursor has no context injection on stop, so the pause summary is written to .vibe-learn/pause-summary.txt and relayed at the next sessionStart; the skills read the file directly. Cloud Agents skip sessionStart, so there the file is the only channel.
Copilot CLI project hooks also require folder trust. On Copilot CLI 1.0.84-4, userPromptSubmitted can arrive before sessionStart; the adapter initializes once on whichever event arrives first, keeps the prompt hook silent, and emits prior-session context from the later sessionStart. A global vibe-learn hook defers when a project vibe-learn hook is present.
Copilot also reads repository .claude/settings.json and .claude/settings.local.json hooks. Avoid installing vibe-learn in both those files and .github/hooks/ for one project. Copilot's documented disableAllHooks repository-settings option pauses every non-policy hook sourceβincluding vibe-learnβso use it only when you intend to pause all hooks; the installer never changes it automatically.
Global install covers most workflows. If you want hooks scoped to one project, or want to commit the config so teammates get vibe-learn automatically:
cd your-project
vibe-learn installDetects which assistants the project already uses (including .github/ for Copilot CLI) and installs only those. Adds .vibe-learn/ to .gitignore.
Save learnings to an Obsidian vault and recall them across sessions:
/learn obsidian β save a learn note to your vault
/learn obsidian:recall authentication β search past notes on a topic (read-only)
/digest obsidian β save the session digest to your vault
/digest obsidian:recall β digest enriched with connections to previous work
On first use, Claude asks for your vault path and offers to save it to .vibe-learn/obsidian.json. Equivalent Codex and Copilot CLI requests work the same way via the skill.
Four lifecycle hooks, all fast and offline:
| Hook | Script | What it does |
|---|---|---|
SessionStart / sessionStart |
bootstrap.sh |
Creates .vibe-learn/, rotates previous log |
UserPromptSubmit / userPromptSubmitted |
capture-prompt.sh |
Logs your prompt with a turn counter |
PostToolUse / postToolUse |
observe.sh |
Appends one JSONL line per tool event (<50ms) |
Stop / agentStop |
pause-summary.sh |
Writes summary, injects context, generates session briefing |
On-demand (never from hooks): vibe-learn briefing, vibe-learn recap, vibe-learn audio-prep, and the knowledge helper scripts/knowledge.sh.
All data stays in .vibe-learn/ inside your project. No network calls, no external services.
brew install bats-core # macOS
apt-get install bats # Linux
bats tests/ # 329 tests- Bash (POSIX-compatible)
- jq (
brew install jq/apt-get install jq) - Claude Code, GitHub Copilot CLI (verified with 1.0.84-4), Codex App/CLI, OpenCode, Grok Build, or Cursor
- v0.10.0 (this branch): GitHub Copilot CLI as a first-class assistant β native JSON hooks Β·
/learn,/digest,/quiz,/explain, andvibe-learnskills Β·--assistant=copilot-cliΒ· auto-detect viacopilot/~/.copilot/COPILOT_HOMEΒ· sessionStart context relay - v0.9.0: Claude Code plugin + self-hosted marketplace Β· Cursor adapter Β·
/explainguided tours Β·vibe-learn recapΒ· ledger-aware briefing Β· demo GIFs and community scaffolding - v0.8.0: Grok Build as a first-class assistant β
/learn,/digest,/quiz,/vibe-learnskill Β·--assistant=grokΒ· auto-detect viagrok/~/.grok/GROK_HOME - v0.7.0: Active recall β
/quizand/quiz reviewΒ· cross-session knowledge ledger (knowledge.json) Β· cumulative "Things to Study" in digests - v0.6.0: OpenCode support Β· session briefing Β· auto-generated briefing after each response Β· turn-structured session log Β·
vibe-learn audio-prepΒ·vibe-learn briefing - v0.5.5: Multi-assistant support β Claude Code and Codex, assistant auto-detection, generic adapter layout
- v0.5.0: Obsidian integration β save notes, recall past learnings with
obsidian:recall
Issues and PRs welcome β see CONTRIBUTING.md for the dev loop, the adapter layout, and how to add a learning command. Looking for a first task? docs/community/good-first-issues.md has five scoped ones.
MIT β see LICENSE. Copyright Β© 2026 Gaurang Karia.



