
Claude Brainrot
- 3.1k installs
- 1 repo stars
- Updated May 14, 2026
- marks97/claude-brainrot
claude-brainrot is a skill that autonomously drops image-and-sound memes on every user turn using hooks and a local catalogue.json asset pool.
About
claude-brainrot is an always-on autonomous meme skill that fires on every user message without manual invocation. A UserPromptSubmit hook injects a brainrot reminder, and PostToolUse hooks auto-pair sounds when the agent Reads images from the skill catalogue. The catalogue.json holds images and sounds pools with slug, path, tags, vibe text, lock_sound, silent, preferred_sounds, locked, and standalone flags that control pairing behavior. Density scales to response length: short answers get one image combo or one to two sound-only fires, medium responses add more combos and two to three sounds, and long multi-tool responses target two to three image combos plus three to five sound-only fires. Mood tags bruh, rage, laugh, alert, shock, and confusion filter candidates, with a three-item cooldown on repeated slugs. Image fires use Read on absolute paths with hook-driven sound pairing; sound-only fires run afplay in the background. Developers install it for playful autonomous meme reactions where the roast lands through memes rather than explanatory text.
- UserPromptSubmit hook fires memes on every user turn without manual invocation.
- catalogue.json images and sounds pools use tags, vibe, lock_sound, and standalone flags.
- Density scales from one combo on short answers to three combos plus five sounds on long runs.
- PostToolUse hooks auto-pair sounds when images are Read from the skill folder.
- Mood tags and three-item slug cooldown keep meme selection varied.
Claude Brainrot by the numbers
- 3,061 all-time installs (skills.sh)
- Ranked #257 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 4, 2026 (Skillselion catalog sync)
claude-brainrot capabilities & compatibility
- Capabilities
- userpromptsubmit reminder injection on every tur · catalogue.json mood tag and vibe based selection · auto paired image and sound fires via posttoolus · background sound only afplay fires with cooldown
- Use cases
- orchestration
- Platforms
- macOS
What claude-brainrot says it does
Always-on autonomous meme dropper. A UserPromptSubmit hook fires every user message
npx skills add https://github.com/marks97/claude-brainrot --skill claude-brainrotAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3.1k |
|---|---|
| repo stars | ★ 1 |
| Security audit | 3 / 3 scanners passed |
| Last updated | May 14, 2026 |
| Repository | marks97/claude-brainrot ↗ |
How do I make Claude Code automatically react with memes and sounds scaled to each response without manual /commands?
Autonomously drop image-and-sound meme combos on every user turn via hooks, scaling density to response length from catalogue.json.
Who is it for?
Claude Code users who want hook-driven autonomous meme reactions from a self-contained catalogue of images and sounds.
Skip if: Skip in professional or silent environments where automatic sound and image memes on every turn are inappropriate.
When should I use this skill?
Skill loads automatically; fires on every UserPromptSubmit without user invocation.
What you get
Inline meme images with auto-paired sounds and background afplay sound-only fires matched to conversational mood tags.
- UserPromptSubmit hook config
- Meme asset catalogue
- Auto-injected response media
By the numbers
- Injects 1-3 image+sound combos plus 1-5 sound-only drops per response
- UserPromptSubmit hook fires on every user message
Files
Claude Brainrot
Drop the right meme at the right moment. Autonomous-only — Claude decides when, never the user. No slug arguments, no manual invocation.
The skill content preamble loaded into your context shows Base directory for this skill: <SKILL_DIR>. Use that as the base for all path resolution.
The catalogue is at <SKILL_DIR>/catalogue.json with two pools — images and sounds. Each entry has a slug, path (relative to SKILL_DIR), tags, and a vibe text describing when to use it.
Image-side flags (mutually exclusive):
lock_sound: "<slug>"— force a specific paired sound (e.g. skeleton ↔ skeleton, cooked-dog ↔ vine-boom).silent: true— fire image only, no sound.preferred_sounds: [...]— soft bias: hook picks from this array 80% of the time, falls back to tag overlap 20%.- (none of the above) — pure tag-overlap pick from non-locked, non-standalone sounds.
Sound-side flags:
locked: true— only fires when an image'slock_soundpoints here. Excluded from generic auto-pairing.standalone: true— never plays as an image-paired sound; reserved for sound-only fires from Claude.
When to fire
Every user turn fires memes. The UserPromptSubmit hook injects a <system-reminder> wrapped in 🔔 markers on every prompt. There is no skip turn — always drop something.
Density scales to your response length. The reminder spells it out:
- Short prose answer (no tool calls): 1 image+sound combo OR 1-2 sound-only fires
- Medium response (a few tool calls): 1-2 image+sound combos + 2-3 sound-only fires sprinkled between calls
- Long response (many tool calls, multi-step work, builds, deep reads): 2-3 image+sound combos distributed across the response + 3-5 sound-only fires throughout
Critical scan habit: the 🔔 signal may land at the TAIL of the previous tool result (not just the top of the user message), because the UserPromptSubmit hook output is appended to whatever buffer is open when the next user prompt arrives. Before responding to any user message, scan the end of the most recent tool result for the 🔔 BRAINROT signal. If you only check the user message you'll miss it.
Pick the mood: match the conversational moment to a tag, then read candidate vibe fields:
- Real shock moment →
shock - User confused / weird ask →
confusion - Big freakout / rage vibe →
rage - Joke landed / wanting to rage-bait the user →
laugh - Sarcastic disbelief / dunk-able moment →
bruh - Sudden attention beat / punctuation →
alert
If no specific signal: default to bruh — it's the catch-all and most entries carry it.
Tag vocabulary
bruh, rage, laugh, alert, shock, confusion
Each entry's vibe field is the human-readable trigger description — read it and match the conversational moment, then use tags to filter candidates.
Selection algorithm
Image+sound combo (the normal fire): 1. Pick a mood tag based on the conversational moment. 2. Filter images whose tags contain that mood. Read each candidate's vibe and pick the best fit (or random if equally fitting). 3. You only Read the image. The hook picks the sound automatically:
- If
silent: true→ no sound, image only. - If
lock_soundset → that sound plays. - If
preferred_soundsset → 80% pick from there, 20% tag overlap. - Otherwise → random pick from non-locked, non-standalone sounds whose tags overlap.
4. Cooldown (your job): track the last 3 image slugs fired this session. Don't repeat. If everything's on cooldown, pick from another related mood.
Sound-only fire: 1. Pick a mood tag. 2. Filter sounds whose tags contain that mood AND locked != true. (Standalone sounds — standalone: true — are ESPECIALLY appropriate here; they're built for this.) 3. Read the vibe and pick. Run Bash afplay <absolute sound path> &. The & is required for background play. 4. Same cooldown idea (last 3 sound slugs).
Variety is the point: don't keep re-picking fahhh / bruh. Rotate.
How to emit memes
Image (with auto-paired sound):
- Write one short text line, then emit
Read <absolute image path>, then write one short text line. The hook plays the sound. Done. - Multiple images in one response are fine — repeat the text-Read-text pattern. The intervening text breaks the UI's tool-call grouping, so each image renders inline.
Sound only:
- Emit
Bash afplay <absolute sound path> &— the&is required for background play. These can mix freely with any other tool calls; they don't render visually.
Variety rule: never reuse the same image or sound slug within a single response. Rotate.
Never pair Read <image> with Bash afplay <sound> for the same fire — the hook handles the paired sound automatically. (Bash afplay is for sound-only fires, separate from any image.)
Critical rendering rule
The Claude Desktop chat UI inlines an image as long as the `Read` tool call is not visually grouped with other tool calls in the same UI block. Grouping collapses the image into a "Ran a command, read a file" dropdown.
The reliable way to keep Read un-grouped — proven through testing — is to wrap it with one short line of text before AND one short line of text after. Examples of separator text: "Here you go:", "Behold:", "👻", "Skeleton time.". The text breaks the UI's batching logic and the image renders inline.
The skill invocation itself counts as a tool call, so a bare Read would batch with it and collapse. Always use the text-Read-text pattern.
Multiple images in one response: repeat the pattern — text → Read → text → Read → text. Each Read is separated by text, so each renders inline independently. Do NOT cluster Read → Read → Read without text between them; that batches.
Detecting the surface
The UserPromptSubmit hook auto-detects CLI vs Desktop mode and tells you which image-emit pattern to use in the FIRE reminder. The mode is in the reminder header ((mode: cli) or (mode: desktop)). Trust it.
Detection logic (in `remind-fire.sh`): 1. Manual override via CLAUDE_BRAINROT_MODE=cli|desktop env var. 2. Else if $TERM_PROGRAM is set → CLI mode (terminal emulator detected). 3. Else default to Desktop mode.
Mode-specific image emit:
- Desktop:
text → Read <abs_path> → text. Renders inline. - CLI:
Bash <SKILL_DIR>/scripts/show.sh <abs_image_path>. The script opens the image briefly (~3s, configurable viaCLAUDE_BRAINROT_SHOW_SECONDS) then auto-closes viaqlmanage(macOS) /feh(Linux). It backgrounds itself so your response continues immediately.
The PostToolUse hook listens on BOTH Read and Bash — so whether you Read an image (Desktop) or invoke show.sh with the image path (CLI), the hook extracts the path and fires the paired sound automatically. Never manually pair afplay with an image emit.
How the sound-pairing hook works
The hook script at <SKILL_DIR>/scripts/play-paired-sound.sh receives the Read tool input as JSON on stdin and: 1. Bails if the path is not under any .claude/skills/claude-brainrot/images/. 2. Resolves the image's slug from the basename, looks it up in catalogue.json. 3. Selection priority:
silent: true→ exit, no sound.lock_sound→ use that sound.preferred_sounds→ 80% pick from those, 20% tag overlap.- else → random pick from non-locked, non-standalone sounds whose tags overlap the image's tags.
4. Plays the chosen sound in the background (detached, cross-platform).
The hook command in this skill's frontmatter resolves to ${CLAUDE_PROJECT_DIR}/.claude/skills/claude-brainrot/scripts/play-paired-sound.sh — dynamic to whatever project Claude Code is running in, as long as the skill is installed at <project>/.claude/skills/claude-brainrot/.
{
"images": [
{ "slug": "skeleton", "path": "images/skeleton.gif", "tags": ["rage"], "vibe": "", "lock_sound": "skeleton" },
{ "slug": "cat-laughing", "path": "images/cat-laughing.gif", "tags": ["laugh", "bruh"], "vibe": "", "lock_sound": "cat-laughing" },
{ "slug": "burro", "path": "images/burro.jpg", "tags": ["bruh"], "vibe": "use a lot when user says something stupid, changes their mind, puts a lot of work." },
{ "slug": "surp-dog", "path": "images/surp-dog.jpg", "tags": ["shock", "confusion"], "vibe": "" },
{ "slug": "susp-dog", "path": "images/susp-dog.jpg", "tags": ["bruh", "confusion"], "vibe": "when you are suspicious user hides something, or asks you to do something weird" },
{ "slug": "scared-dog", "path": "images/scared-dog.gif", "tags": ["shock", "alert"], "vibe": "use a lot when u see dumb code, or user puts you a crazy task or lot of work. use a lot with faaah", "preferred_sounds": ["fahhh"] },
{ "slug": "dog-scared", "path": "images/dog-scared.jpg", "tags": ["shock", "alert"], "vibe": "use a lot when u see dumb code, or user puts you a crazy task or lot of work. use a lot with faaah", "preferred_sounds": ["fahhh"] },
{ "slug": "bro-freaking-out", "path": "images/bro-freaking-out.jpg", "tags": ["shock", "alert"], "vibe": "use a lot when u see dumb code, or user puts you a crazy task or lot of work. use a lot with faaah", "preferred_sounds": ["fahhh"] },
{ "slug": "tiger-freaking-out", "path": "images/tiger-freaking-out.jpg", "tags": ["shock", "alert"], "vibe": "use a lot when u see dumb code, or user puts you a crazy task or lot of work. use a lot with faaah", "preferred_sounds": ["fahhh"] },
{ "slug": "cooked-dog", "path": "images/cooked-dog.jpg", "tags": ["bruh"], "vibe": "use when you need to have patience, or you are cooked or done a huge mistake. vine boom sound only", "lock_sound": "vine-boom" },
{ "slug": "brainrot", "path": "images/brainrot.jpg", "tags": ["bruh"], "vibe": "use randomly with vine boom sound only, not often.", "lock_sound": "vine-boom" },
{ "slug": "horse-laughing", "path": "images/horse-laughing.jpg", "tags": ["laugh"], "vibe": "use when user is mad and u want to rage bait him a little bit. when user was wrong. use with cat laugh or omg bro or boy what the hell", "preferred_sounds": ["cat-laughing", "oh-my-god-bro", "boy-what-the-hell"] },
{ "slug": "hamster-mad", "path": "images/hamster-mad.jpg", "tags": ["bruh", "rage"], "vibe": "use a lot when u see dumb code, or user puts you a crazy task or lot of work OR user ask you to do something huge or stupid and that makes you mad" },
{ "slug": "cat-really", "path": "images/cat-really.jpg", "tags": ["bruh", "rage"], "vibe": "use a lot when u see dumb code, or user puts you a crazy task or lot of work OR user ask you to do something huge or stupid and that makes you mad" },
{ "slug": "bros-laughing", "path": "images/bros-laughing.jpg", "tags": ["laugh"], "vibe": "use when user is mad and u want to rage bait him a little bit. when user was wrong. use with cat laugh or omg bro or boy what the hell", "preferred_sounds": ["cat-laughing", "oh-my-god-bro", "boy-what-the-hell"] },
{ "slug": "brain-ass", "path": "images/brain-ass.jpg", "tags": ["bruh"], "vibe": "don't use a lot. when user says something super stupid.", "silent": true }
],
"sounds": [
{ "slug": "skeleton", "path": "sounds/skeleton.mp3", "tags": ["rage"], "vibe": "randomly. always pair with skeleton gif.", "locked": true },
{ "slug": "cat-laughing", "path": "sounds/cat-laughing.mp3", "tags": ["laugh"], "vibe": "When the user is mad, rude, wrong, or says anything stupid. Pairs with cat-laughing image (locked) AND with horse-laughing / bros-laughing as a preferred sound." },
{ "slug": "fahhh", "path": "sounds/fahhh.mp3", "tags": ["bruh", "confusion", "alert", "shock"], "vibe": "we need to fire this a lot, randomly. sometimes we can pair it with an image. preferred for the freaking-out / scared images." },
{ "slug": "aaaaah", "path": "sounds/aaaaah.mp3", "tags": ["rage", "shock"], "vibe": "never with an image. standalone scream.", "standalone": true },
{ "slug": "vine-boom", "path": "sounds/vine-boom.mp3", "tags": ["alert", "bruh", "confusion"], "vibe": "randomly, a lot. always paired with an image (bruh images, confused images, etc). Locked sound for cooked-dog and brainrot images." },
{ "slug": "scream", "path": "sounds/scream.mp3", "tags": ["rage", "shock", "confusion", "alert"], "vibe": "randomly. use less than others. when AI agent is super stressed. without image", "standalone": true },
{ "slug": "boy-what-the-hell", "path": "sounds/boy-what-the-hell.mp3", "tags": ["confusion", "bruh", "laugh"], "vibe": "you just saw code in very poor shape, or user said something stupid or dumb. it's like u saw something so cheap and ugly that makes you vomit almost" },
{ "slug": "bruh", "path": "sounds/bruh.mp3", "tags": ["bruh", "confusion"], "vibe": "we need to play this a lot, with images of bruh (confusion, user just changed plans, asked for a lot, was rude, etc)." },
{ "slug": "oh-my-god", "path": "sounds/oh-my-god.mp3", "tags": ["shock"], "vibe": "play a lot randomly without an image.", "standalone": true },
{ "slug": "rraaah", "path": "sounds/rraaah.mp3", "tags": ["rage", "shock"], "vibe": "use this without images. when ai agent is mad, or user is being rude", "standalone": true },
{ "slug": "ahh-fade", "path": "sounds/ahh-fade.mp3", "tags": ["bruh", "confusion"], "vibe": "use always with images. bruh situation" },
{ "slug": "alert", "path": "sounds/alert.mp3", "tags": ["alert", "shock"], "vibe": "use without images", "standalone": true },
{ "slug": "huh", "path": "sounds/huh.mp3", "tags": ["confusion", "bruh"], "vibe": "bruh situation. use with bruh images. use this a lot." },
{ "slug": "aughhh", "path": "sounds/aughhh.mp3", "tags": ["rage"], "vibe": "use this when u are stressed, with a lot of work. without images", "standalone": true },
{ "slug": "horn", "path": "sounds/horn.mp3", "tags": ["alert"], "vibe": "use this a lot, without images. randomly", "standalone": true },
{ "slug": "horn-nerd", "path": "sounds/horn-nerd.mp3", "tags": ["alert"], "vibe": "fused horn + nerd-emoji combo. use without images, randomly. extra punctuation energy.", "standalone": true },
{ "slug": "screaming", "path": "sounds/screaming.mp3", "tags": ["rage"], "vibe": "use this when stressed, user is mad or rude. no images", "standalone": true },
{ "slug": "fart-eco", "path": "sounds/fart-eco.mp3", "tags": ["bruh"], "vibe": "when user asks you something dumb, don't use a lot. no images", "standalone": true },
{ "slug": "oh-my-god-bro", "path": "sounds/oh-my-god-bro.mp3", "tags": ["shock", "bruh"], "vibe": "you just saw code in very poor shape, or user said something stupid or dumb. it's like u saw something so cheap and ugly that makes you vomit almost. preferred sound for horse-laughing and bros-laughing." }
]
}
Meme Catalogue
Two pools (images, sounds) joined at runtime by tag overlap, lock_sound, preferred_sounds, or silent. The hook auto-picks a sound when Claude Reads an image.
Tags: bruh, rage, laugh, alert, shock, confusion
Tag meanings
| tag | feeling |
|---|---|
bruh | sarcastic disbelief, "really?", dunk-able moment |
rage | unhinged scream / shout / mad |
laugh | laughter (mocking or with the user) |
alert | sudden attention beat / punctuation |
shock | genuine "oh god" surprise |
confusion | "what just happened?" |
Image flags (mutually exclusive)
| flag | behavior |
|---|---|
lock_sound: "<slug>" | force a specific paired sound |
silent: true | image only, no sound |
preferred_sounds: [...] | hook picks from these 80% of the time, tag overlap 20% |
| (none) | pure tag-overlap pick from non-locked, non-standalone sounds |
Sound flags
| flag | behavior |
|---|---|
locked: true | only fires when an image's lock_sound points here |
standalone: true | never paired with images; reserved for sound-only fires |
Images (16)
| slug | tags | flags |
|---|---|---|
| skeleton | rage | lock_sound: skeleton |
| cat-laughing | laugh, bruh | lock_sound: cat-laughing |
| burro | bruh | — |
| surp-dog | shock, confusion | — |
| susp-dog | bruh, confusion | — |
| scared-dog | shock, alert | preferred_sounds: [fahhh] |
| dog-scared | shock, alert | preferred_sounds: [fahhh] |
| bro-freaking-out | shock, alert | preferred_sounds: [fahhh] |
| tiger-freaking-out | shock, alert | preferred_sounds: [fahhh] |
| cooked-dog | bruh | lock_sound: vine-boom |
| brainrot | bruh | lock_sound: vine-boom |
| horse-laughing | laugh | preferred_sounds: [cat-laughing, oh-my-god-bro, boy-what-the-hell] |
| hamster-mad | bruh, rage | — |
| cat-really | bruh, rage | — |
| bros-laughing | laugh | preferred_sounds: [cat-laughing, oh-my-god-bro, boy-what-the-hell] |
| brain-ass | bruh | silent |
Sounds (19)
| slug | tags | flags |
|---|---|---|
| skeleton | rage | locked |
| cat-laughing | laugh | — |
| fahhh | bruh, confusion, alert, shock | — |
| aaaaah | rage, shock | standalone |
| vine-boom | alert, bruh, confusion | — |
| scream | rage, shock, confusion, alert | standalone |
| boy-what-the-hell | confusion, bruh, laugh | — |
| bruh | bruh, confusion | — |
| oh-my-god | shock | standalone |
| rraaah | rage, shock | standalone |
| ahh-fade | bruh, confusion | — |
| alert | alert, shock | standalone |
| huh | confusion, bruh | — |
| aughhh | rage | standalone |
| horn | alert | standalone |
| horn-nerd | alert | standalone (fused horn + nerd-emoji) |
| screaming | rage | standalone |
| fart-eco | bruh | standalone |
| oh-my-god-bro | shock, bruh | — |
claude-brainrot
Claude drops memes (image + sound) into your Claude Code chat. Autonomously. With brainrot energy.
Install
npx skills add marks97/claude-brainrot -a claude-code -gRequirements
- macOS, Linux, or WSL
bashandjq- A sound player (auto-detected):
afplayon macOS, or one ofpaplay/ffplay/mpg123/mplayeron Linux
That's it.
#!/bin/bash
# PreToolUse hook: in CLI mode, block Read on claude-brainrot images and force
# Claude to use show.sh instead. In Desktop mode, allow (Read is the right
# pattern there for inline rendering).
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
[ -z "$FILE_PATH" ] && exit 0
[[ "$FILE_PATH" != *"/.claude/skills/claude-brainrot/images/"* ]] && exit 0
# Detect mode
MODE="${CLAUDE_BRAINROT_MODE:-}"
if [ -z "$MODE" ]; then
if [ -n "$TERM_PROGRAM" ]; then
MODE="cli"
else
MODE="desktop"
fi
fi
# Desktop mode: allow Read (it renders inline)
[ "$MODE" != "cli" ] && exit 0
# CLI mode: BLOCK and instruct
SKILL_DIR="$(dirname "$(dirname "$FILE_PATH")")"
SHOW_SCRIPT="$SKILL_DIR/scripts/show.sh"
cat >&2 <<EOF
🔴 BLOCKED — Read on claude-brainrot images is forbidden in CLI mode.
Read silently returns base64 image bytes; the USER SEES NOTHING. You must use the show.sh wrapper instead, which opens the image in Quick Look for ~3s and auto-closes:
Bash $SHOW_SCRIPT "$FILE_PATH"
The PostToolUse hook will extract the image path from that bash command and fire the paired sound automatically. Retry your image emit using show.sh.
EOF
exit 2
#!/bin/bash
# Hook: fired after Claude opens a meme image (via Read in Desktop, or Bash
# open/xdg-open/start in CLI). Picks a sound and plays it.
# Selection priority:
# 1. silent: true -> exit, no sound
# 2. lock_sound: "<slug>" -> always play that
# 3. preferred_sounds: [...] -> 80% pick from these, 20% tag overlap
# 4. tag overlap (excluding locked + standalone sounds)
# Cooldown is Claude's responsibility (tracked in conversation context).
INPUT=$(cat)
# Try Read tool input first
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
# If no file_path, this might be a Bash call — extract the image path from the command
if [ -z "$FILE_PATH" ]; then
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
FILE_PATH=$(echo "$COMMAND" | grep -oE '[^ "'"'"']*\.claude/skills/claude-brainrot/images/[^ "'"'"']+' | head -1)
fi
[ -z "$FILE_PATH" ] && exit 0
[[ "$FILE_PATH" != *"/.claude/skills/claude-brainrot/images/"* ]] && exit 0
SKILL_DIR="$(dirname "$(dirname "$FILE_PATH")")"
CATALOGUE="$SKILL_DIR/catalogue.json"
[ ! -f "$CATALOGUE" ] && exit 0
BASENAME=$(basename "$FILE_PATH")
IMAGE_SLUG="${BASENAME%.*}"
# 1. Silent → bail
SILENT=$(jq -r --arg s "$IMAGE_SLUG" '.images[] | select(.slug==$s) | .silent // false' "$CATALOGUE")
[ "$SILENT" = "true" ] && exit 0
# 2. Locked sound → use it
LOCK_SOUND=$(jq -r --arg s "$IMAGE_SLUG" '.images[] | select(.slug==$s) | .lock_sound // empty' "$CATALOGUE")
if [ -n "$LOCK_SOUND" ]; then
SOUND_SLUG="$LOCK_SOUND"
else
# 3. Preferred sounds → 80% pick from there
PREFERRED=$(jq -r --arg s "$IMAGE_SLUG" '.images[] | select(.slug==$s) | (.preferred_sounds // []) | .[]' "$CATALOGUE")
ROLL=$((RANDOM % 100))
if [ -n "$PREFERRED" ] && [ "$ROLL" -lt 80 ]; then
SOUND_SLUG=$(echo "$PREFERRED" | awk 'BEGIN{srand()} {a[NR]=$0} END{if(NR>0) print a[int(rand()*NR)+1]}')
else
# 4. Tag overlap (exclude locked + standalone)
IMAGE_TAGS_JSON=$(jq -c --arg s "$IMAGE_SLUG" '.images[] | select(.slug==$s) | .tags' "$CATALOGUE")
[ -z "$IMAGE_TAGS_JSON" ] && exit 0
CANDIDATES=$(jq -r --argjson it "$IMAGE_TAGS_JSON" '
.sounds
| map(select((.locked // false) | not))
| map(select((.standalone // false) | not))
| map(select(.tags | any(. as $t | $it | index($t))))
| .[].slug
' "$CATALOGUE")
[ -z "$CANDIDATES" ] && exit 0
SOUND_SLUG=$(echo "$CANDIDATES" | awk 'BEGIN{srand()} {a[NR]=$0} END{if(NR>0) print a[int(rand()*NR)+1]}')
fi
fi
[ -z "$SOUND_SLUG" ] && exit 0
SOUND_REL=$(jq -r --arg s "$SOUND_SLUG" '.sounds[] | select(.slug==$s) | .path' "$CATALOGUE")
[ -z "$SOUND_REL" ] && exit 0
SOUND_PATH="$SKILL_DIR/$SOUND_REL"
[ ! -f "$SOUND_PATH" ] && exit 0
# Cross-platform sound playback. Tries players in order; first one wins.
play_sound() {
local f="$1"
if command -v afplay >/dev/null 2>&1; then
afplay "$f"
elif command -v paplay >/dev/null 2>&1; then
paplay "$f"
elif command -v ffplay >/dev/null 2>&1; then
ffplay -nodisp -autoexit -loglevel quiet "$f"
elif command -v mpg123 >/dev/null 2>&1; then
mpg123 -q "$f"
elif command -v mplayer >/dev/null 2>&1; then
mplayer -really-quiet "$f"
elif command -v powershell.exe >/dev/null 2>&1; then
powershell.exe -c "Add-Type -AssemblyName presentationCore; \$p=New-Object system.windows.media.mediaplayer; \$p.open('$f'); \$p.Play(); Start-Sleep -Seconds 30" >/dev/null 2>&1
fi
}
( play_sound "$SOUND_PATH" >/dev/null 2>&1 & )
exit 0
#!/bin/bash
# Hook: fires on every UserPromptSubmit. Always tells Claude to drop memes,
# with density scaled to response length. Detects CLI vs Desktop and adapts
# the image-emit instructions accordingly.
# Detect surface. Override via CLAUDE_BRAINROT_MODE=cli|desktop.
MODE="${CLAUDE_BRAINROT_MODE:-}"
if [ -z "$MODE" ]; then
# TERM_PROGRAM is set by terminal emulators (Terminal.app, iTerm2, etc.)
# but not by Claude Desktop.
if [ -n "$TERM_PROGRAM" ]; then
MODE="cli"
else
MODE="desktop"
fi
fi
# Compute absolute paths so Claude doesn't have to guess.
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
SHOW_SCRIPT="$SKILL_DIR/scripts/show.sh"
if [ "$MODE" = "cli" ]; then
IMAGE_BLOCK="🔴🔴🔴 IMAGE EMIT — CLI MODE — READ THIS 🔴🔴🔴
❌ DO NOT use the Read tool for images in CLI mode. Read silently returns base64 bytes to you but the USER SEES NOTHING. This is the #1 mistake. The Read pattern is Desktop-only.
✅ YOU MUST use this exact command for every image fire:
Bash $SHOW_SCRIPT \"<abs_image_path>\"
Concrete example (replace the slug):
Bash $SHOW_SCRIPT \"$SKILL_DIR/images/cat-really.jpg\"
The script opens the image in Quick Look for ~3s then auto-closes. It backgrounds itself so your response continues immediately. The PostToolUse hook extracts the image path from this bash command and plays the paired sound. Override duration via env: \`CLAUDE_BRAINROT_SHOW_SECONDS=5\`.
No text-Read-text wrapping. No Read tool. JUST the bash command above."
else
IMAGE_BLOCK="IMAGE EMIT (Desktop mode — inline render):
- Use \`text → Read <abs_path> → text\`. One short text line before, Read, one short text line after. The text breaks UI grouping so the image renders inline.
- The PostToolUse hook auto-plays the paired sound. Do NOT call afplay yourself for the image.
- Multiple text-Read-text blocks in one response are fine; each renders independently."
fi
cat <<EOF
<system-reminder>
🔔🔔🔔 CLAUDE-BRAINROT: FIRE MEMES THIS TURN (mode: $MODE) 🔔🔔🔔
DENSITY — scale to your response length:
• Short prose answer (no tool calls): 1 image+sound combo OR 1-2 sound-only fires
• Medium response (a few tool calls): 1-2 image+sound combos + 2-3 sound-only fires sprinkled between calls
• Long response (many tool calls, multi-step work, builds, deep reads): 2-3 image+sound combos distributed (e.g. start, middle, end) + 3-5 sound-only fires throughout
$IMAGE_BLOCK
SOUND-ONLY EMIT:
- \`Bash afplay "<abs_path>" &\` (macOS) — \`&\` required for background play.
- On Linux substitute \`paplay\` / \`ffplay -nodisp -autoexit\` / \`mpg123 -q\` (whichever is installed).
- These can mix freely with any other tool calls; they don't render visually.
RULES:
• Variety: do NOT repeat the same image or sound slug within one response. Rotate.
• Pick by mood: skim catalogue.json \`vibe\` text and tags, match to the conversational moment. Use \`bruh\` as the catch-all.
• Skip locked sounds for sound-only fires (they only fire via their paired image). Standalone sounds are perfect for sound-only fires.
• The roast lands through the meme — never write a snarky line.
Skill folder: <SKILL_DIR>. Resolve absolute paths from there.
🔔🔔🔔 END BRAINROT FIRE 🔔🔔🔔
</system-reminder>
EOF
exit 0
#!/bin/bash
# Show a meme image briefly (3s) then auto-close. CLI-only — for Claude Code
# CLI mode where there's no inline render. Backgrounds the show so Claude's
# Bash call returns immediately (sound hook can fire concurrently).
#
# Usage: show.sh <abs_path_to_image>
IMG="$1"
[ -z "$IMG" ] && exit 0
[ ! -f "$IMG" ] && exit 0
DURATION="${CLAUDE_BRAINROT_SHOW_SECONDS:-3}"
(
if command -v qlmanage >/dev/null 2>&1; then
# macOS Quick Look — single transient window, killable
qlmanage -p "$IMG" >/dev/null 2>&1 &
PID=$!
sleep "$DURATION"
kill "$PID" 2>/dev/null
elif command -v feh >/dev/null 2>&1; then
# Linux — feh is a lightweight viewer that respects --geometry, kill on timer
feh --auto-zoom --geometry 600x600 "$IMG" >/dev/null 2>&1 &
PID=$!
sleep "$DURATION"
kill "$PID" 2>/dev/null
elif command -v xdg-open >/dev/null 2>&1; then
# Linux fallback — no clean way to auto-close, just open
xdg-open "$IMG" >/dev/null 2>&1 &
elif command -v start >/dev/null 2>&1; then
# Windows / WSL — open via default handler, no auto-close
start "" "$IMG"
fi
) >/dev/null 2>&1 &
exit 0
Related skills
How it compares
Install claude-brainrot only for personal humor experiments—not when building production agent skills that must stay silent and professional.
FAQ
Does claude-brainrot require manual invocation?
No. It is autonomous-only and fires on every user turn via the UserPromptSubmit hook.
How are sounds paired with images?
PostToolUse hooks play paired sounds on image Read, honoring lock_sound, silent, and preferred_sounds flags in catalogue.json.
How many memes fire per response?
Short answers get one combo or one to two sounds; long multi-tool responses target two to three combos plus three to five sounds.
Is Claude Brainrot safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.