motd

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 30, 2026 License: MIT

README

motd

A message-of-the-day generator that's half facts, half feelings.

Like fastfetch, but it tells you that your VPN is down, your scrub is overdue, and you have 12 packages to upgrade — instead of telling you which kernel you're running for the seven-thousandth time. With a friendly animal.

   ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆       host    cube
   ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒       up      4d 12h 31m
   ▒▒██████████▒▒▒▒       load    0.42  0.38  0.31
   ▒▒██████████▒▒▒▒       disk    97G / 888G  (10%)
   ▒▒██████████▒▒▒▒               204G / 32T  (0%)
   ▒▒▒██▒▒▒▒██▒▒▒▒▒       mem     8G / 16G  (50%)
   ▒▒▒██▒▒▒▒██▒▒▒▒▒       ip      10.10.10.10  (eth)
                                  100.121.19.125  (tailscale)

  ● 2 services running → motd services
  ⚠ 12 packages outdated → motd updates

(That's an elephant. There are 36 other animals to choose from.)

What it does

  • Mark on the left: a colorful animal of your choosing — pick a different one per host so you know where you logged in
  • Facts on the right: hostname, uptime, load, disk, memory, IP — all driven by tiny built-in collectors so it's <50ms warm
  • Alerts below: each module reports a one-liner only when something's worth saying; the line vanishes when it's not
  • Drill-down: motd <name> runs that module's full version (e.g. motd disk shows a per-mount breakdown with bars + ZFS datasets)
  • --watch mode: edit the config in one pane, watch motd re-render on save in another
  • Cache where it makes sense: per-module TTL for things that genuinely don't change often, no cache for things that respond to user action

Install

From a release
curl -L https://github.com/arne/motd/releases/latest/download/motd_Linux_x86_64.tar.gz | tar xz
sudo install -m 0755 motd /usr/local/bin/motd
sudo mkdir -p /etc/xdg/motd
sudo cp -r examples/marks /etc/xdg/motd/
sudo cp examples/system-config.yaml /etc/xdg/motd/config.yaml
From source
go install github.com/arne/motd/cmd/motd@latest
git clone https://github.com/arne/motd
sudo mkdir -p /etc/xdg/motd
sudo cp -r motd/examples/marks /etc/xdg/motd/
sudo cp motd/examples/system-config.yaml /etc/xdg/motd/config.yaml

Now motd works for any user on the box. Each user can override with their own ~/.config/motd/config.yaml.

Hook it into your shell
# fish
echo "motd" >> ~/.config/fish/config.fish

# bash
echo "motd" >> ~/.bashrc

# zsh
echo "motd" >> ~/.zshrc

Configuration

Single YAML file. Two halves: layout (a recursive tree of stacks) and modules (named things that produce text).

mark: { file: marks/animals/octopus.ansi }

layout:
  vstack:
    - hstack:
        - mark
        - vstack: [host, up, load, disk, mem, ip]
    - vstack: [services, updates, scrub]

modules:
  host:    { builtin: hostname }
  up:      { builtin: uptime }
  load:    { builtin: load }
  mem:     { builtin: mem }
  ip:      { builtin: ip }
  disk:    { builtin: disk }

  services:
    builtin: services
    list:
      - { name: immich,    http: "http://localhost:2283/api/server/ping" }
      - { name: openwebui, cmd:  "incus exec openwebui -- curl -sf http://localhost:8080/health" }

  updates:
    command: |
      n=$(apt list --upgradable 2>/dev/null | tail -n +2 | wc -l)
      [ "$n" -gt 0 ] && echo "$n packages outdated"
    command_full: "apt list --upgradable"

  scrub:
    command: |
      last=$(zpool status storage 2>/dev/null | grep -oP 'on \K.*$' | head -1)
      if [ -n "$last" ]; then
        days=$(( ( $(date +%s) - $(date -d "$last" +%s) ) / 86400 ))
        if [ "$days" -gt 30 ]; then
          echo "storage scrub last ran ${days}d ago"
        fi
      fi
    command_full: "zpool status -v"
    cache: 6h

Modules

Built-ins
Name What it shows
hostname The hostname, in your terminal's primary accent
uptime 4d 12h 31m, friendly format
load 0.42 0.38 0.31
mem 8G / 16G (50%) from /proc/meminfo
ip Non-loopback IPv4 addresses, with friendly category labels (eth, wifi, tailscale, incus, docker, wg, vpn, zerotier, ...)
disk Root + auto-detected zpool roots; motd disk shows per-mount table with utilization bars and ZFS datasets
services Heterogeneous health checks: http, tcp, unit (systemd), or cmd. motd services shows a per-service status table
Custom

Anything you can put in a shell command. Output goes through the styling pipeline.

weather:
  command: "curl -s wttr.in/?format=3"
  command_full: "curl -s wttr.in/"
  cache: 30m

uptime_kuma:
  command: "~/bin/check-status-page"

Convention — for command-based modules:

  • Empty stdout = silent (no alert renders)
  • Any stdout = treated as a warning, framework prepends ⚠ glyph and appends drill-down hint
  • Exit nonzero = treat as failure; keep last good cache, don't overwrite
  • command_full is what motd <name> runs — use it to dump the verbose view

Marks

37 cute animals live in examples/marks/animals/. Pick one per host to differentiate where you logged in:

bat   bear   bee   butterfly   cat   cow   crab   dog
dolphin   dragon   duck   elephant   fox   frog   giraffe
hamster   hedgehog   koala   lion   llama   monkey   mouse
octopus   otter   owl   panda   penguin   pig   rabbit
raccoon   shark   sloth   tiger   turtle   unicorn   whale   wolf

Want one we don't ship? Find its emoji codepoint at openmoji.org and run:

scripts/make-animal-mark.sh <name> <CODEPOINT>
# e.g. scripts/make-animal-mark.sh chicken 1F414

The pipeline: download OpenMoji SVG → render to high-res PNG → trim → chafa-render to colored ASCII at 24×14 cells.

Drill-down

Each module is also accessible directly:

motd services    # full status table for all services
motd disk        # per-mount breakdown with bars + ZFS datasets
motd updates     # apt list --upgradable

If a module has a command_full set, that's what runs. Builtins like disk and services ship their own drill-down.

--watch

motd --watch

Re-renders whenever the config or any referenced file changes. Edit YAML in one pane, see the result in another. Ctrl+C to exit. Watches the config file's directory and the mark file's directory; debounces multi-event editor saves.

Why not fastfetch / cowsay?

fastfetch cowsay motd
System facts
Actionable alerts
Configurable layout partial
Drill-down
Friendly animal
Re-renders on config save
Cute, in 50ms

Configuration file lookup

In order:

  1. --config <path> flag
  2. $MOTD_CONFIG env var
  3. ~/.config/motd/config.yaml (if it exists)
  4. /etc/xdg/motd/config.yaml (system fallback)

Mark file paths in config are resolved relative to the config file's directory, so marks/animals/elephant.ansi works whether you're using the system or user config.

Building from source

git clone https://github.com/arne/motd
cd motd
go build -o motd ./cmd/motd
./motd --config examples/config.yaml

Releases are built via goreleaser on tag push. See .goreleaser.yml for the build matrix.

License

MIT. See LICENSE.

Directories

Path Synopsis
cmd
motd command
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL