1#!/usr/bin/env bash 2# (Re)start whiskersd as a transient user service that comes back if it dies. Transient means it 3# does not survive a reboot of the machine or WSL: run this again after one. 4# 5# WHISKERS_ADDR=<private-ip>:47900 WHISKERS_MODEL_URL=http://127.0.0.1:3456 \ 6# tools/run-whiskersd.sh [daily-voice-chars] (default 1000; ElevenLabs' free plan is about 330) 7# 8# Required: 9# WHISKERS_ADDR address to listen on. Bind a private-network address (a VPN), never 0.0.0.0. 10# WHISKERS_MODEL_URL the model gateway whiskersd proxies to (an Anthropic Messages API). 11# Optional: 12# WHISKERS_WRAP a command prefix that puts the secrets (TYPESAFE_API_KEY and, for the natural voice, 13# ELEVENLABS_API_KEY and ELEVENLABS_VOICE_ID) into the environment, e.g. 14# "op-env-run -e my-environment --". Unset: they must already be in the environment. 15# WHISKERS_BIN the whiskersd binary (default target/release/whiskersd). 16set -euo pipefail 17cd "$(dirname "$0")/.." 18chars="${1:-1000}" 19: "${WHISKERS_ADDR:?set WHISKERS_ADDR to the private address:port whiskersd listens on}" 20: "${WHISKERS_MODEL_URL:?set WHISKERS_MODEL_URL to the model gateway address}" 21bin="${WHISKERS_BIN:-$PWD/target/release/whiskersd}" 22[ -x "$bin" ] || { echo "build it first: cargo build --release -p whiskersd" >&2; exit 1; } 23systemctl --user stop whiskersd 2>/dev/null || true 24systemctl --user reset-failed whiskersd 2>/dev/null || true 25# WHISKERS_WRAP is split into words on purpose: it is a command prefix. 26# shellcheck disable=SC2086 27systemd-run --user --unit=whiskersd \ 28 --description="Whiskers service (Jev, ElevenLabs, model proxy)" \ 29 --property=Restart=always --property=RestartSec=3 \ 30 --setenv=WHISKERS_SPEAK_DAILY_CHARS="$chars" \ 31 --setenv=WHISKERS_MODEL_URL="$WHISKERS_MODEL_URL" \ 32 -- ${WHISKERS_WRAP:-} "$bin" "$WHISKERS_ADDR" 33sleep 6 34systemctl --user is-active whiskersd