Docker Packaging
Spawnfile can generate Docker container artifacts as part of the compile process. This gives you a way to build and run compiled agents against real runtimes using standard Docker tooling.
Core Rule
Section titled “Core Rule”One compile = one container.
The compiler walks the full graph from the root Spawnfile. Everything it resolves — agents, subagents, team members — lands in a single container image. This applies regardless of how many Spawnfiles are in the graph, how many agents are resolved, or how many distinct runtimes appear.
Output Layout
Section titled “Output Layout”The compiler emits container artifacts at the compile output root alongside the runtime-specific output:
.spawn/ Dockerfile entrypoint.sh .env.example container/ rootfs/ var/lib/spawnfile/instances/... runtimes/ openclaw/agents/analyst/... picoclaw/agents/editor/... spawnfile-report.jsonDockerfileandentrypoint.share generated by the compiler based on the resolved graph.runtimes/is the human-inspectable adapter output.container/rootfs/is the final container filesystem for build-time placement into the runtime’s expected paths.
Dockerfile Generation
Section titled “Dockerfile Generation”Base Image
Section titled “Base Image”Each runtime adapter declares container metadata including:
- A standalone base image or install strategy aligned with the pinned runtime ref
- System dependencies
- Expected config and workspace paths inside the container
- The start command and required runtime environment
For single-runtime compiles, the Dockerfile may use that runtime’s base image directly. For multi-runtime compiles, the Dockerfile uses a common base and either installs each runtime or copies prebuilt runtime artifact images with COPY --from.
Pinned Versions
Section titled “Pinned Versions”The runtime version used in the Dockerfile matches the pinned ref from runtimes.yaml. This keeps the container aligned with the runtime version the adapters were written against.
The compile step does not require local runtime clones. The Docker build step is responsible for fetching or installing the pinned runtime artifact.
Entrypoint Generation
Section titled “Entrypoint Generation”The entrypoint script handles:
- Validating required environment variables and files
- Materializing env-backed secret files when a runtime expects file-based auth
- Starting the runtime process(es)
Single-Runtime Agents
Section titled “Single-Runtime Agents”For a single runtime, the compiler pre-places config and workspace files into final runtime paths under container/rootfs/. The entrypoint stays minimal:
- Validate required env vars
- Validate compiled config exists at the expected path
- Write env-backed secret files when needed
execthe runtime’s start command
Multi-Runtime Teams
Section titled “Multi-Runtime Teams”For multiple runtimes in one container, the entrypoint:
- Validates required env and config for each target
- Writes env-backed secret files for each target
- Starts each runtime process
- Traps signals and forwards them to all child processes
- Waits for all processes
Process Mapping
Section titled “Process Mapping”| Project Type | Container Behavior |
|---|---|
| Single agent | One runtime process, one config |
| Agent with subagents | One runtime process — the runtime manages subagent delegation |
| Team on one runtime | One runtime process with multi-agent config, or one process per agent |
| Team on multiple runtimes | One process group, one runtime process per distinct runtime |
Environment and Secrets
Section titled “Environment and Secrets”The compiler emits a .env.example listing all required and optional environment variables:
- Secrets declared in manifests (e.g.
SEARCH_API_KEY) - Model auth variables for providers using
api_keyauth (e.g.ANTHROPIC_API_KEY) - Surface auth variables for declared communication surfaces (e.g.
DISCORD_BOT_TOKEN,TELEGRAM_BOT_TOKEN,SLACK_BOT_TOKEN,SLACK_APP_TOKEN) - Runtime auth variables (e.g.
OPENCLAW_GATEWAY_TOKEN) - Variables the entrypoint or runtime expects
Actual secret values are never emitted. The .env.example contains variable names with empty values and comments.
If a runtime expects secret file references in its config, the adapter declares env-to-file bindings and the entrypoint materializes them before startup.
Auth Profiles
Section titled “Auth Profiles”Spawnfile manages runtime and model auth through local auth profiles. This keeps secrets out of the build and injects them only at run time.
Syncing Auth
Section titled “Syncing Auth”The primary happy path is spawnfile auth sync, which reads model auth intent from the project’s manifests and imports matching local credentials into a named profile:
spawnfile auth sync fixtures/single-agent --profile dev --env-file ./.envThis reads the declared auth methods on each model target and surface, then imports the matching material. For example, if the manifest declares auth.method: claude-code, the sync imports your local Claude Code CLI credentials. If it declares auth.method: api_key, it reads the key from the provided env file.
auth sync also reads declared project secrets from environment.secrets: and inherited team shared.environment.secrets:. Required secrets must be present in the process environment or the provided env file. Optional secrets are copied into the profile only when a value is available.
environment: secrets: - name: GH_TOKEN required: truespawnfile auth sync ./agents/episode-worker --profile dev --env-file ./ops/secrets/episode-worker.envspawnfile run ./agents/episode-worker --auth-profile devThis is the clean path for repository tokens, MCP tokens, and runtime-specific credentials that should be supplied externally instead of committed into the Spawnfile project.
Manual Auth Import
Section titled “Manual Auth Import”Lower-level commands are available for manual profile editing:
# Import a .env file into a profilespawnfile auth import-env --profile dev --env-file ./.env
# Import Claude Code CLI credentialsspawnfile auth import-claude-code --profile dev
# Import Codex CLI credentialsspawnfile auth import-codex --profile devViewing Profiles
Section titled “Viewing Profiles”# List all auth profilesspawnfile auth list
# Show details of a profilespawnfile auth show --profile devAuth Methods
Section titled “Auth Methods”| Method | What Gets Imported |
|---|---|
api_key | Provider API key from env file |
claude-code | Local Claude Code CLI credential store |
codex | Local Codex CLI credential store |
none | Nothing — used for local models |
claude-code and codex imports mount existing local CLI credential stores into runtime homes at spawnfile run time. api_key is the primary path for provider API keys passed as environment variables.
Developer Workflow
Section titled “Developer Workflow”For local development, spawnfile up is the one-command path after auth is synced:
# Sync declared model auth into a local profilespawnfile auth sync fixtures/single-agent --profile dev --env-file ./.env
spawnfile up fixtures/single-agent --out ./bundle/single-agent --tag my-agent --auth-profile dev --detachspawnfile status fixtures/single-agent --out ./bundle/single-agent --liveUse the split-step build and run flow when you want to inspect, extend, or publish the image between steps:
# Compile and build the containerspawnfile build fixtures/single-agent --out ./bundle/single-agent --tag my-agent
# Run with the local auth profilespawnfile run fixtures/single-agent --out ./bundle/single-agent --tag my-agent --auth-profile dev --detachspawnfile status fixtures/single-agent --out ./bundle/single-agent --liveFor teams:
spawnfile auth sync fixtures/multi-runtime-team --profile dev --env-file ./.envspawnfile build fixtures/multi-runtime-team --out ./bundle/team --tag my-teamspawnfile run fixtures/multi-runtime-team --out ./bundle/team --tag my-team --auth-profile dev --detach --deployment devspawnfile status fixtures/multi-runtime-team --out ./bundle/team --live --deployment devThe same commands apply regardless of project complexity. Use up for one-command local startup, or use build and run when you want explicit image staging.
spawnfile build stays secrets-free by default. It compiles the project and then runs docker build against the emitted output directory. The generated Dockerfile installs pinned compiled runtime artifacts — it does not rebuild runtime sources during image build.
spawnfile run is the auth-aware wrapper over docker run. It validates declared model auth before container startup, mounts the right credential material from the selected profile, and attaches any persistent volumes reported by the compiler.
Command boundaries:
spawnfile compilevalidates the graph and writes runtime output, container artifacts, and the compile report.spawnfile buildrunscompile, then builds a Docker image from the generated output.spawnfile runrunscompileagain to derive current runtime wiring, then starts the selected image with ports, env, auth material, and workspace resources.spawnfile upis the local one-command path. It builds the image and then runs it with the same auth and env options asrun.spawnfile dev upstarts a detached development deployment under.spawn-dev;spawnfile dev apply --agent <id>hot-loads one Pi agent into that running container without rebuilding or restarting the rest of the org.spawnfile statusreads the authored graph and compile report by default. With--live, it reads the detached deployment record and inspects the recorded Docker target.
Managed Moltnet SQLite/JSON stores and open-registration agent token directories appear in the compile report as container.persistent_mounts[]. spawnfile run and spawnfile up mount those entries as Docker named volumes so messages, registrations, and generated open-mode agent tokens survive container replacement.
Dev Hot Apply
Section titled “Dev Hot Apply”Use dev mode when you are adding or editing Pi agents and want a tight feedback loop:
spawnfile auth sync fixtures/e2e/pi-harness-org --profile dev --env-file ./.envspawnfile dev up fixtures/e2e/pi-harness-org --auth-profile dev --deployment devspawnfile dev apply fixtures/e2e/pi-harness-org --agent observer --deployment devdev up is a normal detached Docker deployment, but its default output root is
.spawn-dev. dev apply recompiles source into that dev output root without
deleting the record, copies the selected Pi agent workspace/config, matching
Moltnet node configs, and managed Moltnet server configs into the recorded
container, asks the generated Daimon app to load it, and starts only that new
agent’s Moltnet bridges. Existing agents keep running. Running managed Moltnet
servers keep current room membership until an operator-token moltnet apply or
server restart reconciles the copied server config.
Detached Deployments
Section titled “Detached Deployments”Detached run and up write deployment records only after the container starts successfully:
spawnfile up . --detach --deployment dev --auth-profile devspawnfile status . --live --deployment devRecords live under .spawn/deployments/ and store the deployment manager, target, compile fingerprint, image/container ids, hosted agents, runtime instances, and user-provided env-file path. They never store secret values.
If you start the same deployment name again, Spawnfile reuses the recorded target, auth profile, image tag, container name, and user env file unless the command explicitly overrides them. The new successful detached start then replaces the record:
spawnfile up . --detach --deployment devRemote Docker Contexts
Section titled “Remote Docker Contexts”Use Docker contexts when the deployment runs on a remote machine:
docker context create vm1 --docker "host=ssh://ops@example-vm"spawnfile up . --detach --deployment prod --context vm1 --auth-profile prodspawnfile status . --live --deployment prodThe deployment record stores the resolved Docker target. Context targets store the context name plus a fingerprint of the resolved daemon endpoint; DOCKER_HOST deployments store a host target. If a recorded context later points somewhere else, live status reports drift instead of falling back to the local daemon.
You can also pass an env file directly at run time:
spawnfile run ./agents/episode-worker --env-file ./ops/secrets/episode-worker.envThis writes the provided values into Spawnfile’s generated Docker env file for that run. When both an auth profile and --env-file provide the same variable, the env file value wins; if the same variable is set in the shell environment, the shell value wins.
Project-Specific Tools
Section titled “Project-Specific Tools”The generated image contains the compiled organization and runtime support. If an agent needs extra project tools, build a small overlay image on top of the generated image instead of editing the generated Dockerfile:
ARG BASE_IMAGE=my-team:spawnfileFROM ${BASE_IMAGE}
USER rootRUN apt-get update \ && apt-get install -y --no-install-recommends gh python3-pip \ && rm -rf /var/lib/apt/lists/*USER spawnfilespawnfile build . --tag my-team:spawnfiledocker build -f ops/docker/agent-tools.Dockerfile \ --build-arg BASE_IMAGE=my-team:spawnfile \ -t my-team:tools .spawnfile run . --tag my-team:tools --auth-profile devKeep credentials out of the overlay image. Declare required tokens as environment.secrets: or shared.environment.secrets:, then provide them with spawnfile auth sync --env-file ... or spawnfile run --env-file ....
Runtime Inputs
Section titled “Runtime Inputs”Spawnfile supports the common runtime inputs directly in the manifest:
| Runtime need | Spawnfile declaration |
|---|---|
| Repository checkout | workspace.resources with kind: git and a workspace-relative mount |
| Shared scratch directory | shared.workspace.resources with kind: volume and sharing: team |
| Per-agent state or cron data | workspace.resources with kind: volume and default sharing: per_agent |
| Required tokens | environment.secrets: or shared.environment.secrets: plus auth sync or run --env-file |
| Model CLI credentials | execution.model.*.auth.method plus an auth profile |
| Extra operating system packages | Overlay image based on the generated image |
Resource mounts are symlink-backed inside the runtime workspace. Use workspace-relative mounts such as ./repos/product, ./state, and ./cron so each agent sees stable paths without depending on runtime-internal directories.
Manual Docker
Section titled “Manual Docker”Manual Docker remains valid against the compile output:
spawnfile compile fixtures/single-agent --out ./bundle/single-agentcd ./bundle/single-agentdocker build -t my-agent .cp .env.example .env# Fill in secret values...docker run --env-file .env -p 18789:18789 my-agentIf the compile report includes container.persistent_mounts[], add matching -v <volume_name>:<mount_path> arguments to manual docker run commands.
Compile Report Container Section
Section titled “Compile Report Container Section”The compile report includes a container section:
{ "container": { "runtimes_installed": ["openclaw", "picoclaw"], "dockerfile": "Dockerfile", "entrypoint": "entrypoint.sh", "env_example": ".env.example", "secrets_required": ["SEARCH_API_KEY", "ANTHROPIC_API_KEY"], "ports": [3000] }}What Container Compilation Does Not Cover
Section titled “What Container Compilation Does Not Cover”These are out of scope for v0.1:
Image publishing and sourceless run are covered separately in the Distribution guide.
- Docker Compose generation for multi-container topologies
- Orchestration (Kubernetes, ECS, Fly, etc.)
- Runtime-native auth bootstrap (onboarding flows stay manual)
HEALTHCHECKinstructions or readiness contracts- Volume management and persistence strategy
- Network topology between containers
- CI/CD integration