npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ascii-buddy

v1.0.7

Published

Generate and share your ASCII buddy companion card from Claude Code

Readme

ascii-buddy

Export your Claude Code companion buddy as an SVG card.

npx ascii-buddy

That's it. One command. No permissions, no screenshots, no extra sessions.

What it does

Claude Code has a built-in /buddy command that hatches a coding companion tied to your account. Each buddy has a unique rarity, species, stats, and personality — all deterministically generated from your account ID.

ascii-buddy reads your ~/.claude.json, runs the same algorithm Claude Code uses internally, and renders your buddy as a shareable SVG card.

Output

The SVG card includes:

  • Rarity — Common, Uncommon, Rare, Epic, or Legendary (with star rating)
  • Species — one of 18 types (chonk, cat, duck, ghost, robot, etc.)
  • ASCII art — the exact face from Claude Code, with hat and eye style
  • Name & personality — from your companion config
  • Stats — DEBUGGING, PATIENCE, CHAOS, WISDOM, SNARK

Saved to ~/ascii_buddy.svg and automatically submitted to the Buddy Rolodex — a live gallery of every companion found in the wild.

Rolodex

Every time someone runs npx ascii-buddy, their buddy is submitted to a public gallery at asciibuddy.dev. No account needed — your buddy is keyed by a privacy-safe hash of your account ID.

Browse all buddies, filter by rarity, and see the global stats.

Privacy & transparency

This tool reads your ~/.claude.json file. Here's exactly what it accesses and what it doesn't:

What it reads (locally only):

  • companion.name — your buddy's display name
  • companion.personality — your buddy's personality text
  • companion.hatchedAt — when you created your buddy
  • oauthAccount.accountUuid — used ONLY as a seed to generate your buddy's species/rarity/stats

What it sends to the rolodex API:

  • Your buddy's generated attributes (name, personality, species, rarity, eye, hat, shiny, stats)
  • A one-way hash of your account UUID (user_hash) — the raw UUID is never sent
  • A deterministic buddy ID derived from the hash

What it does NOT read or send:

  • Email, API keys, auth tokens, or session data
  • Conversation history or Claude Code usage data
  • System information (OS, hostname, etc.)

The API is a Cloudflare Worker backed by a D1 database. All source code (CLI, worker, and site) is in this repo.

Requirements

  • Claude Code installed with a companion already hatched (run /buddy once first)
  • Node.js 16+
  • Bun (optional) — if installed, uses Bun.hash() for exact stat matching with Claude Code. Falls back to FNV-1a if unavailable, which may produce slightly different stats.

How it works

Your buddy's stats aren't stored anywhere on disk. Claude Code generates them on the fly each time you run /buddy. Only three fields are persisted in ~/.claude.json:

{
  "companion": {
    "name": "Souptuft",
    "personality": "A rotund, googly-eyed disaster who'll...",
    "hatchedAt": 1775131144343
  }
}

Everything else — rarity, species, eye style, hat, shiny status, and all five stats — is computed at render time from a seeded PRNG. This tool reverse-engineered that pipeline from the Claude Code v2.1.90 binary to reproduce it exactly.

The algorithm

Step 1 — Seed

key = accountUuid + "friend-2026-401"
hash = Bun.hash(key) & 0xFFFFFFFF    // wyhash, truncated to 32 bits

accountUuid comes from ~/.claude.jsonoauthAccount.accountUuid. The salt "friend-2026-401" is hardcoded in the binary.

Step 2 — PRNG

The hash seeds a Mulberry32 pseudo-random number generator:

function mulberry32(seed) {
  let s = seed >>> 0;
  return function () {
    s |= 0;
    s = (s + 1831565813) | 0;
    let t = Math.imul(s ^ (s >>> 15), 1 | s);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

Step 3 — Sequential rolls

Each call to rng() produces the next number in the sequence. The order matters:

| Roll | What it determines | How | |------|-------------------|-----| | 1 | Rarity | Weighted: common 60%, uncommon 25%, rare 10%, epic 4%, legendary 1% | | 2 | Species | Uniform pick from 18 species | | 3 | Eye style | Uniform pick from · ✦ × ◉ @ ° | | 4 | Hat | Uniform pick (skipped if common rarity) | | 5 | Shiny | 1% chance | | 6 | High stat | Random stat gets boosted (+50 base + up to 30 random) | | 7+ | Low stat | Random different stat gets nerfed (-10 base + up to 15 random) | | 8-12 | Remaining stats | Each stat = base + up to 40 random |

Base stat values per rarity: common=5, uncommon=15, rare=25, epic=35, legendary=50.

Species list

duck, goose, blob, cat, dragon, octopus, owl, penguin, turtle, snail, ghost, axolotl, capybara, cactus, robot, rabbit, mushroom, chonk

Rarity odds

| Rarity | Weight | Chance | ~Users needed for one to exist | |--------|--------|--------|-------------------------------| | Common | 60 | 60% | 1 | | Uncommon | 25 | 25% | 3 | | Rare | 10 | 10% | 7 | | Epic | 4 | 4% | 25 | | Legendary | 1 | 1% | 100 | | Shiny (any) | — | 1% | 100 | | Shiny + Legendary | — | 0.01% | ~10,000 |

Shiny is an independent 1% roll — any rarity can be shiny. A shiny buddy displays "✨ SHINY ✨" on its card. Getting both shiny AND legendary is the rarest possible combination.

Uniqueness and collisions

Will buddies repeat? Yes and no.

The visual appearance (rarity + species + eye) draws from only 540 combinations (5 × 18 × 6), so many users will share the same look. Two people can both have an uncommon chonk with @ eyes.

However, the full stat spread has billions of possible combinations, so exact stat-for-stat matches are unlikely in practice.

The 32-bit wall. The hash is truncated to 32 bits (~4.3 billion possible seeds). By the birthday paradox, the first hash collision — two different accounts producing a pixel-perfect identical buddy (same rarity, species, eye, hat, shiny, and all 5 stats) — is expected around ~65,000 users. Even then, their names will still differ since names are LLM-generated.

What's NOT deterministic

The name and personality are generated by Claude (the LLM) during the hatching animation and stored in ~/.claude.json. They are not derived from the seed.

Version note

This was reverse-engineered from Claude Code v2.1.90. If Anthropic changes the salt, PRNG, or species list in a future version, the output may differ from /buddy. The core algorithm (hash → mulberry32 → sequential rolls) is unlikely to change.

License

MIT