Standalone retro-CRT 3D screensaver — five seeded procedural scenes, a CRT signal-degradation pass, a self-typing narrative terminal, synthetic Web Audio. three.js + TypeScript, runs in any modern browser. https://jkaindl.codeberg.page/kuro-screensaver/
  • TypeScript 46.8%
  • Swift 32.3%
  • C++ 14%
  • Shell 3.4%
  • Inno Setup 1.4%
  • Other 2.1%
Find a file
2026-07-16 16:22:56 +02:00
.github/workflows fix(installer): quit a running wallpaper before upgrading it, stop asking for a language 2026-07-16 15:55:21 +02:00
docs fix(installer): quit a running wallpaper before upgrading it, stop asking for a language 2026-07-16 15:55:21 +02:00
native chore(release): v0.11.0 2026-07-16 16:22:56 +02:00
scripts feat(windows): foundation for the wallpaper app — utf-8, icon, second target 2026-07-16 14:49:30 +02:00
src feat(settings): the [Anhalten] button the approved layout promised 2026-07-16 16:11:52 +02:00
tests feat(settings): the [Anhalten] button the approved layout promised 2026-07-16 16:11:52 +02:00
.gitignore chore: gitignore the local Codeberg push helper 2026-07-15 16:03:05 +02:00
.nvmrc chore: pin Node 24 via .nvmrc (matches CI + the committed lockfile) 2026-06-30 22:55:18 +02:00
AGENTS.md feat(windows)!: replace .NET host with C++ micro-host in packaging, CI and docs 2026-07-15 11:38:42 +02:00
index.html feat(web): quick-wins pass + prefers-reduced-motion support 2026-06-03 19:37:02 +02:00
LICENSE docs: add README + AGPL-3.0 LICENSE + Codeberg publish scripts 2026-05-28 09:14:05 +02:00
package-lock.json fix(settings): only a touched card may write a monitor's wallpaper mode 2026-07-16 16:01:57 +02:00
package.json chore(release): v0.11.0 2026-07-16 16:22:56 +02:00
README.md ci: release uses the packaging script; docs describe the wallpaper app 2026-07-16 15:36:47 +02:00
screensaver.html feat(screensaver): add auto-starting screensaver-mode web entry 2026-05-28 13:39:56 +02:00
settings.html feat(settings): the [Anhalten] button the approved layout promised 2026-07-16 16:11:52 +02:00
tsconfig.json init: extract screensaver engine from kuro-companion plugin 2026-05-26 13:20:27 +02:00
vite.config.ts feat(windows): HTML settings page for the native /c dialog 2026-07-15 11:15:06 +02:00
vitest.config.ts test(web): add vitest runner (PROF-TS-01) 2026-06-15 16:45:26 +02:00

Kuro Screensaver

A retro-CRT 3D screensaver: six seeded procedural scenes, a full synthetic CRT signal-degradation pass, a self-typing operator-under-attack terminal, and a procedural audio layer. Runs as a native macOS screensaver (live-rendered in Metal), a real Windows .scr, and in any browser.

License: AGPL-3.0 macOS — Metal Swift Web — three.js Windows — .scr

Download the macOS app   Launch the web app

Kuro Screensaver — banking flight over procedural CRT terrain

Started life as a browser engine (extracted from the kuro-companion Obsidian plugin). The headline is a full native rewrite in Metal — a real, live-rendered macOS screensaver: no WebView, no pre-rendered video, the whole engine running on the GPU. The web build lives on for in-browser play and cross-platform packaging.

New in v0.10.0 — Windows grows up. The .scr gets the full settings dialog (looks, seven CRT sliders, story & automation — parity with the macOS app), multi-monitor support (one panoramic image spanning all displays, or per-monitor scene/color/off), an animated desktop wallpaper mode with a tray icon and a power policy that freezes it behind fullscreen apps, on battery, or when locked — plus a render-scale + adaptive-quality package against dropped frames.

v0.6.0 — the world reacts to the story. As the operator's shift escalates (ROUTINE → INTRUSION → ALARM → PANIC), the 3D world tightens with it: the fog closes in, the CRT degrades, the camera hesitates when something is noticed, a storm builds, and an "enemy" colour bleeds into the geometry — a subtle build that pays off near PANIC and is released by the crash. On web + native.

Earlier (v0.4.x): web↔native feature parity — analog-CRT pass, dynamic banking flight, one-click Looks, a cinematic 5-layer matrix rain (also a selectable MATRIX scene), plus a native flat-HUD toggle and richer preset colours.


Six seeded procedural scenes, each recolorable by any of 13 phosphor presets:

Terrain
TERRAIN — seam-free infinite wireframe landscape, banking flythrough
City
CITY — banking down a neon-wireframe corridor
The Rift
THE RIFT — barrel-roll dynamics through a fracture
Tunnel
TUNNEL — banking flight down a Catmull-Rom spine
Void
VOID — flythrough an asteroid belt (depth fade-in)
Matrix
MATRIX — multi-layer 3D-depth digital rain

Live dynamic banking flight
Live engine — dynamic banking flight over the terrain (Toxic Haze)

The narrative terminal in its Apple-Lisa center-window layout
The narrative terminal in its Apple-Lisa center-window layout (also available as a bottom strip or full-width band)

13 phosphor presets

All 13 color presets

Kuro · Neural Bleed · Rust Signal · Toxic Haze · Biolink · Ghost Protocol · Voidwitch · Circuit · Crimson · Phosphor · Ember · Spectre · Pearl


The story that never repeats the same way

Each run is a CORP compliance operator's shift, told through the narrative terminal: ROUTINE → INTRUSION → ALARM → PANIC → SILENCE. An encrypted "ghostlink" backchannel to a former instructor (INSTR-KARSEN) answers in koans — growing guarded, then silent, as things worsen; HQ turns automated and hollow; the operator drafts, hesitates, and deletes. Every shift differs (role × trait × HQ tier × which exchanges fire). When the shift ends the system crashes — a choreographed CRT collapse to a power-off line, black, then an unstable reboot into a fresh shift with a new persona.

The diegetic CRT crash sequence

Signal failure → glitch storm → power-off collapse → dead screen → reboot → new shift. In the pre-rendered video screensaver this black moment is also the seamless loop point — the loop is diegetic, not a hidden crossfade.


Download

The live Metal screensaver as a standalone app — full procedural variation, every CRT effect, the whole narrative.

↓ KuroScreensaver-native-app-macos.dmg → open, drag KuroMetalApp.app to Applications, launch. Turn on auto-start-on-idle in its settings to use it as a real screensaver.

Notarized + stapled with a Developer ID — it opens cleanly, no Gatekeeper warning. Requires macOS 14+ (Apple Silicon).

Windows 11 (.scr + animated wallpaper)

A real .scr — since v0.9.0 a tiny native host (~270 KB zip, no bundled runtime; the old ~65 MB .NET package is history). WebView2 does the rendering and is built into Windows 11 (on Windows 10 the host shows a download link if it's missing). It understands multi-monitor setups, and ships an animated desktop wallpaper as its own app (KuroWallpaper.exe, since v0.11.0) with its own settings.

Download Run
↓ KuroScreensaver-Setup.exe Easiest: one-click installer, per-user, no admin rights.
↓ KuroScreensaver-windows.zip Manual: unzip into a folder you keep, right-click KuroScreensaver.scrInstall.

Full steps + troubleshooting: docs/WINDOWS-INSTALL.md.

Or just play it in a browser: jkaindl.codeberg.page/kuro-screensaver.

All versions: releases page.

The Windows .scr is unsigned, so SmartScreen warns on first run — click "More info" → "Run anyway" (once). Full notes: docs/WINDOWS-INSTALL.md.

The old macOS .saver builds (pre-rendered video .savers + the legacy WebGL .app/.saver) were retired in v0.5.0 — the notarized native app above replaces them.


Features

  • Six procedural 3D scenesTERRAIN · CITY · THE RIFT · TUNNEL · VOID plus a static MATRIX rain scene. Dynamic banking flight: a weaving camera that banks into its turns (adjustable strength, always-level start) with occasional eased maneuvers; seam-free infinite terrain; a Catmull-Rom tunnel spine; barrel rolls in The Rift. Same seed → same run.
  • Narrative terminal — the full operator's-shift story (INSTR-KARSEN ghostlink, HQ escalation drafts, hesitations, last words) driven by a realistic typewriter over a phase-modulated script bank, in three layouts: a bottom strip, a full-width band, or an Apple-Lisa center-window.
  • Retro-CRT suite — screen curvature, aperture-grille phosphor mask, phosphor persistence trails, bloom + warm halation, NTSC dot-crawl, scanlines + vignette, a power-on flash, and a glitch chain (H-sync tear, V-roll, flicker, black frames, static) feeding the diegetic crash→reboot. One intensity knob, or per-effect sliders.
  • Looks — one-click vibe presets (Clean · Heavy CRT · Broken Terminal · Vaporwave · Matrix) that set every effect at once.
  • HUD overlay — tactical info panels, crosshair, scene-label slab, real-time clock, plus a power-on + BIOS boot sequence.
  • Procedural audio — a synthetic CRT hum + Carpenter-style soundscape. No audio assets.
  • Day/night + weather, 13 color presets, scene auto-cycle, and auto-start-on-idle (native app).
  • Multi-monitor (Windows) — span one panoramic image across every display (portrait monitors show their tall slice of it), or configure each monitor individually: on with its own scene + color, random, or off.
  • Animated wallpaper (Windows) — the engine behind your desktop icons, as its own app: a tray icon (pause / settings / autostart / quit), a settings tab with a complete set of values independent of the screensaver's, and a power policy that suspends it when hidden, frozen behind fullscreen apps, or on battery.
  • Performance controls — render-scale slider plus adaptive quality that first dials back effects, then resolution, when frames drop.

Native macOS app: Swift + Metal (shaders compiled at runtime — no Xcode needed). Web / cross-platform builds: TypeScript + three.js (WebGL2).


Usage

  • macOS app — launch KuroMetalApp.app: the config window has a live preview, one-click Looks, and every slider; Start fullscreen (Enter) runs the saver, ←/→ switch scenes with a warp transition, any other input exits. Enable auto-start-on-idle to use it as the real screensaver, or Set as wallpaper for an animated desktop.
  • Windows .scr — right-click → Install, then configure via the Windows screensaver dialog (Settings…): scene/color/tempo, Looks, CRT sliders, story & automation, per-monitor setup, and the performance section. Every input exits the running saver.
  • Windows wallpaper — Start menu → Kuro Wallpaper (from the ZIP: double-click KuroWallpaper.exe). It starts the wallpaper and opens its settings, where the Wallpaper tab holds a full set of values independent of the screensaver's. The tray icon pauses/resumes, opens settings, toggles autostart, and quits.
  • Browserlaunch the web app: 19 pick scenes, ←/→ cycle, M mutes, P pauses, S screenshots, Esc exits; the control bar (mouse) exposes everything else.

Details, troubleshooting, and the full Windows walkthrough: docs/WINDOWS-INSTALL.md · docs/MACOS-INSTALL.md.


Build

Native macOS app (Metal — Xcode-free)

bash scripts/build-native-app.sh       # build + sign → native/macos/build/KuroMetalApp.app
bash scripts/package-native-app.sh     # + notarize + staple → dist-native/ (needs a Developer ID)
bash scripts/run-native-tests.sh       # logic tests (assert-based, headless)

The renderer is verified headlessly by rendering frames to PNG (scripts/build-native-harness.sh) — no window or real screensaver activation needed.

No build step

The native macOS app deliberately needs no Xcode and no build system beyond swiftc — the Metal shaders ship as source and compile at runtime, so the whole app builds from a plain shell script in seconds and stays reviewable as text. (The web target does use Vite, but only as a bundler for three.js — the engine itself is framework-free TypeScript.)

Web app

npm install
npm run dev        # Vite dev server → http://localhost:5173
npm run build      # production bundle → dist/
npm run typecheck  # tsc --noEmit (run before committing src/ changes)

The web app exits on Esc; the native app exits on any input and keeps its settings (scene, preset, effects, terminal layout, bank strength…) in a config window with a live preview.


Architecture at a glance

Native (native/macos/) — a platform-agnostic Metal renderer plus a thin host:

native/macos/
├── KuroNativeSaver/Core/   Platform-agnostic engine (Metal):
│   ├── Renderer · Shaders   scene pass → bloom/trails → CRT composite
│   ├── *Scene.swift         terrain · city · rift · tunnel · void · matrix
│   ├── CameraFly            banked weaving flight choreography
│   ├── Terminal · Script    the operator narrative (+ INSTR-KARSEN ghostlink)
│   ├── Hud · TextRenderer · FontAtlas   overlay + runtime CoreText glyph atlas
│   └── MatrixRain · Synth · Palette · …
├── KuroMetalApp/           Standalone macOS app host (CAMetalLayer + CVDisplayLink)
└── harness/                Headless PNG render harness for verification

Web (src/) — the original engine is plugin-shaped but framework-free (it never imports from obsidian); host-web/ fulfils the host contract in the browser, so the same bundle backports into the Obsidian plugin unchanged.

src/engine/   controller · engine/scenes · fx/crt-sim · audio/synth · terminal · hud · data
src/host-web/ plugin-shim · persistence (localStorage) · obsidian-dom-polyfill

Conventions for contributors and AI assistants are in AGENTS.md; design history is under docs/specs/.


Compatibility

  • macOS 14+ — the native app (Apple Silicon; Metal). The 60 fps cap and adaptive quality keep it smooth on weaker GPUs.
  • Modern browsers — the web app: Chromium ≥ 90, Firefox ≥ 90, Safari ≥ 14, WebGL2 required.

License

GNU AGPL-3.0 — copyleft with the network-use clause. If you host this engine (or a fork) so others can use it over a network, the source of your variant must also be available under the AGPL.