#!/usr/bin/env bash set -euo pipefail # Health check for local OpenClaude stack. # # Modes: # --mode minimal (default): check OpenClaude + Ollama + selected model # --mode full: check minimal + Qdrant + Python deps + optional docs collection # # Usage: # ./healthcheck.sh # ./healthcheck.sh --mode full # ./healthcheck.sh --model qwen2.5:3b --mode minimal MODE="minimal" MODEL="${MODEL:-qwen2.5-coder:7b}" QDRANT_URL="${QDRANT_URL:-http://127.0.0.1:6333}" COLLECTION="${QDRANT_COLLECTION:-docs}" WORKDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" VENV_PY="$WORKDIR/.venv/bin/python" GREEN="\033[0;32m" YELLOW="\033[1;33m" RED="\033[0;31m" NC="\033[0m" pass() { echo -e "${GREEN}[OK]${NC} $1"; } warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } fail() { echo -e "${RED}[FAIL]${NC} $1"; exit 1; } while [[ $# -gt 0 ]]; do case "$1" in --mode) MODE="$2" shift 2 ;; --model) MODEL="$2" shift 2 ;; *) fail "Unknown argument: $1" ;; esac done if [[ "$MODE" != "minimal" && "$MODE" != "full" ]]; then fail "--mode must be minimal or full" fi echo "Healthcheck mode: $MODE" echo "Target model: $MODEL" # 1) openclaude in PATH if command -v openclaude >/dev/null 2>&1; then pass "openclaude found in PATH" else fail "openclaude not found. Install with: npm install -g @gitlawb/openclaude" fi # 2) ollama service/API if command -v ollama >/dev/null 2>&1; then pass "ollama CLI found" else fail "ollama not found. Install Ollama first." fi if curl -fsS "http://127.0.0.1:11434/api/tags" >/dev/null 2>&1; then pass "Ollama API is reachable at 127.0.0.1:11434" else fail "Ollama API is not reachable. Check: sudo systemctl status ollama" fi # 3) model present if ollama list | awk '{print $1}' | rg "^${MODEL}$" >/dev/null 2>&1; then pass "Model is pulled: $MODEL" else warn "Model not found locally: $MODEL" warn "Pull it with: ollama pull $MODEL" fi if [[ "$MODE" == "full" ]]; then # 4) qdrant if curl -fsS "${QDRANT_URL}/collections" >/dev/null 2>&1; then pass "Qdrant is reachable at ${QDRANT_URL}" else fail "Qdrant is not reachable at ${QDRANT_URL}. Start with: docker compose up -d" fi # 5) venv + python deps if [[ -x "$VENV_PY" ]]; then pass "Python venv exists: .venv" else fail "Python venv not found. Run install.sh first." fi if "$VENV_PY" -c "import fastmcp, qdrant_client, requests; print('ok')" >/dev/null 2>&1; then pass "Python dependencies are installed" else fail "Missing Python dependencies. Run: source .venv/bin/activate && pip install -r requirements.txt" fi # 6) collection exists (non-fatal, just info) if curl -fsS "${QDRANT_URL}/collections/${COLLECTION}" >/dev/null 2>&1; then pass "Qdrant collection exists: ${COLLECTION}" else warn "Qdrant collection '${COLLECTION}' not found yet. Run: python index.py" fi fi echo pass "Healthcheck completed."