Reference
Task Launch
How to model process start truthfully, especially for long-running services.
referenceautomation buildersintermediatestable2026-05-30
Recommended next
Purpose
Use this page when you need to decide whether a task should use run, script, command, or launch.
The strong default for long-running service processes is launch.kind: command.
commandowns finite structured argv executionlaunchowns process startruntimeowns what becomes reachable and how readiness is provedrunstays the simple shell shorthand for finite tasksscriptstays the multiline shell escape hatch
Governance rule
Use launch.kind: command for long-running app servers, docs previews, workers, and similar service processes.
Use command for finite argv-owned tasks such as uv run pytest, poetry run pytest, bundle exec rake test, or npm run build when the repo truth is one executable plus stable arguments.
Use run for finite shell tasks, pipelines, or cases where a structured executable shape would be misleading.
- Choose the finite body by owner boundary: use
prepare.kind: sequencewhen one setup task honestly owns more than one typed setup step under shared requirements/effects, including structural prepare steps and deterministic bootstrap steps, useaction.kind: ensure_bundlewhen one setup task honestly owns more than one deterministic setup action under the same owner, and keep steps as separate finite tasks when they need distinct reuse, separate requirements/effects, or independent operator entrypoints. - Use
action.kind: ensure_git_checkoutwhen one setup task honestly owns clone-if-missing materialization of a sibling or vendored repo checkout, including optional declared remote reconciliation, and should not burygit cloneorgit remote add/set-urlbootstrap truth in shell glue. - Use
action.kind: ensure_git_templatewhen one setup task honestly owns deterministic scaffold or factory materialization from a Git-backed template, including inherited.gitremoval and fresh localgit init, and should not burygit clone,rm -rf .git, orgit initbootstrap truth in shell glue. - Use
action.kind: ensure_container_networkwhen one setup task honestly owns shared external Docker network readiness as a standalone lane and should not burydocker network inspect/createlogic in shell glue. tasks.<name>.command.exeis the required executable name or path for structured finite commands, and it is generic rather than npm-specific: it may benpm,pnpm,yarn,bun,node,python3,go,bundle,docker, an absolute path, or a repo-local binary.tasks.<name>.command.argsis the optional ordered argument list for that structured finite command.- Ota constrains the execution shape, not the binary family
workflows.<name>.adapter_inputs.compose.*is the canonical workflow-owned compose overlay surface for selected compose task paths; use it when one workflow should own the base compose stack, Compose profile set, or project name instead of repeating that truth in task-local adapter inputs.workflows.<name>.adapter_inputs.bake.filesis the workflow-owned Bake overlay surface for selected Bake task paths; ota prepends that base file stack ahead of narrower task-local Bake file additions.
Preferred finite command shape
Finite command taskyaml
tasks: test: command: exe: uv args: [run, pytest]Preferred service shape
Long-running service taskyaml
tasks: dev: launch: kind: command exe: bundle args: [exec, rails, server, -b, 0.0.0.0, -p, "3000"] runtime: kind: service surfaces: - apiWhy this is stronger
- the executable and arguments stay structured instead of disappearing into one shell string
- finite argv tasks stop pretending to be shell just because they are not long-running services
- ota can reason about launch separately from the endpoint contract
- service surfaces, listeners, and readiness stay canonical under
runtime, not duplicated in shell glue - examples and generated docs can teach one stable service-launch shape
Use run when shell is the truth
Finite shell taskyaml
tasks: test: run: pnpm test -- --runInBand