main runs hud serve and carries the control channel (normally port 8765), and
every other service is exactly what Compose says it is. The boundaries you would otherwise
hand-build inside one container - privilege drops, hidden paths, scrubbed process environments,
supervised startup order - are the container boundaries and depends_on conditions of the project.
The recipe
1 · The document is the contract
A Compose row selects its document with RuntimeConfig.compose; compose_project names the root
that travels when the project is serialized and uploaded. Everything the build needs - contexts,
bind mounts, env_file, configs, secrets - must live under that root. Host environment
interpolation, include, and extends are not part of the serialized contract: the document that
uploads is the document that runs.Every runnable service has an image, a build, or both; paths are relative to the project. An
optional build.sh beside the document is a preparation hook - it resolves or builds prerequisite
images before the runtime starts the project.a task row selecting a project
2 · Build-only services
A project can build a base image without ever starting a base container. scale: 0 keeps the
service in the Compose model - so the build graph can see it - while up starts no container for
it. Another service consumes the built image through a service: named context, and its Dockerfile
uses it as an ordinary stage. docker compose build builds the base because the graph names it,
not because it runs. The Harbor adapter uses exactly this pattern for hud-base and
hud-verifier.compose.yaml · a base image that never runs
3 · Local named contexts
A path-valued named context injects a payload into a build without placing files inside the
authored context - the consuming Dockerfile reads it with standard BuildKit COPY --from syntax.
This is how generated projects keep SDK payload files out of the authored environment directory:
nothing is copied into your tree, and your .dockerignore rules are never rewritten.a payload outside the authored context
- The boundary is the container. The agent’s shell lives in
main’s workspace; sibling services exist for it only as network endpoints. A service the agent may onlycurlneeds no permission tricks - its filesystem is simply not there. Access levels inside a reachable service (a database role, an API credential) are that service’s own configuration. - The build graph is part of the model. Base images, verifier filesystems, and injected
payloads are all expressed inside the document as build-only services and named contexts, so one
docker compose buildreproduces every image on any BuildKit-capable machine - there is no out-of-band build step to keep in sync.
Runtime behavior
LocalDockerRuntime (hud/eval/runtime.py) runs build.sh when present, stages override
files for main’s security options, resources, and an ephemeral host port, starts the project with
docker compose up (--no-build after a successful preparation hook, otherwise --build),
returns the published control-channel address, and removes the project and its volumes when the
rollout ends.
Hosted execution is HostedRuntime like any other environment: hud deploy uploads the
project root, the platform builds every service privately from it, and hosted rollouts run the
stack. Declared RuntimeResources apply.
compose_service_access=True mounts a Docker socket at /media/hud/docker.sock in main. It is
an explicit capability for environment code that must inspect or copy from sibling service
containers, and what it grants differs by placement:
Build on owned infrastructure
An ordinary Compose project builds with the Compose CLI:hud named context, the direct
BuildKit form is below. The hud/ directory must contain every file named by the Dockerfile;
generated Harbor projects use build.sh to materialize their image-configuration inputs before
this build step.
service: additional contexts require the Compose build graph; use docker compose build or the
generated build.sh when the project contains build-only services. Both forms require a Docker
builder with BuildKit named context support.
Run an image directly
DockerRuntime and its Compose override apply the workspace permissions automatically. A direct
docker run must supply the same seccomp profile and system-path setting:
Workspace sandbox. The systempaths=unconfined option lets that
sandbox replace its own /proc and /dev mounts.