Understand code you didn't write before you change it
A teammate's service, your own project from two years ago, an open-source repo you want to fix. The code works, the person who wrote it is not around to ask, and you need to change one file without breaking what depends on it. Below is an order for reading a file like that, then a worked example.
How to read an unfamiliar file
- Start with who uses it. Search the project for the file's exported names. The callers tell you what the file is for and which parts of it matter.
- Read the imports. They show what the file depends on: a framework, a database client, other modules in the project.
- Read the exported names and their signatures before any function body.
- Read the data shapes: types, schemas and the constants near the top.
- Follow one real input through one function, end to end, and write down what comes out.
- Mark the side effects: network calls, file and database writes, global state, environment variables, timers. These are what break when you change the file.
- Read its tests, if it has any. They show what the author meant it to do, including the edge cases they thought of.
- Read its history.
git log --follow -p -- path/to/fileshows every change to the file;git blame -L 40,60 path/to/fileshows which commit last touched lines 40 to 60. The commit message can explain the line that looks wrong. - Run the tests before you change anything, so you know which failures are yours.
A worked example
You are fixing a sign-up bug and find this function. It runs before an account is saved and before sign-in looks one up.
export function normalizeEmail(raw) {
const email = raw.trim().toLowerCase();
const [local, domain] = email.split("@");
if (domain === "gmail.com" || domain === "googlemail.com") {
return local.split("+")[0].replaceAll(".", "") + "@gmail.com";
}
return email;
}The notes below are written by hand to show what a careful read finds. They are not output from Unvibe.
- The first line removes spaces around the address and lowercases all of it.
const [local, domain] = email.split("@")puts the part before the @ inlocaland the part after it indomain. With no @ at all,domainisundefinedand the function returns the trimmed, lowercased input.- The Gmail branch is the part that needs a reason. Gmail ignores dots before the @ and anything after a +, and googlemail.com reaches the same inbox. So
J.Doe+shop@gmail.comandjdoe@googlemail.comboth becomejdoe@gmail.com. - A likely reason is to treat those addresses as one account, for example so one person cannot sign up twice. That is a guess from the code. The commit that added the branch is the evidence.
- If it has run before every save, existing accounts are stored under the normalized address, and sign-in finds them by it. Change the rule and some people stop matching their own account, so a change here needs a plan for the addresses already saved.
Doing it with Unvibe
- Select the function in your editor.
- Press Control+U on a Mac or Ctrl+Alt+U on Windows. The panel opens beside your editor and the explanation streams in as it is written.
- Pick a depth. New, Beginner, Intermediate and Advanced are free; Expert is part of Pro. Switch any time and the same code is explained again at that depth.
- Type a follow-up under the explanation, such as “What breaks if I remove the Gmail branch?” The answer stays about the code you selected.
- Press Test me. It writes a question about this exact code, and up to three if you want more. Miss one and the lesson is saved to revisit later.
To see why lines are there, use “Why does this exist?”. It answers from git blame and the file's last 8 commits, which Unvibe reads in the repository on your computer. It shows when the lines were added and the commit message behind them, and keeps those facts separate from inference. It needs to know which file the selection came from, and that file has to be in a git repository.
Unvibe does not explain a whole repository in one go. It explains what you select, and your whole codebase is never sent. On Pro, answers can use up to two files the selection imports (the first 4,000 characters of each).
Yes. AI can be wrong even when it sounds sure. Each explanation sits next to the code it describes so you can check it, and Test me helps you spot what doesn't add up.
What leaves your computer
The code you select is sent to a cloud model to write the explanation. Only what you ask about: the selected code and its language, the file's path inside your project when Unvibe knows which file it came from (like src/lib/retry.ts), and the name of the project folder you last worked in with Unvibe. With Pro, some nearby code is added for context, and Briefs send the git changes you ask the AI to explain. Any question you type is sent too. Unvibe checks the code for keys and tokens on your computer first, and from version 0.1.44 your questions and Ask Vibe chat messages too. A known key stops the request. Your repo is never uploaded. If you add your own API key in Settings, the app sends the request straight to that provider instead.
Free and Pro
Free. 50 explanations in your first 30 days without signing in, then 50 explanations a month when you sign in. No card and no separate API key.
- Explain code you select in any app
- New, Beginner, Intermediate and Advanced depths
- Follow-ups and Test me
- Lessons saved to your Library
- Briefs of your Git changes, made on your computer
- “Why does this exist?” from your Git history
- Your code checked for keys and tokens on your device
Pro, $9 a month or $81 a year. One developer account. Your Free plan keeps working until then.
- Everything in Free
- Expert depth
- AI explanations of Git diffs and change Briefs
- Answers that use nearby files
- 200 AI explanations a month
Explain code beside your editor
Unvibe is a free app for Mac and Windows. In the app there is no pasting: select code in any app and press Control+U (Ctrl+Alt+U on Windows).
Install on Mac
curl -fsSL https://unvibe.site/install.sh | bashPaste into Terminal. Unvibe isn't notarized by Apple yet, so this is the smooth path.
Or download the .dmg · Intel Mac build · SHA-256 checksums
Opening the .dmg the first time
- Open the .dmg and drag Unvibe to Applications.
- Open it once; macOS says it can't verify it. Click Done.

Real screen, macOS 15 - System Settings › Privacy & Security › Open Anyway. Confirm, then enter your Mac password. The button shows for about an hour after you try to open Unvibe.

Real screen, macOS 15
The Terminal line checks the download against the published SHA-256 and Unvibe's self-signed signature before it installs anything. More help with the first open