Spaces:
Running
Running
| # OpenClaw on Hugging Face Spaces β Pre-built image (v4.4) | |
| # Changelog: | |
| # v4.2 β sudo access, Homebrew (brew), uv, Go added for agent tooling | |
| # v4.3 β skill dependencies added (wrong go paths β fixed in v4.4) | |
| # v4.4 β FIXED: correct go module paths (all tools are by @steipete); | |
| # gh via official GitHub apt repo; gemini via npm; nano-pdf via pip; | |
| # steipete/tap added for brew; OpenClaw always pulls :latest | |
| # ββ Stage 1: Pull pre-built OpenClaw βββββββββββββββββββββββββββββββββββββββββ | |
| # :latest always fetches the newest release on every rebuild. | |
| # If you ever need to pin a version use e.g. :2026.3.13 | |
| FROM ghcr.io/openclaw/openclaw:latest AS openclaw-prebuilt | |
| # ββ Stage 2: Runtime βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| FROM node:22-bookworm | |
| SHELL ["/bin/bash", "-c"] | |
| # ββ System deps + apt-installable skill tools (root) βββββββββββββββββββββββββ | |
| # Skills unlocked by apt: session-logs+trello (jq, ripgrep), tmux, video-frames (ffmpeg) | |
| # gh added via official GitHub apt repo β more reliable than brew on Linux | |
| RUN echo "[build] Installing system deps + gh..." && START=$(date +%s) \ | |
| && apt-get update \ | |
| && apt-get install -y --no-install-recommends \ | |
| git ca-certificates curl wget python3 python3-pip \ | |
| sudo build-essential procps file \ | |
| jq ripgrep tmux ffmpeg \ | |
| poppler-utils tesseract-ocr \ | |
| # ββ GitHub CLI (gh) via official apt repo ββ | |
| && mkdir -p -m 755 /etc/apt/keyrings \ | |
| && wget -qO /etc/apt/keyrings/githubcli-archive-keyring.gpg \ | |
| https://cli.github.com/packages/githubcli-archive-keyring.gpg \ | |
| && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ | |
| && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ | |
| > /etc/apt/sources.list.d/github-cli.list \ | |
| && apt-get update \ | |
| && apt-get install -y --no-install-recommends gh \ | |
| && rm -rf /var/lib/apt/lists/* \ | |
| && gh --version \ | |
| # ββ Python + pip skill tools ββ | |
| && pip3 install --no-cache-dir --break-system-packages \ | |
| huggingface_hub requests nano-pdf openai-whisper ffmpeg-python \ | |
| && corepack enable \ | |
| && mkdir -p /app/openclaw \ | |
| && chown -R node:node /app \ | |
| && mkdir -p /home/node/.openclaw/workspace /home/node/.openclaw/credentials \ | |
| && chown -R node:node /home/node \ | |
| # ββ Passwordless sudo for node user ββ | |
| && echo "node ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/node \ | |
| && chmod 0440 /etc/sudoers.d/node \ | |
| && echo "[build] System deps: $(($(date +%s) - START))s" | |
| # ββ Go language + Go-based skill tools (root) βββββββββββββββββββββββββββββββββ | |
| # All CLIs are by Peter Steinberger (@steipete) β correct module paths: | |
| # gifgrep β github.com/steipete/gifgrep/cmd/gifgrep | |
| # blucli β github.com/steipete/blucli/cmd/blu | |
| # eightctl β github.com/steipete/eightctl/cmd/eightctl | |
| # songsee β github.com/steipete/songsee/cmd/songsee | |
| # gog β github.com/steipete/gogcli (binary: gog) | |
| RUN echo "[build] Installing Go + Go-based skill CLIs..." && START=$(date +%s) \ | |
| && GO_VER=$(curl -fsSL "https://go.dev/VERSION?m=text" | head -1) \ | |
| && curl -fsSL "https://dl.google.com/go/${GO_VER}.linux-amd64.tar.gz" -o /tmp/go.tar.gz \ | |
| && tar -C /usr/local -xzf /tmp/go.tar.gz \ | |
| && rm /tmp/go.tar.gz \ | |
| && /usr/local/go/bin/go version \ | |
| && GOBIN=/usr/local/bin /usr/local/go/bin/go install \ | |
| github.com/steipete/gifgrep/cmd/gifgrep@latest 2>&1 || echo "[go] WARN: gifgrep" \ | |
| && GOBIN=/usr/local/bin /usr/local/go/bin/go install \ | |
| github.com/steipete/blucli/cmd/blu@latest 2>&1 || echo "[go] WARN: blucli/blu" \ | |
| && GOBIN=/usr/local/bin /usr/local/go/bin/go install \ | |
| github.com/steipete/eightctl/cmd/eightctl@latest 2>&1 || echo "[go] WARN: eightctl" \ | |
| && GOBIN=/usr/local/bin /usr/local/go/bin/go install \ | |
| github.com/steipete/songsee/cmd/songsee@latest 2>&1 || echo "[go] WARN: songsee" \ | |
| && GOBIN=/usr/local/bin /usr/local/go/bin/go install \ | |
| github.com/steipete/gogcli@latest 2>&1 || echo "[go] WARN: gogcli/gog" \ | |
| && echo "[build] Go ${GO_VER} + CLIs: $(($(date +%s) - START))s" | |
| # ββ uv (fast Python package manager by Astral) βββββββββββββββββββββββββββββββ | |
| RUN echo "[build] Installing uv..." && START=$(date +%s) \ | |
| && curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh \ | |
| && uv --version \ | |
| && echo "[build] uv: $(($(date +%s) - START))s" | |
| # ββ npm skill tools (root) ββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Skills unlocked: clawhub, mcporter, oracle, gemini | |
| RUN echo "[build] Installing npm skill tools..." && START=$(date +%s) \ | |
| && npm install -g \ | |
| @anthropic-ai/claude-code \ | |
| acpx@latest \ | |
| clawhub \ | |
| mcporter \ | |
| @steipete/oracle \ | |
| @google/gemini-cli \ | |
| && echo "[build] npm tools: $(($(date +%s) - START))s" | |
| # ββ Copy pre-built OpenClaw βββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| COPY --from=openclaw-prebuilt --chown=node:node /app /app/openclaw | |
| # ββ Switch to node user βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| USER node | |
| ENV HOME=/home/node | |
| WORKDIR /app | |
| # ββ Homebrew (Linux) β must run as non-root βββββββββββββββββββββββββββββββββββ | |
| RUN echo "[build] Installing Homebrew..." && START=$(date +%s) \ | |
| && NONINTERACTIVE=1 /bin/bash -c \ | |
| "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" \ | |
| && echo "[build] Homebrew: $(($(date +%s) - START))s" | |
| ENV HOMEBREW_PREFIX=/home/node/.linuxbrew | |
| ENV HOMEBREW_CELLAR=/home/node/.linuxbrew/Cellar | |
| ENV HOMEBREW_REPOSITORY=/home/node/.linuxbrew/Homebrew | |
| ENV HOMEBREW_NO_ANALYTICS=1 | |
| ENV HOMEBREW_NO_AUTO_UPDATE=1 | |
| # ββ Brew skill tools (steipete/tap + standard formulas) ββββββββββββββββββββββ | |
| # - First add steipete/tap (source of gifgrep, songsee, blucli etc.) | |
| # - Then install formulas β each is soft-fail (|| echo) so build never breaks | |
| # if a formula isn't available on Linux homebrew-core | |
| RUN echo "[build] Installing brew skill tools..." && START=$(date +%s) \ | |
| && BREW=/home/node/.linuxbrew/bin/brew \ | |
| && $BREW tap steipete/tap 2>&1 || echo "[brew] WARN: steipete/tap tap failed" \ | |
| && install_brew() { \ | |
| $BREW install "$@" \ | |
| && echo "[brew] β $*" \ | |
| || echo "[brew] β $* (skipped)"; \ | |
| } \ | |
| # Standard homebrew-core formulas | |
| && install_brew himalaya \ | |
| && install_brew 1password-cli \ | |
| && install_brew gogcli \ | |
| && install_brew openhue \ | |
| && install_brew ordercli \ | |
| && install_brew wacli \ | |
| && install_brew xurl \ | |
| && install_brew summarize \ | |
| && install_brew obsidian-cli \ | |
| && install_brew camsnap \ | |
| && install_brew openai-whisper \ | |
| # steipete/tap formulas (fallback if go install above didn't work) | |
| && install_brew steipete/tap/gifgrep \ | |
| && install_brew steipete/tap/songsee \ | |
| && install_brew steipete/tap/blucli \ | |
| && install_brew steipete/tap/eightctl \ | |
| && echo "[build] brew skill tools: $(($(date +%s) - START))s" | |
| # ββ A2A Gateway Extension βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| RUN echo "[build] Installing A2A gateway..." && START=$(date +%s) \ | |
| && git clone --depth 1 https://github.com/win4r/openclaw-a2a-gateway.git /app/openclaw/extensions/a2a-gateway \ | |
| && cd /app/openclaw/extensions/a2a-gateway \ | |
| && npm install --production \ | |
| && echo "[build] A2A gateway: $(($(date +%s) - START))s" | |
| # ββ Coding Agent Extension ββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| COPY --chown=node:node extensions/coding-agent /app/openclaw/extensions/coding-agent | |
| # ββ Pre-configure acpx ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| RUN mkdir -p /home/node/.acpx \ | |
| && echo '{"defaultAgent":"claude","defaultPermissions":"approve-all","format":"text"}' \ | |
| > /home/node/.acpx/config.json | |
| # ββ npm user-local prefix βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| RUN mkdir -p /home/node/.npm-global \ | |
| && npm config set prefix /home/node/.npm-global | |
| # ββ Prepare runtime dirs ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| RUN mkdir -p /app/openclaw/empty-bundled-plugins \ | |
| && node -e "try{console.log(require('/app/openclaw/package.json').version)}catch(e){console.log('unknown')}" > /app/openclaw/.version \ | |
| && echo "[build] OpenClaw version: $(cat /app/openclaw/.version)" | |
| # ββ Scripts + Config + Frontend βββββββββββββββββββββββββββββββββββββββββββββββ | |
| COPY --chown=node:node scripts /home/node/scripts | |
| COPY --chown=node:node frontend /home/node/frontend | |
| COPY --chown=node:node workspace-templates /home/node/workspace-templates | |
| COPY --chown=node:node openclaw.json /home/node/scripts/openclaw.json.default | |
| RUN chmod +x /home/node/scripts/entrypoint.sh /home/node/scripts/sync_hf.py \ | |
| && VERSION_TS=$(date +%s) \ | |
| && sed "s/{{VERSION_TIMESTAMP}}/${VERSION_TS}/g" /home/node/frontend/electron-standalone.html > /home/node/frontend/index.html \ | |
| && echo "[build] Frontend index.html generated (timestamp=${VERSION_TS})" | |
| # ββ Environment βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ENV NODE_ENV=production | |
| ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/openclaw/empty-bundled-plugins | |
| ENV OPENCLAW_PREFER_PNPM=1 | |
| ENV NPM_CONFIG_PREFIX=/home/node/.npm-global | |
| ENV GOPATH=/home/node/go | |
| # Full explicit PATH β user bins first, then system | |
| ENV PATH=/home/node/.npm-global/bin:/home/node/.linuxbrew/bin:/home/node/.linuxbrew/sbin:/home/node/.local/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin | |
| WORKDIR /home/node | |
| CMD ["/home/node/scripts/entrypoint.sh"] | |