Mac first · Private beta

Understand the code AI writes.

Select any code, choose your depth, and learn what it does without leaving your workflow.

Mac first · Early beta · No credit card

search.ts
1function useDebouncedSearch(query: string) {
2 const [results, setResults] = useState([]);
3 useEffect(() => {
4 const run = debounce((q: string) => {
5 fetchResults(q).then(setResults);
6 }, 300);
7 run(query);
8 }, [query]);
9 return results;
10}
TypeScriptReact HookState management
First timeBeginnerIntermediateAdvancedExpert

live demo

Designed to work beside the tools and languages you already use

TypeScript
JavaScript
Python
React
Go
Rust
SQL
Cursor
VS Code
GitHub
Terminal
Swift
TypeScript
JavaScript
Python
React
Go
Rust
SQL
Cursor
VS Code
GitHub
Terminal
Swift

The gap

Shipping code is not the same as understanding it.

AI closes tickets fast. But merged code you cannot explain becomes tomorrow's mystery bug. Unvibe turns the diff you accepted into something you actually know.

Your agent wrote this and you merged it
cart.ts
1export async function getCart(userId: string) {2  const key = `cart:${userId}`;3  const cached = await redis.get(key);4  if (cached) return JSON.parse(cached);5  const cart = await db.cart.find(userId);6  await redis.set(key, JSON.stringify(cart), "EX", 60);7  return cart;8}
What Unvibe helps you actually understand
cart:${userId}

Namespaced cache key so each user's cart is stored separately.

if (cached) return ...

Cache hit: skips the database entirely and returns early.

"EX", 60

The cache expires after 60 seconds, so stale carts self-correct.

It caches each user's cart for a minute to spare the database, and refreshes automatically when the cache expires.

See the whole loop

Walk through it yourself.

Step through the exact flow — select code, choose a depth, read the explanation, and prove you understood it. Drive it manually, or let it play.

debounce.ts
1function debounce<T extends (...args: any[]) => void>(2  fn: T,3  wait = 3004) {5  let timer: ReturnType<typeof setTimeout> | null = null;6  return (...args: Parameters<T>) => {7    if (timer) clearTimeout(timer);8    timer = setTimeout(() => fn(...args), wait);9  };10}

Select the debounce helper and trigger Unvibe with a keystroke.

One snippet, five depths

From first day to staff engineer, on the same line of code.

Drag the depth from New to Expert and watch the explanation change. Nothing about the code moves — only how much it assumes you already know.

debounce.ts
1function debounce<T extends (...args: any[]) => void>(2  fn: T,3  wait = 3004) {5  let timer: ReturnType<typeof setTimeout> | null = null;6  return (...args: Parameters<T>) => {7    if (timer) clearTimeout(timer);8    timer = setTimeout(() => fn(...args), wait);9  };10}
closureshigher order functionstimers
Beginnerexplanation

debounce takes your function and returns a new version of it. Every time you call the new version it resets a countdown. Only when the countdown finishes without interruption does your original function actually run.

Unvibe follows the context

Start with one line. Leave with the whole reason it exists.

Move from the selected expression to the function, file, dependency, change, project, and concept worth learning next. Each step answers one useful question.

src/services/cart.tsSelected line
1export async function getCart(userId: string) {
2 const key = `cart:${userId}`;
3 const cached = await redis.get(key);
4 if (cached) return JSON.parse(cached);
5 const cart = await db.cart.find(userId);
6 await redis.set(key, JSON.stringify(cart), 'EX', 60);
7 return cart;
8}
Line

What this expression does

Returns the cached cart immediately when one already exists, avoiding another database read.

The early return ends this function before the database query below can run.

1 of 7 · Choose any context level

Try it yourself

A comprehension check, no account required.

This is the same kind of question Unvibe asks after an explanation. Read the code, pick an answer, and see how it reads a correct or missed response.

Question 1 of 3Debounce
typescript
function debounce<T extends (...args: any[]) => void>(  fn: T,  wait = 300) {  let timer: ReturnType<typeof setTimeout> | null = null;  return (...args: Parameters<T>) => {    if (timer) clearTimeout(timer);    timer = setTimeout(() => fn(...args), wait);  };}

If you call the debounced function five times in quick succession within the wait window, how many times does fn run?

See the product

Overlay in the editor. Companion for everything you keep.

Unvibe is not another course catalog. It turns the code you already wrote — or your agent wrote — into explanations, checks, and a knowledge trail.

Progress screen

Progress

What you actually understood

Projects screen

Projects

Repos mapped to concepts

Study screen

Study

Curriculum from real code

Notebook screen

Notebook

Saved explanations

Privacy

Your code remains under your control.

You decide what to review. Before a request leaves your Mac, Unvibe scans the selection for common secrets.

Secrets filtered on your Mac

API keys, tokens, and private keys are detected before anything is sent, and a hit blocks the request.

You choose what to review

Unvibe starts from the selection you ask it to explain. It does not record your screen or read code in the background.

No repository upload

The product sends review context, not an entire repository. Read the policy for the exact current limits and controls.

What Unvibe reviewsselection-first

Sent

  • Your selected snippet
  • The scope you approved
  • Shallow project structure

Blocked

  • .env and .env.*
  • *.pem · *.key · id_rsa
  • node_modules / build output
  • High-entropy secrets

Exact behavior and current limitations are documented in the privacy policy.

Pricing

Pay for explanations. Keep learning free.

Your progress, saved material, comprehension checks, and teaching tools never consume an allowance. Only cloud-generated explanations are metered.

Free

Join the beta and use the core learning loop without a subscription.

$0to start

  • 50 AI explanations each month
  • Study, progress, snippets, and notebook
  • Comprehension checks do not use your allowance
Join the free beta
Most flexible

Pro

For an individual who wants more room for focused explanations.

$12/ person / month

  • 250 AI explanations each month
  • Everything in Free
  • Pro learning modes as they leave beta
Join the Pro waitlist

Team

For teams that want individual learning with a shared path forward.

$8/ person / month

  • 200 AI explanations per person, monthly
  • Everything in Pro
  • Team controls when they are ready
Join the Team waitlist

Free mode does not require a Pro subscription. Paid plans are shown for clarity while billing and team administration are still being prepared for launch.

Private beta

Join the private beta.

Mac first. We’ll email you when an invite is ready.

A few quick details

This takes less than a minute and helps us invite a useful mix of early testers.

By joining, you agree to our terms and privacy policy.

FAQ

Straight answers.

What Unvibe does, what it does not, and how it treats your code — no hedging.

Unvibe is a desktop AI learning layer for code. It lives beside your editor: select code, choose a depth, and get an explanation that stays open while you work. It also helps you save notes, track concepts, and turn real projects into study material. It is not a course platform or another chat window.

Ship with AI. Learn what you shipped.

Join the private beta for a quieter way to understand the code you ship. We'll email you when a Mac invite is ready.

Mac first · Windows planned · No credit card during private beta