After seeing the 'buddy' feature introduced in Claude Code recently, I wanted to build a desktop version of that. Something that sits there and occasionally reacts to what you're doing.
The problem is LLM calls cost money, and paying per reaction for a silly pet app felt wrong.
Then I found something interesting.
The person who started it
There's a project called BonziClaude by zakarth. Bonzi Buddy but for Claude Code -- a little companion that watches your terminal and reacts to what you're doing. Same concept I had.
His readme documented something that caught my eye: an undocumented Anthropic endpoint that Claude Code uses internally for its buddy feature. The little creature that sits in your Claude Code session and comments on your work is powered by a real API call. He figured out what that call looks like.
\buddy pet !
In April 2025, Anthropic quietly shipped a companion feature inside Claude Code. A small ASCII creature that lives in your terminal session, watches what you're doing, and occasionally reacts -- cheering you on, roasting your code, commenting on errors. No announcement. It just appeared in an update.
What made it interesting is that Anthropic also accidentally leaked parts of the Claude Code source around the same time. Inside that source was the entire companion system: sprite definitions, animation sequences, the bone-rolling logic (how each user gets a deterministic species and stats), the soul generation, all of it. Every species, every frame, every hat. Full system. You can read about it in detail in my previous blog post.
I ported that directly.
The free endpoint
Claude code ships as a native executable but it's not really compiled code. it's a bun-bundled javascript app, the entire thing is minified JS packed inside a binary. You can find it at ~/.local/share/claude/versions/{version}/claude on linux or the equivalent on mac. if you run strings on it or just open it in a text editor and scroll past the binary header, you hit a wall of minified JS. inside that bundle there's a function (obfuscated to something like Oo_) that posts to:
POST https://api.anthropic.com/api/organizations/{your-org-uuid}/claude_code/buddy_react
What you send it
| field | what it is | cap |
|---|---|---|
name |
companion's name | 32 chars |
personality |
the system prompt | 200 chars |
species |
companion species (duck, ghost, robot...) | -- |
rarity |
common / uncommon / rare / epic / legendary | -- |
stats |
DEBUGGING, PATIENCE, CHAOS, WISDOM, SNARK scores | -- |
transcript |
conversation or activity context | 5000 chars |
reason |
why it's reacting | -- |
recent |
last few replies, to avoid repetition | 3 entries, 200 chars each |
addressed |
whether the user talked to the companion directly | bool |
The reason field
This tells the model what triggered the reaction. The original values from the leaked source:
| value | when |
|---|---|
turn |
normal conversation reply |
hatch |
companion is being created for the first time |
pet |
user pets the companion |
error |
an error was detected |
test-fail |
tests failed |
large-diff |
a big code diff was produced |
What you get back
{ "reaction": "*ears twitch*\n\noff-by-one error hiding in plain sight, naturally." }
The limits
| thing | limit |
|---|---|
| model | claude 3.5 sonnet |
input context (transcript) |
5000 chars |
system prompt (personality) |
200 chars |
output (reaction) |
~350 chars, truncated server-side |
| quota cost | none |
The model is Claude 3.5 Sonnet. Not Haiku. Actual Sonnet. And it doesn't count against your usage quota. It's a separate endpoint from /v1/messages, metered differently because it's intended for the companion feature, not general inference.
The limits are tight -- short reactions, not essays. But if you're clever, you can use the personality field as a system prompt and transcript as your conversation, and it works as a general chat backend.
Auth
You need a Claude Code OAuth token and your org UUID. If you're logged into Claude Code, both of these already live on your machine. The token is in your keychain under Claude Code-credentials and the org UUID comes from hitting /api/oauth/profile.
No new accounts, no API keys, nothing to pay for. Just reuse the session you already have.
What I built
A small Electron app -- a desktop companion chat. You hatch a companion (random species, name generated by the model itself), it lives at the top of the window as an ASCII sprite, and you can chat with it below.
The whole LLM backend is the buddy_react endpoint. No SDK, no API key, no cost. Just native fetch to the same endpoint Claude Code uses for its own pet feature.
Every companion gets a randomly rolled personality (DEBUGGING, PATIENCE, CHAOS, WISDOM, SNARK stats), a species (duck, ghost, capybara, robot, etc), and a name the model picks based on its traits. It persists between sessions. You can rehatch to get a new one if you don't vibe with it.
The ASCII sprites and the entire companion system are ported directly from the leaked Claude Code source -- same frames, same blink sequences, same eye substitution, same bone-rolling algorithm. As close to the real thing as you can get outside of Claude Code itself.
The funny part
Anthropic built a little mascot system into their CLI tool, leaked the source for it, documented none of the API externally, and accidentally made it into a free inference endpoint for anyone who's already paying for Claude Code.
Probably not intentional. Probably won't last forever. But it works right now and it's a fun thing to build with.
The app is on GitHub: voodootuna/desktop-companion