FROM library/python:3.12-bookworm ARG USER=vscode ARG USER_UID=1000 ARG USER_GID=1000 ARG DEBIAN_FRONTEND=noninteractive # Keep in lockstep with "@playwright/test" in package.json. Playwright pins its # browser build to the library version, so a mismatch makes the baked-in # chromium invisible to the tests ("Executable doesn't exist"). ARG PLAYWRIGHT_VERSION=1.61.1 # Base CLI tooling (sudo, git, ripgrep/fd for editors, etc.). RUN apt update && apt install -y --no-install-recommends \ sudo jq vim curl bash-completion \ ripgrep fd-find git make unzip \ && rm -rf /var/lib/apt/lists/* # Passwordless-sudo dev user (UID/GID injected from the host via compose). RUN useradd -m -s /bin/bash -u ${USER_UID} ${USER} \ && echo "${USER} ALL=(ALL) NOPASSWD: ALL" >/etc/sudoers.d/${USER} \ && chmod 0440 /etc/sudoers.d/${USER} # Node 22 (NodeSource). RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ && apt install -y nodejs # GitHub CLI — used by the postCreate skill installer to authenticate against # private Hestia-Homes repos via the host's mounted ~/.config/gh. RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \ && chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ > /etc/apt/sources.list.d/github-cli.list \ && apt update && apt install -y gh \ && rm -rf /var/lib/apt/lists/* # Download Neovim (latest release tarball from GitHub) and symlink onto PATH. RUN curl -fsSL https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.tar.gz \ | tar -xz -C /opt \ && ln -s /opt/nvim-linux-x86_64/bin/nvim /usr/local/bin/nvim # Playwright's OS-level libraries for chromium (fonts, libnss, libasound, ...). # The npm package is a devDependency; this only pulls the apt side, which needs # root. The browser binary itself is fetched as ${USER} further down so it lands # in that user's cache, which is where the tests run from. RUN npx --yes playwright@${PLAYWRIGHT_VERSION} install-deps chromium \ && rm -rf /var/lib/apt/lists/* # Headed-browser viewer stack, mirroring the Model devcontainer. Pipeline: # Xvfb (virtual :99 screen) -> fluxbox (window manager) -> x11vnc (VNC on 5900) # -> novnc/websockify (desktop in a browser tab on 6080). Lets you watch and # click a headed Playwright run; see scripts/start_viewer.sh. Headless runs # don't need any of this. RUN apt update && apt install -y --no-install-recommends \ xvfb fluxbox x11vnc novnc websockify \ && rm -rf /var/lib/apt/lists/* USER ${USER} # LazyVim starter config (.git stripped so the user owns the files). RUN git clone https://github.com/LazyVim/starter /home/${USER}/.config/nvim \ && rm -rf /home/${USER}/.config/nvim/.git # Download + install Claude Code CLI (installs to ~/.local/bin). RUN curl -fsSL https://claude.ai/install.sh | bash ENV PATH="/home/${USER}/.local/bin:${PATH}" # Chromium browser binary, baked into the image so a fresh container is ready to # run without a several-hundred-MB download on first use. Cached under # /home/${USER}/.cache/ms-playwright, which (unlike the workspace) isn't a bind # mount, so it survives as part of the image. RUN npx --yes playwright@${PLAYWRIGHT_VERSION} install chromium USER root WORKDIR /workspaces/assessment-model