
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@tomtev/touchgrass-avatar
Advanced tools
Pixel art avatar system. 32M+ unique characters from a 7-char hex DNA string.
Pixel-art avatar system for touchgrass.sh. Each avatar is encoded as a 7-character hex DNA string (~32M combinations) that deterministically renders a unique character with hat, eyes, mouth, body, legs, and two independent color hues.
npm install @touchgrass/avatar
# or
bun add @touchgrass/avatar
import {
generateRandomDNA,
decodeDNA,
encodeDNA,
generateGrid,
traitsFromName,
renderSVG,
renderTerminal,
renderTerminalSmall,
hslToRgb,
SLOTS,
EYES, MOUTHS, HATS, BODIES, LEGS,
} from '@touchgrass/avatar';
const dna = generateRandomDNA(); // e.g. "0a3f201"
const traits = decodeDNA('0a3f201');
// { eyes: 0, mouth: 2, hat: 5, body: 1, legs: 3, faceHue: 8, hatHue: 2 }
const dna = encodeDNA(traits); // "0a3f201"
const traits = traitsFromName('my-agent');
// Deterministic — same name always produces same traits
const svg = renderSVG('0a3f201'); // default 10px per pixel
const svg = renderSVG('0a3f201', 20); // 20px per pixel
const svg = renderSVG('0a3f201', 10, 1); // walking frame 1
Returns a complete <svg> string with transparent background. Use it as innerHTML, write to a .svg file, or embed in an <img> via data URI.
const ansi = renderTerminal('0a3f201'); // full size (██ per pixel)
const ansi = renderTerminalSmall('0a3f201'); // compact (half-block ▀▄)
console.log(ansi);
const grid = generateGrid(traits, walkFrame, talkFrame, waveFrame);
// Pixel[][] — 9 columns wide, variable rows tall
<script>
import { Avatar } from '@touchgrass/avatar/svelte';
</script>
<!-- From DNA string -->
<Avatar dna="0a3f201" />
<!-- From name (deterministic hash) -->
<Avatar name="my-agent" />
<!-- Sizes: sm (3px), lg (8px, default), xl (14px) -->
<Avatar dna="0a3f201" size="xl" />
<!-- Animations -->
<Avatar dna="0a3f201" walking />
<Avatar dna="0a3f201" talking />
<Avatar dna="0a3f201" waving />
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
dna | string | — | 7-char hex DNA string |
name | string | — | Fallback: derive traits from name hash |
size | 'sm' | 'lg' | 'xl' | 'lg' | Pixel size (3/8/14px per cell) |
walking | boolean | false | Animate legs |
talking | boolean | false | Animate mouth |
waving | boolean | false | Animate arms |
Either dna or name should be provided. If both are set, dna takes priority.
7 traits packed into a single integer using mixed-radix encoding with fixed slot sizes for forward compatibility:
| Trait | Variants | Slot size | Description |
|---|---|---|---|
| eyes | 11 | 12 | normal, wide, close, big, squint, narrow, etc. |
| mouths | 7 | 12 | smile, smirk, narrow, wide variants |
| hats | 24 | 24 | none, tophat, beanie, crown, cap, horns, mohawk, etc. |
| bodies | 6 | 8 | normal, narrow, tapered (each with/without arms) |
| legs | 6 | 8 | biped, quad, tentacles, thin, wide stance |
| faceHue | 12 | 12 | 0-330 degrees in 30-degree steps |
| hatHue | 12 | 12 | independent from face hue |
Total slot space: 12 x 12 x 24 x 8 x 8 x 12 x 12 = 31,850,496 (~32M, 7 hex chars).
New variants can be added within slot limits without breaking existing DNA strings. Legacy 6-char DNAs decode identically (leading zero is implicit).
The avatar is a 9-column grid with variable height (depends on hat). Each cell is a Pixel type:
| Pixel | Meaning | Rendering |
|---|---|---|
f | Face/body | Solid face color |
e | Eye | Solid dark color |
s | Squint eye | Face bg + dark bottom half |
n | Narrow eye | Face bg + dark center strip |
m | Mouth | Face bg + dark top half |
q | Smile corner left | Face bg + dark bottom-right quarter |
r | Smile corner right | Face bg + dark bottom-left quarter |
d | Dark accent | Solid dark (hat bands, etc.) |
h | Hat | Solid hat color |
l | Thin leg | Half-width face color |
k | Thin hat detail | Half-width hat color |
a | Arm | Half-height face color |
_ | Transparent | Empty |
Each avatar has 3 colors derived from two hue indices (0-11, mapped to 0-330 degrees):
hsl(faceHue * 30, 50%, 50%)hsl(faceHue * 30, 50%, 28%) — eyes, mouthhsl(hatHue * 30, 50%, 50%)The grid generator supports three animation types via frame parameters:
frame): Cycles through leg variant framestalkFrame): 0 = normal mouth, 1+ = open mouth animationwaveFrame): 0 = normal body, 1+ = alternating arm positions@touchgrass/avatar — Core TypeScript (DNA, grid, SVG, terminal, colors)
@touchgrass/avatar/svelte — Svelte 5 component (Avatar)
MIT
FAQs
Pixel art avatar system. 32M+ unique characters from a 7-char hex DNA string.
We found that @tomtev/touchgrass-avatar demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.