#!/bin/bash
# install.sh — Установка платформы на сервере или в контейнере
# Запуск: bash install.sh [SERV]
# Пример: bash install.sh EU | bash install.sh AIPD | bash install.sh RF
#
# Идемпотентный — безопасно запускать повторно.
# Работает на хосте и внутри Docker-контейнера.
set -e
WORKSPACE="$(cd "$(dirname "$0")" && pwd)"
CLAUDE_HOME="${HOME}/.claude"
CLAUDE_SRC="$WORKSPACE/.claude"
hr() { echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"; }
ok() { echo " ✓ $*"; }
skip(){ echo " – $* (уже есть)"; }
err() { echo " ✗ $*"; }
inf() { echo " · $*"; }
hr
echo " Platform Install — $(hostname)"
echo " Workspace : $WORKSPACE"
echo " Claude dir: $CLAUDE_HOME"
hr
echo ""
# ─── 1. SERV ──────────────────────────────────────────────────────────────────
SERV="${1:-}"
if [ -z "$SERV" ]; then
case "$(hostname)" in
xirfbwpmvt*) SERV="EU" ;;
pmvdmyllfo*) SERV="AIPD" ;;
leruepecie*) SERV="RF" ;;
*) SERV="$(hostname | cut -c1-4 | tr '[:lower:]' '[:upper:]')" ;;
esac
inf "SERV определён по hostname: $SERV"
else
inf "SERV задан явно: $SERV"
fi
# ─── 2. Базовые папки ─────────────────────────────────────────────────────────
echo ""
echo " [1] Папки"
mkdir -p "$CLAUDE_HOME"
mkdir -p "$CLAUDE_HOME/output-styles"
ok "~/.claude/ и output-styles/"
# ─── 3. output-styles ─────────────────────────────────────────────────────────
echo ""
echo " [2] Output styles"
if [ -d "$CLAUDE_SRC/output-styles" ]; then
cp -r "$CLAUDE_SRC/output-styles/." "$CLAUDE_HOME/output-styles/"
for f in "$CLAUDE_HOME/output-styles"/*.md; do
[ -f "$f" ] && ok "$(basename "$f")"
done
else
err "Не найдено: $CLAUDE_SRC/output-styles"
fi
# ─── 4. statusline-command.sh ─────────────────────────────────────────────────
echo ""
echo " [3] Statusline"
STATUSLINE_SRC="$CLAUDE_SRC/statusline-command.sh"
STATUSLINE_DST="$CLAUDE_HOME/statusline-command.sh"
if [ -f "$STATUSLINE_SRC" ]; then
cp "$STATUSLINE_SRC" "$STATUSLINE_DST"
chmod +x "$STATUSLINE_DST"
ok "statusline-command.sh"
else
err "Не найдено: $STATUSLINE_SRC"
fi
# ─── 5. settings.json ─────────────────────────────────────────────────────────
echo ""
echo " [4] settings.json"
SETTINGS="$CLAUDE_HOME/settings.json"
write_settings() {
cat > "$SETTINGS" << EOF
{
"statusLine": {
"type": "command",
"command": "bash $CLAUDE_HOME/statusline-command.sh"
},
"permissions": {
"allow": [
"Bash(*)", "Read(*)", "Glob(*)", "Grep(*)",
"Edit(*)", "Write(*)", "Task(*)", "TodoWrite(*)", "NotebookEdit(*)"
],
"deny": ["WebSearch", "WebFetch"]
},
"env": {
"CLAUDE_SERV": "$SERV",
"CLAUDE_WORKSPACE": "$WORKSPACE"
},
"model": "sonnet",
"alwaysThinkingEnabled": true,
"outputStyle": "default"
}
EOF
}
if [ ! -f "$SETTINGS" ]; then
write_settings
ok "Создан (SERV=$SERV)"
else
# Обновить SERV и WORKSPACE, не трогая остальное
if command -v python3 &>/dev/null; then
python3 - "$SETTINGS" "$SERV" "$WORKSPACE" "$CLAUDE_HOME" << 'PYEOF'
import sys, json
path, serv, ws, ch = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]
with open(path) as f:
s = json.load(f)
s.setdefault("env", {})
s["env"]["CLAUDE_SERV"] = serv
s["env"]["CLAUDE_WORKSPACE"] = ws
s.setdefault("outputStyle", "default")
s.setdefault("statusLine", {"type": "command", "command": f"bash {ch}/statusline-command.sh"})
s.setdefault("permissions", {"allow": [], "deny": []})
s["permissions"].setdefault("deny", [])
if "WebSearch" not in s["permissions"]["deny"]:
s["permissions"]["deny"].append("WebSearch")
with open(path, "w") as f:
json.dump(s, f, indent=2, ensure_ascii=False)
PYEOF
ok "Обновлён (SERV=$SERV, WORKSPACE=$WORKSPACE)"
else
write_settings
ok "Перезаписан (python3 не найден)"
fi
fi
# ─── 6. Итог ──────────────────────────────────────────────────────────────────
echo ""
hr
echo " ✓ Установка завершена"
echo ""
echo " SERV : $SERV"
echo " Workspace : $WORKSPACE"
echo " Styles : $CLAUDE_HOME/output-styles/"
echo " Settings : $SETTINGS"
echo " Statusline: $CLAUDE_HOME/statusline-command.sh"
echo ""
echo " Запуск: bash $WORKSPACE/start.sh"
hr
# Маркер для entrypoint (не перезапускать при рестарте контейнера)
touch "$CLAUDE_HOME/.platform-installed"