Run a harness launcher from a working directory that is mounted at the same absolute path inside the Compose service. The shared launch code resolves the current generation once, validates the working directory against the container's bind mounts, and pins one immutable container ID for the session.
Interactive callers receive a TTY. Piped commands and editor wrappers keep stdin/stdout stream-safe. Arguments after the launcher are forwarded to the harness, and session PID bookkeeping is removed on normal exit or signals.
Each launcher prepends a built-in permission flag (see the harness guides).
Set <HARNESS>_LAUNCH_FLAGS, for example CLAUDE_LAUNCH_FLAGS, in the host
environment or config/.env to replace those flags; an empty value clears
them. The override is read at launch, so it affects new sessions only and never
a running one. Override values are split on whitespace, so an individual flag
value cannot contain whitespace.
When SSH_AUTH_SOCK names a live agent socket, every launch also restores the
host-side relay that forwards it into the sandbox (see Setup), so a
relay that died or lost its agent socket returns without a restart of the stack.
The launch also forwards the host terminal's identity when it is set:
TERM_PROGRAM, TERM_PROGRAM_VERSION, LC_TERMINAL, and LC_TERMINAL_VERSION.
docker exec would otherwise start from the container's environment, and the
harness would fall back to plain text for links and the clipboard.
The launchers are claude-docker, codex-docker, pi-docker, and
vibe-docker, and opencode-docker. Matching *-docker-vscode-wrapper commands provide an executable
path for editor integrations.
harness-docker-ctrl owns the shared Compose lifecycle:
start [--no-cache]validates and bootstraps configuration, then starts the current generation or creates one when necessary;stopstops every generation, whilerestartdeliberately stops all of them before starting fresh;statusreports generation state and live session counts;shellopens the configured container shell at the mirrored working path;exec <claude|codex|pi|vibe|opencode> [args...]invokes a supported launcher;rebuild [--no-cache]refreshes harness installs on cached base layers, starts, health-checks, and switches to a replacement;build-image [--no-cache]builds without starting a generation; andgcremoves non-current generations when they have no fresh host-side session heartbeats.
The controller can start and stop the optional host beeper and invokes a configured notifier hook for lifecycle events. Notification setup is documented with the user-facing examples when they are added.
When config/mcpbridge.jsonc contains an enabled server, start and rebuild
also start the optional host MCP gateway. An absent or empty configuration
stops a previously running gateway, and stop always stops it. Use
mcpbridge-start and mcpbridge-stop to apply configuration changes without a
container rebuild. See Host MCP gateway.
start and build-image reuse the last rebuild's harness layers by default.
If the saved refresh token is missing or invalid, the next build mints one.
rebuild uses the cache but refreshes harness installs. Use --no-cache with
any of those commands to rebuild every image layer.
Every successful image build also updates harness-docker:latest for direct
external docker run calls; managed generations remain pinned to versioned
image tags. When start creates a fresh generation, it finishes by listing the
five harness versions recorded in that image. rebuild instead compares them
with the outgoing image as described in Generations and rebuilds.
See Generations and rebuilds for the current-pointer, session pinning, retirement, and garbage-collection guarantees.
See Updates for the default-branch eligibility and fast-forward workflow.