Workflow YAML (config.yml)
Save a project workflow at workflows/<name>/config.yml, then run it with
dockpipe --workflow <name> -- from that project. Installed workflow packages are
also discoverable by name. Use --workflow-file /path/to/config.yml for an explicit
file instead of name lookup.
If you are new to authoring workflows, start with workflow-authoring.md. This page is the field reference; examples are configuration patterns, not a list of preinstalled workflows. See the package model for source/store precedence.
Recommended mental model
For most users, the main concepts are:
- workflow — what should happen
- step — one host or container action inside that workflow
- runtime — where a step runs
- resolver — which tool/profile the step uses
Everything else is secondary:
isolateis the low-level image/template overridestrategyis an advanced lifecycle wrapper
If you are writing a normal workflow, prefer thinking in terms of steps + runtime + resolver first.
Defaults and overrides
Dockpipe uses a simple layering rule:
- top-level
runtimeandresolverset the workflow default - step-level
runtimeandresolveroverride that default for one step isolateis the advanced low-level override when you need to pin the exact image/template
In practice, most workflows should:
- set
runtimeandresolveronce at the top - override them only on the few steps that genuinely differ
- reach for
isolateonly when a step must pin a specific image/template rather than just a substrate/profile
Profiles: workflows select installed runtimes, resolvers and strategies by name. They do not define new execution substrates. Keep tool integrations in resolver packages; see the architecture model.
Arbitrary-path workflow: --workflow-file <path> accepts the same YAML shape.
Relative run: / act: paths resolve beside that file. Resolver definitions come
from the configured package/core lookup, not an arbitrary resolver folder beside
the file. Do not combine --workflow and --workflow-file.
Validate: use dockpipe workflow validate workflows/hello/config.yml from your
project. Validation checks YAML/schema structure; it does not install dependencies,
authenticate providers, execute commands or prove that a workflow will succeed.
Terminology (same as the CLI):
| Word | Meaning |
|---|---|
| run | Host scripts before the container (paths under run:). |
| isolate | Low-level image or template override. Most workflows should start with runtime + resolver and only set isolate when they want to pin the exact image/template. |
| image | Optional image customization for Dockerfile-backed runs. Use image.packages.apt to declare Debian packages that Dockpipe installs into a derived image during package compile/build, instead of bloating every resolver image. Step-level image adds packages for that step only. |
| act | Follow-up after the main command (usually a host script; see ../concepts/architecture.md for in-container DOCKPIPE_ACTION). |
| workflow | This file: a named preset selected with --workflow <name>. |
| strategy | Optional named lifecycle wrapper: small KEY=value files under templates/<workflow>/strategies/<name> (optional) or templates/core/strategies/<name> define host scripts to run before and after the workflow body. See Named strategies below. |
| runtime / resolver | Runtime selects where execution runs; resolver selects an installed tool integration. Profiles come from core and configured package stores. See Architecture model and Isolation. |
Learning path: ../onboarding.md · ../concepts/architecture-model.md · ../concepts/isolation-layer.md.
Single-command vs multi-step
| Mode | When | config.yml |
|---|---|---|
| Single flow | No steps: (or empty) |
Top-level run, runtime / resolver (or advanced isolate), and act / action describe one run. This is the compact shorthand for simple workflows. |
| Multi-step | Non-empty steps: |
Each list item is a step. A step is either a container step (default) or a host step (kind: host). The CLI argument after -- can supply the last step’s command if that step has no cmd/command. Top-level run and act / action are not used in this mode. Optional finally: steps run after the main steps even when a step fails or the run is interrupted. |
Variable precedence for workflows is documented in CLI reference (CLI > config > .env / --env-file / --var).
Image Packages
Workflow authors can declare extra Debian packages for container steps without changing the base runtime or resolver image:
resolver: codex
image:
packages:
apt:
- golang-go
- cargo
steps:
- id: rust-check
cmd: cargo test
image:
packages:
apt:
- rustcDockpipe materializes these declarations as a derived Docker image at package compile/build time. Keep common inspection tools in resolver images; declare heavier project-specific toolchains here.
Host Dependencies
Use dependencies.host when a workflow needs a host executable before it can run. Dockpipe checks
required dependencies before workspace/session mutation or step execution. If the command is missing
and the current host platform is supported, Dockpipe can run the package/workflow-authored install
command after explicit approval (--yes, DOCKPIPE_APPROVE_PROMPTS=1, or an interactive confirm).
platforms: [windows, deb]
dependencies:
host:
- id: act
command: act
description: Runs GitHub Actions workflows locally.
install:
windows: winget install nektos.act
deb: sudo apt-get update && sudo apt-get install -y actcommand is the executable name searched on PATH. required defaults to true; set
required: false to document optional tooling without failing preflight. Top-level platforms
may contain windows, macos, linux, deb, or flatpak; when set, Dockpipe blocks the workflow/package on
unsupported hosts and only offers installers on supported platforms. Every required host dependency
and host script must work on each declared platform. install.<platform> is an
author-provided shell command and must be treated as code. Host dependencies are not package graph
dependencies; use package depends for other Dockpipe packages.
Flatpak is a distinct execution platform and does not implicitly satisfy linux or deb.
Distribution install hints are never offered inside Flatpak. The selected package can provide
executables under assets/tooling/bin; dependency preflight checks that directory first,
and package host scripts receive it at the front of their process-local PATH. Shared
libraries must use package-owned loader paths rather than changing global library search paths.
DorkPipe orchestration cloud workers also accept a run-level consumer image override:
vars:
DORKPIPE_ORCH_CONTAINER_IMAGE_PACKAGES: "make cmake libxml2-utils"When Codex or Claude orchestration workers need extra Debian packages, DorkPipe generates a derived
Dockerfile from the provider image, tags the image with a checksum of provider + base image + package
list, builds it once if missing, and runs workers with --isolate <generated-image>. This keeps
tooling deterministic and cacheable instead of installing packages inside every worker container at
startup.
This override is intentionally consumer-owned. Resolver images keep only a lean baseline, so project workflows should request their own heavier language stacks, for example:
vars:
DORKPIPE_ORCH_CONTAINER_IMAGE_PACKAGES: "python3 ruby-full golang-go dotnet-sdk-8.0"The generated Dockerfile adds Microsoft's Debian package feed on demand when the requested package
set includes .NET packages such as dotnet-sdk-8.0. DORKPIPE_ORCH_CONTAINER_APT_PACKAGES
remains accepted as a compatibility alias, but new workflows should use
DORKPIPE_ORCH_CONTAINER_IMAGE_PACKAGES.
Cloud Codex/Claude workers run a host-auth preflight before the container starts. API-key env vars
pass immediately; otherwise DorkPipe checks the provider auth files resolved by dockpipe scope resolver <name> auth-dir. When auth is missing and the run is interactive, DorkPipe asks whether to
launch the host login command (codex login or claude auth login) and re-checks after the user
finishes. Set DORKPIPE_ORCH_AUTH_LOGIN_ON_MISSING=never to fail fast, or always to launch the
login command without asking. Non-interactive runs fail fast with the manual command to run.
DorkPipe orchestration logging is controlled by DORKPIPE_ORCH_LOG_MODE:
defaulthides raw worker, Docker Compose, and Ollama pull chatter behind progress lines, but prints failure log tails.minimalcurrently behaves likedefaultfor orchestration scripts and is reserved for stricter future output pruning.verbosestreams raw provider and Docker output.nonesuppresses orchestration progress lines where package scripts own the output.
Dev-stack logging can be overridden separately with DORKPIPE_DEV_STACK_LOG_MODE; otherwise it
inherits DORKPIPE_ORCH_LOG_MODE.
If a workflow grows beyond one simple run, prefer moving to steps: instead of piling more meaning onto top-level run / act.
Once you switch to steps:, move those fields onto the specific step that needs them.
Use finally: for teardown that must happen on failure paths as well:
steps:
- id: stack_up
kind: host
run: scripts/dorkpipe/dev-stack-ensure-up.sh
finally:
- id: stack_down
kind: host
run: scripts/dorkpipe/dev-stack-maybe-down.shHost steps (kind: host)
Most steps are container steps. A step becomes a host step when you set kind: host.
For host steps, run: scripts execute on the host. Use kind: host when the step genuinely needs host-side behavior, such as:
- starting or stopping a local helper stack
- calling a host-only CLI
- launching a local GUI tool
- preparing files before a later container step
If a host step starts sidecars or helper containers, the runner can clean them up after the step. The exact marker files and cleanup internals are engine behavior; workflow authors usually only need to know that host steps may register cleanup state under .dockpipe/ and that cleanup can be disabled with DOCKPIPE_SKIP_HOST_CLEANUP=1 when a workflow wants to keep the sidecar alive deliberately.
| Variable | Meaning |
|---|---|
DOCKPIPE_LAUNCH_MODE |
Optional hint for vars: / templates — e.g. gui means the step opens a GUI on the host (desktop app, not a detached “server” process). Scripts can print clearer messaging; dockpipe still waits on the host script until it exits unless the script itself returns early. |
DOCKPIPE_SKIP_HOST_CLEANUP |
If 1 or true, the runner skips ApplyHostCleanup after the host script exits (escape hatch: you stop containers yourself). |
Step working directory and scopes
Steps run from the source workdir by default. Use cwd: repo or cwd: source when
the step should start in the checkout. When a step writes generated files with simple relative
paths, set cwd: artifacts:
steps:
- id: normalize
kind: host
cwd: artifacts
run:
- scripts/dorkpipe/normalize-ci-scans.shDockpipe creates the workflow artifact root under
bin/.dockpipe/workflows/<workflow>/artifacts and starts the step there. Scripts can write
ordinary relative paths such as ci-analysis/findings.json without polluting source control.
Scripts should write ordinary relative paths whenever cwd already puts them in the right root.
When a script needs an explicit generated path, use dockpipe scope. If a path must point back
into the checkout, make that explicit with dockpipe scope source.
When a step needs both worlds, keep cwd: repo and bind source/artifact scopes explicitly:
steps:
- id: doctor
kind: host
cwd: repo
scopes:
source: repo
artifacts: artifacts
run: assets/scripts/cloud-lanes-doctor.shIn that form the process starts in the checkout, while dockpipe scope returns the current workflow
scope object, including source_root, output_root, and dockpipe_bin. Use
dockpipe scope artifacts <path> to resolve under the workflow artifact root.
Relative outputs: files resolve under the output/artifact scope, not the process cwd.
Durable package state uses the same primitive. It is owner-only OS state keyed by stable project
identity and exact package owner ID, outside disposable bin/.dockpipe/**:
dockpipe scope --package dorkpipe
dockpipe scope --package acme.tool settings.json
dockpipe scope workflow docs.orchestrate orchestrateThe package scope object includes the same durable path in root and state_root, plus workdir
and dockpipe_bin. Package caches, build products, scratch, and run evidence use
PackageRuntimeDir or shell SDK dockpipe_sdk path package-runtime <owner-id> ...; workflow
artifacts remain under workflow scope.
Resolver packages can expose resolver-owned paths through their profile, then scripts can read them without hardcoding provider-specific environment names:
dockpipe scope resolver codex auth-dir
dockpipe scope resolver codex container-auth-dir
dockpipe scope resolver codex auth-mount-modeDorkPipe agent orchestration also accepts full-string scope references in path lists such as
agent.accessible_paths, agent.access.read/write/deny, and task context fields:
context:
required_artifacts:
- scope:workflow:docs.orchestrate:orchestrate/verify/result.json
- scope:artifacts:orchestrate/tasks/latest_run_audit/response.mdThose references are resolved through the same dockpipe scope CLI before prompts and task JSON are
written. Use plain relative paths for normal checkout files.
Shared collectors may declare starting_points when a collector needs concrete seeds:
shared:
- path: repo-map.md
collector: repo_map
focus: Current orchestration contract
starting_points:
- packages/dorkpipe/resolvers/dorkpipe/assets/docs/orchestration-contract.mdUse starting_points as optional collector hints only. Do not duplicate broad mounted roots there;
mounts and access.read define the actual exploration boundary.
For task execution lanes, define reusable role agents in sibling agents.yml, then reference those
roles from tasks. If that sibling is absent, DorkPipe searches parent workflow directories for the
nearest agents.yml; the sibling always wins. Search stops at the owning workflows/ directory or,
for package workflows, the package directory containing package.yml; it never falls back to an
unbounded repository-level agents.yml.
agents:
source_scout:
role: source scout
worker: ollama
worker_type: planning
patch_decider:
role: patch decision owner
worker: codex
worker_policy:
mode: require
work_mode: edit
worker_type: patch_decisiontasks:
- id: scout_repo
agent: source_scout
brief: Inventory current repo evidence.
context:
required_artifacts:
- shared/repo-map.mdworker: codex|claude|ollama belongs on the role definition, not each task. DorkPipe maps the role
to seeded lane defaults such as preferred lane family and model provider. By default
worker_policy.mode: prefer lets the orchestrator fall back, compare, or escalate when policy says
it should. Use worker_policy.mode: require only when that role must stay on that worker profile.
Role work_mode separates readonly artifact collection from direct workspace editing. The default
artifact mode tells Codex/Claude workers to inspect mounted sources and return the requested
artifact in response.md; DorkPipe apply/promotion writes approved files later. Set work_mode: edit only for implementation or repair tasks, and pair it with writable container mounts plus
matching agent.access.write policy.
Dockpipe also injects these variables for every step:
| Variable | Meaning |
|---|---|
DOCKPIPE_SOURCE_ROOT |
Absolute source workdir/repo root. Use this when a script running from artifacts needs to read project files. |
DOCKPIPE_ARTIFACT_ROOT |
Absolute generated artifact root selected by scopes.artifacts. |
DOCKPIPE_OUTPUT_ROOT |
Alias for the output/artifact scope used by dockpipe scope. |
DOCKPIPE_STEP_CWD |
Absolute directory Dockpipe uses as the process working directory for the step. |
Top-level keys
| Key | Purpose |
|---|---|
name |
Optional display title for stderr (defaults to the template folder name, e.g. run). |
description |
Optional one-line task summary printed after name (e.g. what this workflow is for). |
category |
Optional UI metadata for tools like Pipeon: e.g. app marks a launchable GUI/container IDE-style workflow shown in Basic mode. Omit or use other values for pipelines and advanced-only flows. |
vars |
Map of default env vars (merged if not already set; --var overrides). |
compose |
Optional Docker Compose settings for host built-ins such as compose_up, compose_down, and compose_ps. Fields: file, project, project_directory, autodown_env, exports, services. Compose runs inherit Dockpipe’s resolved environment and vault-injected vars directly. |
container |
Optional container mount defaults. Use this to override the primary host path bound at /work (workdir_host), set a default container subdirectory under /work (work_path), and declare extra bind mounts (mounts). Relative host paths resolve from the active source/workdir, not the packaged workflow asset directory. |
workspace |
Optional runtime-owned Git workspace/session lifecycle. Use mode: managed for a Dockpipe-owned session workspace, or mode: bind only when a workflow intentionally operates on the current checkout. |
security |
Optional container security policy. Select a core-owned profile, then apply bounded network, filesystem, and process overrides. This applies to container execution only; kind: host steps remain outside Docker policy. |
run |
String or list of host pre-script paths (repo scripts/… or paths under the template). Single-flow shorthand only; do not combine with steps:. Logical resolver script ids like scripts/dorkpipe/... must also have an explicit resolver dependency (requires_resolvers, inject.resolver, or workflow/step resolver selection). |
isolate |
Advanced low-level image/template override. Prefer runtime + resolver for the normal authoring path; use isolate when you need to pin the exact image/template. |
act / action |
Action script after the container command (when not using per-step act). Single-flow shorthand only; do not combine with steps:. |
runtime |
Main where does this run? field. Names an existing core runtime profile under templates/core/runtimes/<name>. Also acts as the default for steps unless a step overrides it. |
resolver |
Main which tool/profile does this use? field. Names an existing core resolver profile under templates/core/resolvers/<name>. Also acts as the default for steps unless a step overrides it. |
steps |
List of steps (multi-step mode). |
imports |
List of paths (relative to this file) to merge before this file: each imported file’s vars are merged (later files override), then steps from imports run before steps here. Circular imports are rejected. Requires loading from disk (not raw bytes-only parse). Use this when you want to change the authored workflow itself. |
inject |
Compile-closure dependencies only. Use this when compile needs extra workflows/packages/resolvers included, but you do not want to merge their YAML into this workflow. inject.resolver also counts as an explicit dependency for logical resolver script ids like scripts/dorkpipe/.... |
strategy |
Default strategy name when the CLI does not pass --strategy <name>. |
strategies |
Optional allowlist: if non-empty, the effective strategy (CLI --strategy or strategy:) must be one of the listed names. |
docker_preflight |
Default true. When false, the runner skips the Docker reachability check before steps: if no step uses the container. Use for host-only workflows whose run: / pre_script scripts do not invoke Docker. If a script calls docker, keep the default or the workflow may fail later. |
types |
Optional PipeLang type entrypoints used by tooling/catalog/launcher surfaces. Execution still runs through normal workflow YAML and env resolution. |
model_policy |
Optional AI model attempt, validation, and escalation policy for DorkPipe harnesses. Use this to express cheap/local attempts, stronger validation, and approval-on-cost escalation intent. |
view |
Optional authored launcher presentation layer. Define pages, sections, and ordered field paths over the typed model while keeping the underlying env contract unchanged. |
Provider-Pool Model Policy
DorkPipe agent workflows can opt selected workflow/subagent workers into the shared provider-pool leasing path without naming a provider-specific YAML field:
model_policy:
execution_mode: provider_pool
role: reviewer
session_scope: workflow
max_active: 1
queue_timeout_seconds: 30execution_mode: provider_pool makes the DorkPipe worker script call dorkpipe provider-pool prompt --json for that worker instead of spawning a direct provider CLI. role is a provider-neutral attribution/session grouping label. session_scope: node isolates each subagent node; session_scope: workflow reuses a role session within the workflow run. max_active narrows the provider catalog's active lease cap for that policy, and queue_timeout_seconds controls how long the worker waits before returning a visible queued failure.
imports vs inject
These two fields solve different problems:
importschanges the workflow you are authoring by merging in other YAMLinjectchanges what compile must include, but does not merge YAML
If you want more vars or earlier steps to become part of this workflow, use imports.
If you want compile/package closure to include additional workflows, packages, or resolver profiles without changing this workflow’s authored structure, use inject.
types and view
Use types: when you want a workflow to expose a typed model to tooling.
Use view: when you want to control how launcher-style clients present that model.
The intended split is:
- PipeLang (
types:) defines data shape, nested objects, lists, defaults, and docs - workflow YAML (
view:) defines pages, sections, ordering, and field-path layout - workflow YAML (
view:) may also define an authored entry choice that writes to a model field and routes the user into the relevant page set vars:/ env names remain the runtime contract consumed by the workflow itself
Minimal example:
types:
- ../../resolvers/qemu/models/QemuVmResolverConfig.pipe
view:
entry:
type: choice
field: General.BootSource
title: Windows VM Source
options:
- value: image
label: Boot existing disk image
pages: [image]
- value: installer-iso
label: Install from ISO
pages: [install]
pages:
- id: image
title: Existing Image
sections:
- id: media
title: Existing Image
fields:
- Storage.Disk
- id: install
title: Install Media
sections:
- id: media
title: Images And Media
fields:
- Storage.CdromRules:
types:is optional. Workflows without it remain plain YAML/env workflows.view:is optional. When omitted, launchers may fall back to the older flat/tree rendering.view.entryis optional. Use it when the launcher should ask a high-level question first and route to the relevant settings pages.view.entry.fieldpoints at a typed model field path, and the chosen option writes that value back into the model/env contract.view.entry.options[].pages[]andview.entry.options[].nextdescribe which page ids should be shown after that choice.view.sections[].fields[]contains field paths into the root typed model, such asGeneral.BootSource.view:is a presentation layer only. It does not replacevars:or create a second runtime binding mechanism.- Invalid field paths should be ignored/pruned by tooling rather than breaking workflow execution.
For PipeLang details, see ../concepts/pipelang.md.
security
Use security to express container hardening intent without dropping to raw Docker flags.
Recommended shape:
security:
profile: secure-default
network:
mode: offline
filesystem:
root: readonly
writes: workspace-only
process:
user: non-root
pid_limit: 256Public authoring fields:
profile:secure-default|internet-client|build-online|sidecar-clientnetwork.mode:offline|restricted|allowlist|internetnetwork.allow,network.block: destination patterns for allowlist/restricted intentfilesystem.root:readonly|writablefilesystem.writes:workspace-only|declaredfilesystem.writable_paths,filesystem.temp_pathsprocess.user:auto|non-root|rootprocess.pid_limitprocess.resources.cpu,process.resources.memory
Dockpipe compiles this into an effective runtime policy manifest and derives the actual enforcement mode there. Public workflow YAML does not set raw Docker security options or the low-level network enforcement mechanism directly. See ../security/security-policy.md for the policy model.
workspace
Use workspace when a workflow should run inside a runtime-owned Git session instead of letting
agents or package scripts own Git lifecycle commands.
workspace:
repo: /path/to/your/project
mode: managed
lifecycle:
branch_prefix: ai
branch: feature/reporting
checkpoint: auto
publish: reviewPublic fields:
repo: logical repository identity or source path/URL.mode:managedorbind.managedis preferred and creates a Dockpipe-owned session workspace;bindopts into the current checkout.base: optional base ref for the session branch; defaults toHEAD.storage: optional advanced implementation hint:worktree,volume, orclone.volumecreates a Docker named volume for container/workwhile keeping a managed Git worktree as the checkpointable source of truth.cloneis reserved for future distributed workers.lifecycle.branch_prefix: branch prefix for the runtime-created session branch; defaults toai.lifecycle.branch: exact session branch name. Use this when a repository has a required branch naming convention; it overrides thebranch_prefix+ session-id derived branch name. The session id remains a separate safe metadata key.lifecycle.checkpoint:manual,auto, orstep.lifecycle.publish:none,branch, orreview.
Current implementation:
mode: managedcreates a runtime-owned Git worktree underbin/.dockpipe/sessions/<id>/workspaceand runs the workflow from that workspace.mode: managedplusstorage: volumecreates a runtime-owned Docker volume and mounts it at/workfor container runs. The runner overlays the worktree into the volume before each container run and overlays volume changes back into the worktree after the run for checkpoints.mode: bindchecks out a runtime-created session branch in the current source checkout.- Dockpipe writes session metadata and event logs under
bin/.dockpipe/sessions/<id>/. - Runtime lifecycle operations now include
CreateSessionBranch,CheckpointSession,SyncSession,PublishSession,ArchiveSession,CreateWorkerLease, andReleaseWorkerLease. - Agents should request lifecycle transitions through Dockpipe behavior; they should not run raw
Git commands such as
git commit,git pull, orgit push.
The long-term architecture is documented in ../runtime/git-runtime-sessions.md.
Named strategies
Strategies are reusable before/after wrappers for a workflow run. Use them when multiple workflows should share the same lifecycle behavior, such as worktree setup or commit-on-success.
Shared definitions live under templates/core/strategies/; see ../concepts/architecture-model.md ( templates/core/ layout ).
Resolution order for the strategy file path: --strategy <name> (overrides strategy: in YAML when both are set) → templates/<this-workflow>/strategies/<name> (beside that workflow’s config.yml, if present) → templates/core/strategies/<name> (see ResolveStrategyFilePath in src/lib/application/strategy.go).
File format (KEY=value, # comments):
| Key | Meaning |
|---|---|
DOCKPIPE_STRATEGY_BEFORE |
Comma-separated repo-relative script paths (under scripts/… from repo root, or paths relative to the workflow template dir), run in order on the host before run: / the container / steps:. |
DOCKPIPE_STRATEGY_AFTER |
Same, run after the workflow body completes successfully (exit 0). Bundled scripts/commit-worktree.sh is treated like today’s commit-on-host path (single commit, no duplicate with workflow act: when the strategy owns commit). |
DOCKPIPE_STRATEGY_KIND |
Optional tag (e.g. git) for documentation only. |
Built-in names (bundled under templates/core/strategies/):
| Name | Role |
|---|---|
worktree |
before: scripts/clone-worktree.sh · after: scripts/commit-worktree.sh — clone/worktree on the host, then resolver-driven isolate, then commit. There is no separate bundled workflow for this; add strategy: worktree to your templates/<name>/config.yml (or --workflow-file). |
commit |
after: commit only — e.g. run workflow. |
Example (your repo, e.g. templates/my-ai/config.yml):
name: my-ai
strategy: worktree
strategies: [worktree, commit]
resolver: claudeThen: dockpipe --workflow my-ai --resolver claude --repo https://github.com/you/repo.git -- claude -p "…"
Do not list clone-worktree.sh in run: when worktree already provides clone (dockpipe will error). Do not duplicate bundled act: commit with the same strategy after hook.
Step fields
Each - under steps: is one step (or a group wrapper — see Async groups below).
| Key | Purpose |
|---|---|
id |
Optional. Used in stderr logs (e.g. [merge] lines). If omitted, logs use step 1, step 2, … |
cmd / command |
Shell command line for this step. In a container step it runs inside the container. In a host step it runs on the host. |
run |
String or YAML list: host pre-scripts before this step’s container. Logical resolver script ids like scripts/dorkpipe/... require an explicit resolver dependency instead of relying on workflow-package fallback. |
pre_script |
Single extra pre-script path (in addition to run). |
isolate |
Template/image for this step (falls back to workflow / CLI / core runtime profile). |
kind |
Step kind. Use container (default) for normal isolated execution, or host for host-side actions. |
cwd |
Step working directory. Omit or use source / repo for the checkout; use artifacts for this workflow's generated artifact root. |
scopes |
Optional { source, artifacts } binding for path roots. Use source: repo plus artifacts: artifacts when the process should run in the checkout but generated output should stay in workflow state. |
runtime |
Optional core runtime profile basename (same as CLI --runtime — must exist under templates/core/runtimes/). Overrides the workflow default for this step. Not meaningful on kind: host steps. |
resolver |
Optional resolver profile basename (same as CLI --resolver). Overrides the workflow default for this step. Not meaningful on kind: host steps. Do not use it for packaged workflow calls. |
workflow |
Marks this as a packaged workflow step. This is the child workflow name to run. |
package |
Required for a packaged workflow step. This is the child workflow namespace and must match the nested workflow’s namespace: in config.yml (resolution searches packaged / staging / workflows/ trees on disk). |
act / action |
Action script for this step. Do not combine this with packaged workflow steps. |
vars |
Per-step env map (merged for that step; --var keys can be “locked”). |
inputs |
Typed input bindings. On normal steps these resolve against the caller workflow model; on packaged workflow steps they resolve against the child packaged workflow model. |
agent |
Optional agentic step declaration consumed by DorkPipe-owned scripts/tooling. Use this to declare startup prompt, accessible paths, model knobs, seeded worker profiles, and orchestration fanout directly in config.yml. |
container |
Optional step-level container mount override. Use this on container steps to change the primary /work bind for one step, change its working subdirectory under /work, or add extra bind mounts without affecting the whole workflow. |
security |
Optional step-level container security override. Use this only on container steps when one step needs a different profile or tighter network / filesystem / process settings than the workflow default. |
outputs |
Path to a dotenv-style file (KEY=value lines) written by the step; merged into env for later steps. Relative paths resolve under DOCKPIPE_OUTPUT_ROOT, not the process cwd. This is the normal way one step passes values forward to later steps. |
capture_stdout |
Host path (relative to DOCKPIPE_WORKDIR / --workdir) — container stdout is also appended to this file (still printed on the terminal). |
manifest |
Host path — after the step, dockpipe writes a small JSON file with exit_code, duration_ms, step_index, id (if set), and step_display. |
is_blocking |
Default true. Keep this at its default on normal steps. Async work should use an explicit group: { mode: async, tasks: [...] } entry instead. |
host_builtin |
Optional engine-owned host action for kind: host steps. Supported values: package_build_store, compose_up, compose_down, compose_ps. Compose built-ins require top-level compose.file. |
Step-level security follows the same shape as top-level security, but it applies only to that one container step. It is not meaningful on kind: host steps, and packaged workflow steps should keep their policy inside the child workflow instead of trying to override it from the parent.
Step-level container follows the same shape as top-level container:
workdir_host: host path to bind at/workwork_path: relative container cwd under/workmounts: additional{ host, guest, mode }bind mounts, wheremodeisroorrw
Like security, this is only meaningful on container steps. Dockpipe rejects container: on kind: host steps and on packaged workflow-call steps.
Agentic steps (agent)
Use agent: when a step should declare agent behavior directly in workflow YAML while still letting
shared DorkPipe scripts act as the harness.
Typical uses:
- startup prompt text
- whether to include
AGENTS.mdcontext - access policy (
read,write,deny) plus lightweight accessible path hints - model/provider knobs that affect generation
- model policy overrides for attempt, validation, and escalation
- orchestration fanout data such as request, tasks, concurrency, merge, verify, and apply policy
- sibling or bounded-parent
agents.ymlrole definitions so worker/model/access policy is reusable across workflow families
This keeps user intent in config.yml and lets shared scripts materialize the contract instead of
forcing one shell file per workflow shape.
accessible_paths is a compatibility/simple-hint field. Prefer access.read, access.write, and
access.deny when the workflow needs a real contract that DorkPipe tooling can materialize into
artifacts and, later, stronger runtime policy.
agent.orchestration.tasks[].context entries are required briefing/discovery hints, not a hard
allowlist. Keep them small: request text, compact source maps, seed paths, and previous role outputs.
Let access.read and the mounted paths define the broader exploration boundary. Prompts should
explicitly say when a role may inspect additional allowed sources and must cite exact paths for any
claim it carries forward.
Prefer reusable role definitions in a sibling agents.yml; when it is absent, DorkPipe uses the
nearest parent agents.yml within the workflow or package authoring root. Inline
agent.orchestration.agents is available for workflow-local overrides. Tasks reference roles via
tasks[].agent. Agent definitions
describe who the worker is: role, worker profile, authority, model policy, access defaults, and
standing constraints. Tasks describe what happens in this workflow: brief,
context.required_artifacts, context.seed_paths, context.source_roots, dependencies, and declared
outputs. Keep source boundaries in access policy and mounts, not in task briefing fields.
agent.orchestration.concurrency lets DorkPipe-owned harnesses cap worker fanout without hiding
scheduling rules in scripts. max_workers caps total runnable workers, while max_local_workers
and max_cloud_workers cap local and cloud-backed lanes separately.
agent.orchestration.apply declares approved artifact-to-worktree writes. DorkPipe harnesses should
write reviewable artifacts first, verify them, require approval when configured, and only then copy
approved content into the checkout as normal uncommitted changes.
agent.orchestration.tasks[].materialize_outputs lets one role worker own a coherent output cluster
without becoming one worker per file. The worker returns <!-- dorkpipe:file path="..." --> blocks in
its response.md; DorkPipe extracts only the declared relative paths into
tasks/<task-id>/materialized/.
Apply can then use either:
- explicit
apply.outputs[]entries withsourceandpath - or
apply.target_rootplusapply.required_artifacts
When target_root is used, DorkPipe infers the full apply set from tasks/*/materialized/*,
requires the listed relative artifact paths to exist, and then writes the whole inferred bundle under
the target root. Use this when the workflow needs a minimum required doc set but should still allow
the AI to split or extend the durable file set beyond a rigid static list.
Step state flow
For most step-based workflows, the normal pattern is:
- a step runs
- it writes values to
outputs - later steps see those values in their environment
If you are trying to pass state from one step to another, start with outputs before inventing custom temp-file or wrapper conventions.
Host step shape
For normal kind: host steps, keep the shape simple:
- use
cmdwhen you want a host shell command - use
run/pre_scriptfor host-side setup scripts - use
host_builtinfor engine-owned host actions such as Compose lifecycle or package store build
Do not put runtime, resolver, or isolate on a host step. Those fields are for containerized execution.
All keys use snake_case in YAML (e.g. is_blocking, not isBlocking).
Compose lifecycle example
name: stack-demo
compose:
file: assets/compose/docker-compose.yml
project: dockpipe-dev
project_directory: ../../..
autodown_env: STACK_AUTODOWN
exports:
OLLAMA_HOST: http://host.docker.internal:11434
services: [proxy]
steps:
- id: stack_up
kind: host
host_builtin: compose_up
- id: stack_status
kind: host
host_builtin: compose_ps
- id: stack_down
kind: host
host_builtin: compose_downIf compose.autodown_env is set, compose_down is skipped when that env resolves to 0, false, no, or off.
If compose.exports is set, those KEY=value pairs are merged into Dockpipe’s workflow environment after a successful compose_up or compose_ps. That makes them available to later steps without an extra env-file layer.
Async groups (parallelism)
Mental model: several steps run concurrently, then one merge, then the next blocking step runs with the merged env.
Prefer the explicit group: { mode: async } form when authoring new workflows. It is easier to read and reason about than relying on adjacency alone.
| Concept | Meaning |
|---|---|
| Async group | Use a single list entry group: { mode: async, tasks: [...] }. This is the supported async authoring form. |
| Join point | The next step with is_blocking: true (or default). It waits until every async member has finished. |
| Inputs | Each async member sees env from the last blocking barrier only, plus its own vars / pre-scripts — not siblings’ live env. |
| Outputs | After all async members finish, each member’s outputs: file is merged in declaration order. Same key → later step wins (same as sequential steps). |
| Merge logging | On collision during that merge, stderr shows: [dockpipe] [merge] variable "KEY" overwritten by … (previously set by …). |
Rules:
- Within one async group, each step needs a distinct
outputspath (duplicate paths are rejected). - Host commit-worktree action cannot be used inside an async group.
kind: hoststeps in a group only contribute at merge time (theiroutputsfile).
Recommended async form (group)
The entry must contain only the key group (no cmd beside it).
steps:
- id: setup
cmd: echo ready
is_blocking: true
- group:
mode: async
tasks:
- id: task_a
cmd: sh -c 'echo BRANCH=a > out-a.env'
outputs: out-a.env
- id: task_b
cmd: sh -c 'echo BRANCH=b > out-b.env'
outputs: out-b.env
- id: join
cmd: sh -c 'echo $BRANCH'
is_blocking: trueInside tasks:, omitting is_blocking means async (forced non-blocking). is_blocking: true inside tasks is invalid and errors.
Do not nest another group inside tasks — unsupported; unknown keys on a step are ignored by the YAML decoder.
Plain-step is_blocking: false is no longer accepted. If you want parallelism, wrap those tasks in an explicit group entry.
Chaining without steps:
Multiple dockpipe runs with the same --workdir are valid (fresh container each time). Example:
dockpipe --workdir "$R" -- make lint && dockpipe --workdir "$R" -- make testPipe stdout between runs if needed. Prefer steps: in config.yml when one workflow should own order, outputs:, and optional parallelism.
Try a complete example
Follow Your first workflow to create hello in your own project,
or Workflow authoring for container, host and output
examples. Run only workflows you have created or installed:
dockpipe workflow validate workflows/hello/config.yml
dockpipe --workflow hello --Dockpipe's own CI and documentation workflows are contributor automation; they are not prerequisites or guaranteed contents of an installed package catalog.
See also
- CLI reference: flags and project selection.
- Package quickstart: discover and install packages.
- Architecture model: workflow, runtime, resolver and strategy.
Packaged workflow step
Use a packaged workflow call directly on the step:
steps:
- id: child
workflow: child-name
package: acme-team
inputs:
General.Mode: fastThat is the explicit nesting form. Do not write runtime: package.
When the child workflow publishes types:, inputs: on the parent step uses the child model. This lets a
package expose stable field paths and editor help while still exporting the env names its scripts consume.
Secret environment selection
Top-level vault: environment loads the named resolver-backed environment selected by --secret-environment NAME or secrets.environment in project configuration. vault: op retains template injection; vault: none disables both. Bindings explicitly select which variables enter the workflow. Configuration and provider examples are in Secret environments.