#!/bin/sh
# Install the coauthr skill for Claude Code.
#
#   COAUTHR_TOKEN=coa_… sh -c 'curl -fsSL https://coauthr.co/skill/install.sh | sh'
#
# Copies the skill into ~/.claude/skills/coauthr/, writes ~/.config/coauthr/token
# (0600), and verifies the token against coauthr.co. Re-run to update; the
# token argument is optional on updates. No sudo, nothing outside your home.
#
#   --enforce   also register a Claude Code PreToolUse hook (~/.claude/settings.json)
#               that redirects the built-in Artifact tool's publishes to coauthr.
#               Skill instructions steer the model; the hook makes it deterministic.
#               Remove: delete the coauthr-artifact-guard entry from settings.json.
set -eu

BASE_URL="${COAUTHR_BASE_URL:-https://coauthr.co}"; BASE_URL="${BASE_URL%/}"
CODE_ORIGIN="https://coauthr.co"
case "$BASE_URL" in
  https://*) ;;
  http://localhost*|http://127.0.0.1*|http://\[::1\]*) ;;
  *) echo "COAUTHR_BASE_URL must be HTTPS (HTTP is allowed only for localhost)" >&2; exit 1 ;;
esac
if [ "$BASE_URL" != "https://coauthr.co" ]; then
  [ "${COAUTHR_ALLOW_CUSTOM_ORIGIN:-}" = "1" ] || {
    echo "custom origins require COAUTHR_ALLOW_CUSTOM_ORIGIN=1 and a separate COAUTHR_TOKEN_FILE" >&2
    exit 1
  }
  [ -n "${COAUTHR_TOKEN_FILE:-}" ] || {
    echo "set COAUTHR_TOKEN_FILE to a separate custom-origin profile" >&2
    exit 1
  }
  COAUTHR_TOKEN="${COAUTHR_CUSTOM_TOKEN:-}"
  export COAUTHR_TOKEN
fi
SKILL_ROOT="${CLAUDE_SKILLS_DIR:-$HOME/.claude/skills}"
SKILL_DIR="$SKILL_ROOT/coauthr"
TOKEN_FILE="${COAUTHR_TOKEN_FILE:-$HOME/.config/coauthr/token}"
ENFORCE=""
while [ $# -gt 0 ]; do
  case "$1" in
    --enforce) ENFORCE=1; shift ;;
    *) echo "unknown option: $1" >&2; exit 1 ;;
  esac
done

mkdir -p "$SKILL_ROOT"
chmod 700 "$SKILL_ROOT" 2>/dev/null || true
TMP="$(mktemp -d "$SKILL_ROOT/.coauthr-install.XXXXXX")"
trap 'rm -rf "$TMP"' EXIT
echo "→ downloading first-party skill from $CODE_ORIGIN/skill.tgz"
curl -fsSL "$CODE_ORIGIN/skill.tgz" -o "$TMP/skill.tgz"
curl -fsSL "$CODE_ORIGIN/skill.sha256" -o "$TMP/skill.sha256"
EXPECTED="$(awk 'NR==1 { print $1 }' "$TMP/skill.sha256")"
if command -v sha256sum >/dev/null 2>&1; then
  ACTUAL="$(sha256sum "$TMP/skill.tgz" | awk '{ print $1 }')"
elif command -v shasum >/dev/null 2>&1; then
  ACTUAL="$(shasum -a 256 "$TMP/skill.tgz" | awk '{ print $1 }')"
else
  echo "install needs sha256sum or shasum to verify the skill archive" >&2
  exit 1
fi
[ "$EXPECTED" = "$ACTUAL" ] || { echo "skill checksum mismatch; nothing was installed" >&2; exit 1; }
tar -tzf "$TMP/skill.tgz" | awk '
  $0 == "SKILL.md" || $0 == "scripts" || $0 == "scripts/" || $0 ~ /^scripts\/[A-Za-z0-9._\/-]+$/ {
    if (index($0, "..") || index($0, "\\")) bad=1
    next
  }
  { bad=1 }
  END { exit bad }
' || { echo "skill archive contains an unsafe path; nothing was installed" >&2; exit 1; }
tar -tvzf "$TMP/skill.tgz" | awk '
  substr($0, 1, 1) != "-" && substr($0, 1, 1) != "d" { bad=1 }
  END { exit bad }
' || { echo "skill archive contains links or special files; nothing was installed" >&2; exit 1; }
mkdir "$TMP/next"
tar -xzf "$TMP/skill.tgz" -C "$TMP/next"
[ -f "$TMP/next/SKILL.md" ] || { echo "skill archive is incomplete; nothing was installed" >&2; exit 1; }
chmod +x "$TMP/next"/scripts/*.sh "$TMP/next"/scripts/*.py 2>/dev/null || true
if [ -e "$SKILL_DIR" ] || [ -L "$SKILL_DIR" ]; then mv "$SKILL_DIR" "$TMP/previous"; fi
if ! mv "$TMP/next" "$SKILL_DIR"; then
  if [ -e "$TMP/previous" ] || [ -L "$TMP/previous" ]; then mv "$TMP/previous" "$SKILL_DIR"; fi
  echo "could not install the verified skill; the previous version was restored" >&2
  exit 1
fi
echo "✓ skill installed at $SKILL_DIR"
# Every agent: ~/.agents/skills is the cross-runtime alias (Gemini CLI, Codex, Copilot CLI);
# ~/.codex/skills is Codex's own dir. Symlinks to the Claude copy so one update serves all.
for d in "$HOME/.agents/skills" "$HOME/.codex/skills"; do
  mkdir -p "$d" 2>/dev/null || continue
  if [ -L "$d/coauthr" ] || [ ! -e "$d/coauthr" ]; then
    rm -f "$d/coauthr"; ln -s "$SKILL_DIR" "$d/coauthr" 2>/dev/null && echo "  also $d/coauthr"
  fi
done

if [ -n "$ENFORCE" ]; then
  SETTINGS="${CLAUDE_SETTINGS_FILE:-$HOME/.claude/settings.json}"
  GUARD="$SKILL_DIR/scripts/coauthr-artifact-guard.sh"
  if command -v python3 >/dev/null 2>&1; then
    mkdir -p "$(dirname "$SETTINGS")"
    SETTINGS="$SETTINGS" GUARD="$GUARD" python3 - <<'PY'
import json, os
path = os.environ["SETTINGS"]; guard = os.environ["GUARD"]
try:
    with open(path) as f: settings = json.load(f)
except FileNotFoundError:
    settings = {}
hooks = settings.setdefault("hooks", {})
pre = hooks.setdefault("PreToolUse", [])
entry = {"matcher": "Artifact", "hooks": [{"type": "command", "command": guard, "timeout": 10}]}
pre[:] = [h for h in pre if not any("coauthr-artifact-guard" in (c.get("command") or "") for c in h.get("hooks", []))]
pre.append(entry)
tmp = path + ".tmp"
with open(tmp, "w") as f: json.dump(settings, f, indent=2); f.write("\n")
os.replace(tmp, path)
PY
    echo "✓ Artifact-tool guard registered in $SETTINGS (Claude Code publishes documents via coauthr)"
  else
    echo "! --enforce needs python3 to edit $SETTINGS; add this PreToolUse hook by hand:" >&2
    echo "  {\"matcher\":\"Artifact\",\"hooks\":[{\"type\":\"command\",\"command\":\"$GUARD\"}]}" >&2
  fi
fi

if [ -n "${COAUTHR_TOKEN:-}" ]; then
  case "$COAUTHR_TOKEN" in
    coa_*) ;;
    *) echo "that doesn't look like a coauthr token (expected coa_…)" >&2; exit 1 ;;
  esac
  mkdir -p "$(dirname "$TOKEN_FILE")"
  umask 077
  printf '%s\n' "$COAUTHR_TOKEN" > "$TOKEN_FILE"
  chmod 600 "$TOKEN_FILE"
  echo "✓ token saved to $TOKEN_FILE"
fi

if [ -f "$TOKEN_FILE" ] || [ -n "${COAUTHR_TOKEN:-}" ]; then
  # Run via the script's own shebang (bash) — `sh` here broke on dash (Debian/
  # Ubuntu): pipefail/source are bashisms, and the failure read as a bad token.
  if ME="$(COAUTHR_BASE_URL="$BASE_URL" "$SKILL_DIR/scripts/coauthr-me.sh" 2>/dev/null)"; then
    EMAIL="$(printf '%s' "$ME" | sed -n 's/.*"email":"\([^"]*\)".*/\1/p')"
    echo "✓ signed in as ${EMAIL:-?} — your Claude Code can now publish to coauthr"
  else
    echo "! the token didn't verify — mint a fresh one at $BASE_URL/settings and re-run with COAUTHR_TOKEN set" >&2
    exit 1
  fi
else
  echo "· not signed in yet — run: curl -fsSL $BASE_URL/login | sh   (or: pnpm dlx coauthr.co login)"
fi
echo "Next: in Claude Code, say “publish to coauthr” — plans, reports and design rounds land at coauthr.co for review."
[ -n "$ENFORCE" ] || echo "     (add --enforce to make Claude Code always prefer coauthr over its built-in Artifact tool)"
