CRTty
Post-processing shader framework for kitty terminal via LD_PRELOAD
Inject custom fragment shaders into kitty (or any EGL/GLX application) — no patches, no Vulkan, no special drivers. Ships with a built-in CRT monitor effect (scanlines, phosphor glow, barrel distortion, vignette, chromatic aberration).
Installation
Requires Linux with glibc, OpenGL 3.3+, and Rust stable (build only).
From source
&&
Arch Linux (AUR)
Nix
System-wide
Uninstall
Usage
Custom GLSL shaders
Write a standard GLSL 330 core fragment shader. It receives these inputs automatically:
| Uniform / Input | Type | Description |
|---|---|---|
in vec2 v_uv |
vec2 | Texture coordinates (0–1) |
uniform sampler2D u_input |
sampler2D | Screen contents |
uniform float u_time |
float | Seconds since init (for animation) |
uniform vec2 u_resolution |
vec2 | Viewport size in pixels |
Must write out vec4 o_color. All uniforms except u_input are optional.
Example — animated RGB wave:
#version 330 core
in vec2 v_uv;
out vec4 o_color;
uniform sampler2D u_input;
uniform float u_time;
uniform vec2 u_resolution;
void main() {
float wave = sin(v_uv.y * 40.0 + u_time * 3.0) * 0.003;
vec3 c;
c.r = texture(u_input, v_uv + vec2(wave, 0.0)).r;
c.g = texture(u_input, v_uv).g;
c.b = texture(u_input, v_uv - vec2(wave, 0.0)).b;
float scan = 0.95 + 0.05 * sin(v_uv.y * u_resolution.y * 3.14 + u_time * 2.0);
o_color = vec4(c * scan, 1.0);
}
See examples/ for more sample shaders.
Write your own effect
Create a new Rust library crate:
&&
Cargo.toml:
[]
= ["cdylib"]
[]
= { = "https://github.com/<you>/CRTty" }
src/lib.rs:
;
main!;
Build and use:
LD_PRELOAD=/target/release/libmy_shader.so ENABLE_CRTTY=1
The Effect trait
Helpers for setting uniforms:
get_uniform_location // -> i32
uniform_1f
uniform_1i
How it works
App (GLFW / EGL / GLX)
│
├─ dlsym(handle, "eglSwapBuffers")
│ ↑ intercepted by your .so
│
└─ eglSwapBuffers(dpy, surface)
├─ glCopyTexSubImage2D → capture framebuffer
├─ Bind your shader (GLSL 330 core)
├─ Your set_uniforms() runs
├─ Draw fullscreen triangle
└─ Call real eglSwapBuffers
Project structure
src/
lib.rs Effect trait, main! macro
hook.rs dlsym interception
pass.rs Render pass engine
gl.rs GL function pointers + helpers
config.rs Config file parser
effects/
crt.rs Built-in CRT effect
greyscale.rs Greyscale effect
invert.rs Color inversion effect
custom.rs Runtime GLSL file loader
cli/
src/main.rs CLI launcher (crtty binary)
crt/
src/lib.rs Default cdylib (Builtin::from_env())
examples/
wave.glsl Animated RGB wave + scanlines
PKGBUILD Arch Linux / AUR package
flake.nix Nix flake
CRT effect configuration
Edit ~/.config/crtty.conf:
enabled=1
scanline_intensity=0.75
phosphor_strength=1.1
curvature=0.04
vignette=0.35
aberration=0.003
| Parameter | Range | Description |
|---|---|---|
enabled |
0/1 |
Master switch |
scanline_intensity |
0.0–1.0 | Horizontal raster line darkness |
phosphor_strength |
0.0–3.0 | Bloom intensity |
curvature |
0.0–0.5 | Barrel distortion |
vignette |
0.0–2.0 | Corner darkening |
aberration |
0.0–0.05 | RGB channel offset |
License
MIT