FROM node:22-slim # Claude Code shells out to git/rg constantly; python3 is needed by the hf CLI installer (it builds a venv). ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ curl \ git \ jq \ less \ python3 \ python3-venv \ ripgrep \ && rm -rf /var/lib/apt/lists/* # Pinned so a job run today behaves like a job run next month. ARG CLAUDE_CODE_VERSION=2.1.220 RUN npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION} \ && npm cache clean --force # --dangerously-skip-permissions is refused when running as root, so the image runs as node (uid 1000). # node:22-slim already ships that user; uid 1000 is also what HF Spaces expects. RUN mkdir -p /workspace && chown -R node:node /workspace WORKDIR /workspace USER node ENV HOME=/home/node ENV PATH=/home/node/.local/bin:${PATH} # Installed as `node` so the venv, wrapper and HF cache all land in a directory this user owns. RUN curl -LsSf https://hf.co/cli/install.sh | bash -s -- --no-modify-path # Bypass permissions by default, for every invocation (interactive, -p, or SDK) — the config # equivalent of --dangerously-skip-permissions, which a bare `claude` call would not pick up. # hasTrustDialogAccepted keeps a fresh /workspace from blocking on the folder-trust prompt. RUN mkdir -p /home/node/.claude \ && printf '%s\n' \ '{' \ ' "permissions": { "defaultMode": "bypassPermissions" },' \ ' "hasTrustDialogAccepted": true,' \ ' "hasCompletedOnboarding": true' \ '}' > /home/node/.claude/settings.json # This image exists to be used as a job image (`hf jobs run` always passes its own command). # The default CMD only serves a placeholder page, so that when the repo is deployed as a Docker # Space the Space itself stays healthy instead of crash-looping. COPY --chown=node:node index.html /home/node/placeholder/index.html ENTRYPOINT [] EXPOSE 7860 CMD ["python3", "-m", "http.server", "7860", "--directory", "/home/node/placeholder"]