Skip to content

binRick/termfun

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

termfun 🎆

Eye-candy demos for your terminal — each at two resolutions.

fireworks in kitty graphics mode

Small C demos built on termpaint. Each one renders as classic ASCII cells everywhere, and at pixel resolution on terminals that speak the kitty graphics protocol (kitty, iTerm2, WezTerm, ...).

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

There are also a few keyboard-driven menu-driven apps — a to-do list, a file browser, 2048, a system monitor, and a process-exec tracer — built on the same toolkit, with the panels floating over the same animated backdrops.

Quick start

git clone --recurse-submodules https://github.com/binRick/termfun.git
cd termfun
make
./build/fireworks-gfx     # pixel mode on kitty-protocol terminals, cells elsewhere
./build/matrix-gfx
./build/ripples-gfx
./build/fire-gfx
./build/starfield-gfx
./build/fireworks         # pure cell versions
./build/matrix
./build/ripples
./build/fire
./build/starfield

./build/taskman-gfx       # menu-driven apps (kitty backdrop + cells)
./build/filer-gfx
./build/2048-gfx
./build/sysmon-gfx
sudo ./build/extracer-gfx # process-exec tracer (Linux + root; wraps extrace)

If you already cloned without --recurse-submodules, make initializes the submodule for you. The make run-<demo> targets (run, run-gfx, run-matrix-gfx, run-ripples-gfx, ...) build and launch in one step; the ./*.sh scripts do the same.

The demos

All recordings below are real iTerm2 sessions running the demos.

fireworks

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

kitty graphics — fireworks-gfx

fireworks in kitty graphics mode

Renders into an RGBA framebuffer transmitted to the terminal every frame:

  • Additive glow — sparks are radial gradients that sum into the framebuffer, so overlapping bursts get hot in the middle.
  • Decay trails — every channel decays toward zero each frame instead of being cleared, so rockets and sparks leave natural fading streaks.
  • Transparent sky — alpha follows the glow, so the status bar and your terminal background show through where nothing is burning.
  • Tear-free — frames are double-buffered image ids wrapped in synchronized-output (DECSET 2026), so cells and pixels land atomically.

ASCII cells — fireworks

fireworks in ASCII cell mode

Pure termpaint: particles pick a glyph by intensity (✸ ● • ·), positions are tracked at half-cell vertical resolution, and the skyline windows flicker. This is also exactly what fireworks-gfx shows on terminals without graphics support.

matrix

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

kitty graphics — matrix-gfx

matrix in kitty graphics mode

The rain falls on its own pixel glyph grid, denser than the cell grid, using randomly generated 5×7 bitmap glyphs with a phosphor glow around each stream head.

ASCII cells — matrix

matrix in ASCII cell mode

Text-glyph rain on the cell grid. On kitty-protocol terminals this version adds a soft pixel bloom layer around the stream heads; set MATRIX_CELLS=1 for the pure text experience shown here.

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.

kitty graphics — ripples-gfx

ripples in kitty graphics mode

The wave field runs at framebuffer resolution and every pixel is shaded by its slope, as if lit from the upper left; steep crests spill over into a specular sun colour. The pool's alpha fades out under the status bar.

ASCII cells — ripples

ripples in ASCII cell mode

The same waves on a half-cell-resolution height field: each cell averages two sim rows and picks from a calm-to-sparkle glyph ramp (· ~ ≈ ✦), brightening with the lit side of each swell.

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 and watch the flames die out.

kitty graphics — fire-gfx

fire in kitty graphics mode

The Doom fire algorithm on 2×2 pixel blocks: every cell scatters its heat to a randomly jittered spot one row up — the collisions and holes are what keep the tongues coherent. Alpha follows the heat, so the flames burn straight over your terminal background.

ASCII cells — fire

fire in ASCII cell mode

The same heat field at half-cell resolution, rendered as an ember-to-blaze glyph ramp (· : ~ * # @) through a four-stop palette — c swaps fire for blue gas, toxic green, or violet plasma.

starfield

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

kitty graphics — starfield-gfx

starfield in kitty graphics mode

Every star draws an additive glow segment from where it was last frame to where it is now, into a framebuffer that decays instead of clearing — so motion leaves warp streaks that stretch with speed and bend when you steer.

ASCII cells — starfield

starfield in ASCII cell mode

The same flight projected onto the cell grid at half-cell vertical resolution, each star picking a glyph from a depth ramp (· • * ✦) and brightening as it approaches.

Menu-driven apps

Beyond the eye-candy, termfun ships a few interactive TUI apps — real keyboard-driven programs built on the same termpaint foundation, sharing a small widget toolkit (tui.c). Each renders as plain cells everywhere and, on kitty-protocol terminals, floats its panels over an animated pixel backdrop — the UI stays crisp text; only the wallpaper behind it is pixels. A per-cell cut-out mask punches the wallpaper transparent wherever a panel is drawn, so the panels read as floating windows.

All recordings below are real iTerm2 sessions, captured with tools/record_iterm.py — same as the demos above.

taskman — to-do list

Add, edit, complete, reorder and delete tasks; the list persists to ~/.termfun-tasks, and a progress bar tracks how much is done.

Keys: ↑↓/j/k move · Space toggle done · a add · e edit · d delete · J/K reorder · c clear completed · g/G top/bottom · q quit.

kitty graphics — taskman-gfx

taskman in kitty graphics mode

The to-do panel floats over a slow indigo-to-teal aurora; the cut-out mask keeps the panel and bars opaque while the wallpaper drifts in the margins.

ASCII cells — taskman

taskman in ASCII cell mode

The same UI over a quiet dark gradient — rounded panel, full-row selection highlight, / checkboxes, an inline add/edit field and a live progress bar.

filer — file browser

A scrolling directory list on the left, a live preview/details pane on the right (text peek, size, mtime, item counts). Directories sort first; files show right-aligned human sizes.

Keys: ↑↓ move · Enter/ open dir · /Backspace up · . toggle hidden · r refresh · g/G top/bottom · q quit.

kitty graphics — filer-gfx

filer in kitty graphics mode

Both panes float over a slate-to-cyan aurora, with the wallpaper showing in the gutter between them and around the edges.

ASCII cells — filer

filer in ASCII cell mode

The two-pane browser on a quiet gradient: colour-coded entries (directories, symlinks, executables), a scroll indicator, and a sanitized text preview.

2048 — sliding-tile game

Slide the board; equal tiles merge; reach 2048. Live score with your best kept in ~/.termfun-2048, one-step undo, and win/lose overlays.

Keys: ↑↓←→ / WASD / HJKL slide · u undo · n/r new game · q quit.

kitty graphics — 2048-gfx

2048 in kitty graphics mode

The classic colour tiles float on a warm animated plasma that glows through the gaps between tiles and around the board.

ASCII cells — 2048

2048 in ASCII cell mode

The same colour-graded tiles (tui_fill background blocks with centred numbers) on a quiet gradient, with centred overlays for win/game-over.

sysmon — system dashboard

A live dashboard: CPU / memory / disk gauges, load average, uptime, core count and OS, plus the top processes by CPU — refreshing on a timer (+/- to tune). Stats come from mach/sysctl on macOS.

Keys: r refresh now · +/- interval · q quit.

kitty graphics — sysmon-gfx

sysmon in kitty graphics mode

The gauge and process panels float over a dark, scrolling neon grid.

ASCII cells — sysmon

sysmon in ASCII cell mode

The same dashboard over a quiet gradient: threshold-coloured gauge bars (green → amber → red) and a ranked process table.

extracer — process-exec tracer

Pick one or more processes, then watch a live tree of every program their subtrees exec(). Each selected process becomes a labelled root () and the commands it spawns nest beneath it, colour-tagged per root so several traces read clearly at once. The picker is a ps --forest tree — just start typing to search (subtree-aware: typing sshd shows sshd and every process running under it) — or launch straight into a search with extracer sshd (or EXTRACER_FILTER=sshd). It's a front-end for extrace: the process picker works anywhere ps does, but the trace pane is Linux-only and needs root (CAP_NET_ADMIN, for the kernel proc connector) — it runs one extrace -p PID per selection and streams their output.

Keys — picker: type to search · ↑↓ move (hold to accelerate) · mouse wheel scroll · click or Space to select · Enter trace · Esc clear search / quit. Trace: ↑↓/wheel scroll · PgUp/PgDn page · f follow · b back to the picker · q quit.

kitty graphics — extracer-gfx

extracer in kitty graphics mode

The process picker and the live exec tree float over a warm magenta plasma; the cut-out mask keeps the panels opaque while the wallpaper drifts in the margins.

ASCII cells — extracer

extracer in ASCII cell mode

The same two-pane workflow over a quiet gradient: a filterable process list with ·/ selection marks, then the colour-tagged exec tree — each traced parent () with its exec()'d children nested under connectors.

Controls

Key fireworks matrix ripples fire starfield
space launch a rocket spawn a wave of drops drop a stone flare the burner hyperjump
mouse click rocket at the pointer drop at the pointer stone at the pointer fireball at the pointer steer to the pointer
a toggle the auto show toggle the rain snuff/relight the burner toggle the autopilot
c cycle the colour scheme cycle the colour scheme cycle the colour scheme cycle the colour scheme
+ / - auto launch rate fall speed rain rate flame height warp speed
q / Esc quit quit quit quit quit

Tuning

Each demo and app reads env vars with its own prefix (FIREWORKS_*, MATRIX_*, RIPPLES_*, FIRE_*, STARFIELD_*, and TASKMAN_*, FILER_*, G2048_*, SYSMON_*):

Env var Default Effect
*_FPS demo-specific target frame rate (gfx)
*_MAXDIM 512 (640 for apps) framebuffer size cap; 1024 for sharper, larger frames
*_CELLS unset set to force cell rendering even on kitty terminals

Frames are uncompressed base64 RGBA, so bandwidth scales with MAXDIM² × FPS — if a remote connection feels sluggish, turn one of them down.

The apps also take a few app-specific vars:

Env var Default Effect
TASKMAN_FILE ~/.termfun-tasks where tasks are stored
FILER_DIR current dir directory to open on launch
G2048_FILE ~/.termfun-2048 where the best score is stored
SYSMON_INTERVAL 1.5 seconds between stat refreshes
EXTRACER_BIN extrace (on PATH) path to the extrace binary to run
EXTRACER_FILTER unset initial picker search (also extracer <term>)

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 (kitty_gfx.c).

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 after the replacement is on screen.

kitty_probe.c is a standalone tool that runs the same detection by hand and hex-dumps the terminal's raw replies — handy for checking what your terminal and multiplexer actually pass through:

./build/kitty_probe

Project layout

File What
fireworks.c, fireworks-gfx.c fireworks demo (cells / kitty pixels)
matrix.c, matrix-gfx.c digital rain demo (cells / kitty pixels)
ripples.c, ripples-gfx.c water ripples demo (cells / kitty pixels)
fire.c, fire-gfx.c demoscene fire demo (cells / kitty pixels)
starfield.c, starfield-gfx.c warp starfield demo (cells / kitty pixels)
taskman.c, taskman-gfx.c to-do list app (cells / kitty backdrop)
filer.c, filer-gfx.c file browser app (cells / kitty backdrop)
2048.c, 2048-gfx.c sliding-tile game (cells / kitty backdrop)
sysmon.c, sysmon-gfx.c system dashboard app (cells / kitty backdrop)
extracer.c, extracer-gfx.c process-exec tracer, a front-end for extrace (cells / kitty backdrop)
tui.{c,h} shared TUI toolkit (panels, lists, input, backdrop)
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

All recordings are real terminal sessions: captured from iTerm2 with tools/record_iterm.py, which launches each demo in a window, drives it, and assembles the frames into the GIFs above.

License

Demo code is 0BSD. termpaint is Boost Software License 1.0.

About

Eye-candy terminal demos in C — ASCII everywhere, pixel-resolution graphics on kitty-protocol terminals. Built on termpaint.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors