An Omarchy theme whose wallpaper is cmatrix.
The desktop is the terminal: the Osaka Jade palette on the terminal's background colour, with the rain from cmatrix falling behind your windows — same glyphs, same 40 ms terminal cadence, same green tails and white heads the terminal would show, drawn with the system monospace font on a real character grid.
Two parts, two repos:
| Part | Repo | What it is |
|---|---|---|
| Plugin | omarchy-omatrix (this repo) | io.github.0x1ocean.omatrix, an Omarchy shell (Quickshell) service that renders the rain on the Wayland bottom layer of every monitor |
| Theme | omarchy-omatrix-theme | Osaka Jade colours + icons + a solid terminal-background wallpaper + omatrix.toml, which switches the rain on |
The theme lives in theme/omatrix/ here and is published as its own repo
(Omarchy installs themes from a repo root, and themes can't carry code).
omarchy plugin add https://github.com/0x1ocean/omarchy-omatrix.git --enable omarchy theme install https://github.com/0x1ocean/omarchy-omatrix-theme.git
Switching to any other theme with omarchy theme set hides the rain
instantly; switching back brings it back. The plugin only draws while the
active theme ships an omatrix.toml, so any theme can opt in by adding one.
Remove it again with:
omarchy plugin remove io.github.0x1ocean.omatrix
omarchy theme remove omatrix # or just switch: omarchy theme set osaka-jadeThe plugin writes nothing outside ~/.config/omarchy/shell.json (its own
entry, added by omarchy plugin enable) and needs no extra packages.
From a checkout instead: ./install.sh symlinks this directory as the plugin
and theme/omatrix as the theme, enables the plugin and applies the theme
(--no-theme to skip that). ./uninstall.sh reverses it.
Reading cmatrix.c shows there is no animation in it at all. The terminal is
a COLS x LINES grid; every 40 ms (napms(update * 10)) the loop walks every
second column, writes a new random head cell, clears one tail cell, and
ncurses repaints only the cells that changed. Nothing ever moves — cells are
written and erased on a fixed grid, and that is the look.
cmatrix.js is a line-for-line port of var_init() and that main loop
(new-style and old-style scrolling, -a pacing classes, -k mutations,
-b/-B bold parity, -m lambda, -r rainbow, the matrix[0] staging row
and the ' ' sentinel included). The one liberty: a column that is still
counting down spaces[] and holds no glyphs is not walked, which the tests
show is unobservable (same cells, same randomness). It has no QML in it, so
node --test tests/*.test.js runs it against the invariants of the C code;
settings.js (option precedence, ANSI colour mapping) is covered the same way.
Rendering mirrors the terminal too:
stateCanvasis aCOLS x LINESpixel image — one pixel per terminal cell holding glyph index, palette slot and bold flag. Each tick repaints only the cells cmatrix wrote (a few hundred), exactly what ncurses does. The canvas item is sized in logical pixels divided by the window's device pixel ratio and each cell painted as a1/dprsquare, so on a scaled monitor (say 1.25) the image is still exactly one texel per cell instead of a ×ばつ image with antialiased, smeared cell values.atlasCanvasdraws the charset once with the system monospace font at the shell's base size (the same 12 px the terminal uses at 9 pt), regular and bold.shaders/matrix.fragruns once per screen pixel on the GPU: find the cell, read its state, sample the glyph, colour it. Cost is flat regardless of how many cells changed.
The layer itself is opaque in the theme's terminal background colour, so
Hyprland blends nothing and the wallpaper beneath is occluded; the rain
stops whenever it can't be seen (fullscreen window on that monitor, session
lock, another theme) and slows down on battery.
The cell grid comes from FontMetrics (advance of M, ascent + descent),
rounded to whole pixels like a terminal emulator, so glyphs land on the same
7 x 16 px cells alacritty would use with the default font. Tails are the
theme's ANSI green (green in colors.toml) and heads are ANSI white
(foreground) — the pairs ncurses asks for, mapped the way Omarchy's terminal
templates map them.
Cost on a 1080p laptop panel (Intel Iris Xe): about 11 % of one core in
the shell plus ~2 % in Hyprland at the default 25 Hz — less than alacritty +
cmatrix fullscreen. It scales linearly with update_delay, drops to ~0 while
paused (fullscreen window, lock, another theme), and slows down on battery.
Every knob is a cmatrix flag. The theme's omatrix.toml carries the
defaults; the plugin's entry in ~/.config/omarchy/shell.json overrides them
per machine (either key style works):
{ "id": "io.github.0x1ocean.omatrix", "bold": "partial", "asynchronous": true }| Key | cmatrix | Default | Notes |
|---|---|---|---|
update_delay |
-u |
4 |
0–10, sleeps delay * 10 ms per tick (4 = 25 Hz) |
asynchronous |
-a |
false |
columns advance in three pacing classes |
bold |
-n / -b / -B |
"none" |
"partial" bolds even character codes + heads, "all" bolds everything |
charset |
-c / -l |
"ascii" |
"katakana" (half-width kana) or "console" (mtx font range) |
lambda |
-m |
false |
every tail glyph is λ |
changes |
-k |
false |
glyphs mutate while scrolling |
oldstyle |
-o |
false |
old-style scrolling |
rainbow |
-r |
false |
random ANSI colour per cell per frame |
color |
-C |
"green" |
ANSI name resolved through the theme, or #rrggbb |
head_color |
"white" |
ANSI name or #rrggbb |
|
opacity |
1.0 |
rain opacity | |
backdrop_opacity |
0.0 |
black scrim between rain and wallpaper | |
start |
"wake" |
"wake": each time the rain appears it starts as an empty terminal that fills up, like launching cmatrix; "full": start mid-run |
|
pause_when_covered |
true |
stop on a monitor while a fullscreen window is on its active workspace | |
pause_when_locked |
true |
stop while the session is locked | |
on_battery |
"slow" |
"slow" raises the delay to battery_update_delay, "pause" stops, "ignore" keeps mains settings |
|
battery_update_delay |
6 |
tick delay used on battery with on_battery = "slow" |
|
font_family / font_size |
system | pin the face / pixel size | |
always_on |
false |
draw under every theme, not just ones with omatrix.toml |
|
paused |
false |
keep the plugin loaded but idle |
IPC:
omarchy-shell omatrix status # JSON: active theme, grid, palette, cadence omarchy-shell omatrix pause omarchy-shell omatrix resume omarchy-shell omatrix toggle omarchy-shell omatrix wake # replay the empty-terminal fill
node --test tests/*.test.js # engine (cmatrix.js) and settings (settings.js) tests quickshell -p Preview.qml # renderer in a window with live per-tick timings ./build-shaders.sh # after editing shaders/matrix.frag
install.sh symlinks the checkout, so edits are live: the shell hot-reloads
plugin QML, and theme changes apply on the next omarchy theme set omatrix.
The theme repo is a git subtree split of theme/omatrix:
git subtree split --prefix=theme/omatrix -b theme-split git push git@github.com:0x1ocean/omarchy-omatrix-theme.git theme-split:main
GPL-3.0-or-later. cmatrix.js is a derivative of cmatrix
(© Chris Allegretta, Abishek V Ashok and contributors, GPL-3.0). Palette from
Omarchy's Osaka Jade theme.