The loading line speaks as a pixel bunny: "🐰 Michel: reading the docs", "nom nom" while a tool runs

Mods for Claude Code: plugins of function hooks that change how the app looks.
| Mod | What it does |
|---|---|
meadow | Claude's replies as pixel bubbles: a short pixel sky and hill on top of each reply, a strip of grass under its last block. Desktop app only; the terminal keeps its own look. |
bunny-spinner | The loading line speaks as a bunny: 🐰 Michel: reading the docs, with · nom nom… while a tool runs. The app keeps its timer beside it. The name is a setting. |
Load one or both in every session by adding their folders to ~/.claude/settings.json (paths separated by :):
{
"env": {
"CLAUDE_CODE_PLUGIN_DIRS": "~/repos/claude-mods/meadow:~/repos/claude-mods/bunny-spinner",
"CLAUDE_CODE_PLUGIN_DIR_WATCH": "1"
}
}
CLAUDE_CODE_PLUGIN_DIR_WATCH reloads a mod when you edit it. Or install them from this repo as a plugin marketplace (/plugin marketplace add DenisGuiraudet/claude-mods).
claude plugin validate meadow
bun test meadow/testshooks/register.tsx 25 lines1import type { Register } from 'claude-code'
2
3// What the bunny says while a tool runs, after what the app says it's doing
4const MUNCHING = ' · nom nom…'
5
6export const register: Register = (on, options) => {
7 const chosen = options as { name?: string } | undefined
8 const name = chosen?.name?.trim() || 'Michel'
9
10 // The loading line speaks as the bunny; the app keeps its own timer and token count beside it
11 on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
12 const doing = e.props.message ?? e.props.word
13 const face = e.props.mode === 'thinking' ? '🤔' : '🐰'
14
15 return next({
16 ...e,
17 props: {
18 ...e.props,
19 message: `${face} ${name}: ${doing.charAt(0).toLowerCase()}${doing.slice(1)}`,
20 suffix: e.props.mode === 'tool-use' ? MUNCHING : e.props.suffix,
21 },
22 })
23 })
24}
25