Shell (macOS / Linux)
Run commands and scripts on Unix-like systems (macOS, Linux, BSD).
Configure the Shell
- DAG defaults (literal values):yaml
shell: ["/bin/bash", "-e", "-u"] steps: - run: echo "Runs with bash -e -u" - Step override (evaluated at runtime so params/secrets/outputs are allowed):yaml
steps: - run: echo "Runs in the step shell" with: shell: ${CUSTOM_SHELL:-/bin/zsh} - Fallback: If no shell is set, Dagu uses
DAGU_DEFAULT_SHELL, then$SHELL, thensh. - String or array:
shellaccepts either"bash -e"or["bash", "-e"]; arrays avoid quoting issues.
Running Commands
- Inline command string:yaml
type: chain steps: - run: echo "Hello" - run: echo "Hello with key" - run: | echo "Multi-line command block" echo "Runs as a script (not split into args)" - Structured direct exec:yaml
steps: - action: exec with: command: /usr/bin/python3 args: - -u - app.py - --limit - 10 - Script block: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: Use
working_dirandenvon the step (or DAG defaults) to control context.
Script Behavior (Unix)
- A
run:block is saved to a temp file in the working directory when possible and removed after the step finishes. - If there is no step-level
shelland the script has a shebang, that interpreter runs the script. Without a shebang, the resolved shell runs it (Dagu appends-efor sh/bash/zsh/ksh/ash/dash when using the default/DAG-level shell; step-level shells are left unchanged). - When both
shelland a multi-linerunblock are set, the shell value is used as the interpreter.
Shell Options
POSIX shells (sh/bash/zsh/ksh/ash/dash)
With the default or DAG-level shell, Dagu appends-eso the shell stops on the first failing command. If you set a step-level shell, add-eyourself when you want errexit.nix-shell
Pin tools per step withwith.shell: nix-shellandwith.shell_packages:yamlsteps: - run: | python3 --version jq --version with: shell: nix-shell shell_packages: [python3, jq]nix-shell must be installed separately. Dagu runs inside
nix-shell --run ...; it defaults to--pureif you do not supply purity flags. Include any flags you need (such as--impure) in theshellarray. When Dagu supplies the shell, it prependsset -e;to the command string unless you already provided it.Direct execution (no shell parsing)
Useaction: execfor explicit argv:yamlsteps: - action: exec with: command: /usr/bin/python3 args: - -u - script.pyaction: execbypasses shell parsing and uses explicitwith.command/with.args.
Tips
- Prefer
action: execwhen you need explicit argv with flags. - Keep DAG-level shells stable; override per-step only when you need a different interpreter.
- Use shebangs in multi-line scripts when you want a specific interpreter without repeating
shell. - When using nix-shell, list every tool your step needs in
with.shell_packagesfor reproducibility.
