neo — Matrix digital rain (canonical single-color screensaver reference)
Batch 8 — rendering / screensaver / ambient-display cluster (highest single-color relevance).
What it is
Section titled “What it is”neo recreates the Matrix “digital rain” — endless columns of characters cascading down the screen, each column a falling stream with a bright leading head and a dimming tail trailing behind it. It ships as a single binary with a deep customization surface: charset selection (default half-width katakana, plus ascii and arbitrary user charsets via --charset / --chars), color selection (-c/--color, 16 / 256 / 32-bit truecolor, --colormode=0 for monochrome), speed control (-S/--speed, adjustable live with arrow keys), glitch/shimmer toggle (--noglitch), full-width support (-F), and a centered message overlay (-m/--message). It auto-detects terminal color and Unicode support and handles resize.
The whole effect is a screensaver in the literal original sense: an idle, evolving, content-free animation that fills the screen and signals “the machine is alive but at rest.” For KN-86 that is exactly the missing affordance — what the deck shows when the operator walks away.
KN-86 rendering relevance
Section titled “KN-86 rendering relevance”neo is the cleanest mechanical reference in the whole cluster because its visual identity reduces to one variable rendered well: brightness as a function of distance behind the head. Reading src/cloud.cpp, each cell’s color-pair index is computed as a linear ramp:
colorPair = numColorPairs - round((headPutLine - line) / length * (numColorPairs - 1))The head sits at the brightest pair; every cell further up the trail steps down the ramp by its fractional distance, clamped to [1, numColorPairs-1]. The droplet model (src/droplet.cpp) tracks a head and a tail crawling down each column independently with their own put/cur line positions and stop timing, so columns desync naturally and the field never looks like a metronome. The glitch layer re-randomizes occasional settled cells in place (the shimmer), and --noglitch disables it.
That is the entire cascade: per-column head/tail crawl + per-cell brightness-by-distance ramp + optional in-place character re-roll. No image input, no per-frame raster, no heavy math — it is a procedural field generator, which is precisely the profile that fits an idle-mode budget.
Single-color adaptation
Section titled “Single-color adaptation”neo’s single-color adaptation is trivial and exemplary — which is why it’s the canonical reference for this cluster. The effect already is a single-color effect with a brightness ramp; the green is incidental. To land it on KN-86:
- Replace the green color-pair ramp with an amber brightness ramp. KN-86 is amber #E6A020 on black #000000 (see CLAUDE.md Canonical Hardware Specification — monochrome, no other colors). The N color pairs become N intensity steps of the single amber phosphor: head at full amber, tail dimming toward black. On the prototype the panel is a real LCD, so “dimming” is amber-at-reduced-luminance, not a palette swap — the same
colorPairinteger just indexes an intensity LUT instead of an ncurses pair. This is the textbook demonstration that brightness gradient is the primary single-color rendering lever: vary luminance of one hue and the cascade reads exactly as it does in full color. - Charset → CP437 / KN-86 code page. neo’s katakana default is non-period-correct for KN-86. The deck’s font is Press Start 2P + CP437 box drawing (Canonical Hardware Spec). The rain charset should be drawn from the KN-86 code page — digits, punctuation, box fragments, the Lisp-primitive glyphs — so the cascade reads as the deck’s own alphabet falling, not generic katakana. neo’s
--charset/--charsmechanism shows the charset is a clean injection point. - Glitch as restraint. neo’s shimmer is good but loud; the KN-86 dispatch voice is terse and unshowy. Default the glitch rate low.
Proposed Deckline ambient / screensaver mode (neo as the seed)
Section titled “Proposed Deckline ambient / screensaver mode (neo as the seed)”neo and astroterm together seed a Deckline ambient mode — the idle state the nOSh runtime enters after an inactivity timeout. Proposed architecture:
- Trigger. A nOSh idle timer (reuse the power-idle path from the platform layer — CPU governor / screen-blank already exists in the device config). After timeout, instead of blanking, nOSh enters ambient mode on the primary 128×75 grid. Any key exits instantly back to the prior surface.
- Renderer is procedural, not raster. Ambient scenes are field generators that write directly into the termbox2 cell grid (per ADR-0027 — 128×75, 8×8 PSF, half-block 128×150 pseudo-pixel canvas). neo is the first scene: amber rain at the deck’s own charset. astroterm is the second: a slow star-map drift. Both are pure CPU procedural loops with no image decode — the right profile for an always-may-be-running idle animation.
- Frame budget. Cap ambient mode at a low refresh (neo runs fine well under 20 fps; the cascade reads at 10–15 fps). This sits comfortably inside the 20 fps animation cap nOSh already enforces and keeps the Pi Zero 2 W idle-cool — ambient mode should lower average draw vs. an active cart, not raise it.
- Scene roster as a SYS setting. Like the CRT-glitch intensity setting already persisted at
/home/shared/nosh-config.toml, the ambient-scene choice (rain / starfield / off) is a SYS-tab setting. This composes with the accelerometer-driven ambient CRT-glitch system already in the spec — ambient mode is the natural home for that motion-reactive glitch.
Relation to the (reveal …) visual language
Section titled “Relation to the (reveal …) visual language”The ambient field and the (reveal …) primitive (ADR-0033) are the same family of “characters changing over time toward or away from a target.” neo’s per-cell character re-roll is mechanically identical to :char-flicker’s per-cell flicker-to-settle — the difference is only that the rain never settles. Ambient-mode exit is a natural (unreveal …) / (reveal …) handoff: the rain collapses and the prior surface reveals back in, reusing the existing primitive rather than authoring a bespoke transition.
- GPL-3.0 — do not vendor. The cascade algorithm is ~tens of lines and fully understood from the source read above; reimplement from first principles in nOSh’s own permissively-licensed C, the same posture taken with no-more-secrets (also GPL).
- Performance caveat is real and informative. neo’s own README warns it “can be a bit of a CPU hog, especially on large screens with slow terminal emulators.” That cost is mostly terminal-emulator escape-sequence overhead, which nOSh avoids by writing the termbox2 cell grid directly rather than emitting ANSI. The field math itself is cheap. Still — measure ambient-mode draw on the Pi Zero 2 W during bring-up and confirm it stays below active-cart draw before committing it as the default idle behaviour.
- Cross-link astroterm — the other half of the ambient-mode seed (starfield scene to neo’s rain scene).
- Cross-link ascii-effects.md and reveal-styles.md — the brightness-gradient lever here is the same one the hover-
brighteneffect and:char-flickerreveal use. - Cross-link no-more-secrets — sibling per-cell character-flicker effect; neo is the never-settling version, no-more-secrets the settle-to-target version.
- Cross-link libcaca and react-video-ascii — those convert imagery to text; neo and astroterm generate the field procedurally. Two distinct rendering modes the deck wants both of.