Files
omarchy-sc/integrations/omarchy/citizenctl
T
2026-08-31 22:20:17 +02:00

520 lines
20 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -u
PLUGIN_ID="local.omarchy-citizen"
PLUGIN_VERSION="1.0.0"
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
PLUGIN_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
SELF="$(readlink -f "${BASH_SOURCE[0]}")"
STATE_DIR="$XDG_STATE_HOME/citizen-launcher"
CACHE_DIR="$XDG_CACHE_HOME/citizen-launcher"
DATA_DIR="$XDG_DATA_HOME/citizen-launcher"
LOG_FILE="$STATE_DIR/omarchy-citizen.log"
UPDATER_LOG="$STATE_DIR/updater.log"
RSI_LOG="$STATE_DIR/rsi-launcher.log"
SANITIZER="$PLUGIN_DIR/support-sanitize.py"
BACKEND_EXTERNAL="$HOME/.local/lib/citizen-launcher/citizen-launcher"
BACKEND_BUNDLED="$PLUGIN_DIR/backend/bin/citizen-launcher"
MANAGED_LUG="$DATA_DIR/vendor/lug-helper/lug-helper.appimage"
MANAGED_WINE="$DATA_DIR/vendor/wine/current"
mkdir -p "$STATE_DIR" "$CACHE_DIR"
ACTION="${1:-status}"
rotate_log() {
local max=$((4 * 1024 * 1024)) keep=$((2 * 1024 * 1024)) size=0
if [[ -f "$LOG_FILE" ]]; then
size="$(stat -c '%s' "$LOG_FILE" 2>/dev/null || echo 0)"
if (( size > max )); then
tail -c "$keep" "$LOG_FILE" > "$LOG_FILE.tmp" 2>/dev/null || true
mv -f "$LOG_FILE.tmp" "$LOG_FILE" 2>/dev/null || true
fi
fi
}
log_line() {
printf '%s [%s] %s\n' "$(date '+%Y-%m-%dT%H:%M:%S%z')" "$$" "$*" >>"$LOG_FILE" 2>/dev/null || true
}
rotate_log
log_line "action=$ACTION version=$PLUGIN_VERSION"
notify() {
local title="$1" body="$2"
if command -v omarchy-notification-send >/dev/null 2>&1; then
omarchy-notification-send "$title" "$body" >/dev/null 2>&1 || true
elif command -v notify-send >/dev/null 2>&1; then
notify-send "$title" "$body" >/dev/null 2>&1 || true
fi
}
notify_error() {
local body="$1"
log_line "error=$body"
if command -v zenity >/dev/null 2>&1; then
zenity --error --width=560 --title="Citizen Launcher" --text="$body" >/dev/null 2>&1 || true
else
notify "Citizen Launcher" "$body"
printf 'Citizen Launcher: %s\n' "$body" >&2
fi
}
find_backend() {
if [[ -x "$BACKEND_EXTERNAL" ]]; then
printf '%s\n' "$BACKEND_EXTERNAL"
elif [[ -x "$BACKEND_BUNDLED" ]]; then
printf '%s\n' "$BACKEND_BUNDLED"
else
return 1
fi
}
backend_exec() {
local backend
backend="$(find_backend)" || {
printf 'Go-Backend nicht gefunden. Plugin bitte neu installieren.\n' >&2
return 127
}
"$backend" "$@"
}
backend_game_status() { backend_exec game-status; }
backend_plugin_status() { backend_exec status; }
backend_game_install() { backend_exec game-install; }
backend_game_launch() { backend_exec game-launch; }
backend_game_repair() { backend_exec game-repair; }
autopilot_enable() { backend_exec autopilot enable; }
autopilot_maintain() { backend_exec maintain; }
wine_doctor() { backend_exec doctor; }
kv_get() {
local key="$1"
sed -n "s/^${key}=//p" | head -n1
}
status() {
local game="" plugin=""
local health="setup" hardware="unknown" hardware_reason="" gpu="" vulkan="unknown"
local prefix="missing" launcher="missing" game_state="missing" wine="" dxvk="" lug="" game_autopilot="false"
local backend_state="missing" backend_version="" managed="manual" auto_apply="false" auto_maintain="false"
local update="unavailable" local_commit="" remote_commit="" maintenance=""
if game="$(backend_game_status 2>/dev/null)"; then
health="$(printf '%s\n' "$game" | kv_get health)"
hardware="$(printf '%s\n' "$game" | kv_get hardware)"
hardware_reason="$(printf '%s\n' "$game" | kv_get hardware_reason)"
gpu="$(printf '%s\n' "$game" | kv_get gpu)"
vulkan="$(printf '%s\n' "$game" | kv_get vulkan)"
prefix="$(printf '%s\n' "$game" | kv_get prefix_state)"
launcher="$(printf '%s\n' "$game" | kv_get launcher_state)"
game_state="$(printf '%s\n' "$game" | kv_get game_state)"
wine="$(printf '%s\n' "$game" | kv_get wine_version)"
dxvk="$(printf '%s\n' "$game" | kv_get dxvk_version)"
lug="$(printf '%s\n' "$game" | kv_get lug_version)"
game_autopilot="$(printf '%s\n' "$game" | kv_get autopilot)"
fi
if plugin="$(backend_plugin_status 2>/dev/null)"; then
backend_state="ready"
backend_version="$(printf '%s\n' "$plugin" | kv_get backend_version)"
managed="$(printf '%s\n' "$plugin" | kv_get managed)"
auto_apply="$(printf '%s\n' "$plugin" | kv_get auto_apply)"
auto_maintain="$(printf '%s\n' "$plugin" | kv_get auto_maintain)"
update="$(printf '%s\n' "$plugin" | kv_get update)"
local_commit="$(printf '%s\n' "$plugin" | kv_get local_commit)"
remote_commit="$(printf '%s\n' "$plugin" | kv_get remote_commit)"
maintenance="$(printf '%s\n' "$plugin" | kv_get maintenance_result)"
fi
[[ -n "$health" ]] || health="setup"
[[ -n "$prefix" ]] || prefix="missing"
[[ -n "$launcher" ]] || launcher="missing"
[[ -n "$game_state" ]] || game_state="missing"
[[ -n "$hardware" ]] || hardware="unknown"
[[ -n "$vulkan" ]] || vulkan="unknown"
[[ -n "$update" ]] || update="unavailable"
printf 'plugin_version=%s\n' "$PLUGIN_VERSION"
printf 'health=%s\n' "$health"
printf 'deps=ready\n'
printf 'deps_missing=\n'
printf 'helper=%s\n' "$([[ -n "$lug" ]] && echo ready || echo missing)"
printf 'helper_managed=optional\n'
printf 'helper_version=%s\n' "$lug"
printf 'update=unknown\n'
printf 'update_version=\n'
printf 'prefix=%s\n' "$prefix"
printf 'prefix_detail=%s\n' "$([[ "$prefix" == partial ]] && echo unvollständig || true)"
printf 'launcher=%s\n' "$launcher"
printf 'game=%s\n' "$game_state"
printf 'backend=%s\n' "$backend_state"
printf 'backend_version=%s\n' "$backend_version"
printf 'plugin_managed=%s\n' "$managed"
printf 'plugin_auto=%s\n' "$auto_apply"
printf 'plugin_update=%s\n' "$update"
printf 'plugin_local_commit=%s\n' "$local_commit"
printf 'plugin_remote_commit=%s\n' "$remote_commit"
printf 'autopilot=%s\n' "$([[ "$auto_maintain" == true ]] && echo true || echo "$game_autopilot")"
printf 'managed_lug_version=%s\n' "$lug"
printf 'managed_wine_version=%s\n' "$wine"
printf 'managed_dxvk_version=%s\n' "$dxvk"
printf 'maintenance_result=%s\n' "$maintenance"
printf 'hardware=%s\n' "$hardware"
printf 'hardware_reason=%s\n' "$hardware_reason"
printf 'hardware_gpu=%s\n' "$gpu"
printf 'hardware_vulkan=%s\n' "$vulkan"
}
hardware_info() {
local game reason gpu vulkan
game="$(backend_game_status 2>/dev/null || true)"
reason="$(printf '%s\n' "$game" | kv_get hardware_reason)"
gpu="$(printf '%s\n' "$game" | kv_get gpu)"
vulkan="$(printf '%s\n' "$game" | kv_get vulkan)"
if command -v zenity >/dev/null 2>&1; then
zenity --warning --width=620 --title="Omarchy Citizen – Hardware" \
--text="<b>Star Citizen ist auf diesem System noch nicht spielbereit.</b>\n\nGPU:\n${gpu:-nicht erkannt}\n\nVulkan: ${vulkan:-unbekannt}\n\n${reason:-Hardware-Prüfung fehlgeschlagen.}" >/dev/null 2>&1 || true
else
printf 'GPU: %s\nVulkan: %s\n%s\n' "${gpu:-nicht erkannt}" "${vulkan:-unbekannt}" "${reason:-Hardware-Prüfung fehlgeschlagen.}"
fi
}
probe_detached_start() {
local label="$1"; shift
"$@" >>"$LOG_FILE" 2>&1 &
local pid=$! rc=0
sleep 0.35
if ! kill -0 "$pid" 2>/dev/null; then
wait "$pid" || rc=$?
if (( rc != 0 )); then
log_line "$label failed rc=$rc"
return "$rc"
fi
else
disown "$pid" 2>/dev/null || true
fi
log_line "$label accepted"
}
launch_terminal_action() {
local action="$1"
log_line "launch-terminal action=$action"
if command -v uwsm-app >/dev/null 2>&1 && command -v xdg-terminal-exec >/dev/null 2>&1; then
probe_detached_start "uwsm-xdg-terminal" setsid uwsm-app -- xdg-terminal-exec \
--app-id=org.omarchy.terminal --title="Citizen Launcher" -e bash "$SELF" "$action" && return 0
fi
if command -v xdg-terminal-exec >/dev/null 2>&1; then
probe_detached_start "xdg-terminal" xdg-terminal-exec --title="Citizen Launcher" -e bash "$SELF" "$action" && return 0
fi
if command -v omarchy-launch-floating-terminal-with-presentation >/dev/null 2>&1; then
probe_detached_start "omarchy-terminal" omarchy-launch-floating-terminal-with-presentation bash "$SELF" "$action" && return 0
fi
notify_error "Das Omarchy-Citizen-Terminal konnte nicht geöffnet werden. Bitte ein Support-Paket erstellen."
return 1
}
install_stack_terminal() {
set -Ee
exec > >(tee -a "$LOG_FILE") 2>&1
setup_failed() {
local rc=$?
trap - ERR
echo
echo "=================================================="
echo " SETUP KONNTE NICHT ABGESCHLOSSEN WERDEN"
echo "=================================================="
echo "Fehlercode: $rc"
echo "Alle Details wurden protokolliert. Im SC-Panel genügt 'Support-Paket erstellen'."
notify "Citizen Launcher" "Setup fehlgeschlagen. Bitte Support-Paket erstellen."
if [[ -t 0 ]]; then read -r -p "Drücke Enter zum Schließen … " _ || true; fi
exit "$rc"
}
trap setup_failed ERR
echo "=================================================="
echo " Omarchy Citizen – Spielbereit machen"
echo "=================================================="
echo
local game health reason
game="$(backend_game_status 2>/dev/null || true)"
health="$(printf '%s\n' "$game" | kv_get health)"
if [[ "$health" == "hardware-blocked" ]]; then
reason="$(printf '%s\n' "$game" | kv_get hardware_reason)"
echo "Hardware-Prüfung nicht bestanden:"
echo "${reason:-Keine Star-Citizen-taugliche Vulkan-GPU erkannt.}"
trap - ERR
return 2
fi
echo "1/4 Autopilot aktivieren und Gaming-Stack synchronisieren …"
autopilot_enable
echo
echo "2/4 Wine-Runner auf diesem Rechner prüfen …"
wine_doctor
echo
echo "3/4 Wine-Prefix, Komponenten und offiziellen RSI Launcher einrichten …"
backend_game_install
echo
echo "4/4 Wartungsstand abschließend synchronisieren …"
autopilot_maintain || true
trap - ERR
echo
echo "=================================================="
echo " SOFTWARE-STACK BEREIT"
echo "=================================================="
echo "Der offizielle RSI Launcher ist eingerichtet. Anmeldung und Spieldownload erfolgen dort."
notify "Citizen Launcher" "Software-Stack ist bereit. RSI Launcher kann gestartet werden."
}
repair_stack_terminal() {
set -Ee
exec > >(tee -a "$LOG_FILE") 2>&1
repair_failed() {
local rc=$?
trap - ERR
echo
echo "REPARATUR FEHLGESCHLAGEN (Code $rc)"
echo "Bitte im SC-Panel ein Support-Paket erstellen."
notify "Citizen Launcher" "Reparatur fehlgeschlagen. Bitte Support-Paket erstellen."
if [[ -t 0 ]]; then read -r -p "Drücke Enter zum Schließen … " _ || true; fi
exit "$rc"
}
trap repair_failed ERR
echo "Omarchy Citizen repariert den verwalteten Gaming-Stack …"
autopilot_maintain || true
backend_game_repair
wine_doctor
trap - ERR
echo "Reparatur abgeschlossen."
notify "Citizen Launcher" "Gaming-Stack wurde repariert."
}
update_stack_terminal() {
set -Ee
exec > >(tee -a "$LOG_FILE") 2>&1
echo "Synchronisiere Wine, DXVK, RSI Launcher und optionale Support-Werkzeuge …"
autopilot_maintain
echo "Gaming-Stack ist aktuell."
}
system_update_terminal() {
set -Ee
exec > >(tee -a "$LOG_FILE") 2>&1
if ! command -v omarchy >/dev/null 2>&1; then
echo "Omarchy-Befehl nicht gefunden." >&2
return 1
fi
echo "Starte den offiziellen Omarchy-Systemupdate-Pfad …"
omarchy update -y
}
primary_action() {
local game health
game="$(backend_game_status 2>/dev/null || true)"
health="$(printf '%s\n' "$game" | kv_get health)"
case "$health" in
hardware-blocked) hardware_info ;;
ready|install-game) backend_game_launch ;;
repair|launcher-repair) launch_terminal_action repair-stack-terminal ;;
*) launch_terminal_action install-stack-terminal ;;
esac
}
repair_assistant() {
launch_terminal_action repair-stack-terminal
}
plugin_update_check() { backend_exec check; }
plugin_update_now() { backend_exec update; }
plugin_auto_enable() { backend_exec auto enable; }
plugin_auto_disable() { backend_exec auto disable; }
open_file() {
local path="$1"
[[ -f "$path" ]] || { notify_error "Datei noch nicht vorhanden: $path"; return 1; }
xdg-open "$path" >/dev/null 2>&1 &
}
open_debug_log() { open_file "$LOG_FILE"; }
open_updater_log() { open_file "$UPDATER_LOG"; }
open_log() { open_file "$RSI_LOG"; }
open_wiki() { xdg-open "https://wiki.starcitizen-lug.org" >/dev/null 2>&1 & }
open_ngl_page() { xdg-open "https://www.nglproject.com/de#downloads" >/dev/null 2>&1 & }
open_helper() {
if [[ -x "$MANAGED_LUG" ]]; then
nohup env APPIMAGE_EXTRACT_AND_RUN=1 "$MANAGED_LUG" >>"$LOG_FILE" 2>&1 &
else
open_wiki
fi
}
sanitize_to() {
local source="$1" target="$2"
[[ -f "$source" ]] || return 0
if command -v python3 >/dev/null 2>&1 && [[ -f "$SANITIZER" ]]; then
python3 "$SANITIZER" <"$source" >"$target"
else
sed -e "s#${HOME//\#/\\#}#~#g" "$source" >"$target"
fi
}
capture_sanitized() {
local target="$1"; shift
local tmp="$CACHE_DIR/capture-$$-$RANDOM.txt"
"$@" >"$tmp" 2>&1 || true
sanitize_to "$tmp" "$target"
rm -f "$tmp"
}
support_build() {
local stamp support_id work downloads archive game_prefix=""
stamp="$(date '+%Y%m%d-%H%M%S')"
support_id="OC-${stamp}-$(printf '%s-%s-%s' "$stamp" "$$" "$RANDOM" | sha256sum | cut -c1-6)"
downloads="$(command -v xdg-user-dir >/dev/null 2>&1 && xdg-user-dir DOWNLOAD 2>/dev/null || true)"
[[ -n "$downloads" && -d "$downloads" ]] || downloads="$HOME/Downloads"
mkdir -p "$downloads"
work="$CACHE_DIR/support-$support_id"
rm -rf "$work" && mkdir -p "$work"
cat >"$work/README_SUPPORT.txt" <<SUPPORT
Omarchy Citizen Support-Paket
Support-ID: $support_id
Plugin-Version: $PLUGIN_VERSION
Erstellt: $(date '+%Y-%m-%d %H:%M:%S %z')
Das Paket enthält technische Diagnoseinformationen. Home-Pfad, Benutzername,
Hostname, E-Mail/IP/MAC und typische Token-/Sessionwerte werden beim Export
best-effort maskiert. Keine Browserdaten, SSH-Schlüssel oder Passwortdateien.
SUPPORT
status >"$work/citizen-status.txt" 2>&1 || true
capture_sanitized "$work/backend-game-status.txt" backend_exec game-status
capture_sanitized "$work/backend-status.txt" backend_exec status
capture_sanitized "$work/wine-doctor.txt" backend_exec doctor
if command -v omarchy >/dev/null 2>&1; then
capture_sanitized "$work/plugin-validation.txt" omarchy plugin validate "$PLUGIN_DIR"
if omarchy debug --no-sudo --print >"$CACHE_DIR/omarchy-debug-$$.txt" 2>&1; then
sanitize_to "$CACHE_DIR/omarchy-debug-$$.txt" "$work/omarchy-debug.txt"
else
{ omarchy version 2>/dev/null || true; omarchy commands --all 2>/dev/null || true; } >"$CACHE_DIR/omarchy-debug-$$.txt"
sanitize_to "$CACHE_DIR/omarchy-debug-$$.txt" "$work/omarchy-debug.txt"
fi
rm -f "$CACHE_DIR/omarchy-debug-$$.txt"
fi
{
echo "=== kernel ==="; uname -rmo 2>/dev/null || true
echo "=== memory ==="; free -h 2>/dev/null || true
echo "=== filesystems ==="; df -hT / "$HOME" 2>/dev/null || true
echo "=== gpu ==="; lspci -nnk 2>/dev/null | grep -A5 -Ei 'VGA|3D|Display' || true
echo "=== vulkan ==="; command -v vulkaninfo >/dev/null 2>&1 && vulkaninfo --summary 2>&1 || true
echo "=== limits ==="; sysctl vm.max_map_count 2>/dev/null || true; ulimit -Hn 2>/dev/null || true
} >"$CACHE_DIR/system-$$.txt"
sanitize_to "$CACHE_DIR/system-$$.txt" "$work/system.txt"
rm -f "$CACHE_DIR/system-$$.txt"
for pair in "$LOG_FILE:omarchy-citizen.log" "$UPDATER_LOG:updater.log" "$RSI_LOG:rsi-launcher.log"; do
local src="${pair%%:*}" dst="${pair#*:}"
if [[ -f "$src" ]]; then
tail -n 1800 "$src" >"$CACHE_DIR/log-$$.txt"
sanitize_to "$CACHE_DIR/log-$$.txt" "$work/$dst"
rm -f "$CACHE_DIR/log-$$.txt"
fi
done
game_prefix="$(backend_game_status 2>/dev/null | kv_get prefix || true)"
if [[ -n "$game_prefix" ]]; then
printf 'prefix=%s\n' "$game_prefix" >"$CACHE_DIR/prefix-$$.txt"
sanitize_to "$CACHE_DIR/prefix-$$.txt" "$work/prefix.txt"
rm -f "$CACHE_DIR/prefix-$$.txt"
fi
archive="$downloads/Omarchy-Citizen-Support-$support_id.tar.gz"
tar -C "$work" -czf "$archive" .
rm -rf "$work"
notify "Citizen Launcher" "Support-Paket erstellt: $(basename "$archive")"
command -v xdg-open >/dev/null 2>&1 && xdg-open "$downloads" >/dev/null 2>&1 &
printf '%s\n' "$archive"
}
ngl_info() {
local msg="NGL ist ein optionaler Community-Mod für den RSI Launcher. Omarchy Citizen installiert ihn nur nach deiner ausdrücklichen Dateiauswahl in den verwalteten Wine-Prefix."
if command -v zenity >/dev/null 2>&1; then
zenity --info --width=540 --title="Omarchy Citizen – NGL" --text="$msg" >/dev/null 2>&1 || true
else
printf '%s\n' "$msg"
fi
}
ngl_install() {
local game prefix selected exe workdir wine
command -v zenity >/dev/null 2>&1 || { notify_error "Für die NGL-Dateiauswahl wird zenity benötigt."; return 1; }
game="$(backend_game_status)"
prefix="$(printf '%s\n' "$game" | kv_get prefix)"
[[ -n "$prefix" && -d "$prefix/drive_c" ]] || { notify_error "Star Citizen muss zuerst eingerichtet werden."; return 1; }
wine="$(readlink -f "$MANAGED_WINE")/bin/wine"
[[ -x "$wine" ]] || { notify_error "Der verwaltete Wine-Runner fehlt."; return 1; }
selected="$(zenity --file-selection --title="NGL Installer auswählen" --filename="$HOME/Downloads/" \
--file-filter="NGL Installer | *.zip *.ZIP *.exe *.EXE" --file-filter="Alle Dateien | *" 2>/dev/null)" || return 0
[[ -f "$selected" ]] || return 1
exe="$selected"
if [[ "${selected,,}" == *.zip ]]; then
workdir="$CACHE_DIR/ngl-installer"
rm -rf "$workdir" && mkdir -p "$workdir"
unzip -q "$selected" -d "$workdir" || { notify_error "NGL-ZIP konnte nicht entpackt werden."; return 1; }
exe="$(find "$workdir" -type f -iname '*.exe' -print -quit)"
fi
[[ -n "$exe" && -f "$exe" ]] || { notify_error "Kein Windows-Installer gefunden."; return 1; }
zenity --question --width=560 --title="NGL experimentell installieren?" \
--ok-label="Installer starten" --cancel-label="Abbrechen" \
--text="NGL ist Community-Code und läuft im selben Wine-Prefix wie der RSI Launcher. Bitte nur Downloads von nglproject.com verwenden." 2>/dev/null || return 0
nohup env WINEPREFIX="$prefix" WINEDEBUG=-all "$wine" "$exe" >>"$LOG_FILE" 2>&1 &
}
case "$ACTION" in
status) status ;;
hardware-info) hardware_info ;;
primary) primary_action ;;
setup|install-stack) launch_terminal_action install-stack-terminal ;;
install-stack-terminal) install_stack_terminal ;;
repair|repair-interactive|recover-prefix) repair_assistant ;;
repair-stack-terminal|recover-prefix-terminal) repair_stack_terminal ;;
support|support-build) support_build ;;
debug-log) open_debug_log ;;
log) open_log ;;
updater-log) open_updater_log ;;
plugin-update-check|check-update) plugin_update_check ;;
plugin-update-now) plugin_update_now ;;
plugin-auto-enable) plugin_auto_enable ;;
plugin-auto-disable) plugin_auto_disable ;;
autopilot-enable) autopilot_enable ;;
autopilot-maintain|update-helper) launch_terminal_action update-stack-terminal ;;
update-stack-terminal|update-helper-terminal) update_stack_terminal ;;
wine-doctor) launch_terminal_action wine-doctor-terminal ;;
wine-doctor-terminal) set -e; wine_doctor ;;
system-update) launch_terminal_action system-update-terminal ;;
system-update-terminal) system_update_terminal ;;
launch) backend_game_launch ;;
helper) open_helper ;;
preflight) open_helper ;;
runners|dxvk) launch_terminal_action update-stack-terminal ;;
repair-launch|repair-rsi) launch_terminal_action repair-stack-terminal ;;
dirs) ( xdg-open "$DATA_DIR" >/dev/null 2>&1 & ) ;;
wiki) open_wiki ;;
ngl-page) open_ngl_page ;;
ngl-info) ngl_info ;;
ngl-install|ngl-install-interactive) ngl_install ;;
*) notify_error "Unbekannte Omarchy-Citizen-Aktion: $ACTION"; exit 2 ;;
esac