Shell
Run system commands and scripts with the default action.
Configure the Shell
- DAG defaults (literal): set
shellfor all steps.yamlshell: ["/bin/bash", "-e", "-u"] steps: - run: echo "Runs with bash -e -u" - Step override (evaluated at runtime, can reference params/secrets/outputs):yaml
steps: - run: echo "Runs in the step shell" with: shell: ${CUSTOM_SHELL:-/bin/zsh} - Fallback: if you set nothing, Dagu uses
DAGU_DEFAULT_SHELL, then$SHELL, thenshon Unix; on Windows it prefers PowerShell, thenpwsh, thencmd.exe. - String or array:
shellaccepts either"bash -e"or["bash", "-e"]; arrays avoid quoting issues.
Running Commands
- Inline command string for quick one-liners or pipelines:yaml
steps: - run: echo "Hello" - run: echo "Hello with key" - run: | echo "Multi-line command block" echo "Runs as a script (not split into args)" - Multiple commands can share one shell step:yamlInstead of duplicating
steps: - run: | echo "step 1" echo "step 2" echo "step 3" env: - MY_VAR: value working_dir: /app stdout: artifact: reports/output.logenv,working_dir,stdout,retry_policy,preconditions, etc. across multiple steps, combine commands into one step. Usestdout.artifact/stderr.artifactwhen command output should appear in the run's Artifacts tab. - Structured direct exec when you want unambiguous arguments and no shell parsing:yaml
steps: - action: exec with: command: /usr/bin/python3 args: - -u - app.py - --limit - 10 - Script block for multi-line scripts:yamlIf you omit a step-level
steps: - run: | #!/usr/bin/env bash set -e echo "Multi-line script"shelland the script has a shebang, that interpreter is used. Otherwise the resolved shell runs the script file. - Interpreter + inline script:yaml
steps: - run: | import sys print("Args:", sys.argv) with: shell: python3 - Working directory and env: set
working_dirandenvon the step (or DAG defaults) to control context.
Script Behavior
- A multi-line
run:block is written to a temp file in the working directory when possible, then removed after the step finishes. - If you omit a step-level
shelland the script starts with a shebang (#!/usr/bin/env python3,#!/bin/bash, etc.), that interpreter runs the script. - Without a shebang, the resolved shell runs the script file. When Dagu provides the default Unix shell, it appends
-eso the script stops on the first failing command (step-level shells are left unchanged). - Multi-line
runstrings (using a YAML|block) are saved to a temp file and executed as a script rather than split into args. action: execbypasses shell parsing entirely and accepts explicitwith.commandandwith.args.
Built-in Safety Defaults
- Auto
-eon POSIX shells: When Dagu supplies the default/DAG-level shell for sh/bash/zsh/ksh/ash/dash, it appends-efor both command strings and script runs. If you set a step-level shell, include-eyourself when desired. - PowerShell scripts: Saved as
.ps1and prefixed with$ErrorActionPreference = 'Stop'and$PSNativeCommandUseErrorActionPreference = $trueso cmdlet errors and native command failures stop execution. - nix-shell: Dagu defaults to
--pureif you do not specify purity flags. When Dagu supplies the shell, it also prependsset -e;to the command string unless you already provided it.
Platform-Specific Guides
- macOS / Linux details — POSIX shells, nix-shell, direct mode
- Windows details — PowerShell/pwsh, cmd.exe, direct mode
