#!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # AgentixTech — one-click developer onboarding (Linux / macOS / WSL2) # Employee runs ONE line: # bash <(curl -fsSL https://onboarddev.agentixtech.ai/setup.sh) # # What it does, in order (idempotent + safe to re-run): # 1. Installs core tools (git, curl) + Node + Claude Code # 2. Fetches the AgentixTech eng-suite payload from this host and stages it # into ~/.claude (skills + graphify + /onboard command + self-heal hook), # merging — never clobbering — your existing config. # 3. Hands off to Claude to follow the hosted ONBOARDING.md runbook. # 4. Runs the deterministic verifier and prints a report. # No secrets are handled here; GitHub/SSO sign-in stays human-gated inside the runbook. # ───────────────────────────────────────────────────────────────────────────── set -euo pipefail BASE_URL="${ONBOARD_BASE_URL:-https://onboarddev.agentixtech.ai}" CLAUDE_HOME="${CLAUDE_HOME:-$HOME/.claude}" STATE_DIR="${STATE_DIR:-$HOME/.onboard}" LOG="$STATE_DIR/run.log" mkdir -p "$STATE_DIR" "$CLAUDE_HOME" exec > >(tee -a "$LOG") 2>&1 log(){ printf '\033[38;5;36m[agentix-onboard %s]\033[0m %s\n' "$(date -u +%H:%M:%S)" "$*"; } have(){ command -v "$1" >/dev/null 2>&1; } detect(){ case "$(uname -s)" in Darwin) OS=macos ;; Linux) grep -qi microsoft /proc/version 2>/dev/null && OS=wsl2 || OS=linux ;; *) OS=unknown ;; esac log "platform=$OS arch=$(uname -m)" } pm_install(){ # pm_install have "$1" && { log "$1 present"; return 0; } log "installing $1…" case "$OS" in macos) have brew || /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"; brew install "$2" ;; linux|wsl2) sudo apt-get update -qq && sudo apt-get install -y "$3" ;; *) log "unsupported OS — install $1 manually"; return 1 ;; esac } install_claude(){ have claude && { log "claude present ($(claude --version 2>/dev/null || echo '?'))"; return 0; } have node || pm_install node node nodejs log "installing Claude Code…" npm install -g @anthropic-ai/claude-code } # Stage the eng-suite payload into ~/.claude WITHOUT clobbering user config. stage_suite(){ log "fetching eng-suite payload from $BASE_URL …" local tgz; tgz="$(mktemp)" curl -fsSL "$BASE_URL/eng-suite.tgz" -o "$tgz" local ex; ex="$(mktemp -d)" tar -xzf "$tgz" -C "$ex" mkdir -p "$CLAUDE_HOME/skills" "$CLAUDE_HOME/commands" "$CLAUDE_HOME/graphify" "$CLAUDE_HOME/hooks" # skills/commands/graphify/hooks are ours to own — safe to replace by name cp -R "$ex"/skills/* "$CLAUDE_HOME/skills/" 2>/dev/null || true cp -R "$ex"/commands/* "$CLAUDE_HOME/commands/" 2>/dev/null || true cp "$ex"/graphify/graphify.py "$CLAUDE_HOME/graphify/graphify.py" 2>/dev/null || true cp "$ex"/hooks/session-start.sh "$CLAUDE_HOME/hooks/session-start.sh" 2>/dev/null || true chmod +x "$CLAUDE_HOME/hooks/session-start.sh" 2>/dev/null || true cp "$ex/ONBOARDING.md" "$CLAUDE_HOME/ONBOARDING.md" 2>/dev/null || true # CLAUDE.md: append a managed block only if absent (never overwrite user content) if [ ! -f "$CLAUDE_HOME/CLAUDE.md" ] || ! grep -q 'BEGIN agentix-eng-suite' "$CLAUDE_HOME/CLAUDE.md" 2>/dev/null; then { printf '\n\n'; printf '## AgentixTech engineering suite\n- Skills auto-activate by intent (eng-req-understanding, eng-planning, eng-implementation, eng-testing, eng-orchestrator, graphify).\n- First-time setup: run /onboard or follow ~/.claude/ONBOARDING.md.\n'; printf '\n'; } >> "$CLAUDE_HOME/CLAUDE.md" fi rm -rf "$ex" "$tgz" log "eng-suite staged into $CLAUDE_HOME (skills + graphify + /onboard + self-heal hook)" } handoff(){ if ! have claude; then log "claude unavailable; prereqs+suite staged. Re-run after Node/npm on PATH."; return 3; fi log "handing off to Claude to follow the ONBOARDING runbook…" claude --permission-mode default --print \ "Fetch $BASE_URL/ONBOARDING.md and execute it per its Execution Protocol. Pause for me on any [ask] gate (e.g. GitHub sign-in). When finished, run the Verification Report and show the table." \ || { log "Claude handoff returned non-zero; run '/onboard' in Claude to continue."; return 1; } } verify(){ local v; v="$(mktemp)" if curl -fsSL "$BASE_URL/verify.sh" -o "$v"; then bash "$v" --json "$STATE_DIR/onboarding-report.json" || true; fi rm -f "$v" } main(){ log "starting AgentixTech onboarding" detect pm_install curl curl curl pm_install git git git install_claude stage_suite handoff || true verify log "✅ onboarding finished — review the verification report above" } main "$@"