SLOPSHOPPER

Bumper Sticker

Your own words on the busy line while Claude works, in place of Baking, Brewing and the rest.

spinner
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · bumper-sticker
› fix the failing auth test and add an audit log call ⏺ Read(src/auth.ts) ⎿ Read 6 lines ⏺ Update(src/auth.ts) ⎿ Added 2 lines, removed 1 line ⏺ Bash(bun test) ⎿ 3 pass, 1 fail ● Done. refresh now rejects expired claims and logs an audit event. ✻ Worked for 42s · done 4:20 PM ✻ Kerning… ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts
README

Bumper Sticker

Your own words on the busy line. While Claude works, Claude Code shows a little word that pulses, such as ✶ Baking… (12s). Bumper Sticker swaps that word for yours.

  • Out of the box it uses the print-shop set: Penciling, Inking the rollers, Cranking the press, Trucking to the newsstand, Riding the coaster, and more.
  • To use your own, open /plugin, find Bumper Sticker, and type your words into Your words, separated by commas: Revving, Idling, Drifting.
  • One turn keeps one word. The next turn gets another. The pick follows the word Claude Code chose for that turn, so nothing is random.

It changes only the word. The timer, the token count and the colour stay as Claude Code draws them. It works in the terminal and in the desktop app. Nothing leaves your machine.

What it runs and sends

Nothing goes anywhere. Here is each thing, plainly.

What it sends, and where.

  • Nothing. It reads your words from the Your words setting and changes the word on your screen.
  • It stores nothing on disk. The setting is kept by Claude Code.

Which programs it runs, and why.

  • None. It runs no programs.

What it puts in the prompts it submits.

  • It submits no prompts, and changes none of yours.

What each hook does.

  • ui.render for Spinner: swaps the busy word for one of yours. It changes only the word.

More mods

See every Rostech mod, live, at rostech.app.

Source 1 files
hooks/register.ts 36 lines
1import type { Register } from 'claude-code'
2
3// The print-shop set: what a comics press does while you wait.
4export const PRESS: readonly string[] = [
5  'Penciling', 'Inking', 'Lettering', 'Coloring', 'Thumbnailing', 'Plotting',
6  'Scripting', 'Paneling', 'Splashing', 'Cliffhanging', 'Retconning',
7  'Crossing over', 'Rebooting', 'Greenlighting', 'Setting type', 'Kerning',
8  'Halftoning', 'Making ready', 'Inking the rollers', 'Pulling proofs',
9  'Cranking the press', 'Checking the plates', 'Folding', 'Stapling',
10  'Bundling', 'Trucking to the newsstand', 'Racking', 'Counting returns',
11  'Answering fan mail', 'Chasing the craze', 'Haggling with the distributor',
12  'Signing the creator', 'Pitching to Hollywood', 'Licensing',
13  'Climbing the ladder', 'Riding the coaster', 'Becoming a household name',
14]
15
16// "a, b ,c" into ["a", "b", "c"]; empty or missing gives the print-shop set.
17export function wordsFrom(text: unknown): readonly string[] {
18  if (typeof text !== 'string') return PRESS
19  const list = text.split(',').map(w => w.trim()).filter(w => w.length > 0)
20  return list.length > 0 ? list : PRESS
21}
22
23// The same word for the whole turn, a different one next turn. The engine
24// samples its own word once per turn, so that word is the seed: no dice.
25export function pick(list: readonly string[], seed: string): string {
26  let h = 0
27  for (let i = 0; i < seed.length; i++) h = (h * 31 + seed.charCodeAt(i)) >>> 0
28  return list[h % list.length]
29}
30
31export const register: Register = (on, options) => {
32  const words = wordsFrom(options.words)
33  on('ui.render', { component: 'Spinner' }, async ($, e, next) =>
34    next({ ...e, props: { ...e.props, word: pick(words, `${e.props.word}|${e.requestId}`) } }))
35}
36