#!/bin/sh # fixhub one-line install (report #7). Run it in the site's source folder: # curl -fsSL https://fix.bebo.kr/api/install.sh | sh -s -- FXC-XXXX-XXXX-XXXX # 1. puts the fixhub CLI in ~/.local/share/fixhub (shallow copy of plugin.git) # and links it as ~/.local/bin/fixhub, # 2. exchanges the one-time code (console → '설치 한 줄 만들기', 10 minutes) # for this project's settings (.fix/config.json) and agent key # (~/.config/fixhub/.key, mode 600; never printed), # 3. installs project Codex skills and/or the Claude plugin (--client selection), # 4. checks the link to the hub. set -eu HUB="${FIXHUB_HUB:-https://fix.bebo.kr}" CODE="${1:-}" CLIENT=auto [ "$#" -eq 0 ] || shift if [ "$#" -gt 0 ]; then [ "$#" -eq 2 ] && [ "$1" = "--client" ] || { printf '%s\n' 'usage: install.sh CODE [--client auto|codex|claude|both]' >&2; exit 1; } CLIENT="$2" fi case "$CLIENT" in auto|codex|claude|both) ;; *) printf '%s\n' 'unknown client' >&2; exit 1 ;; esac say() { printf 'fixhub: %s\n' "$*"; } fail() { say "$*" >&2; exit 1; } [ -n "$CODE" ] || fail "연결 코드가 없습니다. 콘솔의 '설치 한 줄 만들기'가 보여 주는 명령을 그대로 붙여 넣으십시오." command -v git >/dev/null 2>&1 || fail "git 이 필요합니다." command -v python3 >/dev/null 2>&1 || fail "python3 (3.8 이상) 이 필요합니다." case "$CLIENT" in claude|both) command -v claude >/dev/null 2>&1 || fail "선택한 설치 방식에는 Claude Code CLI가 필요합니다. Codex만 사용한다면 --client codex를 선택하십시오." ;; esac python3 -c 'import sys; sys.exit(sys.version_info < (3, 8))' || fail "python3 3.8 이상이 필요합니다." ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) cd "$ROOT" say "프로젝트 폴더: $ROOT" # Slow or stalled transfers give up instead of hanging (no timeout(1) on every system). GIT_NET="-c http.lowSpeedLimit=1000 -c http.lowSpeedTime=30" SRC="${XDG_DATA_HOME:-$HOME/.local/share}/fixhub/plugin" if [ -d "$SRC/.git" ]; then # shellcheck disable=SC2086 git $GIT_NET -C "$SRC" pull -q --ff-only || say "fixhub 명령 갱신 실패 — 기존 사본을 씁니다." else mkdir -p "$(dirname "$SRC")" # shellcheck disable=SC2086 git $GIT_NET clone -q --depth 1 "$HUB/plugin.git" "$SRC" || fail "fixhub 명령을 받지 못했습니다 ($HUB/plugin.git)." fi CLI="$SRC/fix/bin/fixhub" mkdir -p "$HOME/.local/bin" ln -sf "$CLI" "$HOME/.local/bin/fixhub" INSTALL_CODEX=0 case "$CLIENT" in codex|both) INSTALL_CODEX=1 ;; auto) if command -v codex >/dev/null 2>&1 || ! command -v claude >/dev/null 2>&1; then INSTALL_CODEX=1; fi ;; esac if [ "$INSTALL_CODEX" -eq 1 ]; then python3 "$SRC/codex/install.py" --project "$ROOT" || fail "Codex 스킬 설치 실패. 기존 파일을 확인한 뒤 다시 실행하십시오. 연결 코드는 아직 사용하지 않았습니다." fi python3 "$CLI" pair "$CODE" --hub "$HUB" || fail "연결 코드가 맞지 않거나 만료되었습니다(10분, 한 번만 사용). 콘솔에서 새로 만드십시오." if [ "$CLIENT" != codex ] && command -v claude >/dev/null 2>&1; then claude plugin marketplace add "$HUB/plugin.git" >/dev/null 2>&1 || claude plugin marketplace update fixhub >/dev/null 2>&1 || true if claude plugin install fix@fixhub --scope project >/dev/null 2>&1; then say "Claude Code 플러그인을 설치했습니다 (fix@fixhub)." else say "Claude Code 플러그인 설치 실패 — 'claude plugin install fix@fixhub --scope project' 를 직접 실행하십시오." fi fi python3 "$CLI" status || fail "허브 연결을 확인하지 못했습니다." if [ "$INSTALL_CODEX" -eq 1 ]; then say 'Codex: 이 프로젝트에서 $fixhub 를 호출하십시오. 스킬이 보이지 않으면 Codex를 다시 여십시오. 상시 감시는 시작되지 않습니다.' fi if [ "$CLIENT" != codex ] && command -v claude >/dev/null 2>&1; then say 'Claude Code: /fix:watch 로 감시를 시작하십시오.' fi say '설치 완료. 사이트 위젯과 .fix/config.json의 build/test/deploy 설정도 확인하십시오.' case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *) say "참고: fixhub 명령을 바로 쓰려면 ~/.local/bin 을 PATH 에 추가하십시오." ;; esac