第八章:我是如何剖析 Claude Code 里的“电子宠物”彩蛋的

张开发
2026/6/4 18:24:41 15 分钟阅读
第八章:我是如何剖析 Claude Code 里的“电子宠物”彩蛋的
大家好我又来了。本来以为写完第七章的性能优化这个系列就该画个句号了。但本着“贼不走空”的极客精神我又在源码的src目录下瞎溜达了一圈。结果在一个叫src/buddy/的隐秘角落里我挖到了 Anthropic 工程师们藏的一个惊天大彩蛋——他们居然在一个硬核的 CLI 效率工具里偷偷塞了个电子宠物Buddy系统你想啊在这个枯燥的命令行世界里当你每天被满屏的报错、跑不通的单测折磨得想砸键盘的时候如果终端角落里能有一只专属于你的、独一无二的小鸭子或者小恐龙陪着你是不是瞬间就觉得没那么烦躁了今天咱们就当个番外篇不聊什么高深架构纯粹用扒一扒代码的方式看看牛啤工程师们的浪漫是怎么写进代码里的。源码里藏着什么好玩的翻开src/buddy/目录你会发现他们不仅写了个彩蛋还真把它当成个微型 RPG 游戏在做看看他们是怎么用伪随机数生成器PRNG来搞“抽卡”的。看看为了防作弊防止玩家改配置刷极品宠物他们是怎么设计“骨肉分离”的数据结构的。甚至为了躲开代码扫描工具的误伤他们是怎么给宠物种类名字“加密”的。1. 抽卡机制与 Mulberry32 算法这只小宠物是怎么“生”出来的呢如果你打开src/buddy/companion.ts你会看到一个叫mulberry32的函数。为了保证你的宠物虽然属性是随机的但只要“种子Seed”不变你每次打开终端它都长得一模一样他们专门手搓了这个轻量级的伪随机数算法。官方还在注释里调侃了一句// src/buddy/companion.ts// Mulberry32 — tiny seeded PRNG, good enough for picking ducks// 翻译“足够用来抽鸭子了” functionmulberry32(seed:number):()number{letaseed0returnfunction(){a|0a(a0x6d2b79f5)|0lettMath.imul(a^(a15),1|a)t(tMath.imul(t^(t7),61|t))^treturn((t^(t14))0)/4294967296}}他们把你的账号 ID 或者本地标识userId SALT哈希处理后当做 Seed。这意味着什么这意味着从你用 Claude Code 的那一刻起你的这台电脑、这个账号注定只会孵化出那只命中注定的宠物。2. 稀有度、属性与“闪光”设定玩过抽卡手游的兄弟们都知道SSR 有多难出。Anthropic 的工程师们把这套拿捏得死死的。在src/buddy/types.ts里我看到了完整的概率表RARITY_WEIGHTSCommon普通: 60%Uncommon罕见: 25%Rare稀有: 10%Epic史诗: 4%Legendary传说: 1%宠物甚至有五维属性DEBUGGING调试、PATIENCE耐心、CHAOS混沌、WISDOM智慧、SNARK毒舌。稀有度越高属性的保底值就越高。而且每次生成必定有一个巅峰属性和一个拉胯的“下水道”属性。最离谱的是他们还加了个类似宝可梦的“闪光shiny”机制只有可怜的 1% 概率触发// 只有不到百分之一的欧皇能拿到闪光宠物shiny:rng()0.01,3. 防作弊设计骨肉分离的“灵魂”既然属性这么难抽那我直接去改本地配置文件config.json给自己捏个“闪光传说级”宠物不就行了抱歉你想到的工程师早想到了。他们把宠物的数据拆成了两半CompanionBones骨架和CompanionSoul灵魂。灵魂名字、性格是由大模型根据你的属性自动生成的保存在你的本地配置里。骨架稀有度、种类、属性、外观从来不保存每次启动时它都会严格根据你的userId重新计算一遍。源码里是这么写的// src/buddy/companion.ts// What actually persists in config. Bones are regenerated from hash(userId)// on every read so... users cant edit their way to a legendary.// 翻译骨架每次读取时从哈希重新生成这样玩家就没法通过改配置来刷传说宠物了。这波操作直接把想作弊的黑客们按死在了起跑线上。4. 为了躲避扫描连物种名都加密了在看物种列表时我发现了一段极其诡异的代码。普通的数组定义不写非要用String.fromCharCode把字母一个个拼出来// src/buddy/types.tsconstcString.fromCharCodeexportconstduckc(0x64,0x75,0x63,0x6b)asduck// 鸭子exportconstoctopusc(0x6f,0x63,0x74,0x6f,0x70,0x75,0x73)asoctopus// 章鱼为什么要这么搞注释里给出了答案原来他们内部有一个“敏感词扫描”工具用来防止代码里泄露正在研发的 AI 模型代号codename。结果很不巧某个宠物的名字跟内部未发布的模型代号撞车了为了不让扫描工具天天报假警工程师干脆把所有的宠物名字都在运行时动态拼装绕过了静态扫描。这真是一个被逼出来的机智操作啊最后这才是工程师的浪漫看完整个src/buddy/模块我确实被这帮老外圈粉了。在一个承载着巨量代码、复杂的 AST 解析、深度的 MCP 协议的硬核效率工具里在一个每天都在卷性能、卷大模型智商的环境下他们依然愿意花时间写这么一套对核心功能毫无帮助、却趣味拉满的代码。可能它只是终端里一只戴着高顶礼帽、长着星星眼的 ASCII 小鸭子但它确实能在某个深夜给那些对着屏幕抓头发的程序员们带来一丝会心的微笑。这大概就是写代码最纯粹的乐趣吧。开源我自己也做了一个桌宠还在迭代中CodeWalkers让 AI 助手化身桌面宠物陪你敲代码的赛博伙伴源码地址https://github.com/you-want/CodeWalkers 欢迎给个 Star ✨。

更多文章