cb-zoo is a zero-dependency Node.js CLI and terminal UI for rolling, collecting, and applying Claude Code buddies.
It is a Claude Code companion manager with a retro terminal UI, gacha-style roll flow, unified local settings storage, local collection tracking, and backup/restore support for Claude UUID state.
If the embedded video does not render on GitHub, watch it here.
- Default interactive terminal UI for rolling and browsing buddies
- Fast plain CLI flow with
--quickand--plain - Interactive no-flag TTY launches the TUI, while explicit command flags and non-interactive runs stay on plain CLI-safe paths
- Current buddy inspection with UUID-derived traits plus stored profile data
- Unified local settings saved in
~/.cb-zoo/settings.jsonfor backup data, collection capacity, pending roll state, and breed config/state - Shared roll-charge tracking in
~/.cb-zoo/settings.json, with configurable regen interval and max-charge cap - Local collection saved in
~/.cb-zoo/collection.json - Collection surfaces show current capacity, and saves stop at
maxBuddyentries (50by default) - TUI rolls persist unsaved reveals so the "Resume Roll" action restores the pending buddy after backing out or restarting
- TUI breeding uses configurable slot-based incubation stored in
settings.json, so multiple eggs can survive restarts and hatch from a dedicated slot picker - HOME keeps a stable
Breed Buddyaction while a slot summary box shows ready, incubating, and empty breed slots - Backup and restore flow for the original Claude UUID
- Zero runtime npm dependencies
Breed results are symmetric: duck × goose gives the same offspring as goose × duck. Breeding the same species with itself returns that same species.
| A × B | duck | goose | blob | cat | dragon | octopus | owl | penguin | turtle | snail | ghost | axolotl | capybara | cactus | robot | rabbit | mushroom | chonk |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| duck | duck | goose | duck | cat | dragon | axolotl | owl | penguin | turtle | snail | snail | duck | duck | owl | duck | goose | duck | duck |
| goose | goose | goose | blob | goose | dragon | octopus | owl | penguin | goose | snail | ghost | axolotl | capybara | cactus | goose | rabbit | mushroom | chonk |
| blob | duck | blob | blob | blob | dragon | blob | owl | penguin | turtle | snail | dragon | penguin | goose | dragon | blob | blob | blob | blob |
| cat | cat | goose | blob | cat | dragon | octopus | owl | cat | turtle | cat | ghost | cat | cat | cactus | cat | cat | cat | cat |
| dragon | dragon | dragon | dragon | dragon | dragon | dragon | dragon | penguin | turtle | snail | ghost | dragon | capybara | cactus | robot | rabbit | mushroom | chonk |
| octopus | axolotl | octopus | blob | octopus | dragon | octopus | owl | penguin | octopus | snail | ghost | axolotl | octopus | cactus | octopus | octopus | mushroom | octopus |
| owl | owl | owl | owl | owl | dragon | owl | owl | penguin | turtle | owl | ghost | axolotl | capybara | cactus | robot | owl | mushroom | chonk |
| penguin | penguin | penguin | penguin | cat | penguin | penguin | penguin | penguin | turtle | snail | ghost | axolotl | capybara | duck | robot | rabbit | penguin | chonk |
| turtle | turtle | goose | turtle | turtle | turtle | octopus | turtle | turtle | turtle | snail | ghost | axolotl | capybara | cactus | robot | rabbit | turtle | turtle |
| snail | snail | snail | snail | cat | snail | snail | owl | snail | snail | snail | ghost | axolotl | capybara | cactus | robot | goose | mushroom | blob |
| ghost | snail | ghost | dragon | ghost | ghost | ghost | ghost | ghost | ghost | ghost | ghost | axolotl | capybara | cactus | robot | rabbit | mushroom | blob |
| axolotl | duck | axolotl | penguin | cat | dragon | axolotl | axolotl | axolotl | axolotl | axolotl | axolotl | axolotl | capybara | duck | robot | rabbit | mushroom | goose |
| capybara | duck | capybara | goose | cat | capybara | octopus | capybara | capybara | capybara | capybara | capybara | capybara | capybara | goose | robot | rabbit | duck | chonk |
| cactus | owl | cactus | dragon | cactus | cactus | cactus | cactus | duck | cactus | cactus | cactus | duck | goose | cactus | robot | rabbit | mushroom | chonk |
| robot | duck | goose | blob | cat | robot | octopus | robot | robot | robot | robot | robot | robot | robot | robot | robot | rabbit | octopus | chonk |
| rabbit | goose | rabbit | blob | cat | rabbit | octopus | owl | rabbit | rabbit | goose | rabbit | rabbit | rabbit | rabbit | rabbit | rabbit | mushroom | chonk |
| mushroom | duck | mushroom | blob | cat | mushroom | mushroom | mushroom | penguin | turtle | mushroom | mushroom | mushroom | duck | mushroom | octopus | mushroom | mushroom | chonk |
| chonk | duck | chonk | blob | cat | chonk | octopus | chonk | chonk | turtle | blob | blob | goose | chonk | chonk | chonk | chonk | chonk | chonk |
npm install -g cb-zooOr run it without a global install:
npx cb-zoo --help- Node.js 18+
- Claude Code initialized at least once so its account state file exists, usually
~/.claude.jsonor$CLAUDE_CONFIG_DIR/.claude.json
Back up your current Claude UUID before doing anything else:
cb-zoo --backupThis stores your original UUID in ~/.cb-zoo/settings.json so you can always restore it later.
Open the TUI:
cb-zooThen use:
Roll Buddyto roll or resume a pending revealCollectionto browse, apply, or delete saved buddiesBreed Buddyto manage breed slots, incubate eggs, and hatch offspringCurrent Buddyto inspect the UUID currently applied to Claude CodeEdit Current Buddyto rename the stored companion or change personality text
cb-zoo --quick
cb-zoo --current
cb-zoo --collection
cb-zoo --restorecb-zoo --quickruns the fast plain reveal flowcb-zoo --currentprints the currently active buddycb-zoo --collectionprints the saved collectioncb-zoo --restorerestores the backed-up UUID
cb-zooOpens the default interactive TUI in a real terminal.cb-zoo --quickUses the fast plain reveal flow.cb-zoo --plainForces the legacy non-TUI CLI flow.cb-zoo --currentShows the current buddy by merging stored profile data with UUID-derived traits.cb-zoo --collectionShows the saved collection.cb-zoo --set-name "Nova"Updates the stored companion name.cb-zoo --set-personality "Calm under pressure."Updates the stored companion personality.cb-zoo --backupCreates the UUID backup in~/.cb-zoo/settings.jsonif it does not already exist.cb-zoo --restoreRestores the backed-up UUID.
- Run
cb-zoo --backuponce before your first reroll. - Keep that backup UUID untouched unless you intentionally want to replace it.
- If something looks wrong after rerolling or breeding, run
cb-zoo --restore. - Re-run
cb-zoo --backuponly if you intentionally want to pin a different baseline UUID.
If you skip the backup step, recovery is weaker. The safest habit is: back up first, then roll.
Main local state lives in:
~/.cb-zoo/settings.jsonTypical shape:
{
"backup": {
"uuid": "00000000-0000-4000-8000-000000000000",
"stateFile": "C:\\Users\\you\\.claude.json",
"backedUpAt": "2026-04-03T12:00:00.000Z"
},
"maxBuddy": 50,
"rollConfig": {
"maxCharges": 100,
"regenMs": 300000
},
"rollCharges": {
"available": 100,
"updatedAt": 1775217600000
},
"breedConfig": {
"slotCount": 3,
"hatchTimes": {
"common": 10000,
"uncommon": 30000,
"rare": 60000,
"epic": 120000,
"legendary": 300000
}
},
"breedSlots": [
null,
null,
null
],
"pendingBuddy": null
}Field meanings:
backupStores your original Claude UUID socb-zoo --restorecan put Claude back to the old state.backup.uuidThe original UUID you backed up.backup.stateFileWhich Claude state file that UUID came from.backup.backedUpAtWhen the backup was created.maxBuddyMaximum number of buddies allowed incollection.json. Default:50.rollConfigUser-editable reroll settings.rollConfig.maxChargesMaximum reroll charges you can hold. Default:100.rollConfig.regenMsMilliseconds needed to regenerate1reroll charge. Default:300000(5minutes).rollChargesRuntime reroll state. Usually let cb-zoo manage this automatically.rollCharges.availableCurrent reroll charges available right now.rollCharges.updatedAtLast timestamp used for lazy reroll regeneration math.breedConfigUser-editable breeding settings.breedConfig.slotCountNumber of breed slots shown in the TUI. Default:3.breedConfig.hatchTimesMillisecond hatch time per rarity.breedConfig.hatchTimes.commonDefault10000(10seconds).breedConfig.hatchTimes.uncommonDefault30000(30seconds).breedConfig.hatchTimes.rareDefault60000(1minute).breedConfig.hatchTimes.epicDefault120000(2minutes).breedConfig.hatchTimes.legendaryDefault300000(5minutes).breedSlotsRuntime breed-slot state. Each array item is eithernullor one persisted egg.breedSlots[n].parentAUUID of parent A.breedSlots[n].parentBUUID of parent B.breedSlots[n].speciesTarget offspring species for that egg.breedSlots[n].eyeTarget offspring eye.breedSlots[n].hatTarget offspring hat.breedSlots[n].rarityTarget offspring rarity.breedSlots[n].shinyWhether the egg is targeting a shiny offspring.breedSlots[n].createdAtWhen that egg was created, in Unix milliseconds.breedSlots[n].hatchAtWhen that egg becomes ready, in Unix milliseconds.breedSlots[n].hatchedUuidOptional. Set after a ready egg has already resolved to a real UUID, so reopening the slot gives the same offspring again.pendingBuddyRuntime pending reveal state for the roll screen.nullwhen no unsaved reveal exists.pendingBuddy.uuidUUID of the revealed buddy.pendingBuddy.species,rarity,eye,hat,shiny,totalSnapshot of the revealed buddy.pendingBuddy.rolledAtISO timestamp for when that reveal was created.
What you can safely edit:
maxBuddyrollConfig.maxChargesrollConfig.regenMsbreedConfig.slotCountbreedConfig.hatchTimes.*
What you should usually not edit by hand:
rollChargesbreedSlotspendingBuddybackup
These are runtime or recovery fields. Wrong values here can block roll, breed, backup, or restore paths until fixed.
- The tool edits
oauthAccount.accountUuidfor rerolls and can also editcompanion.nameandcompanion.personalityfor the current stored buddy. - The original UUID is backed up inside
~/.cb-zoo/settings.jsonon first run. Existing~/.cb-zoo/backup.jsonfiles migrate automatically on first settings load. - Keep that backup UUID. It is your clean way back to the original Claude state after rerolls, experiments, or failed edits.
settings.jsonalso storesmaxBuddy, the current TUIpendingBuddy,breedConfig.slotCount,breedConfig.hatchTimes, and persistedbreedSlots;maxBuddydefaults to50.- Default breed config is
3slots with rarity hatch timers of10000,30000,60000,120000, and300000ms forcommonthroughlegendary, and users can override those values directly insettings.json. - Legacy single-slot
breedEggdata migrates intobreedSlots[0]on load, so older installs keep their in-progress egg. settings.jsonalso storesrollConfig.maxChargesandrollConfig.regenMs; defaults are100rolls and one refill every300000ms.- New rolls and rerolls spend one shared roll charge, while resuming an already pending reveal does not.
- Plain CLI refunds the spent charge if local persistence fails before the reveal reaches its Apply/Reroll/Quit prompt, and the TUI only commits a charge when it can persist the pending reveal in
settings.json. - When the collection is full, TUI Add/Equip keeps the pending buddy in place instead of discarding it.
- Breeding can still start while the collection is full, but hatched-buddy Add/Equip still respect
maxBuddyuntil you free a slot or discard the hatch. - Claude Code does not document this file schema as a stable public API, so future releases may change it.
- Re-authenticating Claude Code can overwrite the rerolled UUID, so keep the backup.
- Manual release steps live in docs/deployment-guide.md.
- Local release gate:
npm run release:check - CI workflow:
.github/workflows/ci.yml