Reference

Task Launch

How to model process start truthfully, especially for long-running services.

referenceautomation buildersintermediatestable2026-05-30

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.

  • command owns finite structured argv execution
  • launch owns process start
  • runtime owns what becomes reachable and how readiness is proved
  • run stays the simple shell shorthand for finite tasks
  • script stays 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: sequence when one setup task honestly owns more than one typed setup step under shared requirements/effects, including structural prepare steps and deterministic bootstrap steps, use action.kind: ensure_bundle when 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_checkout when one setup task honestly owns clone-if-missing materialization of a sibling or vendored repo checkout, including optional declared remote reconciliation, and should not bury git clone or git remote add/set-url bootstrap truth in shell glue.
  • Use action.kind: ensure_git_template when one setup task honestly owns deterministic scaffold or factory materialization from a Git-backed template, including inherited .git removal and fresh local git init, and should not bury git clone, rm -rf .git, or git init bootstrap truth in shell glue.
  • Use action.kind: ensure_container_network when one setup task honestly owns shared external Docker network readiness as a standalone lane and should not bury docker network inspect/create logic in shell glue.
  • tasks.<name>.command.exe is the required executable name or path for structured finite commands, and it is generic rather than npm-specific: it may be npm, pnpm, yarn, bun, node, python3, go, bundle, docker, an absolute path, or a repo-local binary.
  • tasks.<name>.command.args is 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.files is 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:        - api

Why 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