This repository contains the official collection of screensaver plugins for the trance ecosystem. Each plugin is compiled as a dynamic library (shared object) and dynamically loaded by the trance daemon to render visual terminal effects.
For binary releases, packaging scripts, and repository hosting metadata, see the packages repository.
To install the screensaver and its official plugins, you need to add the repository first, and then install the core trance package (which automatically pulls in the plugins).
- Add the repository:
sudo curl -sSL -o /etc/yum.repos.d/ubermetroid.repo https://ubermetroid.github.io/packages/rpm/ubermetroid.repo
- Install the application:
sudo dnf install trance
- Add the GPG key and repository source:
sudo mkdir -p /etc/apt/keyrings sudo curl -fsSL -o /etc/apt/keyrings/ubermetroid.gpg https://ubermetroid.github.io/packages/apt/ubermetroid-key.gpg echo "deb [signed-by=/etc/apt/keyrings/ubermetroid.gpg] https://ubermetroid.github.io/packages/apt stable main" | sudo tee /etc/apt/sources.list.d/ubermetroid.list sudo apt update
- Install the application:
sudo apt install trance
- beams: sweeps 4 colored spotlight cones over a rising dust starfield.
- bursts: city skyline with color particle fireworks.
- chaos: spring-back chromatic-aberration system logo glitch effects.
- cosmos: full accretion/collapsed singularity universe lifecycle.
- glyphs: terminal stream matrix rain incorporating system info.
- gnats: triadic palette boid-style predator/prey firefly swarm.
- storm: cold forest rain, periodic lightning flashes, walking deer/bears.
- radar: green circular sweeping retro tactical defense radar.
All trance plugins are Rust crates compiled as dynamic libraries (cdylib) that implement the Screensaver trait from trance-api.
Create a new library crate and declare its type as cdylib in Cargo.toml:
[lib]
name = "screensaver_custom"
crate-type = ["cdylib"]
[dependencies]
trance-api = { path = "../trance/trance-api" }Define a struct and implement the Screensaver trait:
use std::time::Duration;
use trance_api::core::screensaver::Screensaver;
use trance_api::core::TerminalCell;
pub struct CustomEffect {
// Add your state fields here
}
impl Screensaver for CustomEffect {
fn init(&mut self, _cols: usize, _rows: usize) {
// Called when the screensaver starts or resize occurs
}
fn update(&mut self, dt: Duration, cols: usize, rows: usize) {
// Progress animations and state by delta time
}
fn draw(&self, grid: &mut [TerminalCell], cols: usize, rows: usize) {
// Render characters and colors to the terminal buffer grid
}
}In your src/lib.rs library file, expose two C-compatible functions to allow the trance daemon to instantiate and deallocate your screensaver:
use trance_api::ScreensaverInstance;
#[unsafe(no_mangle)]
pub extern "C" fn create_screensaver() -> *mut ScreensaverInstance {
let effect = CustomEffect { /* initialize state */ };
let instance = ScreensaverInstance {
inner: Box::new(effect),
};
Box::into_raw(Box::new(instance))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn destroy_screensaver(ptr: *mut ScreensaverInstance) {
if !ptr.is_null() {
unsafe {
let _ = Box::from_raw(ptr);
}
}
}Licensed under the Apache License, Version 2.0. Copyright 2026 UberMetroid.