swarm repositories / source
aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/install-local.sh82
1 files changed, 82 insertions, 0 deletions
diff --git a/scripts/install-local.sh b/scripts/install-local.sh
index b087f70..b60027e 100755
--- a/scripts/install-local.sh
+++ b/scripts/install-local.sh
@@ -3,9 +3,18 @@ set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SKILL_SOURCE_ROOT="${ROOT_DIR}/assets/codex-skills"
+SYSTEMD_TEMPLATE_ROOT="${ROOT_DIR}/assets/systemd"
LOCAL_ROOT="${1:-$HOME/.local}"
SKILL_DEST_ROOT="${2:-$HOME/.codex/skills}"
LOCAL_BIN_DIR="${LOCAL_ROOT}/bin"
+SYSTEMD_USER_DIR="${HOME}/.config/systemd/user"
+UI_SERVICE_NAME="${FIDGET_SPINNER_UI_SERVICE_NAME:-fidget-spinner-libgrid-ui.service}"
+UI_PROJECT_ROOT="${FIDGET_SPINNER_UI_PROJECT:-$HOME/programming/projects/libgrid/.worktrees/libgrid-lp-oracle-cutset}"
+UI_BIND="${FIDGET_SPINNER_UI_BIND:-127.0.0.1:8913}"
+
+escape_sed_replacement() {
+ printf '%s' "$1" | sed -e 's/[\\/&]/\\&/g'
+}
install_skill_link() {
local name="$1"
@@ -17,6 +26,78 @@ install_skill_link() {
printf 'installed skill symlink: %s -> %s\n' "${dest_dir}" "${source_dir}"
}
+listener_pid_for_bind() {
+ local bind="$1"
+ local port="${bind##*:}"
+ ss -ltnp "( sport = :${port} )" 2>/dev/null \
+ | sed -n 's/.*pid=\([0-9]\+\).*/\1/p' \
+ | head -n 1
+}
+
+evict_conflicting_navigator() {
+ local pid
+ pid="$(listener_pid_for_bind "${UI_BIND}")"
+ if [[ -z "${pid}" ]]; then
+ return 0
+ fi
+ local cmd
+ cmd="$(ps -p "${pid}" -o args= || true)"
+ if [[ "${cmd}" == *"fidget-spinner-cli ui serve"* ]]; then
+ kill "${pid}"
+ for _ in {1..20}; do
+ if ! kill -0 "${pid}" 2>/dev/null; then
+ printf 'stopped conflicting navigator process: pid=%s\n' "${pid}"
+ return 0
+ fi
+ sleep 0.1
+ done
+ printf 'failed to stop conflicting navigator process: pid=%s\n' "${pid}" >&2
+ return 1
+ fi
+ printf 'refusing to steal %s from non-spinner process: %s\n' "${UI_BIND}" "${cmd}" >&2
+ return 1
+}
+
+install_libgrid_ui_service() {
+ if [[ ! -d "${UI_PROJECT_ROOT}" ]]; then
+ printf 'libgrid navigator root does not exist: %s\n' "${UI_PROJECT_ROOT}" >&2
+ return 1
+ fi
+ if ! command -v systemctl >/dev/null 2>&1; then
+ printf 'systemctl unavailable; skipping navigator service install\n' >&2
+ return 0
+ fi
+
+ local service_path="${SYSTEMD_USER_DIR}/${UI_SERVICE_NAME}"
+ local template_path="${SYSTEMD_TEMPLATE_ROOT}/${UI_SERVICE_NAME}.in"
+ mkdir -p "${SYSTEMD_USER_DIR}"
+ sed \
+ -e "s|@HOME@|$(escape_sed_replacement "${HOME}")|g" \
+ -e "s|@LOCAL_BIN_DIR@|$(escape_sed_replacement "${LOCAL_BIN_DIR}")|g" \
+ -e "s|@UI_PROJECT_ROOT@|$(escape_sed_replacement "${UI_PROJECT_ROOT}")|g" \
+ -e "s|@UI_BIND@|$(escape_sed_replacement "${UI_BIND}")|g" \
+ "${template_path}" > "${service_path}"
+ chmod 0644 "${service_path}"
+ printf 'installed user service: %s\n' "${service_path}"
+
+ export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
+ if [[ -z "${DBUS_SESSION_BUS_ADDRESS:-}" && -S "${XDG_RUNTIME_DIR}/bus" ]]; then
+ export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"
+ fi
+ if ! systemctl --user daemon-reload; then
+ printf 'systemd user manager unavailable; skipping navigator service activation\n' >&2
+ return 0
+ fi
+ evict_conflicting_navigator
+ if systemctl --user is-enabled --quiet "${UI_SERVICE_NAME}"; then
+ systemctl --user restart "${UI_SERVICE_NAME}"
+ printf 'restarted user service: %s\n' "${UI_SERVICE_NAME}"
+ else
+ systemctl --user enable --now "${UI_SERVICE_NAME}"
+ printf 'enabled user service: %s\n' "${UI_SERVICE_NAME}"
+ fi
+}
+
mkdir -p "${LOCAL_BIN_DIR}"
cargo build --release -p fidget-spinner-cli --manifest-path "${ROOT_DIR}/Cargo.toml"
@@ -28,5 +109,6 @@ printf 'installed binary: %s\n' "${LOCAL_BIN_DIR}/fidget-spinner-cli"
install_skill_link "fidget-spinner"
install_skill_link "frontier-loop"
+install_libgrid_ui_service
printf 'mcp command: %s\n' "${LOCAL_BIN_DIR}/fidget-spinner-cli mcp serve"