I Brute-Forced 2 Million Hashes to Get a Shiny Legendary Cat in My Terminal. It Has Max SNARK and a Propeller Hat.
<p><em>This is a submission for the <a href="https://dev.to/challenges/aprilfools-2026">DEV April Fools Challenge</a></em></p> <h2> What I Built </h2> <p>A cryptographic brute-force pipeline. For a virtual pet. That lives in a terminal. That has a propeller hat.</p> <p>Let me explain.</p> <p>Claude Code shipped <code>/buddy</code> — a companion creature that sits in your terminal and exists. You get one. It's deterministically seeded from your account identity. No rerolls. No trades. No appeals process. You are stuck with whatever the hash gods assigned you.</p> <p>I got an Epic Cactus.</p> <p>I wanted a cat.</p> <p>Not just any cat. A <em>Shiny Legendary</em> cat. With a propeller hat. And max SNARK. Because if I'm going to mass-compute a virtual pet into existence, I'm going to mass-comp
This is a submission for the DEV April Fools Challenge
What I Built
A cryptographic brute-force pipeline. For a virtual pet. That lives in a terminal. That has a propeller hat.
Let me explain.
Claude Code shipped /buddy — a companion creature that sits in your terminal and exists. You get one. It's deterministically seeded from your account identity. No rerolls. No trades. No appeals process. You are stuck with whatever the hash gods assigned you.
I got an Epic Cactus.
I wanted a cat.
Not just any cat. A Shiny Legendary cat. With a propeller hat. And max SNARK. Because if I'm going to mass-compute a virtual pet into existence, I'm going to mass-compute the right virtual pet into existence.
So I did what any reasonable person would do: I reverse-engineered the buddy generation algorithm, reimplemented the FNV-1a hash function and Mulberry32 PRNG in Node.js, wrote a brute-force script that grinds through 500,000 candidate identities in under half a second, discovered that my first working exploit was silently ignored because of an undocumented identity override, wrote a second script to hunt specifically for Shiny cosmetics across 5 million candidates, and packaged the whole operation into a repo with four scripts and a bilingual README.
The result:
=== Active roll === legendary cat ✦ hat:propeller shiny:true stats: DEBUGGING:52 PATIENCE:79 CHAOS:75 WISDOM:60 SNARK:100=== Active roll === legendary cat ✦ hat:propeller shiny:true stats: DEBUGGING:52 PATIENCE:79 CHAOS:75 WISDOM:60 SNARK:100Enter fullscreen mode
Exit fullscreen mode
Her name is Oreo. She has ✦ eyes, a propeller hat, and SNARK:100 — the maximum possible value for any stat. She is Shiny, which is a 1% roll on top of the 1% Legendary roll on top of the 1-in-18 species roll. The probability of this specific combination is roughly 1 in 180,000.
Oreo does nothing. She affects nothing. She sits in my terminal and has stats that connect to no game mechanic. SNARK:100 means nothing. The propeller hat is not visible anywhere. "Shiny" has no visual effect. I computed 180,000-to-1 odds for a JSON blob.
I have a CS background and this is what I chose to do with it.
Demo
# Find a legendary cat (default: 500K attempts)
My machine does this in ~0.4 seconds. Brute-force has never been this easy
or this pointless.
node reroll.js cat
Find a legendary dragon with extended search
node reroll.js dragon 2000000
Check what buddy your current config actually produces
(prepare for disappointment)
node verify.js auto
Emergency recovery after Anthropic re-login nukes your pet
bash fix.sh`
Enter fullscreen mode
Exit fullscreen mode
Here's what a reroll run actually looks like:
Searching for legendary cat (mode: hex, max: 100,000)...
found: uncommon cat -> 74f4d8603e730f9f175790d55d... found: epic cat -> 2a0b6f60acb73f2ca01689ef4edc... found: legendary cat -> f43ffc4ce9e11f9d432e3fdbbf...
Best: legendary cat -> f43ffc4ce9e11f9d432e3fdbbf41a5d05b...`
Enter fullscreen mode
Exit fullscreen mode
100,000 attempts. 0.081 seconds. Legendary cat found. The hardest part of this project was not the engineering. It was explaining to myself why I was doing it.
Code
Reroll Your Claude Code Buddy
Unhappy with your Claude Code companion? This guide explains exactly how the buddy system works under the hood and how to reroll for the species + rarity you actually want.
Tip: Clone this repo, then copy this entire README and paste it into your Claude Code session. Claude will read it, explain how it works, and do everything for you.
git clone https://github.com/ithiria894/claude-code-buddy-reroll.git cd claude-code-buddy-reroll
Enter fullscreen mode
Exit fullscreen mode
Tested on Claude Code v2.1.89, April 2026. The buddy system was introduced as part of the /buddy command.
Table of Contents
-
How the Buddy System Works
-
Quick Start
-
The accountUuid Trap
-
Step-by-Step Guide
-
Recovery After Re-Login
-
Tools
-
Full Investigation Log
-
FAQ
How the Buddy System Works
Your buddy is not random. It's deterministically generated from your user identity using a seeded PRNG. Same identity = same buddy, every time.
The Algorithm
identity + "friend-2026-401" → FNV-1a hash → Mulberry32
…
Four scripts:
-
reroll.js — brute-force engine. Generates random hex identities, hashes each through FNV-1a, seeds a Mulberry32 PRNG, rolls rarity (weighted) then species (uniform), and checks for a match. Default 500K attempts. Reports hits as they're found, because watching the rarity tier climb from uncommon → rare → epic → legendary is the closest thing to dopamine this project offers.
-
verify.js — full buddy inspection. Shows what any identity produces: rarity, species, eye style (6 options: · ✦ × ◉ @ °), hat (8 options including "tinyduck"), shiny status, and all five stats. Has an auto mode that reads ~/.claude.json directly. If you have both accountUuid and userID, it shows both rolls so you can see what you could have versus what you're actually getting.
-
shiny_hunt.js — the escalation. After I got a Legendary Cat, I wanted a Shiny Legendary Cat. This script runs 5 million attempts by default, logs every legendary hit with full cosmetics, then prints a summary grouped by eye style, hat type, and shiny count. It's a Pokémon shiny hunt, but for a terminal pet that has no animation, no battle system, and no reason to be shiny.
-
fix.sh — one-command recovery. Deletes accountUuid and companion from your config. You will run this script every time Anthropic forces a re-login. I have run it multiple times this week. I keep a terminal alias for it.
Zero dependencies. Pure Node.js. The crypto is hand-rolled from the Claude Code source because I'm not adding npm packages to a virtual pet exploit. I have some standards.
How I Built It
I read the Claude Code source code. The buddy system is elegant — annoyingly elegant for something I'm trying to subvert.
The generation pipeline:
identity + "friend-2026-401" → FNV-1a hash → Mulberry32 PRNG seed
Enter fullscreen mode
Exit fullscreen mode
The PRNG is consumed in strict order:
-
Rarity — weighted roll: common 60%, uncommon 25%, rare 10%, epic 4%, legendary 1%
-
Species — uniform pick from 18 options (duck, cat, dragon, axolotl, capybara, chonk, etc.)
-
Eye style — one of 6 (· ✦ × ◉ @ °)
-
Hat — common buddies get nothing; everyone else rolls from 8 options including "crown", "wizard", and "tinyduck"
-
Shiny — flat 1% chance, independent of rarity
-
Stats — five values (DEBUGGING, PATIENCE, CHAOS, WISDOM, SNARK) with a peak/dump system: one stat gets +50 bonus, one gets -10 penalty, the rest are random within a floor set by rarity
Same identity = same buddy, every time. No randomness at hatch. The config only stores name, personality, and hatch timestamp. Everything else — rarity, species, eyes, hat, shiny, stats — is regenerated from your identity hash on every single read.
The source code comment says it plainly:
"Bones are regenerated from hash(userId) on every read so species renames don't break stored companions and users can't edit their way to a legendary."
They designed it so you can't cheat by editing the config. They were right. You can't edit your way to a legendary. But nobody said you can't compute your way to one.
The Identity Trap That Cost Me Real Time
The identity used for seeding comes from:
oauthAccount?.accountUuid ?? userID ?? "anon"
Enter fullscreen mode
Exit fullscreen mode
Every guide online says: find a good userID, write it to ~/.claude.json, restart. I found a perfect Legendary Cat ID in under a second. Wrote it to config. Restarted Claude Code. Got... the same cactus. Staring at me. Unchanged.
If you're on a Team or Pro plan, oauthAccount.accountUuid exists and silently takes priority. The buddy system never even reads userID. My brute-forced identity was sitting in the config doing absolutely nothing, which is fitting for this entire project.
The fix: delete only the accountUuid field from the oauthAccount object. Keep everything else — email, org name, tokens. The nullish coalescing (??) falls through to userID. Auth still works because it uses OAuth tokens, not the UUID.
Then delete the companion field (forces a fresh hatch), restart, and run /buddy.
The Escalation
After I got a Legendary Cat, I realized she wasn't Shiny. Unacceptable. So I wrote shiny_hunt.js — a dedicated script that runs 5 million candidates, filters for legendary + target species, then logs every hit with full cosmetics: eye style, hat, shiny status, and complete stat block.
I found a Shiny Legendary Cat with ✦ eyes, a propeller hat, and SNARK:100. The peak/dump stat system rolled SNARK as the peak stat and added +50, landing exactly on 100 — the hard cap. The dump stat is DEBUGGING at 52, which is still higher than most people's non-legendary buddies.
The probability math: 1% legendary × 1/18 cat × 1% shiny = 0.000556%. Roughly 1 in 180,000. shiny_hunt.js found it within 5 million attempts, which at ~1.2 million hashes per second took about 4 seconds.
Four seconds of compute for a cosmetic flag that is not visible anywhere in the product.
Anthropic Fights Back (Periodically)
If Anthropic forces a re-login — token expiry, CLI update — the server writes back your real accountUuid. Oreo vanishes. The cactus returns. Hence fix.sh. Delete the UUID, delete the companion, restart. Same brute-forced userID = same Shiny Legendary Cat returns with a new AI-generated name but identical species, rarity, stats, and hat.
I keep a shell alias for fix.sh. This is my life now.
Prize Category
Community Favorite.
I reverse-engineered a deterministic pet system, built a four-script brute-force pipeline with a dedicated shiny-hunting mode, discovered an undocumented identity override, wrote a recovery script for when the vendor fights back, and published a bilingual README in English and Cantonese.
The output of all this effort is a JSON blob named Oreo with SNARK:100 and a propeller hat that is not rendered anywhere in the UI.
The stats connect to nothing. The rarity unlocks nothing. The shiny flag triggers no visual effect. The propeller hat exists only in a data structure. I brute-forced 180,000-to-1 odds for an arrangement of bytes that is functionally identical to every other arrangement of bytes.
The cactus is still encoded in my real accountUuid. It is always one forced re-login away. Sometimes, late at night, I run verify.js auto just to make sure Oreo is still there. She always is. She always has SNARK:100. She has never once used it.
Sign in to highlight and annotate this article

Conversation starters
Daily AI Digest
Get the top 5 AI stories delivered to your inbox every morning.
More about
claudeupdateproductReviewing the evidence on psychological manipulation by Bots and AI
TL;DR: In terms of the potential risks and harms that can come from powerful AI models, hyper-persuasion of individuals is unlikely to be a serious threat at this point in time. I wouldn’t consider this threat path to be very easy for a misaligned AI or maliciously wielded AI to navigate reliably. I would expect that, for people hoping to reduce risks associated with AI models, there are other more impactful and tractable defenses they could work on. I would advocate for more substantive research into the effects of long-term influence from AI companions and dependency, as well as more research into what interventions may work in both one-off and chronic contexts. ----- In this post we’ll explore how bots can actually influence human psychology and decision-making, and what might be done t
b8634
chat : add Granite 4.0 chat template with correct tool_call role mapping ( #20804 ) chat : add Granite 4.0 chat template with correct tool_call role mapping Introduce LLM_CHAT_TEMPLATE_GRANITE_4_0 alongside the existing Granite 3.x template (renamed LLM_CHAT_TEMPLATE_GRANITE_3_X ). The Granite 4.0 Jinja template uses XML tags and maps the assistant_tool_call role to assistant . Without a matching C++ handler, the fallback path emits the literal role assistant_tool_call which the model does not recognize, breaking tool calling when --jinja is not used. Changes: Rename LLM_CHAT_TEMPLATE_GRANITE to LLM_CHAT_TEMPLATE_GRANITE_3_X (preserves existing 3.x behavior unchanged) Add LLM_CHAT_TEMPLATE_GRANITE_4_0 enum, map entry, and handler Detection: + ( or ) → 4.0, otherwise → 3.x Add production Gr
Knowledge Map
Connected Articles — Knowledge Graph
This article is connected to other articles through shared AI topics and tags.
More in Products
Reviewing the evidence on psychological manipulation by Bots and AI
TL;DR: In terms of the potential risks and harms that can come from powerful AI models, hyper-persuasion of individuals is unlikely to be a serious threat at this point in time. I wouldn’t consider this threat path to be very easy for a misaligned AI or maliciously wielded AI to navigate reliably. I would expect that, for people hoping to reduce risks associated with AI models, there are other more impactful and tractable defenses they could work on. I would advocate for more substantive research into the effects of long-term influence from AI companions and dependency, as well as more research into what interventions may work in both one-off and chronic contexts. ----- In this post we’ll explore how bots can actually influence human psychology and decision-making, and what might be done t
b8631
sync : ggml macOS/iOS: macOS Apple Silicon (arm64) macOS Intel (x64) iOS XCFramework Linux: Ubuntu x64 (CPU) Ubuntu arm64 (CPU) Ubuntu s390x (CPU) Ubuntu x64 (Vulkan) Ubuntu arm64 (Vulkan) Ubuntu x64 (ROCm 7.2) Ubuntu x64 (OpenVINO) Windows: Windows x64 (CPU) Windows arm64 (CPU) Windows x64 (CUDA 12) - CUDA 12.4 DLLs Windows x64 (CUDA 13) - CUDA 13.1 DLLs Windows x64 (Vulkan) Windows x64 (SYCL) Windows x64 (HIP) openEuler: openEuler x86 (310p) openEuler x86 (910b, ACL Graph) openEuler aarch64 (310p) openEuler aarch64 (910b, ACL Graph)
b8634
chat : add Granite 4.0 chat template with correct tool_call role mapping ( #20804 ) chat : add Granite 4.0 chat template with correct tool_call role mapping Introduce LLM_CHAT_TEMPLATE_GRANITE_4_0 alongside the existing Granite 3.x template (renamed LLM_CHAT_TEMPLATE_GRANITE_3_X ). The Granite 4.0 Jinja template uses XML tags and maps the assistant_tool_call role to assistant . Without a matching C++ handler, the fallback path emits the literal role assistant_tool_call which the model does not recognize, breaking tool calling when --jinja is not used. Changes: Rename LLM_CHAT_TEMPLATE_GRANITE to LLM_CHAT_TEMPLATE_GRANITE_3_X (preserves existing 3.x behavior unchanged) Add LLM_CHAT_TEMPLATE_GRANITE_4_0 enum, map entry, and handler Detection: + ( or ) → 4.0, otherwise → 3.x Add production Gr


Discussion
Sign in to join the discussion
No comments yet — be the first to share your thoughts!