# Canonical claude-code Dockerfile — vendored from
# @ai-hero/sandcastle's InitService.ts (CLAUDE_CODE_DOCKERFILE constant).
# Kept here so `runway init` can write it directly, without invoking
# `sandcastle init` (which has interactive prompts that hang in
# non-TTY environments like CI / Mac Mini cron).
#
# Drift policy: when sandcastle bumps its claude-code Dockerfile,
# refresh this file. The diff should be tiny — runway's tier 2 layer
# patches AFTER this base, so adopters re-run `runway init --force`
# to roll forward.

FROM node:24-bookworm

# Install system dependencies
RUN apt-get update && apt-get install -y \
  git \
  curl \
  jq \
  && rm -rf /var/lib/apt/lists/*

# Build-args for UID/GID alignment: defaults match the host user's
# UID/GID at build time so image-built files and bind-mounted files
# share an owner without runtime chown.
ARG AGENT_UID=1000
ARG AGENT_GID=1000

# Rename the base image's "node" user to "agent" and align UID/GID.
#
# Divergence from sandcastle's stock Dockerfile: stock runs
# `groupmod -g $AGENT_GID node` unconditionally, which fails on macOS
# hosts where the host GID is 20 (`staff`) — Debian's `dialout` group
# already has GID 20, and `groupmod` refuses to assign a duplicate
# GID. We guard with `getent group` so groupmod only runs if the
# target GID is unused; if it's already taken, we point the agent
# user at the pre-existing group via `usermod -g <gid>` and the
# image still works (the in-image group name is irrelevant — only the
# numeric GID matters for bind-mount permissions).
RUN if ! getent group $AGENT_GID >/dev/null; then \
      groupmod -g $AGENT_GID node; \
    fi \
 && usermod -u $AGENT_UID -g $AGENT_GID -d /home/agent -m -l agent node

# VA-351: bake the container env up front so agents don't manually
# work around host-path leaks, missing pnpm, or unset HOME on every
# iteration. Without these, every agent run repeats the same
# corepack/TURBO_CACHE_DIR/HOME setup commands — see VA-312's run log
# for the receipts.
ENV HOME=/home/agent
ENV XDG_CACHE_HOME=/home/agent/.cache
ENV TURBO_CACHE_DIR=/tmp/turbo-cache
ENV pnpm_config_cache=/home/agent/.cache/pnpm
# VA-457: pin corepack's data dir under the agent's cache. `corepack
# prepare` below runs as root (before the USER switch), so without
# COREPACK_HOME it would write the cached pnpm tarball to /root's
# default and the agent UID couldn't read it. Anything that resolves
# `pnpm` through the corepack shim after `USER` — git hooks invoked
# by lefthook in particular — then fails or hangs trying to refetch.
ENV COREPACK_HOME=/home/agent/.cache/corepack

# Pre-create cache dirs with agent ownership so the first pnpm/turbo
# run doesn't have to chown them. Both are inside paths the agent owns
# anyway; this just makes them exist.
RUN mkdir -p /home/agent/.cache /home/agent/.cache/pnpm /home/agent/.cache/corepack /tmp/turbo-cache \
 && chown -R $AGENT_UID:$AGENT_GID /home/agent/.cache /tmp/turbo-cache

# Bake pnpm via corepack at build time so `pnpm` is on PATH inside the
# container before any agent command runs. Pin a default; target repos
# can override at runtime via `packageManager` in package.json +
# `corepack use`. COREPACK_HOME is set above so the data dir lands
# under /home/agent/.cache/corepack; the trailing chown re-asserts
# agent ownership over the files root just wrote there.
RUN corepack enable \
 && corepack prepare pnpm@11.1.1 --activate \
 && chown -R $AGENT_UID:$AGENT_GID /home/agent/.cache/corepack

USER ${AGENT_UID}:${AGENT_GID}

# Install Claude Code CLI
RUN curl -fsSL https://claude.ai/install.sh | bash

# Add Claude to PATH
ENV PATH="/home/agent/.local/bin:$PATH"

WORKDIR /home/agent

# In worktree sandbox mode, Sandcastle bind-mounts the git worktree at
# the sandbox repo dir and overrides the working directory to that dir
# at container start.
ENTRYPOINT ["sleep", "infinity"]
