bthuner/dotsaver

quiets screensavers for your terminal

C

0

12 commits

updated Oct 8, 2026

See the code

See what people are saying

README

   ·  •  ●                                                    ●  •  ·

        ●●●●  ●●●  ●●●●●  ●●●●  ●●●  ●   ●  ●●●●●  ●●●●
        ●   ● ●   ●  ●    ●     ●   ● ●   ●  ●      ●   ●
        ●   ● ●   ●  ●     ●●●  ●●●●● ●   ●  ●●●●   ●●●●
        ●   ● ●   ●  ●        ● ●   ●  ● ●   ●      ●  ●
        ●●●●   ●●●   ●    ●●●●  ●   ●   ●    ●●●●●  ●   ●

   ·  •  ●      a quiet terminal screensaver in dots      ●  •  ·

dotsaver draws slow, calm scenes in your terminal using three characters: · • ●. Dark ground, soft light, no noise. Style inspired by ascii.rest.

One C file. C99 + POSIX. No dependencies beyond libm.

dotsaver cycling through donut and aurora in dots, then forest, earthrise and reef in braille


· build

cc -O2 -o dotsaver dotsaver.c -lm

or make. make install puts it and the idle helpers in ~/.local (PREFIX=/usr/local to change that).

That's it. Copy dotsaver somewhere on your $PATH if you like.

• run

./dotsaver                  # cycle through every scene
./dotsaver -s donut         # play a single scene
./dotsaver -t 20 -c theme   # 20s per scene, in your terminal's palette
./dotsaver -s cabin -b      # braille: 2x4 dots per cell, much finer detail
./dotsaver -g 2             # square dot grid, like ascii.rest
./dotsaver -o -s aurora     # print one frame to stdout and exit
./dotsaver -l               # list scenes
flagwhat it does
-s sceneplay one scene (default: cycle through all)
-t secondsseconds per scene when cycling (default 30)
-c modecolours: truecolor (default), theme or mono
-msame as -c mono
-g ndot spacing 1–4 (default 1; 2 = square grid)
-bbraille density: 2×4 dots per cell
-nno backdrop: leave empty grid points blank
-3classic glyphs: 3 dot sizes instead of 4
-Ssimple detail: the plainer first version of scenes
-oprint a single frame and exit (uses $COLUMNS × $LINES)
-pwith -o: draw the settings menu on the frame
-kwith -o: draw the key help on the frame
-llist scenes
-hhelp

● scenes

aurora      slow curtains of light over a few stars
cabin       northern lights over snowy peaks, a cabin and a lake
dawn        snow peaks catching first light above a misty lake
reef        light shafts through blue water, coral, fish, bubbles
desert      moonlit dunes, the milky way and a falling star
earthrise   the earth climbing over a grey lunar horizon
kyoto       a pagoda against a dusk sky, lanterns and birds
marine      a night seafront: a curve of street lights, a lit skyline
forest      layered pines fading into drifting mist
coast       a moonlit sea, cliffs and a sweeping lighthouse
sunset      the sun sinking into the sea, a glittering path
storm       rolling clouds over plains, rain and lightning
taj         a domed mausoleum at dawn, mirrored in its pool
ghats       river steps and temples, floating lamps and fires
donut       the classic, in dots
stars       slow flight through a starfield
fireflies   wandering lights that blink and glow
rain        soft vertical drops with fading trails

./dotsaver -o -m -s donut

                                ●●●●●●●●●●●●●●●
                             ●●●●●••●●●●●●●●●●●●●
                           ●●●•••••••••••●●●●●●●●●●
                          ●●••••••···••••••●●●●●●●●●●
                        •●●••••···   ···••••●●●●●●●●●●
                        ●●●••••·       ··••••●●●●●●●●●
                       •●●●●•••·        ·•••●●●●●●●●●●•
                      •●●●●●●●●•       •••••●●●●●●●●●••
                      ••●●●●●●●●●•    •••••●●●●●●●●●•••
                      ·•●●●●●●●●●●●●●●●●●●●●●●●●●●••••·
                       ••●●●●●●●●●●●●●●●●●●●●●•●••••••
                       ·••●●●●●●●●●●●●●●●●●●•••••••••
                        ·••••●●●●●●●●●●●•••••••••••·
                          •••••••●•••••••••••••••·
                            ·•••••••••••••••••··
                               ··••••••······

· keys

keywhile it runs
← →previous / next scene
↑ ↓more / less dot spacing
spaceswitch between dots and braille
cnext colour mode
bbackdrop on / off
gfine / classic glyphs
drich / simple detail
popen the settings menu
hshow these keys
any otherquit
┌─ dotsaver ───────────────────┐
│                              │
│▸ scene    ‹ all (cycle)  › ←→│
│  seconds  ‹ 30s          ›   │
│  color    ‹ truecolor    › c │
│  spacing  ‹ 1            › ↑↓│
│  density  ‹ normal       › sp│
│  backdrop ‹ on           › b │
│  glyphs   ‹ fine         › g │
│  detail   ‹ rich         › d │
│                              │
│  ↑↓ select    ←→ change      │
│  p / esc close    q quit     │
│  h help                      │
│                              │
└──────────────────────────────┘

The menu and the key help open in the top-left corner. Each menu row
shows its shortcut on the right.
keyin the menu
↑ ↓ / k jselect a setting
← → / lchange it (space / enter too)
hkey help
p / escclose the menu
qquit
c b g dsame shortcuts as outside it

• as a screensaver

dotsaver can start by itself after a while without input: in your shell (bash, zsh), in tmux, or on the whole desktop. Install everything first:

make install                # dotsaver and helpers into ~/.local

Every helper reads the same two settings:

DOTSAVER_IDLE   seconds without input before it starts (default 300)
DOTSAVER_ARGS   flags for dotsaver, e.g. "-s cabin -g 2 -c theme"

bash: add to ~/.bashrc

DOTSAVER_IDLE=300
source ~/.local/share/dotsaver/dotsaver.bash

zsh: add to ~/.zshrc

DOTSAVER_IDLE=300
source ~/.local/share/dotsaver/dotsaver.zsh

Both start dotsaver at the prompt once nothing has been typed for DOTSAVER_IDLE seconds, and never while a command is running. A key brings the prompt back, with any half-typed line intact. bash uses the ALRM trap and zsh TMOUT/TRAPALRM, so they replace your own if you have one.

tmux: add to ~/.tmux.conf

source-file ~/.local/share/dotsaver/dotsaver.tmux.conf

or set the two options yourself:

set -g lock-after-time 300
set -g lock-command "dotsaver -s cabin"

tmux counts input across all its panes and windows. When tmux runs dotsaver this way, the bash and zsh hooks step aside inside it, so it never starts twice.

the desktop (Wayland: niri, sway, Hyprland, river, ...): a systemd user service runs swayidle, which opens dotsaver fullscreen in a terminal after DOTSAVER_IDLE seconds of no input anywhere, and closes it when you come back.

cp ~/.local/share/dotsaver/dotsaver-idle.service ~/.config/systemd/user/
systemctl --user enable --now dotsaver-idle.service
systemctl --user edit dotsaver-idle.service     # change the settings:
#   [Service]
#   Environment=DOTSAVER_IDLE=600
#   Environment=DOTSAVER_ARGS=-s aurora -g 2

It needs swayidle and one of foot, kitty, alacritty, konsole or xterm (DOTSAVER_TERM picks one). dotsaver-screen opens and dotsaver-screen --stop closes the fullscreen window, if you want to wire it into another idle tool (hypridle, xidlehook, ...).

Claude Code (in tmux): a plugin shows dotsaver in a full-size tmux popup over Claude Code once it has been waiting for you for about a minute. Any key closes it.

claude plugin marketplace add /path/to/dotsaver
claude plugin install dotsaver@dotsaver

(or /plugin marketplace add and /plugin install inside Claude Code). It uses Claude Code's idle_prompt notification, which comes about 60 s after Claude finishes. It only opens when Claude's pane is the one on screen, so it never covers work in another tmux pane or window. DOTSAVER_ARGS picks the scene and look.

• look

colour

truecolor   24-bit ink on dotsaver's own dark ground (default)
theme       your terminal's 16-colour palette and background, so the
            scenes follow your shell theme (works without truecolor)
mono        your terminal's foreground colour only

spacing puts empty cells between dots. 1 is the classic dense look. Terminal cells are about twice as tall as they are wide, so 2 leaves a gap every other column and gives a square grid like ascii.rest. 3 and 4 spread the dots further.

density braille packs 2×4 dots into each cell with braille characters (⣿), for about 8× the detail. Every braille dot is the same size, so brightness comes from colour and from how many dots are lit. Spacing applies to these dots too.

backdrop puts a faint · on every empty grid point, so the whole screen reads as one dotted canvas. Turn it off for blank darkness.

glyphs fine uses four dot sizes, · ∙ • ●. classic uses three (· • ●) if your font draws ∙ badly.

detail rich gives cabin separate aurora rays, a violet haze, forested mountains and long window reflections. simple is its first, plainer version.

Scenes keep their shape and speed whatever the spacing and density.

● notes

  • truecolor wants a 24-bit colour terminal (most modern ones are). If yours isn't, use -c theme.
  • -o is handy for screenshots, previews, or piping a frame into something else: COLUMNS=80 LINES=24 ./dotsaver -o -s rain > frame.txt

· license

MIT — see LICENSE.

   ·  •  ●                     rest.                        ●  •  ·

bthuner/dotsaver

quiets screensavers for your terminal

C

0

12 commits

updated Oct 8, 2026

See the code

See what people are saying

README

   ·  •  ●                                                    ●  •  ·

        ●●●●  ●●●  ●●●●●  ●●●●  ●●●  ●   ●  ●●●●●  ●●●●
        ●   ● ●   ●  ●    ●     ●   ● ●   ●  ●      ●   ●
        ●   ● ●   ●  ●     ●●●  ●●●●● ●   ●  ●●●●   ●●●●
        ●   ● ●   ●  ●        ● ●   ●  ● ●   ●      ●  ●
        ●●●●   ●●●   ●    ●●●●  ●   ●   ●    ●●●●●  ●   ●

   ·  •  ●      a quiet terminal screensaver in dots      ●  •  ·

dotsaver draws slow, calm scenes in your terminal using three characters: · • ●. Dark ground, soft light, no noise. Style inspired by ascii.rest.

One C file. C99 + POSIX. No dependencies beyond libm.

dotsaver cycling through donut and aurora in dots, then forest, earthrise and reef in braille


· build

cc -O2 -o dotsaver dotsaver.c -lm

or make. make install puts it and the idle helpers in ~/.local (PREFIX=/usr/local to change that).

That's it. Copy dotsaver somewhere on your $PATH if you like.

• run

./dotsaver                  # cycle through every scene
./dotsaver -s donut         # play a single scene
./dotsaver -t 20 -c theme   # 20s per scene, in your terminal's palette
./dotsaver -s cabin -b      # braille: 2x4 dots per cell, much finer detail
./dotsaver -g 2             # square dot grid, like ascii.rest
./dotsaver -o -s aurora     # print one frame to stdout and exit
./dotsaver -l               # list scenes
flagwhat it does
-s sceneplay one scene (default: cycle through all)
-t secondsseconds per scene when cycling (default 30)
-c modecolours: truecolor (default), theme or mono
-msame as -c mono
-g ndot spacing 1–4 (default 1; 2 = square grid)
-bbraille density: 2×4 dots per cell
-nno backdrop: leave empty grid points blank
-3classic glyphs: 3 dot sizes instead of 4
-Ssimple detail: the plainer first version of scenes
-oprint a single frame and exit (uses $COLUMNS × $LINES)
-pwith -o: draw the settings menu on the frame
-kwith -o: draw the key help on the frame
-llist scenes
-hhelp

● scenes

aurora      slow curtains of light over a few stars
cabin       northern lights over snowy peaks, a cabin and a lake
dawn        snow peaks catching first light above a misty lake
reef        light shafts through blue water, coral, fish, bubbles
desert      moonlit dunes, the milky way and a falling star
earthrise   the earth climbing over a grey lunar horizon
kyoto       a pagoda against a dusk sky, lanterns and birds
marine      a night seafront: a curve of street lights, a lit skyline
forest      layered pines fading into drifting mist
coast       a moonlit sea, cliffs and a sweeping lighthouse
sunset      the sun sinking into the sea, a glittering path
storm       rolling clouds over plains, rain and lightning
taj         a domed mausoleum at dawn, mirrored in its pool
ghats       river steps and temples, floating lamps and fires
donut       the classic, in dots
stars       slow flight through a starfield
fireflies   wandering lights that blink and glow
rain        soft vertical drops with fading trails

./dotsaver -o -m -s donut

                                ●●●●●●●●●●●●●●●
                             ●●●●●••●●●●●●●●●●●●●
                           ●●●•••••••••••●●●●●●●●●●
                          ●●••••••···••••••●●●●●●●●●●
                        •●●••••···   ···••••●●●●●●●●●●
                        ●●●••••·       ··••••●●●●●●●●●
                       •●●●●•••·        ·•••●●●●●●●●●●•
                      •●●●●●●●●•       •••••●●●●●●●●●••
                      ••●●●●●●●●●•    •••••●●●●●●●●●•••
                      ·•●●●●●●●●●●●●●●●●●●●●●●●●●●••••·
                       ••●●●●●●●●●●●●●●●●●●●●●•●••••••
                       ·••●●●●●●●●●●●●●●●●●●•••••••••
                        ·••••●●●●●●●●●●●•••••••••••·
                          •••••••●•••••••••••••••·
                            ·•••••••••••••••••··
                               ··••••••······

· keys

keywhile it runs
← →previous / next scene
↑ ↓more / less dot spacing
spaceswitch between dots and braille
cnext colour mode
bbackdrop on / off
gfine / classic glyphs
drich / simple detail
popen the settings menu
hshow these keys
any otherquit
┌─ dotsaver ───────────────────┐
│                              │
│▸ scene    ‹ all (cycle)  › ←→│
│  seconds  ‹ 30s          ›   │
│  color    ‹ truecolor    › c │
│  spacing  ‹ 1            › ↑↓│
│  density  ‹ normal       › sp│
│  backdrop ‹ on           › b │
│  glyphs   ‹ fine         › g │
│  detail   ‹ rich         › d │
│                              │
│  ↑↓ select    ←→ change      │
│  p / esc close    q quit     │
│  h help                      │
│                              │
└──────────────────────────────┘

The menu and the key help open in the top-left corner. Each menu row
shows its shortcut on the right.
keyin the menu
↑ ↓ / k jselect a setting
← → / lchange it (space / enter too)
hkey help
p / escclose the menu
qquit
c b g dsame shortcuts as outside it

• as a screensaver

dotsaver can start by itself after a while without input: in your shell (bash, zsh), in tmux, or on the whole desktop. Install everything first:

make install                # dotsaver and helpers into ~/.local

Every helper reads the same two settings:

DOTSAVER_IDLE   seconds without input before it starts (default 300)
DOTSAVER_ARGS   flags for dotsaver, e.g. "-s cabin -g 2 -c theme"

bash: add to ~/.bashrc

DOTSAVER_IDLE=300
source ~/.local/share/dotsaver/dotsaver.bash

zsh: add to ~/.zshrc

DOTSAVER_IDLE=300
source ~/.local/share/dotsaver/dotsaver.zsh

Both start dotsaver at the prompt once nothing has been typed for DOTSAVER_IDLE seconds, and never while a command is running. A key brings the prompt back, with any half-typed line intact. bash uses the ALRM trap and zsh TMOUT/TRAPALRM, so they replace your own if you have one.

tmux: add to ~/.tmux.conf

source-file ~/.local/share/dotsaver/dotsaver.tmux.conf

or set the two options yourself:

set -g lock-after-time 300
set -g lock-command "dotsaver -s cabin"

tmux counts input across all its panes and windows. When tmux runs dotsaver this way, the bash and zsh hooks step aside inside it, so it never starts twice.

the desktop (Wayland: niri, sway, Hyprland, river, ...): a systemd user service runs swayidle, which opens dotsaver fullscreen in a terminal after DOTSAVER_IDLE seconds of no input anywhere, and closes it when you come back.

cp ~/.local/share/dotsaver/dotsaver-idle.service ~/.config/systemd/user/
systemctl --user enable --now dotsaver-idle.service
systemctl --user edit dotsaver-idle.service     # change the settings:
#   [Service]
#   Environment=DOTSAVER_IDLE=600
#   Environment=DOTSAVER_ARGS=-s aurora -g 2

It needs swayidle and one of foot, kitty, alacritty, konsole or xterm (DOTSAVER_TERM picks one). dotsaver-screen opens and dotsaver-screen --stop closes the fullscreen window, if you want to wire it into another idle tool (hypridle, xidlehook, ...).

Claude Code (in tmux): a plugin shows dotsaver in a full-size tmux popup over Claude Code once it has been waiting for you for about a minute. Any key closes it.

claude plugin marketplace add /path/to/dotsaver
claude plugin install dotsaver@dotsaver

(or /plugin marketplace add and /plugin install inside Claude Code). It uses Claude Code's idle_prompt notification, which comes about 60 s after Claude finishes. It only opens when Claude's pane is the one on screen, so it never covers work in another tmux pane or window. DOTSAVER_ARGS picks the scene and look.

• look

colour

truecolor   24-bit ink on dotsaver's own dark ground (default)
theme       your terminal's 16-colour palette and background, so the
            scenes follow your shell theme (works without truecolor)
mono        your terminal's foreground colour only

spacing puts empty cells between dots. 1 is the classic dense look. Terminal cells are about twice as tall as they are wide, so 2 leaves a gap every other column and gives a square grid like ascii.rest. 3 and 4 spread the dots further.

density braille packs 2×4 dots into each cell with braille characters (⣿), for about 8× the detail. Every braille dot is the same size, so brightness comes from colour and from how many dots are lit. Spacing applies to these dots too.

backdrop puts a faint · on every empty grid point, so the whole screen reads as one dotted canvas. Turn it off for blank darkness.

glyphs fine uses four dot sizes, · ∙ • ●. classic uses three (· • ●) if your font draws ∙ badly.

detail rich gives cabin separate aurora rays, a violet haze, forested mountains and long window reflections. simple is its first, plainer version.

Scenes keep their shape and speed whatever the spacing and density.

● notes

  • truecolor wants a 24-bit colour terminal (most modern ones are). If yours isn't, use -c theme.
  • -o is handy for screenshots, previews, or piping a frame into something else: COLUMNS=80 LINES=24 ./dotsaver -o -s rain > frame.txt

· license

MIT — see LICENSE.

   ·  •  ●                     rest.                        ●  •  ·