Open Source · C + termpaint

🎆termfun

Eye-candy demos for your terminal — 17 of them, each at two resolutions. Small C demos built on termpaint that render as classic ASCII cells everywhere, and at pixel resolution on terminals that speak the kitty graphics protocol (kitty, iTerm2, WezTerm, …).

fireworks demo in kitty graphics mode

📺The demos

17 demos, each shipped as a <demo>.c / <demo>-gfx.c pair. The -gfx build auto-detects graphics support and renders pixels where it can, cells where it can't. Click any demo to see both modes recorded side by side.

fireworks demo

🎆fireworks

Rockets, bursts, a twinkling sky, and a city skyline.

View both modes →
matrix demo

🟩matrix

Digital rain with half-width katakana, bright stream heads, and fading tails. Press c to cycle colour schemes (green, cyan, amber, …).

View both modes →
ripples demo

💧ripples

A rain-dappled pool: a damped wave equation lit by the slope of the surface, with sun-coloured glints on the steepest crests. Click anywhere to toss in a stone.

View both modes →
fire demo

🔥fire

The classic demoscene fire: a heat field that cools in chunky random quanta as it rises, carving the flames into ragged tongues. Click to lob a fireball, space to flare the burner, a to snuff it.

View both modes →
starfield demo

🚀starfield

Stars streaming past the camera toward a vanishing point that cruises around on autopilot — or wherever you click. Space punches a hyperjump.

View both modes →
plasma demo

🌈plasma

The classic demoscene plasma: interfering sine fields that breathe and shift colour. Press c to cycle palettes, click to move the wave centre.

View both modes →
tunnel demo

🌀tunnel

An endless flight down a textured throat, steering wherever you click.

View both modes →
aurora demo

🌌aurora

Northern lights: slow curtains of green and violet light over a transparent night sky.

View both modes →
julia demo

🔮julia

An animated Julia-set fractal whose seed constant wanders the edge of the Mandelbrot cardioid.

View both modes →
metaballs demo

🫧metaballs

A lava lamp: soft blobs that drift, merge, and split.

View both modes →
boids demo

🐦boids

An emergent flock that swirls, splits at a predator, and re-forms.

View both modes →
lightning demo

lightning

Branching bolts that fork across the sky and flash the whole frame.

View both modes →
snow demo

❄️snow

A quiet snowfall with wind and a drift that builds along the floor.

View both modes →
sand demo

sand

A falling-sand toy: pour materials and watch them pile and flow.

View both modes →
smoke demo

💨smoke

Ink billowing through an invisible current.

View both modes →
coral demo

🪸coral

A Gray-Scott reaction-diffusion system growing coral, spots, and mazes.

View both modes →
donut demo

🍩donut

The spinning torus, in its two most famous renderings.

View both modes →

⚙️How pixel mode works

Graphics support is detected before termpaint takes over the tty: the demo asks the terminal to validate (not display) a 1×1 image and chases it with a DA1 query. Every terminal answers DA1; only kitty-protocol terminals answer the graphics query first. Each frame is then transmitted as a chunked, base64-encoded RGBA image (a=T,f=32) stretched over the full cell grid, layered above the text with alpha. Old frames are deleted by id once the replacement is on screen.

No dependencies beyond a C compiler and make — termpaint is vendored as a submodule and built straight into the binaries.

⌨️Quick start

git clone --recurse-submodules https://github.com/binRick/termfun.git
cd termfun
make

# pixel mode on kitty-protocol terminals, cells elsewhere:
./build/fireworks-gfx
./build/plasma-gfx
./build/donut-gfx
# ...one -gfx binary per demo

# drop the -gfx suffix for the pure cell version of any demo:
./build/fireworks
./build/donut

If you already cloned without --recurse-submodules, make initializes the submodule for you. The make run-<demo> targets and the ./*.sh launcher scripts build and run in one step.

🎛️Tuning

Each demo reads env vars with its own prefix (FIREWORKS_*, MATRIX_*, RIPPLES_*, FIRE_*, STARFIELD_*, PLASMA_*, TUNNEL_*, AURORA_*, JULIA_*, METABALLS_*, BOIDS_*, LIGHTNING_*, SNOW_*, SAND_*, SMOKE_*, CORAL_*, DONUT_*). Frames are uncompressed base64 RGBA, so bandwidth scales with MAXDIM² × FPS — if a remote connection feels sluggish, turn one of them down.

Env varDefaultEffect
*_FPSdemo-specifictarget frame rate (gfx)
*_MAXDIM512framebuffer size cap; 1024 for sharper, larger frames
*_CELLSunsetforce cell rendering even on kitty terminals

📦Project layout

fireworks.c, fireworks-gfx.c
matrix.c, matrix-gfx.c
ripples.c, ripples-gfx.c
fire.c, fire-gfx.c
starfield.c, starfield-gfx.c
plasma.c, plasma-gfx.c
tunnel.c, tunnel-gfx.c
aurora.c, aurora-gfx.c
julia.c, julia-gfx.c
metaballs.c, metaballs-gfx.c
boids.c, boids-gfx.c
lightning.c, lightning-gfx.c
snow.c, snow-gfx.c
sand.c, sand-gfx.c
smoke.c, smoke-gfx.c
coral.c, coral-gfx.c
donut.c, donut-gfx.c
kitty_gfx.{c,h}    minimal kitty graphics protocol support library
kitty_probe.c     terminal graphics-support probe
tools/            recording & screenshot harness for the README media
termpaint/        termpaint submodule

Demo code is 0BSD; termpaint is under the Boost Software License 1.0.