Ferro (a Norwich Terrier) runs across a pixel-art meadow in a band above the prompt while Claude works on a long turn; now and then she stops to sit, sniff…

<img src="preview/ball-sit.svg" width="100%" alt="Ferro, a pixel-art Norwich Terrier, chasing an orange ball across a scrolling meadow, then sitting down to look at you">
A Claude Code mod for the Code tab of Claude Desktop. When Claude works on a turn for longer than 20 seconds, a band opens above the prompt and Ferro, a Norwich Terrier, runs across a pixel-art meadow. When the turn ends, the band disappears. Nothing is interactive, so there is nothing to miss when you are not looking.
Every turn picks a meadow, a program for the run and whether she chases a ball, all at random. A program is a run with a moment every 6 to 12 seconds, the first one too. In about three moments of ten nothing happens and she just runs on; in the rest she sits, sniffs, drinks, looks around, listens, eats a piece of bread or poops, never the same thing twice in a row and poops at most once. The scenes below have one stop each, 9 seconds in.
On the way she runs past things on the meadow, behind her or in front of her: a rock, a tuft of grass, a bush, a beach ball, a knight's helmet, a sword stuck in the ground. About every 10 seconds of running something comes in from the right, picked anew on every turn by its chance, and a few are rare easter eggs (a landed spaceship now and then). The library is assets/props.json, one line per prop.
Sits down and looks at you (the first stop in a fifth of the programs; a short turn sees only that one). She brakes, sits, turns her head to you, blinks, tilts her head, turns back, gets up on all fours and sets off from where she stood.
<img src="preview/sit.svg" width="100%" alt="Ferro sits down on the meadow and looks at you">
Sniffs a spot (the first stop in a tenth). She slows down with her head lowering, pushes her nose into the grass a few times, lifts her head and runs on.
<img src="preview/sniff.svg" width="100%" alt="Ferro stops and sniffs a spot on the meadow">
Drinks from her bowl (the first stop in a tenth). A red bowl comes in with the grass, she slows down with her head lowering and laps the water while drops splash out beside the bowl, then lifts her head and runs on.
<img src="preview/drink.svg" width="100%" alt="Ferro runs to a red water bowl on the meadow and laps the water">
Looks around (the first stop in a tenth). She stops, turns her head to you, looks back over her shoulder, turns forward again and runs on.
<img src="preview/look.svg" width="100%" alt="Ferro stops on the meadow and looks around">
Listens (the first stop in a tenth). She stops, lifts her head with her ears pricked, tilts it and runs on.
<img src="preview/listen.svg" width="100%" alt="Ferro stops on the meadow and listens with her ears pricked">
Eats a piece of bread (the first stop in a tenth), as the real Ferro does on a walk. A piece of bread comes in with the grass, she slows down, sniffs it, picks it up, chews and licks her lips.
<img src="preview/bread.svg" width="100%" alt="Ferro finds a piece of bread on the meadow and eats it">
Poops while walking (the first stop in a fifth), the way the real Ferro does: hunched, walking slowly forward, leaving a row of droppings that scrolls away with the grass.
<img src="preview/run.svg" width="100%" alt="Ferro poops while walking across the meadow">
Poops in one spot (the first stop in a tenth), the rare way.
<img src="preview/autumn-run-still.svg" width="100%" alt="Ferro stops and poops in one spot on the autumn meadow">
Chases an orange ball (a third of the turns, on top of the above). The ball bounces ahead of her; at every stop it rolls on and waits on the grass until she reaches it, then pops up again.
<img src="preview/autumn-ball-run.svg" width="100%" alt="Ferro chases an orange ball across the autumn meadow">
Falls asleep after 5 minutes. She lies down and breathes, and z's rise above her head.
<img src="preview/autumn-sleep.svg" width="100%" alt="Ferro asleep on the autumn meadow">
The meadow is summer or autumn, in three layers (clouds, hills with trees, grass) that scroll at different speeds. A winter meadow is built but switched off for now.
<img src="preview/winter-sit.svg" width="100%" alt="Ferro sits down on the winter meadow">
Art. ChatGPT drew the frames (run, poop, sleep and sit as 6-frame strips, the hunched walk as a 4-frame strip with three droppings, lapping as a 4-frame strip with the bowl and the drops, standing still and eating bread as 6-frame strips, the bread also on its own, all on a magenta background) and the three meadows. tools/build.py turns them into real pixel art: it cuts the frames, removes the magenta, snaps them to a true pixel grid, maps every pixel to a frozen 22-colour palette (assets/palette.json, plus three reserved shades for the tongue and one colour for the eye highlight), cleans the outline, keeps one highlight in each eye and aligns the frames on the ground line and on the ear, or on the front paws where the head turns. Where she stands still and only her head moves, ChatGPT kept her body, so those frames are used as drawn, each laid on one frame by the silhouette of her hindquarters. ChatGPT drew some strips at a different scale than asked, so each strip has its own factor that gives Ferro the same head size everywhere. The sleeping breath and the blink while she sits are derived in code from one frame, so the pose never jumps, and when she gets up from sitting she stands in the standing frame of the poop strip. ChatGPT redrew her whole body in every lapping frame, so the lapping keeps one body and one bowl and takes only the head and the tongue from each frame; the bowl and the water get colours of their own. The orange ball is drawn in code. Each meadow is split into its three layers, and the clouds get their own small palette so their light-blue shading survives. Colours the meadow palette misses by far get extra slots, which keeps the brown trunks of the winter trees brown.
<img src="assets/ref/ferro-ref.png" width="100%" alt="Reference sheet for ChatGPT: Ferro standing, running and facing the viewer, the palette and every frame of every animation">
The reference sheet above goes into every ChatGPT request for new frames, so new drawings keep the same Ferro. The instructions and the prompts that produced each strip are in assets/ref/chatgpt-project.md.
Rendering. The Desktop band can draw an Svg element. Every frame and background layer is a small indexed-colour PNG in an <image> (data URI), defined once in <defs> and placed with <use>; image-rendering="pixelated" keeps the pixels sharp at 2x. The band renders <image> only when the Svg is drawn as an image, not in the sandboxed frame (isInteractive), so the mod draws it as an image. Until version 0.7.2 every frame was converted to vector strokes (one <path> per colour, one stroke per horizontal run of pixels), about six times the size. All animation is SMIL inside the SVG, so the mod draws the scene once and the browser engine animates it. tools/scene.py puts a run together from its stops (each kind of stop is one function that says which frames show when and how far the ground moves), draws ten programs per meadow with a fixed seed, since SMIL has no randomness, and writes them with the sleeping scene into one module per meadow (plugin/hooks/scene-<meadow>.ts, each under the 1 MiB the hooks loader reads) and preview/.
Constraints that shaped it. The facts about Claude Code and the Desktop band behind them, with the build and the date they were last checked, are in docs/desktop-band.md.
Svg element accepts at most 131,072 characters. A run is a head every program of a meadow shares (the meadow and every frame of every stop, about 57k) and the program's own timeline; the largest program with the ball is about 124k (winter), and the sleeping scene about 18k. The props a turn picks go in on top; should a run ever go over, the mod leaves out the last ones, which in a simulation of 3,000 turns never happened. As vector strokes a scene with a single stop was 85k to 118k, and winter with the ball came within 117 characters of the limit, so until the PNG frames each kind of stop was a scene of its own and a turn had one kind.[4, 3, 2, 5, 0].The mod. plugin/hooks/register.tsx starts its timers on turn.start (20 s to run, 5 min to sleep) and picks the turn's meadow, program (one of ten) and ball (one in three), keeping all of it in $.state. The timers are cleared on the main turn's turn.complete. The band is drawn with a ui.render hook on AbovePrompt, only on the desktop surface. Ferro is only a pastime, so she gives the band up to any other mod that has something to show there (the files a delete prompt is about, for one): the hook asks the plugins beneath first and draws only when the band would otherwise be empty. The band starts a scene from its first frame whenever it draws it anew, as when a conversation is opened again, so once Ferro has lain down the hook swaps in a sleeping scene without lying down, which starts where the first one is at that moment; otherwise she would lie down again every time the conversation is opened.
claude plugin marketplace add <path-to-this-repo>
claude plugin install cc-mod-ferro@cc-mod-ferro --scope user
Function hooks of installed plugins may need "CLAUDE_CODE_ENABLE_FUNCTION_HOOKS": "1" in the env block of ~/.claude/settings.json. It works only in the Code tab of Claude Desktop: the band above the prompt exists only there and in the terminal, and the terminal has no Svg element.
Check and test: claude plugin validate ./plugin and claude plugin test ./plugin.
hooks/register.tsx 109 lines1import { atom, read, update } from 'claude-code'
2import type { Register, Timer } from 'claude-code'
3
4import type { FerroPhase } from '../types'
5import { pickProps, runScene } from './run'
6import type { PropPicks } from './run'
7import { SCENE_MAX_WIDTH, SCENES, SLEEP_INTRO_MS } from './scene'
8
9// Ferro comes out only when a turn lasts longer than this, so short answers do not flash the band.
10const RUN_AFTER_MS = 20_000
11// When Claude works for too long, Ferro lies down and falls asleep.
12const SLEEP_AFTER_MS = 300_000
13const PX_PER_COLUMN = 8
14// In about a third of the turns she chases an orange ball.
15const BALL_SHARE = 1 / 3
16
17const phase = atom({ plugin: 'cc-mod-ferro', key: 'phase' } as const, null as FerroPhase)
18// This turn's background, an index into SCENES: picked at random on every turn.
19const scene = atom({ plugin: 'cc-mod-ferro', key: 'scene' } as const, 0)
20// This turn's run, an index into the background's programs, also picked per turn. A program is a
21// run with its stops (sitting, sniffing, drinking, pooping), drawn in tools/scene.py: SMIL has no randomness.
22const program = atom({ plugin: 'cc-mod-ferro', key: 'program' } as const, 0)
23// Whether she chases the ball this turn, also picked per turn.
24const ball = atom({ plugin: 'cc-mod-ferro', key: 'ball' } as const, false)
25// What stands in the program's prop slots this turn (run.ts), picked per turn by the props' chances.
26const props = atom({ plugin: 'cc-mod-ferro', key: 'props' } as const, { ground: [], far: [] } as PropPicks)
27
28export const register: Register = on => {
29 let timers: Timer[] = []
30 const cancelTimers = () => {
31 timers.forEach(t => t.cancel())
32 timers = []
33 }
34
35 on('turn.start', async ($, e, next) => {
36 cancelTimers()
37 await update($, phase, () => null)
38 const background = Math.floor(Math.random() * SCENES.length)
39 await update($, scene, () => background)
40 const run = Math.floor(Math.random() * SCENES[background].programs.length)
41 await update($, program, () => run)
42 await update($, props, () => pickProps(SCENES[background].programs[run]))
43 await update($, ball, () => Math.random() < BALL_SHARE)
44 timers = [
45 $.clock.after(RUN_AFTER_MS, () => void update($, phase, () => 'run')),
46 $.clock.after(SLEEP_AFTER_MS, () => void update($, phase, () => 'sleep')),
47 // The band starts a scene from its first frame whenever it draws it anew (reopening the
48 // conversation), so once she has lain down she sleeps on in the scene without lying down.
49 // It starts where the other one is when she has lain down, so the swap does not show.
50 $.clock.after(SLEEP_AFTER_MS + SLEEP_INTRO_MS, () => void update($, phase, () => 'asleep')),
51 ]
52 return next(e)
53 })
54
55 on('turn.complete', async ($, e, next) => {
56 // Subagent turns do not close the band, only the end of the main turn does.
57 if (e.agentId === undefined) {
58 cancelTimers()
59 await update($, phase, () => null)
60 }
61 return next(e)
62 })
63
64 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
65 // The terminal has no Svg element.
66 if (e.surface === 'terminal' || e.props.hasSurvey || !e.props.isWorking) {
67 return next(e)
68 }
69 const now = await read($, phase)
70 if (now === null) {
71 return next(e)
72 }
73 // Ferro is only a pastime, so any band drawn beneath her (the files a delete prompt is about,
74 // background tasks) goes first and she waits. `{ type: 'engine' }` is the engine's own band,
75 // which is empty: nobody beneath has anything to show.
76 const beneath = await next(e)
77 if (beneath.type !== 'engine') {
78 return beneath
79 }
80
81 const { Box, Svg } = $.ui.resolve(e)
82 const s = SCENES[await read($, scene)] ?? SCENES[0]
83 const p = s.programs[await read($, program)] ?? s.programs[0]
84 const withBall = await read($, ball)
85 // every program of a background shares the head (the meadow and all drawings); the ball and the
86 // props are pieces of SVG inserted into the program's body
87 const run = runScene(s, p, withBall, await read($, props))
88 const runAlt = withBall ? `Ferro chasing an orange ball across ${s.place}` : `Ferro running across ${s.place}`
89
90 // Without an explicit width the frame stays at 300 px. Desktop counts the band in columns
91 // of ~8 CSS pixels (measured 4.10.2026: 94 columns, ~753 px). On a narrower band the scene
92 // is cropped at the sides and the pixels keep their size.
93 const width = Math.min(SCENE_MAX_WIDTH, Math.max(300, e.props.bodyColumns * PX_PER_COLUMN - 8))
94
95 // Drawn as an image (no isInteractive): only then does the band render the PNG frames, and
96 // SMIL animates there too.
97 return (
98 <Box>
99 <Svg
100 source={now === 'sleep' ? s.sleep : now === 'asleep' ? s.asleep : run}
101 alt={now === 'run' ? runAlt : `Ferro asleep on ${s.place}`}
102 width={width}
103 height={s.height}
104 />
105 </Box>
106 )
107 })
108}
109hooks/run.ts 81 lines1import { PROPS, SCENES, SVG_LIMIT } from './scene'
2
3type Scene = (typeof SCENES)[number]
4type Program = Scene['programs'][number]
5
6// What stands in each slot of a run this turn: an index into PROPS, -1 for an empty slot.
7export type PropPicks = { ground: number[]; far: number[] }
8
9// The prop a slot gets for a roll in [0, 1), by the chances in percent; -1 for none (what is left
10// to 100). A ground slot takes a ground prop, a far slot one behind the hills or one at the edge of
11// the meadow, in front of the forest. tools/scene.py does the same for its previews (pick_prop).
12export function pickProp(where: 'ground' | 'far', roll: number): number {
13 let r = roll * 100
14 for (let i = 0; i < PROPS.length; i++) {
15 const w = PROPS[i].where
16 if (where === 'ground' ? w !== 'ground' : w !== 'far' && w !== 'edge') continue
17 r -= PROPS[i].chance
18 if (r < 0) return i
19 }
20 return -1
21}
22
23export function pickProps(p: Program, random: () => number = Math.random): PropPicks {
24 return { ground: p.slots.map(() => pickProp('ground', random())), far: p.far.map(() => pickProp('far', random())) }
25}
26
27const use = (i: number, x: number, bottom: number) =>
28 `<use href="#prop-${PROPS[i].name}" x="${x}" y="${bottom - PROPS[i].h + 1}"/>`
29
30function compose(s: Scene, p: Program, withBall: boolean, picks: PropPicks): string {
31 let far = ''
32 let edge = ''
33 let behind = ''
34 let front = ''
35 p.far.forEach((x, k) => {
36 const i = picks.far[k] ?? -1
37 if (i < 0) return
38 // a far or edge prop stands on its own row (a tall far one lower, behind the hills)
39 if (PROPS[i].where === 'edge') edge += use(i, x, PROPS[i].bottom)
40 else far += use(i, x, PROPS[i].bottom)
41 })
42 p.slots.forEach(([x, bottom, inFront], k) => {
43 const i = picks.ground[k] ?? -1
44 if (i < 0) return
45 if (inFront) front += use(i, x, bottom)
46 else behind += use(i, x, bottom)
47 })
48 const pieces: [number, string][] = [
49 [p.marks[0], far],
50 [p.marks[1], edge],
51 [p.marks[2], behind],
52 [p.marks[3], front],
53 ]
54 if (withBall) pieces.push([p.ballAt, p.ball])
55 // from the last index to the first, so each index still points into the program's body
56 let body = p.body
57 for (const [at, piece] of pieces.sort((a, b) => b[0] - a[0])) {
58 body = body.slice(0, at) + piece + body.slice(at)
59 }
60 const used = [...new Set([...picks.ground, ...picks.far].filter(i => i >= 0))].sort((a, b) => a - b)
61 const defs = used.map(i => PROPS[i].def).join('')
62 return s.head + (defs ? `<defs>${defs}</defs>` : '') + body
63}
64
65// The run of a turn: the background's head, the program's body, the ball and the props picked for
66// it. Should the props ever take a run over the Svg limit, the last ones are left out until it fits.
67export function runScene(s: Scene, p: Program, withBall: boolean, picks: PropPicks): string {
68 let ground = picks.ground.slice()
69 let far = picks.far.slice()
70 let run = compose(s, p, withBall, { ground, far })
71 while (run.length > SVG_LIMIT) {
72 const g = ground.findLastIndex(i => i >= 0)
73 const f = far.findLastIndex(i => i >= 0)
74 if (g < 0 && f < 0) break
75 if (g >= 0) ground = ground.map((i, k) => (k === g ? -1 : i))
76 else far = far.map((i, k) => (k === f ? -1 : i))
77 run = compose(s, p, withBall, { ground, far })
78 }
79 return run
80}
81hooks/scene.ts 11 lines1// Generated by tools/scene.py - do not edit by hand.
2import { SCENE as SCENE_0 } from './scene-meadow'
3import { SCENE as SCENE_1 } from './scene-autumn'
4export const SCENE_MAX_WIDTH = 1280
5export const SLEEP_INTRO_MS = 4800
6export const SVG_LIMIT = 131072
7export const FAR_BASE = 34
8export const EDGE_BASE = 56
9export const PROPS = [{"name": "rock", "where": "ground", "chance": 28, "h": 12, "bottom": 56, "def": "<image id=\"prop-rock\" width=\"19\" height=\"12\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAMCAMAAAC3DnawAAAAOVBMVEUAAAAYERcgFh8/QT9IS0lNUU9VWVZgZWFrbmp0d3F8fneEhX6Li4KRkIefnI+qp5i5tKO+uanY0b/i+a2pAAAAE3RSTlMA////////////////////////Pj/cLQAAAINJREFUeNpVz1sWQiEIBVBBEUF8zn+wod1adb5wLwEN4QkgYPgL4t5z4o8izL3WnL3Ct03H8FuuGj+IWs2WU6FEb4RYTFrvoslzDdvozGZNJCVV9j1AZQzOZibUu0n0kZCZ+RycatV4DDORiPDpU6Vr/oGcRXKkWoRSfN6NiHBzihDCC1kwBRM6rpAWAAAAAElFTkSuQmCC\"/>"}, {"name": "tuft", "where": "ground", "chance": 28, "h": 24, "bottom": 56, "def": "<image id=\"prop-tuft\" width=\"28\" height=\"24\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAYCAMAAADeQm2wAAAAOVBMVEUAAAAHQC4JUjQKKiMNZTUODxMWdTQcFCIfgjMhLyYwji1AnCtNFUhQqClgtyl3yCiL1iqa4C6x7TsfAiheAAAAE3RSTlMA////////////////////////Pj/cLQAAAUVJREFUeNp1UVty5DAINIiHLIKAuf9hg+1skq2a8EGpaGi60XH8H+d5/BXKW99U75pW6ruRPTplvSX9WM3HeQ3y+c30TwPvs0HqDufG/Bu8+jV2D0KXsTvjh17zPHRt9gS1HtQ0/gGjVMXBcow5mcN/a9baKnNbgswqD/n4BXLUQilLwayxfTySH0WtswDTIrCEXFhLD20X7Yh5eBjaii0b5wJ7qWq0Kt3CBWZdWgFugARl+spTb/ve7qWIlq054YUZXBsfxeiSQlW4xAgLMWzG5OeEPGe4QPuQhd2zN6w1eilfPoDcBHbiJCtBdyAaWev6hUhHI5gJEzJwOjWY+SzliNE3p01I6U3Zz/IbG4OlTYaNbeDbabWiJrlPf11LrI0idvZJAqu5Ae4Lsq1+S2eD6YjYjQDTvnYyECB3gHCDzNhzF/YJDhcPXRnM2eIAAAAASUVORK5CYII=\"/>"}, {"name": "bush", "where": "ground", "chance": 18, "h": 34, "bottom": 56, "def": "<image id=\"prop-bush\" width=\"49\" height=\"34\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADEAAAAiCAMAAADBAMEbAAAAP1BMVEUAAAAGSjMHWTcIOiwKZTkPDRUPcjcYGx4ZfjYjiDQoEC0rVCcukzI8nS5KqSpZtClqwCl5yyiI1CiQ2iqZ4C14WrDpAAAAFXRSTlMA//////////////////////////9QsPovAAACwElEQVR42pVUgXYjIQgM6KLmVBD3/7/1hk3a1/bl2p7Zl2SVEWYYvd3+OUq5/ec47P774Ni+mJXfxiJYS3Gz43b/EVRUD3wvs7HN0oHXH0rD7ogp203P8xyuquX7klC8pjmrbsXj7jrLtyVZO/eeOid+dC4g/PhOaJDQ6XP72HubbnfpXXKJhZcQrIy9EGgyqmTf28/WBcTsNeLoR8fes6+lA6O2uhZn2mdD7lcy33sHYiwEC40xGwQYoL62AtTmC5lL78yjjZFPZ/zwrCjMda9T15xfRAtXJAJPxlKDUDkTUdMFCrqg9PoKGOWw1R3KMMK3rUYi3JrU6Mop0trnog7UsGxpq9EHFZ3tdDdqQQRNkdxa/Zjkfkfx7QFwR10KCgikKmom7jnG/X68gf70nlFwr42braQq4ALAnoBLkywkuluycPNTo94Nn8pELBB377UiGqjOoFOxxXakm++Itmae9dzLFyF/NPIaxrUyc0W6bX6+H7FSUsXSRcI95TAIFIaoYNAoJZkQRB295TepaiU87NuXJwGGCXlCJWaqXbrb8A0jHG85uFJi6OpjRc9r7ey+GDmJkNDQV3DffLTy9CD2p1MvYYcZCkT3BfUjVw0Pq4lAsoZxQUrT3gkbDl8zzl5OIV9QkzmmxRmDiB1OuBDlyBzraCsqCJ28ESxWE6jtc+FELkwmhrpU496IEvLq2onyNtD3GfrEg5fr5J4dtFNt+ribIrepLOtwH19+4BQlg4iAmyAzplOYOefy6Ea2qCucWhEJs5DO0RknK/BAUDixpXgLyME5pYtoplAD9aDbhj2mSKWGpjNy5pbSE4GJ0CbBUOAC1gT5l8B3Y2ZBq7BI6BdJKuV5GRVUnkIfwUpKsSmHU4mf8z2E4MzleHMJcylEAwt04RFJkINinh85MA3E59v/MW7v/2IcH+Yfi7e/VIsvbxYwNkcAAAAASUVORK5CYII=\"/>"}, {"name": "beach-ball", "where": "ground", "chance": 12, "h": 26, "bottom": 56, "def": "<image id=\"prop-beach-ball\" width=\"28\" height=\"26\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAaCAMAAACTisy7AAAAPFBMVEUAAAARUpcVdMkaEBleNyp+dWG2sKXNw7TSKiLakRTf1MXuqQ/xQCjx6Nfz69v279/5gmH69uv8xAX9/PgowSUSAAAAFHRSTlMA/////////////////////////7rhY6kAAADnSURBVHjabdLbtoUgCAXQEi9Yqan//68HgaxOez300BwwUFmWGdAs3wDkUnIurX0YoBZOTvt/huM48BAmJH7bCFKhc/GlbKew6706wh2eJmh733pfjVmdqGVjRMLEaAxo4SmIWIOrNVljLtWuJ9ZK5wzO2jYRUCftwyhjGsYVFLFTBqVtHORGUkxJMfMdtAeS5SKmOA4jiKNdzk9sZIpTaNo2Ucb1ifIubFzI6EffxJ8b5RKC914rJ8b1ur+hylEoRimcGqguRaEYzf2gm5e4qNmfq6B60f5eIml90Xf/gqf/+w/6vdR/hjoWmcOzXsMAAAAASUVORK5CYII=\"/>"}, {"name": "helmet", "where": "ground", "chance": 6, "h": 20, "bottom": 56, "def": "<image id=\"prop-helmet\" width=\"25\" height=\"20\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUCAMAAABPqWaPAAAAP1BMVEUAAAADAgIJBwcRCw4YEBUmGRssKyw9QUBNVFNYMBdcY2FpcG57gX2JjYmVl5GfoJisq6G+uq7RzL3n38758uMrnd2jAAAAFXRSTlMA//////////////////////////9QsPovAAABAklEQVR42m2RW3bDIAxEbQmMjF6AvP+1Vk7a9CQn88mVmBnYtpdqKds3FVwR3xiamYxw/DyvZiOG9pB3VN18XXOa0egV38m6bqJ8sM9/t6LiHr7MOuWE6igvd1l+i8Z1WQUgxd8VzmDmQnkO+74DynMJpaumOceCWzH6MyEKs1ptFhMBR0yhpnQvFaaudQUbYItJZJi3PAi1rhjUs9PoCjAbyG1UmHuTg+0Q02Ofgu54PEi2zyIFlNkcZCB6jibZEWqY9oYzCZUxhOloNzkrYqgQdmZ3MyZeMfcMTWeyJU1gZMjWZcYqgPv9Zed54vJSybNJxEIo5/l4hfIUIhYsf9p+ALFGDuT6sOl7AAAAAElFTkSuQmCC\"/>"}, {"name": "sword", "where": "ground", "chance": 5, "h": 41, "bottom": 56, "def": "<image id=\"prop-sword\" width=\"16\" height=\"41\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAApCAMAAAALWFk2AAAAP1BMVEUAAAAHBAQRCA4YDRUkERs1LDJKIxZSUk9mbm12Nh6CioWTmJKZViWsraW6bizHxbrcnzHq4s71w0/28uP55JYLIci+AAAAFXRSTlMA//////////////////////////9QsPovAAAAxUlEQVR42n1SS7LDIAwD7NJgCB/D/c/6kmnTQV48dghJljw49zvMDg4vj3edlXaAtHYAXNQSUBPRlIo3QyoClCxQU8QZtfCe+FKkbwqeSsyUUvym8Fp1raWFH8bF5aJLe+eP/H4hijGV7udTh87jTYFiL49uHBJu4lOPp2So+ho578vgeeYXFLkA2BbPjBY0jcUY+dgBGg0tyFqwtWgji7V4BwCyjWWa0RATq8mBwCn0n+IGJECsJhirnQI/hQ3Bsfd+Z/wB6z0IDZQ1ZuUAAAAASUVORK5CYII=\"/>"}, {"name": "ship-2", "where": "edge", "chance": 0.5, "h": 51, "bottom": 56, "def": "<image id=\"prop-ship-2\" width=\"121\" height=\"51\" href=\"data:image/png;base64,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\"/>"}, {"name": "ship-3", "where": "edge", "chance": 0.5, "h": 49, "bottom": 56, "def": "<image id=\"prop-ship-3\" width=\"152\" height=\"49\" href=\"data:image/png;base64,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\"/>"}, {"name": "ship-4", "where": "edge", "chance": 0.5, "h": 47, "bottom": 56, "def": "<image id=\"prop-ship-4\" width=\"146\" height=\"47\" href=\"data:image/png;base64,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\"/>"}, {"name": "ship-5", "where": "edge", "chance": 0.5, "h": 44, "bottom": 56, "def": "<image id=\"prop-ship-5\" width=\"127\" height=\"44\" href=\"data:image/png;base64,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\"/>"}, {"name": "ship-6", "where": "edge", "chance": 0.5, "h": 49, "bottom": 56, "def": "<image id=\"prop-ship-6\" width=\"111\" height=\"49\" href=\"data:image/png;base64,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\"/>"}, {"name": "tower", "where": "far", "chance": 30, "h": 29, "bottom": 34, "def": "<image id=\"prop-tower\" width=\"26\" height=\"29\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAdCAMAAACDkYxEAAAAPFBMVEUAAAA+cpRAeJdQkIRRiaZWapBbmYdhkrRzqJZ0o7yItJGQucWSubabucegvqSjv5KrxMrA0dDO2dTT3deGmRJ9AAAAFHRSTlMA/////////////////////////7rhY6kAAADHSURBVHjarZHbDoMgEETdi8CKFov//6+d1WpqxCZNOm964MyG7brPmOWp+2NY7wix2g1x1L7HRGoWr8AqV164ar2iCVkqckERLD9B5qsRPTrF2HoNHyFXayGDsVnlc+iE+doo3qJvwnu03Zp/FO5I2l0cKkk4L0TWW8whEImctiiieClsU4iZzwuWhBQPa0pHIQiQ7Ew10Bv1RL0ISzCzsZSxDJA4Q00YoMGXgOX8cOna5/8ggpQ4HUyTE/aRcbCnYdhYhjaFF0MvCtcY0aF9AAAAAElFTkSuQmCC\"/>"}, {"name": "town", "where": "far", "chance": 30, "h": 23, "bottom": 34, "def": "<image id=\"prop-town\" width=\"74\" height=\"23\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEoAAAAXCAMAAACbHilqAAAAP1BMVEUAAAA/dJRBeZlMi41TjaRXmINro410pLt4qpx5b56ErMKUt8OYuq2fvMejv5Stxcq0bH/FqKXO2dPW39nehX9nTf9YAAAAFXRSTlMA//////////////////////////9QsPovAAAB30lEQVR42s2T627DIAyFY2Muw4Ewyvs/646drqu2auqk/pilhqjEH+fYZtuei7G2V8XrUGOsV7FU53wZiuf/UUV3qGXx5yJ/vjCFbQNg3FCXP3brbBdRIKJaQZmGqu1oeA1xswOerIsXxoBrURGtoOgca64m88IhPI8SlWnawJorQtVOY40BRe20SV+sX0aX46lqOArZMXXlON7f1yXPutd1sq4mfxld4hgMpR6tThVJgWIsYx4Nz2WVg9noKFf+iMUpMXPOqkeOKigMLCGEwOqzQ5x5ztMWIklbNQMPBo6BSkU1h5g5Roi6TI7NgyV14mCZvReRUoASqaJTfqKKxY4bwiEyUBE5trb7AOo45i1abj9V5ZxBgjegODB6JKVHcsNfJGSm447VshlM5RvJQw1YOgJemSK7uBstK4pwOEzShH1XJeUByUEnqncr9mm079kUowFWxApUQ2OT2c/+jg5cJ4CMwlRugWQDwB6+ToZ2vuYsnOwYcRQFF+0eriQGC9eNjcIRD/tir/om7G3tnelUh1rWWkoCCvfHDuq+o/WTxKgzVrBsV7CbkIQm7G92PLya0x1Sa61eU1WQOWB8Tbf9b/PtcQL9F30W9GSpW8Em8NXy9dofZ2GPjdV0r/UDp0oh3PjCrBkAAAAASUVORK5CYII=\"/>"}]
10export const SCENES = [SCENE_0, SCENE_1]
11types/index.d.ts 18 lines1// What Ferro does in the band: nothing (the band is not shown), runs, lies down and falls asleep
2// ('sleep'), or is already asleep ('asleep', the sleeping scene without lying down).
3export type FerroPhase = 'run' | 'sleep' | 'asleep' | null
4
5declare module 'claude-code' {
6 interface PluginState {
7 // program: which run this turn plays, an index into the background's programs; props: what
8 // stands in its prop slots (indices into PROPS, -1 for none)
9 'cc-mod-ferro': {
10 phase: FerroPhase
11 scene: number
12 program: number
13 ball: boolean
14 props: { ground: number[]; far: number[] }
15 }
16 }
17}
18