Imported from dagucloud/dagu (
skills/dagu/SKILL.md). Install upstream withnpx skills add dagucloud/dagu --skill dagu. Copyright stays with the author.
DAG Authoring
Load only the reference file that matches the task.
Default Approach
- Prefer
type: graphfor new DAGs. It supports both sequential flow viadepends:and parallel flow. - Use an Agent DAG (
type: agent) only when the step order cannot be written down in advance and an LLM must choose it. It requiresllm:and atasks:list stating when the run is finished. The model may select multiple distinct, independent actions in one turn; Dagu runs them concurrently up tomax_active_steps(0is unlimited,1is serial). Same-batch actions cannot consume sibling outputs, while failures do not cancel siblings.set_task_statusandask_usermust be called alone. - Use
type: buildonly for local regular-file pipelines whose unchanged transformations should be reused across runs. - Prefer
idon every step. Omitnameunless the display label must differ from the step ID. - Prefer
dagu schema ...anddagu validate ...over guessing field names or shapes. - Prefer
action: template.renderwhen generating text files, prompts, or artifacts instead of assembling them with shellechoor heredocs. - Prefer
file.*actions for local file operations such as stat, read, write, copy, move, delete, mkdir, and list instead of shelling out tocp,mv,rm, ormkdir. - Prefer
git.worktree.addandgit.worktree.removewhen steps need isolated branches inside an existing local Git repository. Add an explicit remove step when the workflow should delete the worktree. - Prefer
stdout.artifact/stderr.artifactwhen a command stream should become a DAG-run artifact, especially for large reports, JSON, Markdown, logs, or generated files. - Prefer
artifact.*actions for explicit artifact reads/writes/lists. UseDAG_RUN_ARTIFACTS_DIRonly when a tool truly needs a filesystem path inside the step. - Prefer string-form
output: VAR_NAMEfor capturing small stdout values into flat variables. - Prefer object-form
output:when downstream steps need structured values via${step_id.output.*}. - Prefer declared step
outputs:with$DAGU_OUTPUT_FILEwhen a step must publish explicit values for${steps.<step_id>.outputs.<name>}. - Use
action: human.taskwhen an operator must provide typed input before downstream steps continue. Human task form outputs use${steps.<step_id>.outputs.<name>}without an authoredoutputs:field. - Prefer
stdout.outputsoraction: outputs.writewhen a DAG or remote action needs to return caller-visible values via${step_id.outputs.*}. - Prefer
state.*actions for small persistent JSON state across DAG runs, such as cursors, checkpoints, and previous-value comparisons. - Prefer temporary files in the artifacts dir only when downstream steps need file paths; otherwise let commands write large artifact content to stdout and attach it with
stdout.artifact. - Prefer scoped Dagu references for named values:
${consts.NAME},${params.NAME}, and${env.NAME}. Avoid unscoped braced names in examples unless the example is intentionally showing shell syntax. - Declare portable external CLI dependencies in top-level
toolsusing aqua shorthand when the binary version affects reproducibility, for exampletools: ["jqlang/jq@jq-1.7.1"]. Append#sha256:<64 hex>to also pin the downloaded artifact content for the run platform, for examplejqlang/jq@jq-1.7.1#sha256:<hex>. - For remote actions, put
toolsin the referenced action DAG file, not indagu-action.yaml; caller DAG tools are not inherited across the action boundary. - Declare step-level
dependencieswhen a run needs files from the DAG working directory. Use literal working-directory-relative paths or glob patterns; do not use value references. - Use remote action packages (
dagu-action.yaml) when reusable logic needs helper files, its own DAG, versioning, or an input/output schema contract.
High-Signal Rules
output:has two modes:- string form captures trimmed stdout into an env-scope variable such as
${env.VERSION} - object form publishes structured step-scoped output for
${step_id.output.*}access
- string form captures trimmed stdout into an env-scope variable such as
- Value declarations in step
outputs:publish explicit values through${steps.<step_id>.outputs.<name>}. Write those values to$DAGU_OUTPUT_FILE; Dagu captures them only after the command succeeds. Build path declarations publish the final materialization path after commit or reuse. human.taskis a processless root-DAG step with an explicitid, a requiredwith.prompt, and an optional flat scalar form. A root DAG containing one can run locally or on a distributed worker. Every declared form property is a step output, published when submitted or defaulted, and available as${steps.<step_id>.outputs.<name>}.stdout.artifact/stderr.artifactstore command stdout/stderr directly as relative artifact paths, for examplestdout: {artifact: reports/report.md}. Artifact outputs auto-enable artifacts unlessartifacts.enabled: falseis explicitly set, which is invalid.${step_id.stdout}is a log file path, not stdout content.- Use
${context.*}for run metadata in DAG YAML, for example${context.dag.name},${context.run.id}, or${context.paths.artifacts_dir}. Unavailable context values remain unresolved text instead of becoming empty strings. - In a build step,
${inputs.<name>}is the final input path and${outputs.<name>}is a fresh attempt staging path. Write file results only to the staging path; dependencies read the committed path as${steps.<step_id>.outputs.<name>}. - Do not read attempt-only
${step_id.stdout},${step_id.stderr}, or${step_id.exit_code}from potentially reusable producers. This also applies to${step_id.output.<name>}and${step_id.outputs.<name>}, including their whole-value${step_id.output}and${step_id.outputs}forms. Path-output steps cannot usecontinue_on.mark_success. - Build workflows are local-only. Path declarations are supported only on host command or shell steps without containers, and stream redirects cannot target declared build inputs or outputs.
- Use
${consts.NAME},${params.NAME}, and${env.NAME}for Dagu-side named values. Use shell$NAMEorprintenv NAMEonly when the target shell or process should read the variable at execution time. consts:must use list form with one key per item, for exampleconsts: [{service: api}]. Const values are resolved while loading the DAG and can reference inherited or earlier consts.env:should use list-of-maps when values depend on earlier env vars.params:values arrive as strings. Theparams:field supports JSON schema-like types and validation, check for schema to see how to specify types and validation rules.- Single-line
run:values are command-form entries. Array-formrun:entries run one by one. Multi-linerun:values are scripts. Dagu does not split pipes, redirects,&&, or;into separate commands; those stay with the selected shell. - Do not assume
bashforrun:steps. If a script depends on a specific interpreter, add a shebang such as#!/bin/shor#!/usr/bin/env bashonly after checking that shell exists on the target host or container. Otherwise keep the script portable or setwith.shell:explicitly. parallel:currently requiresaction: dag.runto a child DAG.- Sub-DAGs do not inherit parent env vars; pass what you need via
params:. - For arbitrary text inside shell steps, prefer
printenv VAR_NAMEoraction: template.renderover Dagu interpolation such as${env.VAR_NAME}. harness.runsupports built-in provider adapters (aider,amp,claude,cline,codex,copilot,cursor,deepseek,droid,gemini,goose,kiro,opencode,pi,qwen) and custom top-levelharnesses:entries. Built-in OpenCode uses managed sessions on long-lived Dagu hosts by default; containers and unsupported options use the CLI path. It can use top-levelcontainer:or step-levelcontainer:.- Container runtime selection is service-level, not a DAG YAML field. Set
DAGU_CONTAINER_RUNTIME=podmanto use Podman, and setDAGU_PODMAN_HOSTonly when the Podman Docker-compatible socket is not the default. - DAG/action outputs are collected from string-form
output: VAR_NAME,stdout.outputs, andaction: outputs.write. Object-formoutput:stays step-scoped for${step_id.output.*}unless the workflow explicitly republishes values throughstdout.outputsoroutputs.write. state.get,state.set,state.delete,state.list, andstate.diffpersist small JSON values across DAG runs. State scopes aredag,root_dag,global, andcustom; use artifacts or external storage for large payloads.- Git worktree actions discover the repository from the step
working_dir. Relative worktree paths resolve from the repository root, and the actions never fetch or push. - Remote action packages define
dagu-action.yamlwithapiVersion: v1alpha1,name,dag, and optionalinputs/outputsJSON Schemas.inputsvalidates callerwith:before the action DAG starts;outputsvalidates the final action output object after the action DAG returns. - Remote action manifests do not support
tools. Declare external CLI tools in the action DAG itself so local and distributed workers prepare the right binaries for that action run. dependenciessnapshots files from the DAG working directory for both local and distributed execution. The materialized bundle is available throughDAG_RUN_WORK_DIRand${context.paths.work_dir}and becomes the DAG process working directory.- In remote action examples, prefer
dag: workflow.yamlfor the action DAG filename. Thedagfield accepts any safe relative file path, butworkflow.yamlavoids confusing the executable DAG with thedagu-action.yamlmanifest. - Object-form
output:withdecode: jsonordecode: yamlcan act as lightweight runtime validation. Malformed data or an unresolvedselect:path fails the step, so normalretry_policyapplies. - Use DAG-level
shellandshell_argsonly when every inheritedrun:step should use the same shell invocation. Use step-levelwith.shellandwith.shell_argsfor a single step. - Use
dagu schema dagto check the full list of available fields and their shapes. - Use
dagu exampleto see different DAG patterns and how to express them in YAML.
Example of Params, template step, and artifacts
params:
type: object
properties:
name:
type: string
maxLength: 50
age:
type: integer
minimum: 0
maximum: 120
favorite_color:
type: string
required: [name, age]
steps:
- id: render
action: template.render
with:
data:
name: ${params.name}
age: ${params.age}
favorite_color: ${params.favorite_color}
template: |
Hello, {{ .name }}!
You are {{ .age }} years old.
{{- if .favorite_color }}
Your favorite color is {{ .favorite_color }}.
{{- end }}
stdout:
artifact: greeting.txt
Example of Large Command Output as Artifact
steps:
- id: report
run: ./generate-report --format markdown
stdout:
artifact: reports/report.md
Example of Reproducible External CLI
tools:
- jqlang/jq@jq-1.7.1
steps:
- id: inspect
run: jq --version
Example of Object-Form Output
steps:
- id: inspect_build
run: echo '{"version":"v1.2.3","artifact":{"url":"https://example.test/app.tgz"}}'
output:
# decode + select act as a lightweight contract check:
# malformed JSON or a missing selected field fails the step.
version:
from: stdout
decode: json
select: .version
artifact:
from: stdout
decode: json
select: .artifact
- id: publish
depends: [inspect_build]
output:
versionLabel: "ver - ${inspect_build.output.version}"
artifactUrl: "${inspect_build.output.artifact.url}"
Example of Action Outputs
steps:
- id: classify
run: ./classify.sh "${params.INPUT}"
stdout:
outputs:
fields:
label:
decode: json
select: .label
confidence:
decode: json
select: .confidence
- id: publish
depends: [classify]
action: outputs.write
with:
values:
label: ${classify.outputs.label}
reviewed: false
Example of Human Input
steps:
- id: review
action: human.task
with:
prompt: Choose the deployment target
form:
type: object
properties:
environment:
type: string
enum: [staging, production]
note:
type: string
default: ""
required: [environment]
- id: deploy
depends: [review]
run: ./deploy --environment '${steps.review.outputs.environment}' --note '${steps.review.outputs.note}'
Complete the task from a local CLI context with dagu human-task complete --run-id=<run-id> --step=review --input environment=production <dag-name>. A form is optional for acknowledgement-only tasks. Human tasks cannot be used in sub-DAGs; a distributed root run is re-queued through the scheduler after completion.
Reference Guide
Load only the file you need:
references/steptypes.mdwhen choosing an action or checking action-specific behavior such ashuman.task,dag.run,parallel,git.worktree.*,jq.filter,file.*,state.*, ortemplate.renderreferences/dagu-action.mdwhen creating a reusabledagu-action.yamlpackage or checking action input/output schema behaviorreferences/cli.mdwhen choosing or using Dagu CLI commands, including workflow inspection, execution, and cleanup operationsreferences/context.mdwhen using${context.*}metadata references or declared stepoutputs:references/build.mdwhen creating or troubleshooting atype: buildfile workflow, path references, reuse decisions, or--no-reusereferences/file-dependencies.mdwhen a DAG needs scripts, configuration, or other files from its working directoryreferences/harnesses.mdonly when the DAG invokes external CLI harnesses throughharness.run