This is a macOS screen saver based on the iconic rain of characters and symbols known from the movie The Matrix.
The screen saver also comes with an app replacing your wallpaper with the animation so you can enjoy being in the matrix all the time 🙂.
brew trust --cask patrickschaper/tap/matrix-screen-saver
brew install --cask patrickschaper/tap/matrix-screen-saver && open /Applications/MatrixWallpaper.app- Wallpaper: open MatrixWallpaper in Applications. options available through menubar icon.
- Screen saver options: System Settings → Wallpaper → Screen Saver → MatrixScreenSaver → Options….
There is no spoon. There is coffee. Donations help cover the Apple Developer membership and ongoing development.
The saver exposes a native Options… sheet. The values are stored with ScreenSaverDefaults.
| Option | Description | Default |
|---|---|---|
| Number scene | Show the startup number scene before continuous rain. | On |
| Twinkle | Turn on/off the twinkling effect. | On |
| Diffuse | Turn on/off the glow effect. | On |
| Character size | Set the character cell width and height in pixels. Example pairs: 8 x 15, 9 x 17, 10 x 19, 11 x 21, 12 x 23, and 13 x 24. |
9 x 17 |
| Rain density | Set the factor for the density of rain drops. A positive number. | 1.0 |
| Frame rate | Set the frame rate per second. A positive number less than or equal to 1000. | 25 |
| Error rate | Set the factor for the rate of character changes. A non-negative number. | 1.0 |
| Characters | Restrict rain glyphs to a custom set (e.g. ATGC). Leave empty for the default. | (empty) |
| Font | Pick one installed font for the rain glyphs. Intro text stays in the system font. See Matrix fonts. | (system font) |
| Neo message scene | Show the Neo message intro before the main scene. | On |
| Typing speed | Typing speed multiplier for Neo messages, custom command entry and the trace program. A positive number; pauses keep their natural duration. Output is not typed. | 1.0 |
| Name | Name used in the intro message ("Wake up, {name}..."). Only applies when Neo message lines is empty. | (empty — uses "Neo") |
| Neo message lines | Custom lines typed during the Neo message intro, up to 10 lines / 256 characters each. Leave empty to use the Name-based default message instead. | (empty) |
| Show custom scene | Animate each command using trace's initial cursor blink, natural typing rhythm and final pause, then clear it and execute it. Uses the general typing speed. Only output is shown afterward, appearing immediately as it arrives from the top row. Full screens scroll upward; wide rows are clipped without wrapping. Each command clears the screen first. Commands use a size-configured terminal with combined stdout/stderr and receive COLUMNS, LINES, and stty size. No keyboard input is provided. Commands run until exit or cancellation, not a fixed 12-second deadline; use ping -c 100 google.com for 100 replies. A command that never exits keeps its scene active until stopped. Displayed output is limited to the first 64 KiB; excess output is drained. Configure commands with Edit… in Intro scenes. Skipped if disabled or empty; the enabled trace program follows. |
Off |
| Output hold (seconds) | Keep each command's output visible after it finishes, before the next command or scene. Non-negative seconds; 0 advances immediately. | 10 |
| command playback | Radio buttons select all commands in sequence, one random command, or all commands in random order on each scene entry. Random order runs every command once and reshuffles each cycle; all displays agree on the pick or order. Add, edit, remove, or drag command rows to change their execution order in Edit…. Both whole-list modes finish each command and its message playback before running the next. | One random command |
| Scan lines intensity | Opacity of the CRT scan line overlay (0 = off, 100 = fully opaque). | 25 |
| Scan lines vertical | Orientation of the scan line overlay (vertical or horizontal). | On (vertical) |
Custom shell commands execute through /bin/sh with the host's permissions.
Only enter commands you trust, and avoid sensitive command text or output: both are visible on the screen saver,
including while the screen is locked. Command text and output are not logged. Live commands run
until exit and retain at most 64 KiB of combined output; stopping or restarting playback
cancels its command. The sandboxed screen saver may not have the same access as the wallpaper app.
The Glyph set radio buttons in Rain select Default, Classic, or Resurrections. Classic and Resurrections use their original bundled fonts and glyph artwork. Default keeps the existing configurable rain. Switching presets preserves your custom font and character settings; these controls are editable when Default is selected.
The Font option selects one installed font family, including hidden fonts discovered in the standard system and user font folders. Choosing another font replaces the selection; Reset restores the system font. Existing multi-font settings retain only the first font. Default and custom characters missing from the selected font use macOS font fallback when glyph images are cached, with no extra font lookup during playback. Install any additional fonts yourself.
The bundled Matrix Code and Matrix Resurrected fonts are published in Rezmason/matrix (MIT, © Rezmason 2018), which recreate the glyphs from the films. Thanks to Rezmason for making them available. See font provenance and the included license.
- Native Swift/AppKit screen saver bundle
- Edge-to-edge full-screen saver output, with terminal-style chrome kept in the preview host
- In-process renderer for
rain-foreverwith an optional upstreamnumberintro - Native Options… sheet for Number scene, Twinkle, Diffuse, Character size, Rain density, Frame rate, Error rate, Characters, Fonts, Neo message scene/speed/lines, custom shell commands/playback, and Scan lines
- Preview app for fast iteration without reinstalling
Sources/MatrixScreenSaver/MatrixScreenSaverView.swift- screen saver view, layout, drawing, and option wiringSources/MatrixScreenSaver/NativeMatrixRenderer.swift- native Matrix scene rendererSources/MatrixScreenSaver/CmdCaptureScene.swift- streams command output into scrolling terminal rows before the full trace programSources/MatrixScreenSaver/MatrixScreenSaverOptions.swift- options model and native configure sheetSources/MatrixScreenSaver/TerminalSupport.swift- small shared terminal types used by the active rendererScripts/install-saver.sh- shared ditto-based installer used by local installsTools/PreviewHost.swift- local preview host used by./preview.shResources/Info.plist- bundle metadata
- macOS
- Xcode Command Line Tools with
swiftc
Full Xcode is not required.
./build.sh
./build-wallpaper.shThese create the screen saver bundle and wallpaper app:
build/MatrixScreenSaver.saver
build/MatrixWallpaper.app
Both build scripts read the current version from ./VERSION and write it into their bundle metadata.
Local builds and ordinary CI use ad-hoc signing and do not need Apple credentials. Only the GitHub release publish job uses Developer ID signing and Apple notarization.
./tests.shCompiles and runs the test suite using swiftc. No Xcode required — Command Line Tools are sufficient.
For wallpaper checks, build the app first and run from a logged-in graphical macOS session:
./wallpaper-tests.sh
./wallpaper-install-tests.shThe UI tests briefly create desktop windows and open Options. Installer tests use a temporary home directory; neither suite changes your real login items.
./preview.shThis rebuilds the bundle, compiles the preview host, and opens the saver in a normal macOS window for quick iteration.
To launch the built wallpaper app without installing:
open build/MatrixWallpaper.app./install.shinstall.sh:
- rebuilds the saver bundle
- strips quarantine from the source bundle and copies it to
~/Library/Screen Savers/MatrixScreenSaver.saver - verifies the installed executable matches the build output
- stops running
ScreenSaverEngine/legacyScreenSaverprocesses so macOS reloads the updated bundle
After installing:
- open System Settings > Wallpaper > Screen saver...
- select MatrixScreenSaver
To relaunch the screen saver host manually:
open -a ScreenSaverEngineTo install and launch the wallpaper app in your user Applications folder:
./install-wallpaper.sh
open ~/Applications/MatrixWallpaper.appThe installer builds and verifies the app, gracefully quits running copies before replacement, and retains preferences. It does not launch the app or enable login startup.
When MatrixScreenSaver is installed in ~/Library/Screen Savers or /Library/Screen Savers,
the wallpaper menu shows Sync with Screen Saver. It is checked by default: the saver
shares the wallpaper's animation. Uncheck it to let the saver animate independently.
The choice survives app restarts and saver reinstallation; opening the menu refreshes
installation detection. This does not change visual options or synchronization between monitors.
While Matrix Wallpaper runs, it saves each display's desktop image and display options, then sets the underlying wallpaper to plain black. Stop and Quit Matrix Wallpaper restore those settings. Temporary pauses and animation restarts keep the original backup. If you choose a different wallpaper while Matrix runs, that newer choice is preserved.
Backups are stored in ~/Library/Application Support/MatrixWallpaper/DesktopWallpaper/.
After a crash or force-quit, reopen Matrix Wallpaper and choose Stop to restore the desktop.
Disconnected displays and failed restores keep their backups for a later retry.
Exact restoration is supported for static images; macOS's public API cannot preserve every
dynamic/aerial wallpaper, rotating collection, or separate Space configuration.
This project started as an attempt to wrap cxxmatrix inside a macOS screen saver.
The current implementation is based on the upstream akinomyoga/cxxmatrix project and keeps its look and scene behavior, but it no longer launches an external terminal process at runtime. The active saver is a native in-process Swift/AppKit renderer because ScreenSaverEngine did not reliably render the external terminal stream.
The active renderer currently ports rain-forever and can optionally start with the upstream number intro.



