|
| 1 | +#!/usr/bin/env bash |
| 2 | +# |
| 3 | +# Post-extract helper for the Skiller tar.xz Linux build. |
| 4 | +# |
| 5 | +# Why this exists: Electron's setuid sandbox wants `chrome-sandbox` owned by |
| 6 | +# root with mode 4755. .deb and AppImage builds handle this automatically |
| 7 | +# (postinst / runtime respectively); the tar.xz has no install step, so we |
| 8 | +# ship this script to do the same dance on demand. |
| 9 | +# |
| 10 | +# Usage (from inside the extracted directory): |
| 11 | +# ./install.sh |
| 12 | +# |
| 13 | +# What it does: |
| 14 | +# 1. Sets SUID on chrome-sandbox (needs sudo). |
| 15 | +# 2. Writes a `.desktop` entry pointing at the local `skiller` binary so |
| 16 | +# the app appears in your app launcher. |
| 17 | +# 3. Copies the icon into `~/.local/share/icons`. |
| 18 | +# |
| 19 | +# To undo everything, run `./install.sh --uninstall`. |
| 20 | +set -euo pipefail |
| 21 | + |
| 22 | +APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 23 | +BIN="$APP_DIR/skiller" |
| 24 | +SANDBOX="$APP_DIR/chrome-sandbox" |
| 25 | +ICON_SRC="$APP_DIR/resources/app.asar.unpacked/assets/icons/app/icon-512.png" |
| 26 | +DESKTOP_DIR="$HOME/.local/share/applications" |
| 27 | +DESKTOP_FILE="$DESKTOP_DIR/skiller.desktop" |
| 28 | +ICON_DIR="$HOME/.local/share/icons" |
| 29 | +ICON_DEST="$ICON_DIR/skiller.png" |
| 30 | + |
| 31 | +if [[ ! -x "$BIN" ]]; then |
| 32 | + echo "error: $BIN not found or not executable — run this script from inside the extracted Skiller directory" >&2 |
| 33 | + exit 1 |
| 34 | +fi |
| 35 | + |
| 36 | +if [[ "${1:-}" == "--uninstall" ]]; then |
| 37 | + rm -f "$DESKTOP_FILE" "$ICON_DEST" |
| 38 | + echo "✓ removed $DESKTOP_FILE and $ICON_DEST" |
| 39 | + echo " (chrome-sandbox SUID bit is harmless — left in place)" |
| 40 | + exit 0 |
| 41 | +fi |
| 42 | + |
| 43 | +# 1) chrome-sandbox SUID — needs root |
| 44 | +if [[ -f "$SANDBOX" ]]; then |
| 45 | + current_mode=$(stat -c '%a' "$SANDBOX" 2>/dev/null || stat -f '%Lp' "$SANDBOX") |
| 46 | + current_owner=$(stat -c '%U' "$SANDBOX" 2>/dev/null || stat -f '%Su' "$SANDBOX") |
| 47 | + if [[ "$current_mode" != "4755" || "$current_owner" != "root" ]]; then |
| 48 | + echo "→ setting SUID on $SANDBOX (needs sudo)…" |
| 49 | + sudo chown root:root "$SANDBOX" |
| 50 | + sudo chmod 4755 "$SANDBOX" |
| 51 | + else |
| 52 | + echo "✓ chrome-sandbox already configured" |
| 53 | + fi |
| 54 | +fi |
| 55 | + |
| 56 | +# 2) Desktop entry |
| 57 | +mkdir -p "$DESKTOP_DIR" |
| 58 | +cat > "$DESKTOP_FILE" <<EOF |
| 59 | +[Desktop Entry] |
| 60 | +Name=Skiller |
| 61 | +Comment=Manage AI agent skills across Claude Code, Cursor, Copilot, and more |
| 62 | +Exec="$BIN" %U |
| 63 | +Icon=skiller |
| 64 | +Terminal=false |
| 65 | +Type=Application |
| 66 | +Categories=Development; |
| 67 | +StartupWMClass=Skiller |
| 68 | +EOF |
| 69 | +echo "✓ wrote $DESKTOP_FILE" |
| 70 | + |
| 71 | +# 3) Icon |
| 72 | +if [[ -f "$ICON_SRC" ]]; then |
| 73 | + mkdir -p "$ICON_DIR" |
| 74 | + cp "$ICON_SRC" "$ICON_DEST" |
| 75 | + echo "✓ wrote $ICON_DEST" |
| 76 | +else |
| 77 | + echo "! icon source not found at $ICON_SRC — skipping (app will use a fallback icon)" |
| 78 | +fi |
| 79 | + |
| 80 | +# Best-effort: ask the DE to refresh its caches. No error if the tools aren't |
| 81 | +# installed — the .desktop file still works on next login. |
| 82 | +if command -v update-desktop-database >/dev/null 2>&1; then |
| 83 | + update-desktop-database -q "$DESKTOP_DIR" || true |
| 84 | +fi |
| 85 | +if command -v gtk-update-icon-cache >/dev/null 2>&1; then |
| 86 | + gtk-update-icon-cache -q -t "$ICON_DIR" 2>/dev/null || true |
| 87 | +fi |
| 88 | + |
| 89 | +echo |
| 90 | +echo "All set. Launch Skiller from your app menu, or run: \"$BIN\"" |
0 commit comments