Language: English | δΈζ | ζ₯ζ¬θͺ
Whenever Claude Code finishes a task, cheerer plays a danmaku (bullet-screen) floating-subtitle animation and a contextual encouragement message to make coding more fun. Voice output is available and can be enabled when you want spoken encouragement.
- π Six danmaku animations: basketball, dance, fireworks, rocket, trophy, wave
- π Multilingual voice encouragement (Chinese / English / Japanese / Korean / Spanish)
- π² Random animation selection, or force a specific animation
- π Epic mode that plays all six animations in sequence
- π Trigger stats and milestone celebrations (
--stats, milestone fireworks) - π Optional custom message pool loaded from
custom-messages.txt - π₯οΈ Automatic dumb-terminal fallback and session-scoped cooldown handling
After Claude Code finishes a task, your terminal instantly plays a short danmaku animation (floating subtitles scrolling right-to-left) and a matching voice encouragement. This is a text placeholder for now β a GIF demo will be added later.
Requires Claude Code. First add this repo as a plugin marketplace, then install the cheerer plugin from that marketplace:
claude plugin marketplace add chinadbo/cheerer
claude plugin install cheerer@cheererOr from inside a Claude Code session:
/plugin marketplace add chinadbo/cheerer
/plugin install cheerer@cheerer
Then run /reload-plugins if you installed it during an active session.
If you manage a team marketplace, add cheerer as an entry in your marketplace.json:
{
"name": "your-marketplace",
"plugins": [
{
"name": "cheerer",
"source": {
"source": "github",
"repo": "chinadbo/cheerer"
},
"description": "Danmaku animations + voice encouragement when tasks complete"
}
]
}This repository also works as a single-plugin marketplace out of the box:
claude plugin marketplace add chinadbo/cheerer
claude plugin install cheerer@cheerergit clone https://github.com/chinadbo/cheerer.git ~/.cheerer
chmod +x ~/.cheerer/scripts/cheer.sh
chmod +x ~/.cheerer/scripts/animations/*.sh
chmod +x ~/.cheerer/scripts/voices/*.sh
chmod +x ~/.cheerer/bin/cheerAdd to ~/.claude/settings.json:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "~/.cheerer/scripts/cheer.sh",
"async": true,
"statusMessage": "π Cheering..."
}
]
}
],
"TaskCompleted": [
{
"hooks": [
{
"type": "command",
"command": "~/.cheerer/scripts/cheer.sh",
"async": true,
"statusMessage": "π Cheering..."
}
]
}
]
}
}If Claude Code prompts for plugin settings during /plugin enable cheerer, you can configure:
/plugin enable cheerer
> Voice language (zh / en / ja): zh
> Animation style (random / basketball / dance / fireworks / epic): random
> Enable voice output (on / off): off
> Celebration style (adaptive / balanced / hype / cozy): adaptive
> Celebration intensity (soft / normal / high): normal
If no prompt appears, set the same values with environment variables instead.
Voice is opt-in on fresh installs. Leave CHEERER_VOICE unset (or set it to off) to keep cheerer text-first, and set it to on when you want spoken encouragement.
Set in your shell profile (~/.bashrc, ~/.zshrc) or .claude/settings.json:
| Variable | Description | Values | Default |
|---|---|---|---|
CHEERER_ENABLED |
Master switch | true / false |
true |
CHEERER_LANG |
Voice language | zh / en / ja / ko / es |
zh |
CHEERER_ANIM |
Animation style | basketball / dance / fireworks / rocket / trophy / wave / epic / random |
random |
CHEERER_VOICE |
Voice output | on / off / true / false |
off |
CHEERER_DUMB |
Force text-only fallback or keep auto-detect | auto / true / false |
auto |
CHEERER_MODE |
Output mode | auto / full / text |
auto |
CHEERER_COOLDOWN |
Cooldown between triggers (seconds) | positive integer | 3 |
CHEERER_EPIC_THRESHOLD |
Auto-enable epic mode when task duration reaches this many seconds | positive integer | 60 |
CHEERER_EPIC |
Force epic mode for one run | true / false |
false |
CHEERER_CUSTOM_ONLY |
Use only custom messages when available | true / false |
false |
CHEERER_STYLE |
Celebration personality | adaptive / balanced / hype / cozy |
adaptive |
CHEERER_INTENSITY |
Celebration energy | soft / normal / high |
normal |
CHEERER_*env vars override pluginuserConfigsettings.
CHEERER_MODE=autoplays animation onTaskCompleted, and keepsStophooks text-only unlessCHEERER_INTENSITY=high.CHEERER_MODE=fullalways plays animation.CHEERER_MODE=textalways skips animation and prints only the encouragement text/voice.CHEERER_ANIM=epic,CHEERER_EPIC=true, or a task duration at or aboveCHEERER_EPIC_THRESHOLDplays all six animations in sequence.CHEERER_COOLDOWNhas an effective minimum of 1 second, even if you set0.- Cooldown suppresses animation only; text/voice output still runs.
CHEERER_DUMB=autois the default; cheerer also auto-detects dumb terminals and emptyTERMvalues.CHEERER_STYLE=adaptiveuses hook type, duration, milestones, and recent history to vary cheer tone.CHEERER_INTENSITY=softkeeps quick wins lighter;highmakes celebration output more energetic, including animatedStophooks inCHEERER_MODE=auto.- Messages are selected from per-language catalogs and avoid immediate repeats when possible.
Built-in locale catalogs are validated in tests so every supported language keeps the same reachable celebration coverage for the current policy rules. If a locale loses a required (tier, mood) path, the test suite fails before release.
From a repo checkout:
# Main script
bash scripts/cheer.sh
CHEERER_LANG=en bash scripts/cheer.sh
CHEERER_LANG=ja CHEERER_VOICE=off bash scripts/cheer.sh
CHEERER_ANIM=fireworks bash scripts/cheer.sh
CHEERER_ANIM=epic bash scripts/cheer.sh
CHEERER_MODE=text bash scripts/cheer.sh
CHEERER_DUMB=true bash scripts/cheer.sh
# Wrapper command
bash bin/cheer --epic
bash bin/cheer --stats
bash bin/cheer --preview
bash bin/cheer --list
bash bin/cheer --doctor
bash bin/cheer --why < tests/fixtures/taskcompleted-short.jsonbin/cheer supports six flags:
--epicβ force epic mode (plays all six animations in sequence)--statsβ print total triggers, milestones reached, and last trigger time--preview [name]β play an animation without a hook trigger;nameis optional (random if omitted)--listβ list all available animations and languages--doctorβ run read-only install/runtime/config diagnostics; exits non-zero when any hard failure is found--whyβ explain the current celebration decision in plain text without animation, voice, or state mutation
cheer --doctor prints grouped PASS, WARN, and FAIL lines for config safety, runtime mode resolution, assets, catalogs, and optional user files.
- Exit code
0: onlyPASS/WARN - Exit code non-zero: one or more
FAILlines
cheer --why explains a single celebration decision in plain text. It reads the same hook JSON payload as the normal runtime path, or uses a deterministic short-task probe when stdin is empty.
Both commands are read-only diagnostic paths: they do not append history, update stats, write cooldown state, play animation, or emit voice.
bash tests/run.sh all
bash tests/run.sh state
bash tests/run.sh policy
bash tests/run.sh render
bash tests/run.sh integrationBy default, cheerer stores plugin data in ${CLAUDE_PLUGIN_DATA:-$HOME/.config/cheerer}:
stats.jsonβ total triggers, last trigger time, milestone historyhistory.logβ per-trigger log (timestamp, event, duration, tier, mood, animation, message id); trimmed to the last 50 rowscustom-messages.txtβ optional custom encouragements, one message per line (#starts a comment)
Cooldown state is tracked separately in /tmp/cheerer_last_trigger_${CLAUDE_SESSION_ID:-default}.
Milestones currently trigger at 10, 25, 50, 100, 250, 500, and 1000 total runs. Milestone runs append a trophy message and force the fireworks animation.
- Pure Shell implementation with zero runtime dependencies
- ANSI escape codes for colors and cursor movement
- Danmaku engine β floating subtitles scroll right-to-left at configurable rows, speeds, and delays
- Voice fallback: macOS
sayβespeakβ plain text - Animation duration: around 2β3 seconds, designed not to interrupt your workflow
- Terminal compatibility: automatically detects dumb terminals and falls back gracefully
cheerer/
βββ .claude-plugin/
β βββ plugin.json # Plugin manifest
βββ bin/
β βββ cheer # Wrapper command (--epic, --stats, --preview, --list)
βββ hooks/
β βββ hooks.json # Hook configuration
βββ scripts/
β βββ cheer.sh # Main entry point (hooks + routing + stats)
β βββ animations/
β β βββ basketball.sh # Basketball danmaku theme
β β βββ dance.sh # Dance danmaku theme
β β βββ fireworks.sh # Fireworks danmaku theme
β β βββ rocket.sh # Rocket danmaku theme
β β βββ trophy.sh # Trophy danmaku theme
β β βββ wave.sh # Wave danmaku theme
β βββ lib/
β β βββ animation.sh # Shared danmaku engine
β β βββ policy.sh # Tier/mood selection logic
β β βββ render.sh # Message selection and output
β β βββ state.sh # Stats, history, milestones
β βββ messages/
β β βββ catalog_en.tsv # English message catalog
β β βββ catalog_zh.tsv # Chinese message catalog
β β βββ catalog_ja.tsv # Japanese message catalog
β β βββ catalog_ko.tsv # Korean message catalog
β β βββ catalog_es.tsv # Spanish message catalog
β βββ voices/
β βββ cheer_zh.sh # Chinese encouragement
β βββ cheer_en.sh # English encouragement
β βββ cheer_ja.sh # Japanese encouragement
β βββ cheer_ko.sh # Korean encouragement
β βββ cheer_es.sh # Spanish encouragement
βββ tests/
β βββ run.sh # Test runner
β βββ fixtures/ # JSON hook event fixtures
β βββ integration_test.sh
β βββ policy_test.sh
β βββ render_test.sh
β βββ state_test.sh
βββ README.md
βββ README.en.md
βββ README.zh.md
βββ README.ja.md
- Create a new
.shfile inscripts/animations/β setDANMAKU_*arrays then callanim_danmaku_run - The animation is auto-discovered at runtime (no registration needed)
- Run
bash scripts/cheer.shorCHEERER_ANIM=<name> bash scripts/cheer.shto verify it works
- Create
cheer_XX.shinscripts/voices/ - Add the matching language handling in
scripts/cheer.sh - Run
CHEERER_LANG=<code> bash scripts/cheer.shto verify the output
Create ${CLAUDE_PLUGIN_DATA:-$HOME/.config/cheerer}/custom-messages.txt:
Ship it!
Nice refactor.
Tests are green β enjoy the win.
Set CHEERER_CUSTOM_ONLY=true if you want to skip the built-in message pool.
MIT Β© chinadbo