#!/usr/bin/env bash # dev-setup.sh — set up the muse local development environment. # # Nukes and rebuilds .venv from scratch, installs muse in editable mode # with all grammars and dev tools, and symlinks the binary to ~/bin/muse. # # Run this once after cloning and again any time dependencies drift: # bash dev-setup.sh # # The ~/bin/muse symlink stays valid across rebuilds because it points to # .venv/bin/muse, which pip regenerates on every editable install. set -euo pipefail REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" VENV="$REPO/.venv" BIN_LINK="$HOME/bin/muse" PYTHON="${PYTHON:-python3.14}" log() { printf '\033[1;34m%s\033[0m\n' "$*"; } ok() { printf '\033[1;32m✅ %s\033[0m\n' "$*"; } die() { printf '\033[1;31m❌ %s\033[0m\n' "$*" >&2; exit 1; } # ── 1. Verify Python ────────────────────────────────────────────────────────── log "[1/5] Checking Python" command -v "$PYTHON" >/dev/null 2>&1 || die "$PYTHON not found. Install Python 3.14+." PY_VERSION=$("$PYTHON" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") [[ "$PY_VERSION" == 3.14* ]] || die "Python 3.14 required, found $PY_VERSION." ok "Python $PY_VERSION at $("$PYTHON" -c 'import sys; print(sys.executable)')" # ── 2. Rebuild venv ─────────────────────────────────────────────────────────── log "[2/5] Rebuilding .venv (clean)" rm -rf "$VENV" "$PYTHON" -m venv "$VENV" ok ".venv created" # ── 3. Install muse (editable + all extras) ─────────────────────────────────── log "[3/5] Installing muse[all,dev] in editable mode" "$VENV/bin/pip" install --quiet --upgrade pip "$VENV/bin/pip" install --quiet -e "$REPO[all,dev]" ok "muse installed" # ── 4. Verify critical extras resolved correctly ───────────────────────────── log "[4/5] Verifying HTTP/2 dependency chain" H2=$("$VENV/bin/python" -c "import h2; print(h2.__version__)" 2>/dev/null || true) [[ -n "$H2" ]] || die "h2 not installed — httpx[http2] extras chain is broken." ok "h2 $H2" HTTPCORE=$("$VENV/bin/pip" show httpcore | grep "^Version" | awk '{print $2}') ok "httpcore $HTTPCORE" HTTPX=$("$VENV/bin/pip" show httpx | grep "^Version" | awk '{print $2}') ok "httpx $HTTPX (http2 extras resolved)" # ── 5. Symlink binary ───────────────────────────────────────────────────────── log "[5/5] Symlinking binary" mkdir -p "$(dirname "$BIN_LINK")" ln -sf "$VENV/bin/muse" "$BIN_LINK" ok "~/bin/muse -> $VENV/bin/muse" # ── Done ────────────────────────────────────────────────────────────────────── printf '\n' log "Dev environment ready." log " muse: $("$VENV/bin/muse" --version)" log " venv: $VENV" log " binary: $BIN_LINK" printf '\n' log "To dog-food the user install path (from staging.musehub.ai):" log " curl -fsSL https://staging.musehub.ai/install.sh | sh" log "That installs to ~/.local/share/muse/venv — a separate env, no conflict." # testing