Every developer has a muscle-memory routine for errors: copy the stack trace, open a browser, paste it into a search engine or a chatbot, read, switch back, and try to remember what you were doing.
I wanted to cut that loop out. So I built errbuddy: you put it in front of any command, and when something breaks, it explains the error right under it, in your terminal.
bash
npm install -g error-solution-ai-buddy
errbuddy node app.js
In this post I'll walk through how it works, the decisions behind it, and a few lessons from turning a side project into a package other people can install.
How it works
The idea is simple: errbuddy runs your command as a child process and watches what it prints.
errbuddy node app.js
│
▼
Runs your command ──► stdout passes straight through
│ stderr is shown AND captured
▼
Error detector ──► language, error type, file and line
▼
Sanitizer ──► strips file paths and anything that looks like a secret
▼
AI explains it (Ollama or Gemini) ── or ── built-in pattern explanation
▼
Prints WHAT / WHY / FIX / EXAMPLE, then exits with your program's exit code
A few details turned out to matter more than I expected:
- Output is streamed, not buffered. errbuddy uses spawn() instead of exec(), so you see your program's output live, exactly as if errbuddy weren't there.
- It returns your program's exit code. If your script fails with exit code 1, so does errbuddy. That means it doesn't break scripts or CI steps that check for failure.
- It only steps in when there's an error. Normal output passes through untouched.
Local first: why Ollama is the default
Pasting a stack trace into a chatbot means sending bits of your code and file paths to someone else's server. For a lot of developers (and a lot of employers) that's not OK.
So errbuddy's default provider is Ollama, which runs the model on your own machine. The default model is qwen2.5:0.5b. It's about 400 MB and runs on low-RAM laptops, which matters because that's exactly the kind of machine people learning to code tend to have.
Even with a local model, errbuddy cleans the error first, before it reaches any model:
function sanitizeError(errorText) {
let sanitized = errorText;
// Remove Windows-style absolute paths (C:\Users\...)
sanitized = sanitized.replace(/[A-Za-z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*/g, '[path]\\');
// Remove Unix-style absolute paths (/home/user/...)
sanitized = sanitized.replace(/\/(?:home|Users|var|usr|opt)\/[^\s:]+/g, '[path]');
// Remove common secret patterns
sanitized = sanitized.replace(/(?:api[_-]?key|secret|password|token)\s*[:=]\s*['"]?[^'"\s]+['"]?/gi, '[REDACTED]');
return sanitized;
}
When you can't run a local model
Then I hit a problem myself: I didn't have the disk space to run a model comfortably. If I couldn't, plenty of users couldn't either, and without a model they only got the basic pattern-matching explanations.
So version 1.1 added an opt-in cloud provider: Gemini, which anyone can use with a free API key:
export GEMINI_API_KEY="your-key"
errbuddy --provider gemini node app.js
Two rules kept this honest:
- The cloud is never used unless you ask. Ollama stays the default, and Gemini only runs with
--provider gemini(orERRBUDDY_PROVIDER=gemini). - The key never goes in a URL or a command-line argument. It's read from an environment variable and sent in a header, so it doesn't end up in your shell history or in logs:
const response = await fetch(`${this.baseUrl}/models/${this.model}:generateContent`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': this.apiKey,
},
// ...
});
To keep both providers consistent, I moved the prompt and the response parser into one shared module. Each provider only has to do two things: checkConnection() and explainError(). A better prompt now improves both providers at once.
Getting a reliable answer format out of an LLM
For the output to look good in a terminal, every answer needs the same shape. The system prompt insists on it:
Always respond in this EXACT format:
WHAT: [Name the specific error and what it means]
WHY: [Explain specifically why this code causes that error]
FIX: [Clear steps to fix the error]
EXAMPLE: [Short code example if helpful]
It also has rules that came from real bad answers, like "Do NOT assume frameworks (like Spring, React) unless the error explicitly mentions them" and "only suggest installing a package if the error is explicitly Module/Package not found". Small models love to recommend installing things.
The parser then pulls out each section. And when the model ignores the format anyway (it happens), the parser falls back to splitting the answer into sentences, so the user still gets something useful.
Bugs real usage found
Two bugs only showed up once Gemini, a stronger model, started giving longer, nicely formatted answers:
Numbered steps were mangled. My text wrapper split on spaces only, so a "word" like array.\n2. counted as one long word and lines broke in strange places. The fix was to wrap each line separately so the model's own line breaks survive. The small local model rarely wrote numbered lists, which is why tests with Ollama never caught it.
Markdown leaked into the terminal. The model wrapped its examples in
```javascript fences, which terminals print literally. Now they're stripped before printing.
Both fixes came with tests that reproduce the exact output that broke.
Shipping it properly
The code was the easy half. Making it something strangers can install took more work than I expected:
- The repo had about 14,000 committed
**node_modules**files. Removing them and adding a.gitignoretook the repo from 14,207 files to 43. The tests still passed from a clean install, which proved nothing depended on them. - The npm package ships only what the CLI needs. A
fileslist inpackage.jsonkeeps it to around 20 kB, instead of shipping the VS Code extension, tests and setup scripts too. - Tests gate every publish.
prepublishOnlyruns the full suite (86 tests, on Node's built-in test runner), so a broken build can't reach npm. - Releases are automated. I keep a
CHANGELOG.md. Pushing a version tag triggers a GitHub Actions workflow that runs the tests, checks the tag matchespackage.json, and publishes a GitHub Release using that version's changelog section as the notes.
Try it
npm install -g error-solution-ai-buddy
errbuddy node app.js
It supports JavaScript/Node.js, Java and C#/.NET errors today. Python is next on the list.
GitHub: github.com/sithija-jayasinghe/errbuddy
npm: error-solution-ai-buddy
If it explains an error badly, please open an issue with the error text. Those reports are how the prompts get better.
Thanks for reading! I'm a full-stack developer in Colombo, Sri Lanka, and I'd love to hear how you deal with errors in your own workflow.

Top comments (0)