clawdie-iso/ADMIN-PANEL.md
Sam & Claude c47cd44251 Add .prettierrc + reformat all active markdown to match
Codifies the markdown format Sam applied in bd94b87 / 30cf590 as a
project rule rather than per-file judgment. Prettier 3 defaults with
proseWrap=preserve (no prose reflow), printWidth=80, embedded code
formatting off so we don't touch fenced shell/JSON blocks.

.prettierignore scopes Prettier to active docs:
  - excludes tmp/, cache/, node_modules/, build artifacts
  - excludes CHANGELOG.md + RELEASE-NOTES-*.md (hand-formatted, rigid)
  - excludes .archive/ and .opencode/ (historical / tooling internal)
  - excludes bundled bootstrap.html

Reformatted 16 active .md files: padded markdown tables, blank line
before lists (CommonMark-strict), `*emph*` -> `_emph_`. No content
changes — diffs are all whitespace/alignment/emphasis style.

Verified: `npx prettier@3 --check '**/*.md'` reports all clean.

Build: not run — docs + tooling config only.
Tests: pass — prettier --check is green; git diff confirms no content
deletions, only formatting.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 11:16:42 +02:00

22 KiB

Clawdie Admin Panel — System Management UI

Purpose: bsddialog-based system administration interface for Clawdie desktop users

Philosophy: Pure shell + bsddialog (no external GUI toolkits), inspired by PC-BSD warden's CLI approach


Overview

clawdie-admin is a lightweight terminal UI that lets users manage:

  • Clawdie service — start/stop, view status
  • Jails — list, start/stop, open console (jexec)
  • ZFS snapshots — create, list, restore (inspired by Life-Preserver)
  • System health — CPU, RAM, disk usage, pool status
  • Logs — tail service and jail logs
  • Configuration — change assistant name, timezone, LLM provider

Entry Points

1. Desktop Launcher / Panel Entry

Right-click system tray
  └─ "Clawdie Admin"
      └─ Launches /usr/local/bin/clawdie-admin

2. CLI (Terminal)

$ clawdie-admin
# Opens interactive menu

3. Desktop Launcher

Launch ~/.local/share/applications/clawdie-admin.desktop from the desktop or file manager.


Menu Structure

Main Menu

┌─ Clawdie Admin Panel ──────────────────────────────────────┐
│                                                             │
│  Quick Status                                               │
│  ├─ Clawdie service:    ✓ Running (pid 42315)              │
│  ├─ ZFS pool (zroot):   15.2 GB / 100 GB (15% used)        │
│  ├─ Memory:             2.3 GB / 8.0 GB (29%)              │
│  ├─ CPU Load:           0.24 (1 min avg)                   │
│  ├─ Audio:              ✓ OSS (Intel HDA)                  │
│  └─ Network:            ✓ em0 (DHCP, 192.168.1.100)        │
│                                                             │
│  [  System Health  ]  [  Jails  ]  [  Snapshots  ]          │
│  [  Hardware  ]       [  Config  ]  [  Quit  ]              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

System Health Submenu

┌─ System Health ────────────────────────────────────────┐
│                                                        │
│  CPU  Load                                             │
│  │   1-min: 0.24                                      │
│  │   5-min: 0.18                                      │
│  │   15-min: 0.12                                     │
│  │                                                    │
│  Memory Usage                                         │
│  │   Used: 2.3 GB                                     │
│  │   Free: 5.7 GB                                     │
│  │   Cache: 0.8 GB                                    │
│  │                                                    │
│  ZFS Pool: zroot                                      │
│  │   Used: 15.2 GB                                    │
│  │   Free: 84.8 GB                                    │
│  │   Pool health: ✓ ONLINE                            │
│  │                                                    │
│  Clawdie Service                                      │
│  │   Status: ✓ Running                                │
│  │   PID: 42315                                       │
│  │   Memory: 145 MB                                   │
│  │                                                    │
│  [  Back  ]                                            │
│                                                        │
└────────────────────────────────────────────────────────┘

Hardware Submenu

┌─ Hardware Detection ───────────────────────────────────────┐
│                                                            │
│  Audio Card                                                │
│  │   Device: Intel HDA (pci0:27:0:0)                      │
│  │   Status: ✓ Working (OSS)                              │
│  │   Mixer: /dev/mixer0                                   │
│  │                                                         │
│  Network Interfaces                                        │
│  │   em0: Ethernet (DHCP) — 192.168.1.100                │
│  │   re0: Ethernet (not configured)                       │
│  │   Wireless: None detected                              │
│  │   Note: WiFi firmware can be installed post-boot       │
│  │                                                         │
│  Other Devices                                             │
│  │   USB: 3 devices detected                              │
│  │   Bluetooth: Not found (optional feature, v1.0+)       │
│  │                                                         │
│  [  Configure Audio  ]  [  Network Setup  ]  [  Back  ]    │
│                                                            │
└────────────────────────────────────────────────────────────┘

Post-Install Suggestions:

If WiFi detected but no firmware:

⚠️ WiFi Device Detected: Intel AC 8260
→ Install firmware: sudo pkg install iwm-firmware-8260
→ Then restart: sudo service netif restart

If audio not working:

⚠️ No audio output detected
→ Check: cat /dev/sndstat
→ Install: pkg install snd-hda-generic (for Intel/AMD)
→ Install: pkg install snd-usb-audio (for USB headsets)

Jails Submenu

┌─ Clawdie Jails ────────────────────────────────────────┐
│                                                        │
│  (N) Name      Status     Process Count   IP Address  │
│  1) worker     Running    4               10.0.0.101  │
│  2) db         Running    ✓ Healthy       10.0.0.102  │
│  3) cms        Running    ✓ Ready         10.0.0.103  │
│  4) mgmt       Stopped    --              10.0.0.104  │
│                                                        │
│  Manage jail:                                          │
│  [  Boot All  ]  [  Stop All  ]  [  Back  ]            │
│                                                        │
│  Select jail number (1-4) to manage:                  │
│  >_                                                    │
│                                                        │
└────────────────────────────────────────────────────────┘

# After selecting jail (e.g., "1" for worker):

┌─ Jail: worker ──────────────────────────────────────────┐
│                                                         │
│  Status:       ✓ Running                               │
│  IPv4:         10.0.0.101                              │
│  PID:          42350                                   │
│  Memory:       234 MB                                  │
│                                                         │
│  [  Start  ]  [  Stop  ]  [  Restart  ]                │
│  [  Console (jexec)  ]  [  Back  ]                     │
│                                                         │
└─────────────────────────────────────────────────────────┘

Snapshots Submenu

┌─ ZFS Snapshots ────────────────────────────────────────┐
│                                                        │
│  Snapshot Management                                   │
│  [  Create Snapshot  ]                                 │
│  [  List Snapshots  ]                                  │
│  [  Restore Snapshot  ]                                │
│                                                        │
│  Auto-Backup Status                                    │
│  │   Last backup: 2026-03-23 18:45 UTC                │
│  │   Interval: Daily at 02:00                         │
│  │   Retention: 7 days                                │
│  │   Status: ✓ Enabled                                │
│                                                        │
│  [  Back  ]                                            │
│                                                        │
└────────────────────────────────────────────────────────┘

# After selecting "List Snapshots":

┌─ ZFS Snapshots on zroot ──────────────────────────────┐
│                                                        │
│  Snapshot                    Created        Size       │
│  zroot@auto-2026-03-23       2026-03-23 02:00  2.3 GB  │
│  zroot@auto-2026-03-22       2026-03-22 02:00  2.1 GB  │
│  zroot@manual-20260323_1842  2026-03-23 18:42  1.8 GB  │
│  zroot@manual-20260323_1200  2026-03-23 12:00  1.7 GB  │
│                                                        │
│  Total snapshots: 4                                    │
│  Total space: 7.9 GB                                   │
│                                                        │
│  Select snapshot to restore: (or press Back)           │
│  >_                                                    │
│                                                        │
└────────────────────────────────────────────────────────┘

# After selecting snapshot:

┌─ Restore zroot@manual-20260323_1842 ──────────────────┐
│                                                        │
│  ⚠ WARNING: This will rollback ZFS to the snapshot     │
│  point. All changes since creation will be lost.       │
│                                                        │
│  Created:    2026-03-23 18:42 UTC                      │
│  Size:       1.8 GB                                    │
│  Systems affected: postgres, apps                      │
│                                                        │
│  [  Confirm Restore  ]  [  Cancel  ]                   │
│                                                        │
└────────────────────────────────────────────────────────┘

Logs Submenu

┌─ System Logs ──────────────────────────────────────────┐
│                                                        │
│  View logs from:                                       │
│  [  Clawdie Service (syslog)  ]                        │
│  [  Clawdie Service (stdout/stderr)  ]                 │
│  [  Worker Jail Console  ]                             │
│  [  Database Jail Console  ]                           │
│  [  System Messages (/var/log/messages)  ]             │
│                                                        │
│  [  Back  ]                                            │
│                                                        │
└────────────────────────────────────────────────────────┘

# After selecting log:

┌─ Clawdie Service Log (last 50 lines) ──────────────────┐
│                                                        │
│  [2026-03-23 23:15:22] Agent startup complete         │
│  [2026-03-23 23:15:21] Jails ready: worker, db, cms  │
│  [2026-03-23 23:15:18] PostgreSQL health check: OK    │
│  [2026-03-23 23:15:15] Nginx config validated         │
│  ...                                                   │
│  [2026-03-23 23:15:01] rc.d clawdie service start    │
│                                                        │
│  [  Refresh  ]  [  Tail (follow mode)  ]  [  Back  ]  │
│                                                        │
└────────────────────────────────────────────────────────┘

Config Submenu

┌─ Configuration ────────────────────────────────────────┐
│                                                        │
│  Current Settings                                      │
│  ├─ Assistant Name:  Clawdie                           │
│  ├─ Domain:         clawdie.local                      │
│  ├─ Timezone:       Europe/Ljubljana                   │
│  ├─ LLM Provider:   Anthropic                          │
│  └─ Telegram:       ✓ Configured                       │
│                                                        │
│  [  Change Assistant Name  ]                           │
│  [  Change Timezone  ]                                 │
│  [  Change LLM Provider  ]                             │
│  [  Export .env  ]                                     │
│  [  View .env (sensitive)  ]                           │
│  [  Back  ]                                            │
│                                                        │
└────────────────────────────────────────────────────────┘

Implementation (clawdie-admin.sh)

File Locations

/usr/local/bin/clawdie-admin           ← wrapper script (user-callable)
/usr/local/libexec/clawdie-admin.sh    ← main menu logic (sourced)
/usr/local/libexec/clawdie-lib-admin.sh ← helper functions (jail, snap, log ops)

Wrapper Script

#!/bin/sh
# /usr/local/bin/clawdie-admin

# Make sure we're running as clawdie user (or via sudo for root ops)
if [ "$(id -u)" != 1001 ]; then
  # If run as root, switch to clawdie user
  if [ "$(id -u)" = 0 ]; then
    exec su - clawdie -c "clawdie-admin"
  fi
  echo "Error: must run as clawdie user or root"
  exit 1
fi

# Source main menu
. /usr/local/libexec/clawdie-admin.sh

# Start menu
clawdie_admin_main_menu

Main Menu Function

#!/bin/sh
# /usr/local/libexec/clawdie-admin.sh

. /usr/local/libexec/clawdie-lib-admin.sh

clawdie_admin_main_menu() {
  while true; do
    # Refresh status each iteration
    STATUS=$(clawdie_admin_quick_status)

    CHOICE=$(bsddialog --title "Clawdie Admin Panel" \
      --menu "Quick Status:\n$STATUS" 20 70 0 \
      "1" "System Health" \
      "2" "Jails" \
      "3" "Snapshots" \
      "4" "Logs" \
      "5" "Configuration" \
      "0" "Quit" \
      2>&1 >/dev/tty)

    case $CHOICE in
      1) clawdie_admin_health ;;
      2) clawdie_admin_jails ;;
      3) clawdie_admin_snapshots ;;
      4) clawdie_admin_logs ;;
      5) clawdie_admin_config ;;
      0) break ;;
      *)  ;;
    esac
  done
}

clawdie_admin_quick_status() {
  # Returns 4-line status string for main menu display

  # Check if clawdie service running
  if service clawdie status > /dev/null 2>&1; then
    PID=$(service clawdie status | grep -oP 'pid \K\d+' || echo "?")
    SERVICE_STATUS="✓ Running (pid $PID)"
  else
    SERVICE_STATUS="✗ Stopped"
  fi

  # ZFS pool usage
  POOL_USAGE=$(zfs list -H -o used,available zroot 2>/dev/null | awk '{
    used = $1 / 1024 / 1024 / 1024
    avail = $2 / 1024 / 1024 / 1024
    total = used + avail
    pct = int(used / total * 100)
    printf "%.1f GB / %.1f GB (%d%%)", used, total, pct
  }')

  # Memory usage
  MEM=$(free -m | grep "^Mem:" | awk '{
    used = $3
    total = $2
    pct = int(used / total * 100)
    printf "%.1f GB / %.1f GB (%d%%)", used/1024, total/1024, pct
  }')

  # CPU load
  LOAD=$(uptime | sed 's/.*load average: //' | awk '{print $1}')

  echo "Clawdie: $SERVICE_STATUS"
  echo "ZFS pool (zroot): $POOL_USAGE"
  echo "Memory: $MEM"
  echo "CPU Load: $LOAD (1 min)"
}

Helper Library Functions

#!/bin/sh
# /usr/local/libexec/clawdie-lib-admin.sh

# Jail operations
clawdie_jail_list() {
  jls -N name hostname state ip4.addr 2>/dev/null | grep -E "^(worker|db|cms|mgmt)" || echo "No jails found"
}

clawdie_jail_status() {
  local jail=$1
  jls -j "$jail" state 2>/dev/null || echo "unknown"
}

clawdie_jail_start() {
  local jail=$1
  service jail onestart "$jail" 2>&1 | tail -5
}

clawdie_jail_stop() {
  local jail=$1
  service jail onestop "$jail" 2>&1 | tail -5
}

clawdie_jail_console() {
  local jail=$1
  jexec "$jail" /bin/sh
}

# ZFS operations
clawdie_snapshot_create() {
  local label=$1
  local snapshot="zroot@manual-$(date +%Y%m%d_%H%M)"
  zfs snapshot "$snapshot" 2>&1
  echo "Created: $snapshot"
}

clawdie_snapshot_list() {
  zfs list -t snapshot -r zroot 2>/dev/null | grep "^zroot" || echo "No snapshots"
}

clawdie_snapshot_restore() {
  local snapshot=$1
  bsddialog --title "Confirm Restore" \
    --yesno "Restore $snapshot? This will rollback all changes since creation." 0 0

  if [ $? -eq 0 ]; then
    zfs rollback "$snapshot" 2>&1 | head -20
    echo "Rollback complete. System restart recommended."
  fi
}

# Log operations
clawdie_log_service() {
  tail -50 /var/log/clawdie.log 2>/dev/null || echo "No log found"
}

clawdie_log_jail() {
  local jail=$1
  jexec "$jail" tail -50 /var/log/messages 2>/dev/null || echo "No jail log"
}

# Config operations
clawdie_config_read_env() {
  # Read current .env without exposing secrets
  grep -E "^(ASSISTANT_NAME|AGENT_DOMAIN|TZ|LLM_PROVIDER)" \
    /home/clawdie/clawdie-ai/.env 2>/dev/null || echo "Config not found"
}

clawdie_config_change_name() {
  bsddialog --title "Change Assistant Name" \
    --inputbox "Enter new assistant name:" 0 0 "$CURRENT_NAME" 2>&1 | \
    xargs -I {} sed -i '' "s/^ASSISTANT_NAME=.*/ASSISTANT_NAME={}/" \
    /home/clawdie/clawdie-ai/.env
}

Usage Examples

Example 1: Start Worker Jail

# User: Jails → select "1" (worker) → [Start]
clawdie_jail_start worker
# Output: "Jail worker started"

Example 2: View Recent Logs

# User: Logs → [Clawdie Service] → shows tail -50 /var/log/clawdie.log
tail -50 /var/log/clawdie.log

Example 3: Create Manual Snapshot

# User: Snapshots → [Create Snapshot]
clawdie_snapshot_create "manual"
# Output: "Created: zroot@manual-20260323_2145"

Desktop Integration

Tray Applet

Binary: /usr/local/libexec/clawdie-tray-applet (shell script)

#!/bin/sh
# Updates tray icon every 5 seconds

RUNNING_ICON="/usr/local/share/icons/clawdie-running.png"
STOPPED_ICON="/usr/local/share/icons/clawdie-stopped.png"

while true; do
  if service clawdie status > /dev/null 2>&1; then
    echo "ICON:$RUNNING_ICON"
    echo "LABEL:Clawdie"
  else
    echo "ICON:$STOPPED_ICON"
    echo "LABEL:Clawdie (offline)"
  fi
  sleep 5
done

Right-click binding: Exec=/usr/local/bin/clawdie-admin


Permissions & Security

User (clawdie) Operations

  • Jail status queries: via jls (unprivileged)
  • Logs: read /var/log/clawdie.log (user-owned)
  • Config: read .env (user-owned)

Privileged Operations (via sudo)

  • Jail start/stop: requires root via sudo service jail ...
  • ZFS snapshot/rollback: requires root via sudo zfs ...
  • System restart: requires root via sudo shutdown ...

sudo Setup (automatic in firstboot.sh):

# /usr/local/etc/sudoers.d/clawdie-admin
# Clawdie admin operations
%wheel ALL=(ALL) NOPASSWD: /usr/local/libexec/clawdie-lib-admin.sh
%wheel ALL=(ALL) NOPASSWD: /usr/sbin/service
%wheel ALL=(ALL) NOPASSWD: /usr/sbin/zfs
%wheel ALL=(ALL) NOPASSWD: /usr/sbin/jail
%wheel ALL=(ALL) NOPASSWD: /usr/bin/killall

Accessibility

  • Keyboard navigation: bsddialog supports tab/arrow keys, Enter
  • High contrast: Inherits the active desktop theme settings
  • No mouse required: All functions accessible via keyboard
  • Screen reader: Standard bsddialog output readable by screen readers

Performance Considerations

  • Startup: <200 ms (pure shell, no Java/Python startup overhead)
  • Refresh rate: 5-second poll for status (minimal CPU)
  • Memory: <5 MB footprint
  • Concurrency: Lock file prevents multiple instances (/tmp/clawdie-admin.lock)

Testing Checklist

  • clawdie-admin launches from the desktop tray or launcher
  • clawdie-admin launches from terminal
  • System Health displays correct CPU/memory/disk stats
  • Jails submenu lists all jails (worker, db, cms)
  • Can toggle jail start/stop with sudo confirmation
  • Can open jail console via jexec
  • Snapshots create/list/restore work with sudo
  • Logs display correctly (tailed, not truncated)
  • Config display matches current .env
  • No secrets logged to console
  • Multiple concurrent instances prevented (lock file)
  • Menu navigation works with keyboard only

Future Enhancements

  1. Backup scheduling UI — configure daily/weekly backups
  2. Network config — change IP addresses, DNS
  3. Service management — start/stop nginx, PostgreSQL within jails
  4. Metrics export — export system stats to Grafana
  5. Terminal multiplexing — tmux split for multiple jails open simultaneously