dsc-rs 0.10.15

Discourse CLI tool for managing multiple Discourse forums: track installs, run upgrades over SSH, manage emojis, sync topics and categories as Markdown, and more.
Documentation
#!/usr/bin/env bash
#
# Serve the docs locally with hot-reload at http://localhost:8000.
#
# Requires `zensical` — install with `pip install -r requirements.txt`
# in a venv, then re-run this script with that venv activated (or
# invoke ./.venv/bin/zensical directly).
#
# Common gotcha on Linux: Zensical's watcher consumes inotify
# instances. The kernel default (128 per user) runs out quickly on
# a dev machine with editors and file-syncers already open. If you
# see `Too many open files` / inotify panics, raise the cap:
#
#     sudo sysctl fs.inotify.max_user_instances=512
#
# Persist it with:
#
#     echo 'fs.inotify.max_user_instances=512' \
#       | sudo tee /etc/sysctl.d/99-inotify.conf
#     sudo sysctl --system
#

set -euo pipefail

# Preflight: Zensical's watcher fails at inotify_init1 if the user's
# cap (fs.inotify.max_user_instances) is saturated by other running
# processes — typically VS Code, file syncers, etc. Count what's
# actually held and compare to the sysctl cap.
limit=$(sysctl -n fs.inotify.max_user_instances 2>/dev/null || echo 0)
held=$(find /proc -maxdepth 3 -user "$(id -u)" -name fd 2>/dev/null \
  | xargs -I{} ls -l {} 2>/dev/null \
  | grep -c 'anon_inode:inotify' || true)

if [[ "$limit" -gt 0 && "$held" -ge "$limit" ]]; then
  cat >&2 <<EOF
ERROR: no free inotify instances for Zensical's file watcher
  cap:  fs.inotify.max_user_instances = $limit
  held: $held (by existing processes in your user session)

Fix (this session):
  sudo sysctl fs.inotify.max_user_instances=$(( limit * 2 < 512 ? 512 : limit * 2 ))

Persist across reboots:
  echo 'fs.inotify.max_user_instances=512' | sudo tee /etc/sysctl.d/99-inotify.conf
  sudo sysctl --system

Then re-run $0.
EOF
  exit 1
fi

# Non-fatal: getting close to the cap — warn but proceed.
if [[ "$limit" -gt 0 && "$held" -ge $(( limit - 4 )) ]]; then
  echo >&2 "warning: only $(( limit - held )) free inotify instances (cap $limit, held $held)"
  echo >&2 "         if Zensical panics with \"Too many open files\", raise the cap:"
  echo >&2 "           sudo sysctl fs.inotify.max_user_instances=$(( limit * 2 ))"
  echo >&2
fi

exec zensical serve "$@"