Reverse Engineering Claude Code's 2026 April Fools
/ 4 min read
Table of Contents
When Claude Code first came out there was a little easter egg discoverable by looking through the source on release day: if you asked about swag, a Google Form would pop up. The Claude Code team actually hand-packed the mailers for the first 1k folks.
Claude Code’s source code was leaked which leads to another easter egg, their April Fools joke this year: a “tamagotchi”-style buddy strangely reminiscent of Figma’s April Fools in 2025, FigPals.
Thanks to the source leak, we can reverse engineer how the buddy system works. Let’s hunt some pokemon buddies:
The Buddy System
Buddies are broken down by rarity, species, eye, hat, shiny, and stats:
| Hat | none , crown , tophat , propeller , halo , wizard , beanie , tinyduck |
| Species | duck , goose , blob , cat , dragon , octopus , owl , penguin , turtle , snail , ghost , axolotl , capybara , cactus , robot , rabbit , mushroom , chonk |
| Eyes | · , ✦ , × , ◉ , @ , ° |
| Shiny | true , false |
| Stats | debugging , patience , chaos , wisdom , snark |
| Rarity | common , uncommon , rare , epic , legendary |
Stats and shiny appear to be dead code, rolled but never consumed. Here’s what they all actually look like:
18 species, each with unique ASCII art and 3 animation frames. Purely cosmetic: species doesn’t affect stats.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ The OG. Subtle tail wag.
(·>
||
_(__)_
^^^^ (·>
||
_(__)_
^^^^ (·>>
||
_(__)_
^^^^ Long neck, menacing energy.
.----. ( · · ) ( ) `----´
.------. ( · · ) ( ) `------´
.--.
(· ·)
( )
`--´ Breathes (expands/contracts).
/\_/\
( · ·)
( ω )
(")_(") /\_/\
( · ·)
( ω )
(")_(")~ /\-/\
( · ·)
( ω )
(")_(") ω mouth. Tail flick on frame 2.
/^\ /^\ < · · > ( ~~ ) `-vvvv-´
/^\ /^\ < · · > ( ) `-vvvv-´
~ ~ /^\ /^\ < · · > ( ~~ ) `-vvvv-´
Smoke puffs on frame 3.
.----. ( · · ) (______) /\/\/\/\
.----. ( · · ) (______) \/\/\/\/
o .----. ( · · ) (______) /\/\/\/\
Tentacles alternate. Ink bubble on frame 3.
/\ /\ ((·)(·)) ( >< ) `----´
/\ /\ ((·)(·)) ( >< ) .----.
/\ /\ ((·)(-)) ( >< ) `----´
Winks on frame 3. Feet shuffle.
.---. (·>·) /( )\ `---´
.---. (·>·) |( )| `---´
.---. (·>·) /( )\ `---´ ~ ~
Flippers alternate. Hops on frame 3.
_,--._ ( · · ) /[______]\ `` ``
_,--._ ( · · ) /[______]\ `` ``
_,--._ ( · · ) /[======]\ `` ``
Shell pattern changes on frame 3.
· .--. \ ( @ ) \_`--´ ~~~~~~~
· .--. | ( @ ) \_`--´ ~~~~~~~
· .--. \ ( @ ) \_`--´ ~~~~~~
Eyestalk sways. Single eye species.
.----. / · · \ | | ~`~``~`~
.----. / · · \ | | `~`~~`~`
~ ~ .----. / · · \ | | ~~`~~`~~
Bottom edge ripples. Floats up on frame 3.
}~(______)~{
}~(· .. ·)~{
( .--. )
(_/ \_) ~}(______){~
~}(· .. ·){~
( .--. )
(_/ \_) }~(______)~{
}~(· .. ·)~{
( -- )
~_/ \_~ Gills wave in alternating directions.
n______n ( · · ) ( oo ) `------´
n______n ( · · ) ( Oo ) `------´
~ ~ u______n ( · · ) ( oo ) `------´
Calm. Occasional nostril twitch.
n ____ n | |· ·| | |_| |_| | |
____
n |· ·| n
|_| |_|
| | n n | ____ | | |· ·| | |_| |_| | |
Arms move up and down between frames.
.[||]. [ · · ] [ ==== ] `------´
.[||]. [ · · ] [ -==- ] `------´
* .[||]. [ · · ] [ ==== ] `------´
Antenna blinks. Mouth pattern shifts.
(\__/)
( · · )
=( .. )=
(")__(") (|__/)
( · · )
=( .. )=
(")__(") (\__/)
( · · )
=( . . )=
(")__(") Ear droops on frame 2. Nose wiggles.
.-o-OO-o-. (__________) |· ·| |____|
.-O-oo-O-. (__________) |· ·| |____|
. o . .-o-OO-o-. (__________) |· ·| |____|
Cap spots shift. Spores on frame 3.
/\ /\ ( · · ) ( .. ) `------´
/\ /| ( · · ) ( .. ) `------´
/\ /\ ( · · ) ( .. ) `------´~
Ear flick on frame 2. Tail wag on frame 3.
6 eye styles. Applied via {E} placeholder substitution in the sprite template.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Default. Minimal, calm.
__
<(✦ )___
( ._>
`--´ __
<(✦ )___
( ._>
`--´~ __
<(✦ )___
( .__>
`--´ Sparkly. Excited energy.
__
<(× )___
( ._>
`--´ __
<(× )___
( ._>
`--´~ __
<(× )___
( .__>
`--´ Dizzy or mischievous.
__
<(◉ )___
( ._>
`--´ __
<(◉ )___
( ._>
`--´~ __
<(◉ )___
( .__>
`--´ Wide-eyed. Alert.
__
<(@ )___
( ._>
`--´ __
<(@ )___
( ._>
`--´~ __
<(@ )___
( .__>
`--´ Digital. Robotic feel.
__
<(° )___
( ._>
`--´ __
<(° )___
( ._>
`--´~ __
<(° )___
( .__>
`--´ Surprised. Hollow stare.
8 hats. Commons always get “none”. Other rarities roll from the full set. Hat replaces the blank top line of the sprite.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Common rarity always gets this.
\^^^/
__
<(· )___
( ._>
`--´ \^^^/
__
<(· )___
( ._>
`--´~ \^^^/
__
<(· )___
( .__>
`--´ \^^^/ — Regal.
[___]
__
<(· )___
( ._>
`--´ [___]
__
<(· )___
( ._>
`--´~ [___]
__
<(· )___
( .__>
`--´ [___] — Classy.
-+-
__
<(· )___
( ._>
`--´ -+-
__
<(· )___
( ._>
`--´~ -+-
__
<(· )___
( .__>
`--´ -+- — Playful.
( )
__
<(· )___
( ._>
`--´ ( )
__
<(· )___
( ._>
`--´~ ( )
__
<(· )___
( .__>
`--´ ( ) — Angelic.
/^\
__
<(· )___
( ._>
`--´ /^\
__
<(· )___
( ._>
`--´~ /^\
__
<(· )___
( .__>
`--´ /^\ — Magical.
(___)
__
<(· )___
( ._>
`--´ (___)
__
<(· )___
( ._>
`--´~ (___)
__
<(· )___
( .__>
`--´ (___) — Cozy.
,>
__
<(· )___
( ._>
`--´ ,>
__
<(· )___
( ._>
`--´~ ,>
__
<(· )___
( .__>
`--´ ,> — A duck on your head.
Rarity sets the stat floor and determines if hats are possible. Commons never get hats; all other rarities can.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Floor: 5. No hat. Peak stat: 55–84.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Floor: 15. Hat possible. Peak: 65–94.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Floor: 25. Hat possible. Peak: 75–100.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Floor: 35. Hat possible. Peak: 85–100.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Floor: 50. Hat possible. Peak: 100.
5 stats are rolled but currently unused: as far as I can tell they don’t affect behavior, visuals, or prompts. Pure bragging rights, like Pokemon IVs that don’t affect battle. Each buddy gets one peak stat and one dump stat.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Peak: floor+50 to floor+79. Dump: floor-10 to floor+4.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Same formula. Just a different slot in the array.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Same formula. The stat names are flavor only.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Same formula. No stat affects any behavior.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Same formula. All five stats are cosmetic.
1% chance, independent of rarity. Like stats, shiny is currently dead code, rolled and stored but never read. No visual difference, no behavior change. A shiny legendary is the rarest possible roll: 0.01% chance.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Default. No visual difference from shiny.
__
<(· )___
( ._>
`--´ __
<(· )___
( ._>
`--´~ __
<(· )___
( .__>
`--´ Flagged but unused. Maybe someday…
Your buddy is determined strictly by your userId and a fixed SALT:
export function companionUserId(): string { const config = getGlobalConfig(); return config.oauthAccount?.accountUuid ?? config.userID ?? "anon";}
export function roll(userId: string): Roll { const key = userId + SALT; if (rollCache?.key === key) return rollCache.value; const value = rollFrom(mulberry32(hashString(key))); rollCache = { key, value }; return value;}Notice mulberry32 being used: a 32-bit deterministic pseudo-random number generator. It is not cryptographically secure, but the source indicates it is “good enough for picking ducks”. Because it operates in a 32-bit space, there are exactly 2^32 (about 4.29 billion) possible PRNG states, which is trivial for a modern CPU to brute force in seconds. That means you can pick any combo you want and find a matching UUID in seconds, just using your browser. So let’s do exactly that…
Build your own
Choose your ideal species, eyes, hat, rarity, and shiny. We’ll brute-force a UUID that rolls your exact combo, right in your browser:
click a trait to start To use your UUID, edit ~/.claude.json and change oauthAccount.accountUuid to the generated value, then restart Claude Code. As far as I can tell, changing this value has no negative effect on how Claude Code operates, but it doesn’t hurt to capture a backup first.
Since the name and personality are LLM-generated (not deterministic), they’re stored in a separate companion section you can also customize freely:
{ "oauthAccount": { "accountUuid": "461d455b-53f9-4f07-87c5-46dc0e2db302" }, "companion": { "name": "Gristle", "personality": "Insists every variable name should rhyme with the one above it." }}So go ahead, build your shiny wizard axolotl, give it whatever name you want, and let it judge your code.
But wait: there’s more!
This post was written before the buddy system came out, now that it is out in Claude Code v2.1.89 (just type /buddy) I’ve uncovered a little more info.
It looks like buddies also get names, and all the previously unused stats (shiny, etc.) influence the name and personality. Here’s the system prompt:
You generate coding companions — small creatures that live in a developer’s terminal and occasionally comment on their work.
Given a rarity, species, stats, and a handful of inspiration words, invent:
- A name: ONE word, max 12 characters. Memorable, slightly absurd. No titles, no “the X”, no epithets. Think pet name, not NPC name. The inspiration words are loose anchors — riff on one, mash two syllables, or just use the vibe. Examples: Pith, Dusker, Crumb, Brogue, Sprocket.
- A one-sentence personality (specific, funny, a quirk that affects how they’d comment on code — should feel consistent with the stats)
Higher rarity = weirder, more specific, more memorable. A legendary should be genuinely strange. Don’t repeat yourself — every companion should feel distinct.
The user message is templated with the buddy’s rolled traits and 4 random inspiration words picked from a bank, e.g.:
Generate a companion.Rarity: LEGENDARYSpecies: owlStats: debugging:86 patience:51 chaos:80 wisdom:71 snark:100Inspiration words: cobble, fennel, apex, murmurSHINY variant — extra special.
Make it memorable and distinct.If the API call fails, it falls back to one of 6 hardcoded default names. Here’s the 6 hardcoded fallback names and the complete 156-word inspiration bank:
| Defaults | Crumpet , Soup , Pickle , Biscuit , Moth , Gravy |
| Inspiration | thunder , biscuit , void , accordion , moss , velvet , rust , pickle , crumb , whisper , gravy , frost , ember , soup , marble , thorn , honey , static , copper , dusk , sprocket , bramble , cinder , wobble , drizzle , flint , tinsel , murmur , clatter , gloom , nectar , quartz , shingle , tremor , umber , waffle , zephyr , bristle , dapple , fennel , gristle , huddle , kettle , lumen , mottle , nuzzle , pebble , quiver , ripple , sable , thistle , vellum , wicker , yonder , bauble , cobble , doily , fickle , gambit , hubris , jostle , knoll , larder , mantle , nimbus , oracle , plinth , quorum , relic , spindle , trellis , urchin , vortex , warble , xenon , yoke , zenith , alcove , brogue , chisel , dirge , epoch , fathom , glint , hearth , inkwell , jetsam , kiln , lattice , mirth , nook , obelisk , parsnip , quill , rune , sconce , tallow , umbra , verve , wisp , yawn , apex , brine , crag , dregs , etch , flume , gable , husk , ingot , jamb , knurl , loam , mote , nacre , ogle , prong , quip , rind , slat , tuft , vane , welt , yarn , bane , clove , dross , eave , fern , grit , hive , jade , keel , lilt , muse , nape , omen , pith , rook , silt , tome , urge , vex , wane , yew , zest |
There’s also an interesting “reaction” system: occasionally (or when addressed directly) your buddy will react to what is going on in your Claude Code session. As you would expect, the endpoint (POST /api/organizations/{org_uuid}/claude_code/buddy_react) also takes the buddy’s name, personality, species, rarity, and stats (debugging, patience, chaos, wisdom, snark) into account. These reactions don’t count against your usage quota though… free inference, anybody?