# 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)

```bash
$ 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

```bash
#!/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

```bash
#!/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

```bash
#!/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

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

### Example 2: View Recent Logs

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

### Example 3: Create Manual Snapshot

```bash
# 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)

```bash
#!/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):**

```bash
# /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
