No description
Find a file
Théo Codatte 4672719f4b Open the Claude Code popup whenever Claude's pane is on screen
- tmux's client_activity counts terminal replies and focus events as
  input, so it was rarely 60 s old when idle_prompt fired and the popup
  never opened
- check instead that Claude's pane is the active pane of the current
  window; idle_prompt already means nobody has answered for ~60 s
- drop DOTSAVER_CC_IDLE

Co-authored with AI
2026-10-07 23:54:54 +02:00
.claude-plugin Add a Claude Code plugin that shows dotsaver in a tmux popup 2026-10-07 23:45:57 +02:00
assets Add an animated demo GIF to the README 2026-10-07 23:34:21 +02:00
claude-plugin Open the Claude Code popup whenever Claude's pane is on screen 2026-10-07 23:54:54 +02:00
contrib Add idle triggers for bash, zsh, tmux and the desktop 2026-10-07 23:27:48 +02:00
.gitignore Initial commit: dotsaver, a quiet terminal screensaver in dots 2026-10-07 22:35:13 +02:00
dotsaver.c Open the menu and key help in the top-left corner 2026-10-07 23:16:26 +02:00
LICENSE Initial commit: dotsaver, a quiet terminal screensaver in dots 2026-10-07 22:35:13 +02:00
Makefile Add idle triggers for bash, zsh, tmux and the desktop 2026-10-07 23:27:48 +02:00
README.md Open the Claude Code popup whenever Claude's pane is on screen 2026-10-07 23:54:54 +02:00

   ·  •  ●                                                    ●  •  ·

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

   ·  •  ●      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 aurora, cabin, dawn, reef and desert


· 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
flag what it does
-s scene play one scene (default: cycle through all)
-t seconds seconds per scene when cycling (default 30)
-c mode colours: truecolor (default), theme or mono
-m same as -c mono
-g n dot spacing 1–4 (default 1; 2 = square grid)
-b braille density: 2×4 dots per cell
-n no backdrop: leave empty grid points blank
-3 classic glyphs: 3 dot sizes instead of 4
-S simple detail: the plainer first version of scenes
-o print a single frame and exit (uses $COLUMNS × $LINES)
-p with -o: draw the settings menu on the frame
-k with -o: draw the key help on the frame
-l list scenes
-h help

● 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

key while it runs
← → previous / next scene
↑ ↓ more / less dot spacing
space switch between dots and braille
c next colour mode
b backdrop on / off
g fine / classic glyphs
d rich / simple detail
p open the settings menu
h show these keys
any other quit
┌─ 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.
key in the menu
↑ ↓ / k j select a setting
← → / l change it (space / enter too)
h key help
p / esc close the menu
q quit
c b g d same 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.                        ●  •  ·