#!/usr/bin/env bash # # ustatus - Status dashboard for the Ultimate Notetaking System # # Shows status of all sync and backup systems. # # Usage: # ustatus - Show full status # ustatus brief - Show brief status set -euo pipefail # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' BOLD='\033[1m' NC='\033[0m' status_ok() { echo -e "${GREEN}●${NC} $1" } status_warn() { echo -e "${YELLOW}●${NC} $1" } status_error() { echo -e "${RED}●${NC} $1" } header() { echo -e "\n${BOLD}═══ $1 ═══${NC}" } # Check if a command exists has_cmd() { command -v "$1" &> /dev/null } brief_status() { echo -e "${BOLD}Ultimate Notetaking System Status${NC}" echo "" # nb if has_cmd nb; then notebook_count=$(nb notebooks --names 2>/dev/null | wc -l || echo 0) status_ok "nb: $notebook_count notebooks" else status_error "nb: not installed" fi # Syncthing if has_cmd syncthing && syncthing cli show system &> /dev/null 2>&1; then status_ok "Syncthing: running" elif has_cmd syncthing; then status_warn "Syncthing: not running" else status_error "Syncthing: not installed" fi # Backup if systemctl is-active restic-backup.timer &> /dev/null; then status_ok "Backup: timer active" elif has_cmd restic; then status_warn "Backup: timer not active" else status_error "Backup: restic not installed" fi } full_status() { echo -e "${BOLD}╔════════════════════════════════════════════════════════════╗${NC}" echo -e "${BOLD}║ Ultimate Notetaking, Sync & Backup System ║${NC}" echo -e "${BOLD}╚════════════════════════════════════════════════════════════╝${NC}" # ==================== TIER 1: Configuration ==================== header "TIER 1: Configuration" # Nix/NixOS if has_cmd nixos-rebuild; then generation=$(nixos-rebuild list-generations 2>/dev/null | head -1 | awk '{print $1}' || echo "?") status_ok "NixOS generation: $generation" fi if has_cmd nix; then nix_version=$(nix --version | head -1) status_ok "Nix: $nix_version" fi # Git if has_cmd git; then status_ok "Git: $(git --version | cut -d' ' -f3)" fi # ==================== TIER 2: Notes ==================== header "TIER 2: Notes (nb)" if has_cmd nb; then nb_version=$(nb version 2>/dev/null || echo "unknown") status_ok "nb version: $nb_version" echo "" echo "Notebooks:" nb_dir="${NB_DIR:-$HOME/.nb}" for notebook in $(nb notebooks --names 2>/dev/null || true); do if [ -d "$nb_dir/$notebook" ]; then note_count=$(find "$nb_dir/$notebook" -name "*.md" 2>/dev/null | wc -l) # Check if has remote if [ -d "$nb_dir/$notebook/.git" ]; then remote=$(git -C "$nb_dir/$notebook" remote get-url origin 2>/dev/null || echo "") if [ -n "$remote" ]; then last_sync=$(git -C "$nb_dir/$notebook" log -1 --format="%ar" 2>/dev/null || echo "never") echo -e " ${GREEN}●${NC} $notebook: $note_count notes, last sync: $last_sync" else echo -e " ${YELLOW}●${NC} $notebook: $note_count notes (no remote)" fi else echo -e " ${YELLOW}●${NC} $notebook: $note_count notes (not git repo)" fi fi done else status_error "nb not installed" fi # ==================== TIER 2: Syncthing ==================== header "TIER 2: File Sync (Syncthing)" if has_cmd syncthing; then if syncthing cli show system &> /dev/null 2>&1; then uptime=$(syncthing cli show system 2>/dev/null | jq -r '.uptime // 0' | awk '{printf "%dd %dh %dm", $1/86400, ($1%86400)/3600, ($1%3600)/60}') status_ok "Syncthing running (uptime: $uptime)" echo "" echo "Folders:" syncthing cli show config 2>/dev/null | jq -r '.folders[] | "\(.label // .id)|\(.path)"' 2>/dev/null | while IFS='|' read -r label path; do if [ -d "$path" ]; then file_count=$(find "$path" -type f 2>/dev/null | wc -l) echo -e " ${GREEN}●${NC} $label: $path ($file_count files)" else echo -e " ${YELLOW}●${NC} $label: $path (not found)" fi done || echo " Unable to list folders" echo "" echo "Devices:" syncthing cli show config 2>/dev/null | jq -r '.devices[] | "\(.name // .deviceID[:8])"' 2>/dev/null | while read -r device; do echo " ● $device" done || echo " Unable to list devices" else status_warn "Syncthing installed but not running" fi else status_error "Syncthing not installed" fi # ==================== TIER 3: Backup ==================== header "TIER 3: Backup (restic)" if has_cmd restic; then status_ok "restic: $(restic version | head -1)" # Check systemd timer if systemctl is-active restic-backup.timer &> /dev/null; then next_run=$(systemctl show restic-backup.timer --property=NextElapseUSecRealtime 2>/dev/null | cut -d= -f2) status_ok "Backup timer active (next: $next_run)" else status_warn "Backup timer not active" fi # Try to show recent snapshots (requires RESTIC_REPOSITORY to be set) if [ -n "${RESTIC_REPOSITORY:-}" ]; then echo "" echo "Recent snapshots:" restic snapshots --last 3 2>/dev/null | tail -n +3 | head -5 || echo " Unable to list snapshots" fi else status_error "restic not installed" fi # ==================== TIER 3: Services ==================== header "TIER 3: Services" # Check common services for service in forgejo immich jellyfin; do if systemctl is-active "$service" &> /dev/null 2>&1; then status_ok "$service: running" elif systemctl is-enabled "$service" &> /dev/null 2>&1; then status_warn "$service: enabled but not running" else echo -e " ${BLUE}○${NC} $service: not configured" fi done # ==================== Summary ==================== header "Quick Actions" echo " usync - Sync all (nb + Syncthing)" echo " ubackup now - Run backup immediately" echo " nb add - Create new note" echo "" } # Main case "${1:-full}" in brief|short|b) brief_status ;; full|"") full_status ;; -h|--help|help) echo "ustatus - System status dashboard" echo "" echo "Usage:" echo " ustatus Show full status" echo " ustatus brief Show brief status" echo " ustatus help Show this help" ;; *) echo "Unknown option: $1" echo "Run 'ustatus help' for usage" exit 1 ;; esac