Nested .claude/skills/ dirs (previously under server/) are only auto-discovered on-demand once a file under that subdirectory is touched, so /make-widget and /run-server weren't invocable from a fresh session. Root .claude/skills/ is scanned at session start. Fixes setup.sh/start-server.sh's relative cd-depth math (was hardcoded for the old server/.claude/skills/run-server/ depth) to instead resolve the repo root via git and cd into server/ explicitly, and updates SKILL.md/driver.py's path references to match the new layout.
111 lines
5.2 KiB
Bash
Executable File
111 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# One-time (idempotent) environment bootstrap for running the
|
|
# espresso_frame FastAPI server and browser-driving its UI, in a
|
|
# container that ships with NO Python/Node/Docker/browser and NO sudo.
|
|
# Re-run any time; every step checks whether it already happened.
|
|
set -euo pipefail
|
|
cd "$(git -C "$(dirname "${BASH_SOURCE[0]}")" rev-parse --show-toplevel)/server"
|
|
|
|
UV_BIN="$HOME/.local/bin/uv"
|
|
DEPS_ROOT="/tmp/run-server-chromium-deps"
|
|
APT_WORK="/tmp/apt-work-run-server"
|
|
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ENV_FILE="$SKILL_DIR/env.sh"
|
|
|
|
# 1. uv: a static Rust binary that can fetch its own Python build with
|
|
# no C compiler needed (this container has none).
|
|
if [ ! -x "$UV_BIN" ]; then
|
|
echo "installing uv..."
|
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
fi
|
|
|
|
# 2. Python 3.12 + venv + server deps
|
|
if [ ! -x .venv/bin/uvicorn ]; then
|
|
echo "creating venv + installing server deps..."
|
|
"$UV_BIN" python install 3.12
|
|
"$UV_BIN" venv --python 3.12 .venv
|
|
"$UV_BIN" pip install -r requirements.txt
|
|
fi
|
|
|
|
# 3. Playwright (Python) + its Chromium download (~280MB: full chrome +
|
|
# chrome-headless-shell + ffmpeg)
|
|
if ! .venv/bin/python -c "import playwright" 2>/dev/null; then
|
|
echo "installing playwright..."
|
|
"$UV_BIN" pip install playwright
|
|
fi
|
|
if ! ls "$HOME"/.cache/ms-playwright/chromium-*/chrome-linux64/chrome >/dev/null 2>&1; then
|
|
echo "downloading chromium..."
|
|
.venv/bin/playwright install chromium
|
|
fi
|
|
|
|
# 4. Chromium's shared libs + fonts. `playwright install-deps` and
|
|
# `apt-get install` both need root; neither is available. Instead:
|
|
# download the .deb files directly (apt-get download works read-only
|
|
# without root once given a user-writable state dir) and extract
|
|
# (not install) them with dpkg-deb -x, which needs no root either.
|
|
if [ ! -f "$DEPS_ROOT/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0" ]; then
|
|
echo "fetching chromium's shared libs + fonts (non-root)..."
|
|
mkdir -p "$APT_WORK/lists" "$APT_WORK/cache/archives/partial" "$APT_WORK/debs" "$DEPS_ROOT"
|
|
|
|
apt-get -o Dir::State::Lists="$APT_WORK/lists" -o Dir::Cache="$APT_WORK/cache" \
|
|
-o Dir::Etc::SourceParts=/dev/null update
|
|
|
|
PKGS="libglib2.0-0t64 libnspr4 libnss3 libatk1.0-0t64 libatk-bridge2.0-0t64
|
|
libdbus-1-3 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1
|
|
libxkbcommon0 libasound2t64 libatspi2.0-0t64 libcups2t64 libcairo2
|
|
libpango-1.0-0 libpangocairo-1.0-0 libx11-6 libxcb1 libxext6
|
|
fonts-liberation fontconfig libfontconfig1"
|
|
# ^ first row: what chrome-headless-shell's ldd reported missing.
|
|
# second row: what the FULL chrome binary additionally needed (we use
|
|
# full chrome, not headless-shell -- see Gotchas in SKILL.md).
|
|
|
|
apt-get -o Dir::State::Lists="$APT_WORK/lists" -o Dir::Cache="$APT_WORK/cache" \
|
|
-o Dir::Etc::SourceParts=/dev/null install --download-only --reinstall -y \
|
|
--print-uris $PKGS | grep -oP "^'[^']+'" | tr -d "'" > "$APT_WORK/urls.txt"
|
|
|
|
(cd "$APT_WORK/debs" && xargs -n1 -P8 curl -sS -O --max-time 30) < "$APT_WORK/urls.txt"
|
|
for f in "$APT_WORK"/debs/*.deb; do dpkg-deb -x "$f" "$DEPS_ROOT"; done
|
|
|
|
# fonts.conf as shipped points at the real /usr/share/fonts, which is
|
|
# root-owned and has nothing extracted into it. Point it at our
|
|
# extracted copy instead, and give it a writable cache dir.
|
|
mkdir -p /tmp/run-server-fontcache
|
|
sed -i "s#<dir>/usr/share/fonts</dir>#<dir>$DEPS_ROOT/usr/share/fonts</dir>#" \
|
|
"$DEPS_ROOT/etc/fonts/fonts.conf"
|
|
sed -i "s#<cachedir>.*</cachedir>#<cachedir>/tmp/run-server-fontcache</cachedir>#" \
|
|
"$DEPS_ROOT/etc/fonts/fonts.conf"
|
|
|
|
PATH="$DEPS_ROOT/usr/bin:$PATH" \
|
|
LD_LIBRARY_PATH="$DEPS_ROOT/usr/lib/x86_64-linux-gnu:$DEPS_ROOT/lib/x86_64-linux-gnu" \
|
|
FONTCONFIG_PATH="$DEPS_ROOT/etc/fonts" \
|
|
"$DEPS_ROOT/usr/bin/fc-cache" -f
|
|
fi
|
|
|
|
# 5. tmux -- also missing, also no apt/sudo. Same non-root download +
|
|
# dpkg-deb -x trick, into the same extracted root (so its `usr/bin` is
|
|
# already on PATH via env.sh).
|
|
if [ ! -f "$DEPS_ROOT/usr/bin/tmux" ]; then
|
|
echo "fetching tmux (non-root)..."
|
|
mkdir -p "$APT_WORK/lists" "$APT_WORK/cache/archives/partial" "$APT_WORK/debs" "$DEPS_ROOT"
|
|
apt-get -o Dir::State::Lists="$APT_WORK/lists" -o Dir::Cache="$APT_WORK/cache" \
|
|
-o Dir::Etc::SourceParts=/dev/null install --download-only --reinstall -y \
|
|
--print-uris tmux | grep -oP "^'[^']+'" | tr -d "'" > "$APT_WORK/tmux_urls.txt"
|
|
(cd "$APT_WORK/debs" && xargs -n1 -P3 curl -sS -O --max-time 30) < "$APT_WORK/tmux_urls.txt"
|
|
for f in $(sed -E 's#.*/##' "$APT_WORK/tmux_urls.txt"); do dpkg-deb -x "$APT_WORK/debs/$f" "$DEPS_ROOT"; done
|
|
fi
|
|
|
|
CHROME_BIN="$(ls "$HOME"/.cache/ms-playwright/chromium-*/chrome-linux64/chrome | head -1)"
|
|
|
|
cat > "$ENV_FILE" <<EOF
|
|
# Generated by setup.sh. Source this before running driver.py (it
|
|
# needs LD_LIBRARY_PATH/FONTCONFIG_PATH set before the Chromium
|
|
# subprocess launches -- driver.py does not source it for you).
|
|
# start-server.sh does NOT need this file -- uvicorn has no such deps.
|
|
export PATH="\$HOME/.local/bin:$DEPS_ROOT/usr/bin:\$PATH"
|
|
export LD_LIBRARY_PATH="$DEPS_ROOT/usr/lib/x86_64-linux-gnu:$DEPS_ROOT/lib/x86_64-linux-gnu"
|
|
export FONTCONFIG_PATH="$DEPS_ROOT/etc/fonts"
|
|
export RUN_SERVER_CHROME_BIN="$CHROME_BIN"
|
|
EOF
|
|
|
|
echo "setup complete -> $ENV_FILE"
|