Lots of config tweaks, adding isync and local mutt. - dotfiles - These are my dotfiles. There are many like it, but these are mine.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 389acd89db618a968c35226fa151cbd0263f217f
 (DIR) parent 2274190a12736e2d3c2dce6e346e582a7092dd5e
 (HTM) Author: Jay Scott <me@jay.scot>
       Date:   Sat, 25 Jan 2025 17:12:37 +0000
       
       Lots of config tweaks, adding isync and local mutt.
       
       Diffstat:
         M README                              |       4 ++--
         A bin/fet.sh                          |     266 +++++++++++++++++++++++++++++++
         M bin/link-handler                    |       6 +++---
         D bin/pass                            |     279 -------------------------------
         M bootstrap.sh                        |       4 ++--
         A isync/mbsyncrc                      |      24 ++++++++++++++++++++++++
         M kshrc                               |       5 +----
         M mpd/mpd.conf                        |      17 ++++++-----------
         M mutt/muttrc                         |     149 ++++++++++++++++++++-----------
         D newsraft/config                     |       9 ---------
         D newsraft/feeds                      |      19 -------------------
         A pkg.list                            |      20 ++++++++++++++++++++
         M suckless/slstatus/config.h          |       6 +++---
         M xenodm/Xsetup_0                     |      12 ++++++++++--
         A xsession                            |      10 ++++++++++
       
       15 files changed, 443 insertions(+), 387 deletions(-)
       ---
 (DIR) diff --git a/README b/README
       @@ -16,10 +16,10 @@ main desktop OS and are forever evolving.
          window manager : dwm
          terminal       : xterm
          launcher       : dmenu
       -  email          : neomutt
       +  email          : neomutt / isync / smtpd
          browser        : firefox / lynx
          media          : mpv
          password mgmt  : pass
          vpn            : mullvad
       -  news           : newsraft
       +  news           : rss2email
        
 (DIR) diff --git a/bin/fet.sh b/bin/fet.sh
       @@ -0,0 +1,266 @@
       +#!/bin/sh
       +#
       +#    fet.sh
       +#  a fetch in pure POSIX shell
       +#
       +
       +# supress errors
       +exec 2>/dev/null
       +set --
       +eq() {  # equals  |  [ a = b ] with globbing
       +        case $1 in
       +                $2) ;;
       +                *) return 1;;
       +        esac
       +}
       +
       +## DE
       +wm=$XDG_CURRENT_DESKTOP
       +[ "$wm" ] || wm=$DESKTOP_SESSION
       +
       +## Distro
       +# freedesktop.org/software/systemd/man/os-release.html
       +# a common file that has variables about the distro
       +for os in /etc/os-release /usr/lib/os-release; do
       +        # some POSIX shells exit when trying to source a file that doesn't exist
       +        [ -f $os ] && . $os && break
       +done
       +
       +if [ -e /proc/$$/comm ]; then
       +        ## Terminal
       +        while [ ! "$term" ]; do
       +                # loop over lines in /proc/pid/status until it reaches PPid
       +                # then save that to a variable and exit the file
       +                while read -r line; do
       +                        eq "$line" 'PPid*' && ppid=${line##*:?} && break
       +                done < "/proc/${ppid:-$PPID}/status"
       +
       +                # Make sure not to do an infinite loop
       +                [ "$pppid" = "$ppid" ] && break
       +                pppid=$ppid
       +
       +                # get name of binary
       +                read -r name < "/proc/$ppid/comm"
       +
       +                case $name in
       +                        *sh|"${0##*/}") ;;  # skip shells
       +                        *[Ll]ogin*|*init|*systemd*) break;;  # exit when the top is reached
       +                        # anything else can be assumed to be the terminal
       +                        # this has the side affect of catching tmux, but tmux
       +                        # detaches from the terminal and therefore ignoring that
       +                        # will just make the init the term
       +                        *) term=$name
       +                esac
       +        done
       +
       +        ## WM/DE
       +        [ "$wm" ] ||
       +                # loop over all processes and check the binary name
       +                for i in /proc/*/comm; do
       +                        read -r c < "$i"
       +                        case $c in
       +                                *bar*|*rc) ;;
       +                                awesome|xmonad*|qtile|sway|i3|[bfo]*box|*wm*) wm=${c%%-*}; break;;
       +                        esac
       +                done
       +
       +        ## Memory
       +        # loop over lines in /proc/meminfo until it reaches MemTotal,
       +        # then convert the amount (second word) from KB to MB
       +        while read -r line; do
       +                eq "$line" 'MemTotal*' && set -- $line && break
       +        done < /proc/meminfo
       +        mem="$(( $2 / 1000 ))MB"
       +
       +        ## Processor
       +        while read -r line; do
       +                case $line in
       +                        vendor_id*) vendor="${line##*: } ";;
       +                        model\ name*) cpu=${line##*: }; break;;
       +                esac
       +        done < /proc/cpuinfo
       +
       +        ## Uptime
       +        # the simple math is shamefully stolen from aosync
       +        IFS=. read -r uptime _ < /proc/uptime
       +        d=$((uptime / 60 / 60 / 24))
       +        up=$(printf %02d:%02d $((uptime / 60 / 60 % 24)) $((uptime / 60 % 60)))
       +        [ "$d" -gt 0 ] && up="${d}d $up"
       +
       +        ## Kernel
       +        read -r _ _ version _ < /proc/version
       +        kernel=${version%%-*}
       +        eq "$version" '*Microsoft*' && ID="fake $ID"
       +
       +        ## Motherboard // laptop
       +        read -r model < /sys/devices/virtual/dmi/id/product_name
       +        # invalid model handling
       +        case $model in
       +                # alternate file with slightly different info
       +                # on my laptop it has the device model (instead of 'hp notebook')
       +                # on my desktop it has the extended motherboard model
       +                'System '*|'Default '*|'To Be Filled'*)
       +                        read -r model < /sys/devices/virtual/dmi/id/board_name
       +        esac
       +
       +        ## Packages
       +        # clean environment, then make every file in the dir an argument,
       +        # then save the argument count to $pkgs
       +        set --
       +        # kiss, arch, debian, void, gentoo
       +        for i in '/var/db/kiss/installed/*'  '/var/lib/pacman/local/[0-9a-z]*' \
       +        '/var/lib/dpkg/info/*.list'  '/var/db/xbps/.*'  '/var/db/pkg/*/*'; do
       +                set -- $i
       +                [ $# -gt 1 ] && pkgs=$# && break
       +        done
       +
       +        read -r host < /proc/sys/kernel/hostname
       +elif [ -f /var/run/dmesg.boot ]; then
       +        # Both OpenBSD and FreeBSD use this file, however they're formatted differently
       +        read -r bsd < /var/run/dmesg.boot
       +        case $bsd in
       +        Open*)
       +                ## OpenBSD cpu/mem/name
       +                while read -r line; do
       +                        case $line in
       +                                'real mem'*)
       +                                        # use the pre-formatted value which is in brackets
       +                                        mem=${line##*\(}
       +                                        mem=${mem%\)*}
       +                                ;;
       +                                # set $cpu to everything before a comma and after the field name
       +                                cpu0:*)
       +                                        cpu=${line#cpu0: }
       +                                        # Remove excess info after the actual CPU name
       +                                        cpu=${cpu%%,*}
       +                                        # Set the CPU Manufacturer to the first word of the cpu
       +                                        # variable [separated by '(' or ' ']
       +                                        vendor=${cpu%%[\( ]*}
       +                                        # We got all the info we want, stop reading
       +                                        break
       +                                ;;
       +                                # First 2 words in the file are OpenBSD <version>
       +                                *) [ "$ID" ] || { set -- $line; ID="$1 $2"; }
       +                        esac
       +                done < /var/run/dmesg.boot
       +                [ -d /var/db/pkg ] && set -- /var/db/pkg/* && pkgs=$#
       +                read -r host < /etc/myname
       +                host=${host%.*}
       +        ;;
       +        # Everything else, assume FreeBSD (first line is ---<<BOOT>> or something)
       +        *)
       +                # shellcheck source=/dev/null
       +                . /etc/rc.conf
       +                # shut shellcheck up without disabling the warning
       +                host=${hostname:-}
       +
       +                while read -r line; do
       +                        case $line in
       +                                # os version
       +                                FreeBSD*)
       +                                        # If the OS is already set, no need to set it again
       +                                        [ "$ID" ] && continue
       +                                        ID=${line%%-R*}
       +                                ;;
       +
       +                                CPU:*)
       +                                        cpu=${cpu#CPU: }
       +                                        # Remove excess info from after the actual CPU name
       +                                        cpu=${line%\(*}
       +                                ;;
       +                                *Origin=*)
       +                                        # CPU Manufacturer
       +                                        vendor=${line#*Origin=\"}
       +                                        vendor="${vendor%%\"*} "
       +                                ;;
       +
       +                                'real memory'*)
       +                                        # Get the pre-formatted amount which is inside brackets
       +                                        mem=${line##*\(}
       +                                        mem=${mem%\)*}
       +                                        # This appears to be the final thing we need from the file,
       +                                        # no need to read it more.
       +                                        break
       +                        esac
       +                done < /var/run/dmesg.boot
       +        ;;
       +        esac
       +elif v=/System/Library/CoreServices/SystemVersion.plist; [ -f "$v" ]; then
       +        ## Macos
       +        # make sure this variable is empty as to not break the following loop
       +        temp=
       +        while read -r line; do
       +                case $line in
       +                        # set a variable so the script knows it's on the correct line
       +                        # (the line after this one is the important one)
       +                        *ProductVersion*) temp=.;;
       +                        *)
       +                                # check if the script is reading the derired line, if not
       +                                # don't do anything
       +                                [ "$temp" ] || continue
       +                                # Remove everything before and including the first '>'
       +                                ID=${line#*>}
       +                                # Remove the other side of the XML tag, and insert the actual OS name
       +                                ID="MacOS ${ID%<*}"
       +                                # We got the info we want, end the loop.
       +                                break
       +                esac
       +        done < "$v"
       +fi
       +
       +eq "$0" '*fetish' && printf 'Step on me daddy\n' && exit
       +
       +# help i dont know if it's a capital consistently
       +eq "$wm" '*[Gg][Nn][Oo][Mm][Ee]*' && wm='foot DE'
       +
       +## GTK
       +while read -r line; do
       +        eq "$line" 'gtk-theme*' && gtk=${line##*=} && break
       +done < "${XDG_CONFIG_HOME:=$HOME/.config}/gtk-3.0/settings.ini"
       +
       +# Shorten $cpu and $vendor
       +# this is so messy due to so many inconsistencies in the model names
       +vendor=${vendor##*Authentic}
       +vendor=${vendor##*Genuine}
       +cpu=${cpu##*) }
       +cpu=${cpu%% @*}
       +cpu=${cpu%% CPU}
       +cpu=${cpu##CPU }
       +cpu=${cpu##*AMD }
       +cpu=${cpu%% with*}
       +cpu=${cpu% *-Core*}
       +
       +col() {
       +        printf '  '
       +        for i in 1 2 3 4 5 6; do
       +                printf '\033[9%sm%s' "$i" "${colourblocks:-▅▅}"
       +        done
       +        printf '\033[0m\n'
       +}
       +
       +print() {
       +        [ "$2" ] && printf '\033[9%sm%6s\033[0m%b%s\n' \
       +                "${accent:-4}" "$1" "${separator:- ~ }" "$2"
       +}
       +
       +# default value
       +: "${info:=n user os sh wm up gtk cpu mem host kern pkgs term col n}"
       +
       +for i in $info; do
       +        case $i in
       +                n) echo;;
       +                os) print os "$ID";;
       +                sh) print sh "${SHELL##*/}";;
       +                wm) print wm "${wm##*/}";;
       +                up) print up "$up";;
       +                gtk) print gtk "${gtk# }";;
       +                cpu) print cpu "$vendor$cpu";;
       +                mem) print mem "$mem";;
       +                host) print host "$model";;
       +                kern) print kern "$kernel";;
       +                pkgs) print pkgs "$pkgs";;
       +                term) print term "$term";;
       +                user) printf '%7s@%s\n' "$USER" "$host";;
       +                col) col;;
       +        esac
       +done
 (DIR) diff --git a/bin/link-handler b/bin/link-handler
       @@ -24,10 +24,10 @@ case "$uri_lower" in
                        $gopher "$uri" &
                        ;;
                magnet:*)
       -                $launcher "$torrent" "$uri" &
       +                $torrent "$uri" &
                        ;;
                *.pdf | *.ps | *.epub)
       -                $launcher "$pdf" "$uri"
       +                $pdf "$uri"
                        ;;
                *.jpg | *.jpe | *.jpeg | *.png | *.gif | *.webp)
                        echo "in"
       @@ -35,6 +35,6 @@ case "$uri_lower" in
                        wget -qO- $uri | $images -
                        ;;
                *)
       -                $launcher "$BROWSER" "$uri"
       +                $BROWSER "$uri"
                        ;;
        esac
 (DIR) diff --git a/bin/pass b/bin/pass
       @@ -1,279 +0,0 @@
       -#!/bin/sh -e
       -#
       -# https://romanzolotarev.com/bin/pass
       -# copyright 2018 roman zolotarev <hi@romanzolotarev.com>
       -# copyright 2019-2022 romanzolotarev.com ou <hi@romanzolotarev.com>
       -#
       -# permission to use, copy, modify, and/or distribute this software for any
       -# purpose with or without fee is hereby granted, provided that the above
       -# copyright notice and this permission notice appear in all copies.
       -#
       -# the software is provided "as is" and the author disclaims all warranties
       -# with regard to this software including all implied warranties of
       -# merchantability and fitness. in no event shall the author be liable for
       -# any special, direct, indirect, or consequential damages or any damages
       -# whatsoever resulting from loss of use, data or profits, whether in an
       -# action of contract, negligence or other tortious action, arising out of
       -# or in connection with the use or performance of this software.
       -#
       -
       -fail() { echo "$1"; exit 1; }
       -should_exist() { if [ ! -f "$1" ]; then fail "Can't find $1."; fi; }
       -should_not_exist() { if [ -f "$1" ]; then fail "$1 already exists."; fi; }
       -should_be_dir() { if [ ! -d "$1" ]; then fail "$1 is not a directory."; fi; }
       -should_be_defined() { if [ ! "$1" ]; then fail "$2 should be defined."; fi; }
       -
       -
       -keygen() {
       -  private_key="$1"
       -  public_key="$2"
       -  should_be_defined "$private_key" "Private key path"
       -  should_be_defined "$public_key" "Public key path"
       -  should_not_exist "$private_key"
       -  should_be_dir "$(dirname "$private_key")"
       -  should_not_exist "$public_key"
       -  should_be_dir "$(dirname "$public_key")"
       -
       -  echo 'Generating public/private key pair.'
       -
       -  printf 'New pass phrase: '; stty -echo; read -r pass; stty echo; printf '\n'
       -  if [ ! "$pass" ]; then fail 'The pass phrase cannot be empty.'; fi
       -  printf 'Confirm: '; stty -echo; read -r pass_confirm; stty echo; printf '\n'
       -
       -  if [ "$pass" = "$pass_confirm" ]; then
       -    openssl genrsa 2048 |
       -      openssl pkcs8 -topk8 -inform pem -outform pem -out "$private_key" -v2 aes256 -passout "pass:$pass"
       -    chmod 0400 "$private_key"
       -    openssl rsa -in "$private_key" -out "$public_key" -outform pem -pubout -passin "pass:$pass"
       -    chmod 0600 "$public_key"
       -  else
       -    fail 'Pass phrase mismatch.'
       -  fi
       -}
       -
       -
       -passphrase() {
       -  private_key="$1"
       -  should_be_defined "$private_key" "Private key path"
       -  should_exist "$private_key"
       -
       -  echo "Changing $private_key pass phrase."
       -
       -  printf 'Current pass phrase: '; stty -echo; read -r pass; stty echo; printf '\n'
       -  printf 'New pass phrase: '; stty -echo; read -r new_pass; stty echo; printf '\n'
       -  if [ ! "$new_pass" ]; then fail 'The pass phrase cannot be empty.'; fi
       -  printf 'Confirm: '; stty -echo; read -r new_pass_confirm; stty echo; printf '\n'
       -
       -  if [ "$new_pass" = "$new_pass_confirm" ]; then
       -    chmod 0600 "$private_key" &&
       -    openssl rsa -aes256 -in "$private_key" -out "$private_key" -passin "pass:$pass" -passout "pass:$new_pass" 2>/dev/null ||
       -      fail 'Pass phrase change failed.' &&
       -      { echo 'Pass phrase changed.'; chmod 0400 "$private_key"; }
       -  else
       -    fail 'Pass phrase mismatch.'
       -  fi
       -}
       -
       -
       -encrypt() {
       -  public_key="$1"
       -  data_file="$2"
       -  should_be_defined "$data_file" "Data file path"
       -  enc_file="$data_file.enc"
       -  key_file="$data_file.key"
       -  base_dir="$(dirname "$data_file")"
       -  should_be_dir "$base_dir"
       -  should_exist "$public_key"
       -  should_not_exist "$enc_file"
       -  should_not_exist "$key_file"
       -
       -  key=$(openssl rand -base64 180)
       -  cleartext="$(cat)"
       -  dir=$(dirname "$data_file"); mkdir -p "$dir"; chmod 0700 "$dir"
       -
       -  echo "$key" |
       -    openssl rsautl -encrypt -pubin -inkey "$public_key" |
       -      openssl enc -md md5 -base64 -out "$key_file" >/dev/null 2>&1 ||
       -      fail 'Encryption failed.'
       -
       -  echo "$cleartext" |
       -    openssl enc -md md5 -aes-256-cbc -base64 -salt -k "$key" -out "$enc_file"
       -
       -  cleartext=''
       -  key=''
       -
       -  tar cf "$data_file" -C "$base_dir" "$(basename "$key_file")" "$(basename "$enc_file")"
       -  rm "$key_file" "$enc_file"
       -  chmod 0600 "$data_file"
       -}
       -
       -
       -sign() {
       -  private_key="$1"
       -  data_file="$2"
       -  pass="$3"
       -  should_be_defined "$data_file" "Data file path"
       -  signature="$data_file.sig"
       -  base_dir="$(dirname "$data_file")"
       -  should_be_dir "$base_dir"
       -  should_exist "$private_key"
       -  should_exist "$data_file"
       -
       -  if [ ! "$pass" ]; then
       -    if ! openssl dgst -sha256 -sign "$private_key" -out "$signature" "$data_file" 2>/dev/null; then
       -      rm "$signature"
       -      fail 'Signing failed.'
       -    fi
       -  else
       -    if ! openssl dgst -sha256 -passin "pass:$pass" -sign "$private_key" -out "$signature" "$data_file" 2>/dev/null; then
       -      rm "$signature"
       -      fail 'Signing failed.'
       -    fi
       -  fi
       -
       -  chmod 0600 "$signature"
       -}
       -
       -
       -decrypt() {
       -  private_key="$1"
       -  data_file="$2"
       -  pass="$3"
       -  should_be_defined "$private_key" "Private key path"
       -  should_be_defined "$data_file" "Data file path"
       -  enc_file="$data_file.enc"
       -  key_file="$data_file.key"
       -  should_exist "$private_key"
       -  should_exist "$data_file"
       -
       -  base_dir="$(dirname "$data_file")"
       -  tar xf "$data_file" -C "$base_dir"
       -  if [ ! "$pass" ]; then
       -    key=$(openssl enc -d -base64 -in "$key_file"|openssl rsautl -decrypt -inkey "$private_key" 2>/dev/null)
       -  else
       -    key=$(openssl enc -d -base64 -in "$key_file"|openssl rsautl -passin "pass:$pass" -decrypt -inkey "$private_key" 2>/dev/null)
       -  fi
       -  openssl enc -md md5 -aes-256-cbc -d -base64 -k "$key" -in "$enc_file" 2>/dev/null
       -  rm "$key_file" "$enc_file"
       -}
       -
       -verify () {
       -  public_key="$1"
       -  data_file="$2"
       -  signature="$data_file.sig"
       -  should_exist "$public_key"
       -  should_exist "$data_file"
       -  should_exist "$signature"
       -
       -  if ! openssl dgst -sha256 -verify "$public_key" -signature "$signature" "$data_file" >/dev/null 2>&1; then
       -    fail 'Invalid signature.'
       -  fi
       -}
       -
       -if [ ! "$PASS_BASE_DIR" ]; then PASS_BASE_DIR="$HOME/.pass"; fi
       -if [ ! "$PASS_PRIVATE_KEY" ]; then PASS_PRIVATE_KEY="$PASS_BASE_DIR/.key"; fi
       -if [ ! "$PASS_PUBLIC_KEY" ]; then PASS_PUBLIC_KEY="$PASS_BASE_DIR/.key.pub"; fi
       -if [ "$2" ]; then ID="$2"; fi
       -if [ "$3" ]; then PASS="$3"; fi
       -
       -
       -case "$1" in
       -
       -passphrase)
       -  passphrase "$PASS_PRIVATE_KEY"
       -  ;;
       -
       -
       -init)
       -  mkdir -p "$(dirname "$PASS_PRIVATE_KEY")"; chmod 0700 "$(dirname "$PASS_PRIVATE_KEY")"
       -  mkdir -p "$(dirname "$PASS_PUBLIC_KEY")"; chmod 0700 "$(dirname "$PASS_PUBLIC_KEY")"
       -  keygen "$PASS_PRIVATE_KEY" "$PASS_PUBLIC_KEY"
       -  ;;
       -
       -add)
       -  should_be_defined "$ID" "id"
       -  should_not_exist "$PASS_BASE_DIR/$ID"
       -  printf 'Pass phrase: '; stty -echo; read -r pass; stty echo; printf '\n'
       -  if [ ! "$pass" ]; then fail 'The pass phrase cannot be empty.'; fi
       -  openssl rand -base64 10 |
       -    openssl dgst -sha256 -passin "pass:$pass" -sign "$PASS_PRIVATE_KEY" >/dev/null 2>&1 ||
       -    fail 'Invalid pass phrase.'
       -  echo 'Press Enter and CTRL-D to complete.'
       -  encrypt "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
       -  sign "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID" "$pass"
       -  ;;
       -
       -import)
       -  should_be_defined "$ID" "id"
       -  should_not_exist "$PASS_BASE_DIR/$ID"
       -  encrypt "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
       -  sign "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID" "$PASS"
       -  ;;
       -
       -show)
       -  should_be_defined "$ID" "id"
       -  verify "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
       -  cleartext="$(decrypt "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID")"
       -  echo "$cleartext"|head -n1
       -  totp_seed="$(echo "$cleartext"|grep 'totp: '|head -n1|cut -d' ' -f2)"
       -  if [ "$totp_seed" ]; then
       -    if oathtool --version >/dev/null 2>&1; then
       -      oathtool --totp -b "$totp_seed"
       -    else
       -      echo 'oathtool(1) should be installed'
       -    fi
       -  fi
       -  ;;
       -
       -export)
       -  should_be_defined "$ID" "id"
       -  verify "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
       -  decrypt "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID" "$PASS"
       -  ;;
       -
       -ls)
       -  cd "$PASS_BASE_DIR"
       -  find . \( -type f \
       -    -name "${ID}"\* \
       -    \! -name \*.enc \
       -    \! -name \*.key \
       -    \! -name \*.sig \
       -    \! -name \.key \
       -    \! -name \.key.pub \
       -    \! -path \*/.git/\* \) | cut -f2 -d'/' | sort
       -  ;;
       -
       -edit)
       -  should_be_defined "$ID" "id"
       -  # verify "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
       -  cleartext_file="$PASS_BASE_DIR/$ID.cleartext"
       -  cleartext=$(decrypt "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID")
       -  touch "$cleartext_file"; chmod 0600 "$cleartext_file"
       -  echo "$cleartext" > "$cleartext_file"
       -  ${EDITOR:-$(which vi)} "$cleartext_file"
       -  after=$(cat "$cleartext_file")
       -  rm "$cleartext_file"
       -  if [ "$(echo "$cleartext"|openssl dgst -r -sha256)" = "$(echo "$after"|openssl dgst -r -sha256)" ]; then
       -    echo "No changes in $ID"
       -  else
       -    echo "$after"|encrypt "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
       -    sign "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID"
       -  fi
       -  ;;
       -
       -*)
       -  echo 'usage: export PASS_BASE_DIR=~/.pass'
       -  echo '       export PASS_PRIVATE_KEY=~/.pass/.key'
       -  echo '       export PASS_PUBLIC_KEY=~/.pass/.key.pub'
       -  echo
       -  echo '       pass init'
       -  echo '          | passphrase'
       -  echo '          | add        id'
       -  echo '          | import     id <pass>'
       -  echo '          | show       id'
       -  echo '          | export     id <pass>'
       -  echo '          | ls        <id>'
       -  exit 1
       -  ;;
       -
       -esac
 (DIR) diff --git a/bootstrap.sh b/bootstrap.sh
       @@ -2,9 +2,9 @@
        
        DOTFILES=$(pwd)
        
       -FILES='kshrc profile Xdefaults Xresources'
       +FILES='kshrc profile Xdefaults xsession'
        ROOT='bin'
       -CONFIG='git lynx mpd mutt ncmpcpp newsraft nvim'
       +CONFIG='git lynx mpd mutt ncmpcpp nvim isync'
        
        link() {
                for f in $FILES; do ln -sfn "$DOTFILES/$f" "$HOME/.$f"; done
 (DIR) diff --git a/isync/mbsyncrc b/isync/mbsyncrc
       @@ -0,0 +1,24 @@
       +Create Both
       +Expunge Both
       +Remove Both
       +Sync All
       +SyncState *
       +
       +IMAPAccount jay
       +Host imap.mailbox.org
       +User me@jay.scot
       +PassCmd "pass tech/mailbox.org | head -n1"
       +TLSType IMAPS
       +
       +IMAPStore jay-remote
       +Account jay
       +
       +MaildirStore jay-local
       +SubFolders Verbatim
       +Path ~/.mail/jay/
       +Inbox ~/.mail/jay/Inbox
       +
       +Channel jay
       +Far :jay-remote:
       +Near :jay-local:
       +Patterns *
 (DIR) diff --git a/kshrc b/kshrc
       @@ -17,9 +17,7 @@ export PATH=$PATH:$HOME/bin
        export OPENER=~/bin/link-handler
        
        # pass
       -export PASS_BASE_DIR=~/src/pass
       -export PASS_PRIVATE_KEY=~/src/pass/.key
       -export PASS_PUBLIC_KEY=~/src/pass/.key.pub
       +export PASSWORD_STORE_DIR=$HOME/src/pass
        
        # lynx
        export LYNX_CFG=$HOME/.config/lynx/config
       @@ -44,7 +42,6 @@ alias gma='git commit -am'
        alias vim='nvim'
        alias mutt='neomutt'
        alias mpv="mpv --autofit=30% --really-quiet --no-terminal"
       -alias w="w3m -B"
        
        # vpn
        alias von='mullvad ~/.config/mullvad/se-mma-wg-111.conf'
 (DIR) diff --git a/mpd/mpd.conf b/mpd/mpd.conf
       @@ -1,19 +1,14 @@
        music_directory                "/home/jay/media/music"
        playlist_directory         "/home/jay/.config/mpd/playlists"
       -db_file                 "/home/jay/.config/mpd/mpd.db"
       +db_file                         "/home/jay/.config/mpd/mpd.db"
        log_file                   "syslog"
       -pid_file                 "/home/jay/.config/mpd/mpd.pid"
       -state_file                 "/home/jay/.config/mpd/mpdstate"
       +pid_file                         "/home/jay/.config/mpd/mpd.pid"
       +state_file                         "/home/jay/.config/mpd/mpdstate"
        
        audio_output {
       -        type "pulse"
       -        name "pulse audio"
       -}
       -audio_output {
       -    type                    "fifo"
       -    name                    "my_fifo"
       -    path                    "/tmp/mpd.fifo"
       -    format                  "44100:16:2"
       +        type "sndio"
       +        name "sndio output"
       +        mixer_type "software"
        }
        
        bind_to_address "127.0.0.1"
 (DIR) diff --git a/mutt/muttrc b/mutt/muttrc
       @@ -1,44 +1,28 @@
        # info
       -set imap_user = 'me@jay.scot'
       -set imap_pass = `pass tech/mailbox.org | head -n1`
       -set realname = 'Jay Scott'
       -set from = 'me@jay.scot'
       -
       -# smtp settings
       -set smtp_pass = $imap_pass
       -set smtp_url = smtps://$imap_user@smtp.mailbox.org
       -set ssl_force_tls = yes
       -
       -# imap settings
       -set spoolfile ="imaps://imap.mailbox.org/"
       -set folder = $spoolfile
       -set postponed = "+Drafts"
       -set record = "+Sent"
       -set trash = "+Trash"
       -set folder=imaps://imap.mailbox.org/
       -set imap_check_subscribed
       +set realname        = 'Jay Scott'
       +set from                = 'me@jay.scot'
        
        # general
       -set envelope_from = yes
       -set use_from = yes
       -set editor = "nvim"
       -set markers = no
       -set mark_old = no
       -set delete = yes
       -set forward_format = "Fwd: %s"
       -set fcc_attach = no
       -set edit_headers = yes
       -set fast_reply = yes
       -set include = yes
       +set envelope_from        = yes
       +set use_from                = yes
       +set editor                        = "nvim"
       +set markers                 = no
       +set mark_old                 = no
       +set delete                        = yes
       +set forward_format        = "Fwd: %s"
       +set fcc_attach                 = no
       +set edit_headers        = yes
       +set fast_reply                = yes
       +set include                        = yes
        
        # gpg encryption
        source ~/.config/mutt/gpg.rc
        bind compose p pgp-menu
       -set pgp_use_gpg_agent = yes
       -set pgp_sign_as = 0726AF07C73389E1E4475B7EC88BBC696A39CCB0
       -set pgp_timeout = 3600
       -set crypt_autosign = no
       -set crypt_replyencrypt = yes
       +set pgp_use_gpg_agent         = yes
       +set pgp_sign_as                 = 0726AF07C73389E1E4475B7EC88BBC696A39CCB0
       +set pgp_timeout                 = 3600
       +set crypt_autosign                 = no
       +set crypt_replyencrypt         = yes
        
        # html emails
        auto_view text/html
       @@ -49,11 +33,20 @@ unset wait_key
        unset allow_8bit
        
        # paths
       -set header_cache = ~/.cache/mutt/headers
       -set message_cachedir = ~/.cache/mutt/bodies
       -set mailcap_path = ~/.config/mutt/mailcap
       -set alias_file = ~/.config/mutt/aliases
       -set tmpdir = ~/.cache/
       +set folder           = ~/.mail
       +set header_cache     = ~/.config/mutt/cache/headers
       +set message_cachedir = ~/.config/mutt/cache/bodies
       +set mailcap_path     = ~/.config/mutt/mailcap
       +set alias_file              = ~/.config/mutt/aliases
       +set tmpdir           = ~/.cache/
       +
       +set spoolfile        = "+jay/Inbox"
       +set postponed   = "+jay/Drafts"
       +set record      = "+jay/Sent"
       +
       +# inbox
       +mailboxes ! `echo ~/.mail/jay/*`
       +
        set sort_alias = alias
        set reverse_alias = yes
        source $alias_file
       @@ -63,20 +56,24 @@ bind index g noop
        bind index gg first-entry
        bind index G last-entry
        bind index <space> collapse-thread
       -macro index A "<save-message>=Keep<enter><enter><sync-mailbox><enter>" "save to archive"
       +macro index \Cr "T~U<enter><tag-prefix><clear-flag>N<untag-pattern>.<enter>" "mark all messages as read"
       +macro index o "<shell-escape>mbsync -a -c \"$XDG_CONFIG_HOME\"/isync/mbsyncrc<enter>" "run isync to sync all mail"
       +macro index C "<copy-message>?<toggle-mailboxes>" "copy a message to a mailbox"
       +macro index A "<save-message>=jay/archive<enter><enter><sync-mailbox><enter>" "save to archive"
       +macro index M "<save-message>?<toggle-mailboxes>" "move a message to a mailbox"
        
        # sorting
       -set sort = threads
       -set sort_aux = reverse-date
       -set pager_index_lines = 15
       -set pager_context = 1
       -set index_format = '%Z | %{%b %d %Y} | %-15.15F | %s'
       +set sort                                = threads
       +set sort_aux                        = reverse-date
       +set pager_index_lines        = 15
       +set pager_context                = 1
       +set index_format                = '%Z | %{%b %d %Y} | %-15.15F | %s'
        
        # sidebar
       -set mail_check_stats = yes
       -set sidebar_visible = yes
       -set sidebar_width = 25
       -set sidebar_short_path = yes
       +set mail_check_stats         = yes
       +set sidebar_visible         = yes
       +set sidebar_width         = 25
       +set sidebar_short_path         = yes
        set sidebar_folder_indent = yes
        set sidebar_format = "%B%* %?N?%N?"
        set sidebar_divider_char = │
       @@ -86,11 +83,57 @@ bind index,pager <backtab> sidebar-prev
        bind index,pager \Cl sidebar-open
        
        # disable help menu
       -set help = no
       +set help                 = no
        
        # status bar
        set sidebar_delim_chars = "/"
       -set status_chars = " *%A"
       -set status_format = "───[ Folder: %f ]───[%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]───%>─%?p?( %p postponed )?───"
       +set status_chars          = " *%A"
       +set status_format         = "───[ Folder: %f ]───[%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]───%>─%?p?( %p postponed )?───"
       +
       +# default
       +#color normal color223 color0
       +
       +# status bar
       +#color status color8 color0
       +
       +# highlight bar
       +#color indicator        color223 color237
       +
       +# replied to
       +color index color2 color0 ~Q
       +
       +# email info header
       +#color header color11 color0 "^(To:|From:|Date:|^Subject:)"
       +
       +# web links
       +color body color2 color0 "https?://[^ ]+"
       +color body color2 color0 "www.[^ ]+"
       +
       +# email addresss
       +color body color2 color0 "[-a-z_0-9.%$]+@[-a-z_0-9.]+\\.[-a-z][-a-z]+"
       +color body color2 color0 "mailto:[-a-z_0-9.]+@[-a-z_0-9.]+"
       +
       +# image links
       +color body color2 color0 "\\[image\\ [0-9]+\\]"
       +
       +# sidebar
       +#color sidebar_new bold color11 color0
       +color sidebar_divider bold color2 color0
       +
       +# patch syntax
       +color body brightwhite default ^[[:space:]].*
       +color body brightwhite default ^(diff).*
       +#color body white default ^[\-\-\-].*
       +color body white default ^[\+\+\+].*
       +color body green default ^[\+].*
       +color body red default ^[\-].*
       +color body brightblue default [@@].*
       +color body brightwhite default ^(\s).*
       +color body brightwhite default ^(Signed-off-by).*
       +color body brightwhite default ^(Cc)
        
       -source ~/.config/mutt/theme
       +ignore *
       +unignore from date subject to cc
       +unignore x-mailer
       +unignore x-spam-status
       +unignore x-spam-report
 (DIR) diff --git a/newsraft/config b/newsraft/config
       @@ -1,9 +0,0 @@
       -# settings
       -set open-in-browser-command ~/bin/link-handler "%l"
       -set clean-database-on-startup  true
       -
       -set menu-feed-sorting unread-desc
       -set menu-item-sorting unread-desc
       -
       -# key bindings
       -bind f exec "~/bin/link-handler %l"
 (DIR) diff --git a/newsraft/feeds b/newsraft/feeds
       @@ -1,19 +0,0 @@
       -@ TECH
       -https://noted.lol/rss/ "Noted"
       -https://selfh.st/rss/ "Selfh"
       -https://planet.kernel.org/rss20.xml "Planet Kernel"
       -https://bearblog.dev/discover/feed/ "Bear Blogs"
       -
       -@ MEDIA
       -https://showrss.info/other/all.rss "TV Torrents"
       -
       -@ PEOPLE
       -https://codemadness.org/atom.xml "CodeMadness"
       -https://drewdevault.com/blog/index.xml "Drew DeVault"
       -http://joeyh.name/blog/index.rss "Joey H"
       -https://www.uninformativ.de/blog/feeds/en.atom "Uninformativ"
       -https://fabiensanglard.net/rss.xml "Fabiensanglard"
       -https://pluralistic.net/feed/ "Pluralistic"
       -https://k0.tel/feed.xml "Koutsie"
       -https://labnotes.org/rss/ "Lab Notes"
       -https://www.jeffgeerling.com/blog.xml "Jeff Geerling"
 (DIR) diff --git a/pkg.list b/pkg.list
       @@ -0,0 +1,20 @@
       +colorls--
       +firefox--
       +git--
       +hack-fonts--
       +htop--
       +isync--
       +lf--
       +lynx--
       +mpd--
       +mpv--
       +ncmpcpp--
       +neomutt--gpgme-sasl
       +neovim--
       +ntfs_3g--
       +obsdfreqd--
       +password-store--
       +qbittorrent--
       +quirks--
       +terminus-font--
       +wireguard-tools--
 (DIR) diff --git a/suckless/slstatus/config.h b/suckless/slstatus/config.h
       @@ -1,7 +1,7 @@
        /* See LICENSE file for copyright and license details. */
        
        /* interval between updates (in ms) */
       -const unsigned int interval = 1000;
       +const unsigned int interval = 60000;
        
        /* text to show if no value can be retrieved */
        static const char unknown_str[] = "n/a";
       @@ -66,6 +66,6 @@ static const char unknown_str[] = "n/a";
        static const struct arg args[] = {
                /* function format          argument */
                { run_command, "VPN:%4s | ", "if curl -s https://am.i.mullvad.net/connected | grep -q 'server'; then echo 'On'; else echo 'Off'; fi" },
       -        // { run_command, "VOL:%4s | ", "pactl list sinks | tr ' ' '\n' | grep -m1 '%'" },
       -        { datetime, "%s",            "%T" },
       +        { vol_perc, "VOL:%s | ", NULL },
       +        { datetime, "%s", "%H:%M" },
        };
 (DIR) diff --git a/xenodm/Xsetup_0 b/xenodm/Xsetup_0
       @@ -1,7 +1,15 @@
        #!/bin/sh
        # $OpenBSD: Xsetup_0.in,v 1.1 2021/08/30 15:38:27 matthieu Exp $
        
       -xrandr --output default --dpi 96
       +prefix="/usr/X11R6"
       +exec_prefix="${prefix}"
       +extmon=$(${exec_prefix}/bin/xrandr | /usr/bin/awk '/DP-2-2/ { print $2 }')
       +
       +if [ "$extmon" = "connected" ]; then
       +            ${exec_prefix}/bin/xrandr --output DP-2-2 --auto --output eDP-1 --off
       +fi
       +
       +${exec_prefix}/bin/xrandr --output default --dpi 96
        
        # set background
       -/usr/X11R6/bin/xsetroot -solid black
       +${exec_prefix}/bin/xsetroot -solid black
 (DIR) diff --git a/xsession b/xsession
       @@ -0,0 +1,10 @@
       +# x settings
       +xset -b
       +xsetroot -solid black
       +
       +# apps
       +slstatus &
       +mpd &
       +
       +# window manager
       +exec dwm