narze/bad-apple-claude-mod
bad-apple
一个 Claude Code plugin,在提示符信息带或侧边 pane 中播放带同步声音的 Bad Apple!! 剪影艺术视频,并通过 function hooks 将画面渲染为象限字形。
关于这个 mod
bad-apple-claude-mod 是一个由 function hooks 组成的 Claude Code mod,并以 plugin 打包。它会在 Claude Code 内播放 Bad Apple!! 剪影艺术 PV,可放在提示符上方的信息带或侧边 pane 中,歌曲保持同步。画面以象限字形单元格(▘▀▌▙█)渲染,192x144 的源画面最多压缩到 96x36 个单元格,并通过 $.ui.blit 大约每秒重绘 60 次。可选的灰度模式会为每个单元格近似 32 个等级中的两个等级,以实现抗锯齿。命令包括 /bad-apple、pane、pause、resume、restart、gray 和 stop,状态列中有屏幕按钮及时间/进度条。音频使用 afplay(仅限 macOS)。视频和歌曲资源不包含在内,必须通过 scripts/download-video.sh 和 scripts/build-assets.sh,使用 ffmpeg、python3 与 yt-dlp 在本地构建,然后用 claude --plugin-dir 加载。代码采用 MIT License;媒体不包含在许可范围内。
安装
请先查看作者 README 确认 marketplace 和插件名称;命令可能随仓库结构改变。
claude plugin marketplace add narze/bad-apple-claude-mod claude plugin install bad-apple
原文 / README
bad-apple-claude-mod
Plays Bad Apple!! inside Claude Code, as a mod (a plugin of function hooks). The video plays in the band above the prompt, or in a side pane, with the song in sync.
- Quadrant cells: each cell is a solid quadrant glyph (
▘▀▌▙█…) over 2x2 quarters, drawn as oneRaster. Black and white by default; with gray on, each cell takes two of 32 gray levels, the best two-tone fit to how much of each quarter is lit, so edges are antialiased - 192x144 frames into at most 96x36 cells; smaller sites average bigger pixel blocks, never upscale
- About 60 repaints a second with
$.ui.blit, frame picked from the wall clock so video stays in sync with the song - Pause and resume, also for the song (the mod cuts the constant-bitrate MP3 at the right byte)
- Time and a progress bar beside the video, and in the status line
Use
| Command | What it does |
| --- | --- |
| /bad-apple | Play in the band above the prompt (default) |
| /bad-apple pane | Play in a pane (Esc closes it) |
| /bad-apple pause / resume | Pause or resume |
| /bad-apple restart | Play again from 0:00, in the same place |
| /bad-apple gray | Turn grayscale antialiasing on or off (off by default; remembered across sessions) |
| /bad-apple stop | Stop |
The band has Pause/Resume (p), Restart (r), Gray (g) and Stop (s) buttons; the pane has all but Stop (Esc closes it).
Sound plays through afplay, so only on macOS. Other systems get the video only.
Install
The video frames and the song are not in this repo. Build them on your machine.
You need ffmpeg, python3, and yt-dlp (or uvx, which runs the latest yt-dlp).
git clone https://github.com/narze/bad-apple-claude-mod
cd bad-apple-claude-mod
./scripts/download-video.sh # yt-dlp: YouTube -> work/bad-apple.webm
./scripts/build-assets.sh # work file -> assets/
claude --plugin-dir "$PWD"
Scripts
| Script | What it does |
| --- | --- |
| scripts/download-video.sh [url] [--force] | Downloads the PV from YouTube with yt-dlp (480p or less) to the working file work/bad-apple.<ext>. Skips the download when the file is there; --force downloads again. Default URL: https://www.youtube.com/watch?v=FtutLA63Cp8 |
| scripts/build-assets.sh [url] [--force] | Runs download-video.sh (same arguments), then makes 192x144 1-bit frames at 30 fps in assets/frames-*.bin and a 96 kbit/s mono MP3 in assets/bad-apple.mp3 |
If YouTube refuses the download (HTTP Error 403), update yt-dlp, or install uv so the script uses uvx yt-dlp@latest.
work/ and assets/ are git-ignored.
Develop
claude plugin validate .
claude plugin test .
npx -p typescript tsc -p . # after Claude Code has loaded the mod once (it writes .claude-plugin/types/)
| File | Role |
| --- | --- |
| hooks/register.tsx | Command, player, band and pane drawing |
| hooks/frames.ts | Pure helpers: grid fit, frame encoding, MP3 offset |
| hooks/bad-apple.test.ts | Tests (claude plugin test) |
| types/index.d.ts | $.state contract (mode, isPaused, isMono) |
| scripts/download-video.sh | Downloads the working video file to work/ |
| scripts/build-assets.sh | Builds assets/ from the working file |
Credits
Bad Apple!! is a song from Touhou Project by ZUN, arranged by Alstroemeria Records, with the shadow-art PV by Anira. This repo has no part of the video or the song.
License
The code is MIT. The MIT license does not cover the video or the song.


