# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## What this repo is A single-purpose repository that builds a **CI base image**: `eclipse-temurin:17` (Java 17) extended with Node.js and the Docker CLI/daemon (via `get.docker.com`). The resulting image is meant to be used as a build/runner environment that needs Java, Node, and Docker-in-Docker available together. There is no application code, no test suite, and no build tooling — the entire deliverable is the [Dockerfile](Dockerfile). "Building" means building the Docker image; "shipping" means pushing it to the Gitea container registry. ## Commands ```bash # Build locally (mirror what CI does) docker build -t gitea.tail276105.ts.net/boxi/ci-image:local . ``` CI builds and pushes automatically — see below. There is nothing to lint or test. ## CI/CD — Gitea Actions [.gitea/workflows/docker.yml](.gitea/workflows/docker.yml) runs on every push to `main` and: logs in to the registry → builds the image → tags it as both `${GITHUB_RUN_NUMBER}` and `latest` → pushes both → logs out. Target registry: `gitea.tail276105.ts.net`, image path `boxi/ci-image` (derived from `${{ gitea.repository }}`, lowercased). ### Registry auth — important gotchas The push step is the fragile part. Login can succeed while the push fails with `401 Unauthorized` on `blobs/uploads`. That is **not** a workflow bug — it means the credentials authenticate but lack write access to the `boxi` package namespace. Requirements: - `REGISTRY_USER` must be the **namespace owner** (`boxi`) or a user with write access to that namespace — a separate service user cannot push to `boxi/...`. - `REGISTRY_PASSWORD` should be a Gitea **access token with `write:package` scope** (Gitea → Settings → Applications → Manage Access Tokens). The plain account password fails when 2FA is enabled. ### Package ↔ repository linking A pushed package shows up under the **user namespace**, not automatically under the repository's **Packages** tab. Auto-linking via the `org.opencontainers.image.source` label in the Dockerfile is unreliable here because BuildKit produces a multi-arch manifest list with an attestation manifest, which Gitea's label-based linking does not reliably read. Link the package to the repo **manually once** in the Gitea UI (Package → Package Settings → Repository); the link then persists across future pushes. ## Conventions - Commits & pushes are done by the maintainer manually — do not commit or push unless explicitly asked. - Node 16 in the Dockerfile is EOL; bumping the `setup_NN.x` version is a known pending improvement but is intentionally left untouched to keep scope small.