🪨 why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman
Workflow orchestrator for scripts, SSH, and containers
Dagu runs workflows defined in YAML and keeps the orchestration outside your business logic. It supports shell commands, Docker, Kubernetes Jobs, SSH, scheduling, retries, human tasks, logs, and a built-in web UI and MCP server.

Builders who want to schedule and observe existing automation without rewriting it into a framework.
You can turn scripts and runbooks into tracked workflows with scheduling, retries, and run history.
What it does
Declarative YAML workflows
Define DAGs in YAML and keep the workflow structure separate from the scripts and commands they call.
Single-binary self-hosting
Run the server, scheduler, coordinator, and worker roles from one Go binary with no external database or message broker.
Built-in scheduling and retries
Schedule runs with cron syntax, overlap policies, catch-up windows, and retry policies.
Human tasks and approvals
Pause a workflow for acknowledgment or typed input, then pass that response to later steps.
Multiple execution backends
Run shell commands, Docker containers, Kubernetes Jobs, SSH commands, SFTP transfers, HTTP requests, SQL, and more through actions.
MCP server and wiki support
Use the built-in MCP server to inspect workflows and runs, edit wiki pages, apply changes, and control runs.
How to get it
- 1macOS/Linux
curl -fsSL https://raw.githubusercontent.com/dagucloud/dagu/main/scripts/installer.sh | bash
- 2Homebrew
brew install dagu
- 3npm
npm install -g --ignore-scripts=false @dagucloud/dagu
- 4Windows (PowerShell)
irm https://raw.githubusercontent.com/dagucloud/dagu/main/scripts/installer.ps1 | iex
- 5Docker
docker run --rm -v ~/.dagu:/var/lib/dagu -p 8080:8080 ghcr.io/dagucloud/dagu:latest dagu start-all
- 6Kubernetes (Helm)
helm repo add dagu https://dagucloud.github.io/dagu helm repo update helm install dagu dagu/dagu --set persistence.storageClass=<your-rwx-storage-class>
README
Dagu
Dagu is a local-first workflow engine for operations and internal automation. It is open source and self-hostable: a single binary with a built-in Web UI, no external database or message broker, running on Linux, macOS, and Windows. Define DAGs in a declarative YAML format. It natively supports shell commands, Docker containers, Kubernetes Jobs, remote commands via SSH, and more through Dagu Actions.
Dagu turns existing scripts and runbooks into production workflows with scheduling, retries, human tasks, and run history. It runs where your data and credentials live: on-prem, air-gapped, edge, or cloud, and scales from a single node to a fleet of workers.
Highlights:
- Single binary installation.
- Self-contained: no external DBMS or message broker required.
- Runs on Linux, macOS, and Windows.
- Declarative YAML format for defining DAGs.
- Run existing shell commands, Docker containers, Kubernetes Jobs, and remote commands over SSH without modifications.
- Compose reusable Sub-DAGs and run work in parallel with concurrency controls.
- Schedule workflows with cron syntax, timezones, overlap policies, and catch-up windows.
- Keep logs, run history, retries, notifications, and webhook triggers in one place.
- Built-in MCP server for inspecting workflows and runs, maintaining Wiki pages, applying changes, and controlling runs.
Quick Look
For a quick look at how workflows are defined, see the examples.
| Run Details | Step Logs | Wiki |
|---|---|---|
![]() | ![]() | ![]() |
Try it live: Live Demo (credentials: demouser / demouser)
Why Dagu?
Orchestration is not your main work. You have scripts and containers that already work. You want a schedule, retries, dependencies, and a place to see logs. The usual options each have a cost:
- cron runs commands, but gives you no dependencies, no retries, no history.
- Airflow orchestrates, but you operate a platform for it (scheduler, metadata database, workers, a Python environment), and your jobs get rewritten as
@dag/@taskframework code. - Temporal gives durable execution, but your business logic moves into its SDK and programming model.
You wanted to schedule some jobs. Now you operate a second system, and the orchestrator lives inside the code it was supposed to serve.
Dagu treats workflow structure as configuration, not code. Order, dependencies, retries, schedules, and human tasks go in one YAML file next to your scripts; the engine that runs them is a single process:
Traditional Orchestrator Dagu
┌────────────────────────┐ ┌──────────────────┐
│ Web Server │ │ │
│ Scheduler │ │ dagu start-all │
│ Worker(s) │ │ │
│ PostgreSQL │ └──────────────────┘
│ Redis / RabbitMQ │ Single binary.
│ Python Runtime │ Self-hosted.
└────────────────────────┘ Adds scheduling, retries, and human tasks around existing automation.
6+ services to manage
Your scripts never import the orchestrator. Delete the YAML and they run exactly as before. Keep it, and every run gets a dependency graph, retries, per-step logs, history, and a Web UI.
Performance
Dagu stores state in local files and reaches production throughput without external services.
- Throughput: A single machine can run thousands of workflow runs per day. Actual capacity depends on CPU, memory, disk, and workflow shape.
- Load control: Queues, concurrency limits, and resource limits control how many runs execute at once and where they run.
- Scale out: Workers spread execution across machines when one node is not enough.
Real-World Use Cases
| Use Case | How Dagu Helps |
|---|---|
| ETL and data operations | Turn data extraction scripts, SQL queries, dbt commands, and data-processing runbooks into observable pipelines with durable execution. |
| Legacy scripts and scheduled jobs | Turn interdependent scripts into maintainable DAGs with a UI, automatic logging, retries, and notifications instead of opaque cron jobs. |
| Media conversion | Run ffmpeg for video transcoding and format conversion. File-backed state allows workers to run heavy conversions in parallel without single-machine bottlenecks or external databases. |
| Infrastructure and server automation | Run any command or script over SSH on remote servers, keeping logs, results, and notifications in one place. |
| GitHub-driven workflows | Trigger workflows from GitHub events to run automation on private infrastructure without exposing servers to the public internet. |
| Container and Kubernetes workflows | Run Docker containers and Kubernetes Jobs as steps in your workflows without building a custom control plane around containers. |
| Customer support automation | Provide self-service workflows that non-engineering teams can run for diagnostics, database queries, and routine operations without escalating to engineering. |
| IoT and edge workflows | Run sensor polling, local ML inference, data preprocessing, backups, offline sync, and health checks close to the data source with Web UI visibility. |
Quick Start
Install
macOS/Linux:
curl -fsSL https://raw.githubusercontent.com/dagucloud/dagu/main/scripts/installer.sh | bash
Homebrew:
brew install dagu
npm:
npm install -g --ignore-scripts=false @dagucloud/dagu
Windows (PowerShell):
irm https://raw.githubusercontent.com/dagucloud/dagu/main/scripts/installer.ps1 | iex
Docker:
docker run --rm -v ~/.dagu:/var/lib/dagu -p 8080:8080 ghcr.io/dagucloud/dagu:latest dagu start-all
This command does not expose the host Docker daemon to Dagu. Workflows that use
container:oraction: docker.runneed the container-step Docker setup. Mounting the Docker socket grants workflows control of the host daemon.
Kubernetes (Helm):
helm repo add dagu https://dagucloud.github.io/dagu
helm repo update
helm install dagu dagu/dagu --set persistence.storageClass=<your-rwx-storage-class>
Replace
<your-rwx-storage-class>with a StorageClass that supportsReadWriteMany. See charts/dagu/README.md for chart configuration.
The script installers run a guided wizard that can add Dagu to your PATH, set it up as a background service, and create the initial admin account. Homebrew, npm, Docker, and Helm install without the wizard. See the Installation documentation for all options.
Create and run a workflow
Create hello.yaml:
steps:
- id: hello
run: echo "hello from Dagu"
Run the workflow with:
dagu start hello.yaml
Start the server
dagu start-all --dags .
Visit http://localhost:8080
How You Run Dagu
Dagu runs on one machine, on temporary workers your platform creates for each run, or on workers you keep running. All three are self-hosted, and the same workflow YAML runs on any of them. See the Deployment Models guide.
Single server
|
Temporary workers
|
Distributed workers
|
| Topology | Execution | Best for |
|---|---|---|
| Single server | dagu start-all runs the server, scheduler, and steps in one process on one machine. | Development, single-machine scheduled workloads, edge jobs, and internal automation. |
| Temporary workers | Cloud Run Jobs, Kubernetes Jobs, or CI provision a worker per run that invokes the binary and is destroyed when the run ends. The server reads run state from a shared volume. | Ephemeral compute, capacity that falls to zero between jobs, and launchers you already operate. |
| Distributed workers | Workers you keep running poll a coordinator over gRPC and are routed work by label. | Docker and private-network steps, warm toolchains, and multiple execution hosts. |
Licensing
- Community self-host: No license key required. You operate the server, storage, upgrades, networking, and workers. Start with the installation guide.
- Self-host license: Adds SSO, RBAC, audit logging, and incident SaaS integration to Dagu. See self-host licensing.
Key Features
- Observability: Shared workflows and scheduling with clear visualizations, status tracking, and logs in the Web UI.
- Language-agnostic: No framework required. Define workflow steps using shell commands, Docker containers, Kubernetes Jobs, SQL queries, HTTP requests, and any other tool via official and third-party Dagu Actions.
- Build workflows: Reuse a step's result when its command and files have not changed. Dagu can also infer dependencies from matching file paths.
- Reproducibility: Reproducible runs with pinned tools, plus automatic installation and caching on workers, eliminating the need to manually install dependencies on the server or workers.
- Human Tasks: Pause a workflow for acknowledgement or typed operator input, then expose the response to downstream steps.
- Secret management: Built-in secret management with secure log masking, preventing credentials from leaking into logs or the Web UI.
- Self-hosted: A single binary that runs on Linux, macOS, and Windows. Execution scales out to a fleet of workers.
- Permission Control: RBAC and SSO support for team environments, controlling who can view, run, and edit workflows through granular permissions and audit logging.
- MCP Server: Authenticated MCP clients can inspect workflows and runs, maintain Wiki pages, apply changes, and control runs.
Architecture
One binary carries every role. Which roles you start, and where, is what the deployment models differ on.
- Server serves the Web UI and REST API.
- Scheduler owns
schedule:and drains the queue. - Coordinator is the gRPC endpoint workers poll. It also persists what they report: run status, streamed logs, and artifacts.
- Worker polls a coordinator, executes dispatched runs locally, and reports back. Routed by labels.
dagu start-allruns the server, scheduler, and coordinator in one process.
Set DAGU_HEADLESS=true to run without the Web UI, which applies to any of the topologies and suits CI or CLI-only environments.
Single server:
┌─────────────────────────────────────────┐
│ dagu start-all │
│ ┌───────────┐ ┌───────────┐ ┌────────┐ │
│ │ HTTP / UI │ │ Scheduler │ │Executor│ │
│ └───────────┘ └───────────┘ └────────┘ │
│ File-based storage (logs, state, queue)│
└─────────────────────────────────────────┘
Distributed workers:
┌────────────┐ ┌────────────┐
│ Scheduler │ │ HTTP / UI │
│ │ │ │
│ ┌────────┐ │ └─────┬──────┘
│ │ Queue │ │ Dispatch (gRPC) │ Dispatch / GetWorkers
│ │(file) │ │─────────┐ │ (gRPC)
│ └────────┘ │ │ │
└────────────┘ ▼ ▼
┌─────────────────────────┐
│ Coordinator │
│ ┌───────────────────┐ │
│ │ Dispatch Task │ │
│ │ Store (pending/ │ │
│ │ claimed) │ │
│ └───────────────────┘ │
└────────▲────────────────┘
│
Worker poll / task response
Heartbeat / ReportStatus /
StreamLogs (gRPC)
│
┌─────────────┴─────────────┐
│ │ │
┌────┴───┐ ┌────┴───┐ ┌────┴───┐
│Worker 1│ │Worker 2│ │Worker N│ Sandbox execution of DAGs
│ │ │ │ │ │
└────────┘ └────────┘ └────────┘
Temporary workers:
┌────────────┐ provisions ┌──────────────┐
│ Launcher │───────────────▶│ dagu start │
│ Cloud Run │ │ exits when │
│ K8s Job/CI │ │ the run ends │
└────────────┘ └──────┬───────┘
│ writes
▼
┌────────────┐ reads ┌──────────────────┐
│ Dagu server│◀───────────────│ Shared volume │
│ UI / API │ │ dags/state/logs │
└────────────┘ └──────────────────┘
No coordinator, and no network path between the two.
Parameter Definition
Workflows can define parameters that render as typed input forms in the Web UI and can be referenced by steps.
params:
- name: customer_id
type: string
description: Customer or account identifier
- name: change_scope
type: string
description: What the repair is allowed to change
enum:
- metadata_only
- permissions
- full_account
default: metadata_only
- name: dry_run
type: boolean
default: true
steps:
- id: extract
run: >-
./scripts/extract.sh
--customer "${params.customer_id}"
--scope "${params.change_scope}"
--dry-run="${params.dry_run}"
retry_policy:
limit: 3
interval_sec: 30
Workflow Examples
Docker step
When Dagu itself runs in Docker, enable Docker daemon access before using container steps.
Pass standard docker run options directly in YAML, including the image, pull policy, platform, volume mounts, working directory, and resource limits:
resources:
limits:
cpu: 500m
memory: 512Mi
steps:
- id: report
action: docker.run
with:
image: ghcr.io/acme/reporting:1.4.2
pull: always
platform: linux/amd64
working_dir: /work
volumes:
- ~/orders:/work/data
auto_remove: true
command: python generate_report.py --input /work/data/orders.csv
See the Docker and DAG Run Resource Limits documentation for all configuration options.
Parallel Sub-DAG execution
The parent invokes the same child DAG for multiple targets and limits concurrent child runs:
steps:
- id: patch
action: dag.run
with:
dag: patch-host
params:
host: ${ITEM}
parallel:
items:
- web-1.internal
- web-2.internal
- db-1.internal
max_concurrent: 2
---
name: patch-host
params:
- name: host
type: string
ssh:
user: deploy
host: ${params.host}
steps:
- id: apply
run: apt-get update -q && apt-get upgrade -y
See the Sub-DAGs documentation for parameter passing and fan-out options.
SSH remote execution
ssh:
user: deploy
host: web-1.internal
key: ~/.ssh/deploy_key
steps:
- id: health
run: curl -f http://localhost:8080/health
retry_policy:
limit: 3
interval_sec: 10
- id: restart
run: systemctl restart myapp
depends: health
See the SSH documentation for authentication and connection options.
Scheduling with overlap control and catch-up
schedule:
- "0 */6 * * *" # Every 6 hours
overlap_policy: skip # Skip if previous run is still active
catchup_window: "5h" # Catch up missed runs when scheduler is down for up to 5 hours
timeout_sec: 3600
handler_on:
failure:
run: notify-team.sh
exit:
run: cleanup.sh
See the Scheduling and Lifecycle Handlers documentation for all options.
Retry and error handling
steps:
- name: flaky-api-call
run: curl -f https://api.example.com/data
retry_policy:
limit: 3
interval_sec: 10
continue_on:
failure: true
See the Durable Execution and Continue On documentation for retry policies and failure handling.
More Workflow Examples
Parallel executions
steps:
- id: extract
run: ./extract.sh
- id: transform_a
run: ./transform_a.sh
depends: extract
- id: transform_b
run: ./transform_b.sh
depends: extract
- id: load
run: ./load.sh
depends: [transform_a, transform_b]
%%{init: {'theme': 'base', 'themeVariables': {'background': '#18181B', 'primaryTextColor': '#fff', 'lineColor': '#888'}}}%%
graph LR
A[extract] --> B[transform_a]
A --> C[transform_b]
B --> D[load]
C --> D
style A fill:#18181B,stroke:#22C55E,stroke-width:1.6px,color:#fff
style B fill:#18181B,stroke:#22C55E,stroke-width:1.6px,color:#fff
style C fill:#18181B,stroke:#22C55E,stroke-width:1.6px,color:#fff
style D fill:#18181B,stroke:#3B82F6,stroke-width:1.6px,color:#fff
See the Control Flow documentation for dependencies, conditions, and repetition.
Reuse unchanged results
Save this as workflow.yaml:
type: build
working_dir: .
steps:
- id: uppercase
inputs:
- name: source
path: source.txt
outputs:
- name: result
path: uppercase.txt
run: |
#!/bin/sh
tr '[:lower:]' '[:upper:]' < "${inputs.source}" > "${outputs.result}"
Run it:
printf 'alpha\n' > source.txt
dagu start workflow.yaml
Run dagu start workflow.yaml again and Dagu reuses uppercase.txt. Change source.txt and the step runs again. ${outputs.result} is a temporary path that Dagu publishes as uppercase.txt after the command succeeds.
Build workflows currently run locally. See Build Workflows for dependency inference and reuse rules.
External tools with pinning and caching
tools:
- jqlang/jq@jq-1.7.1
steps:
- id: inspect
run: jq --version
- id: summarize
action: python-script@v1
with:
input:
rows: [42, 8]
script: |
return {"total": sum(input["rows"])}
Dagu installs declared portable CLIs before the DAG run, exposes them on PATH for host command steps, and caches them on each worker. Tool provisioning uses aqua as the default provider; the standard registry resolves to the latest aqua-registry release automatically. Pin a specific artifact with package@version#sha256:<hex> when the release tag alone is not a strong enough guarantee. See the Tools documentation and Dagu Actions for more details.
Third-party Dagu Actions
params:
- BUILD_ID
steps:
- id: notify
action: acme/dagu-action-notify@v1.2.0
with:
text: "Build ${params.BUILD_ID} finished"
- id: audit
depends: notify
run: 'echo "Notification result: ${steps.notify.outputs.messageId}"'
A third-party Dagu Action package contains a DAG, manifest, schemas, and helper files behind an action: reference. See the Dagu Actions and Third-Party Actions documentation for details.
Kubernetes Pod execution
steps:
- name: batch-job
action: kubernetes.run
with:
namespace: production
image: my-registry/batch-processor:latest
resources:
requests:
cpu: "2"
memory: "4Gi"
command: ./process.sh
See the Kubernetes documentation for Job configuration options.
For more examples, see the Examples documentation.
MCP
Dagu includes a built-in MCP server at http://localhost:8080/mcp. MCP clients can inspect workflows and run state, maintain Dagu's built-in Wiki pages, preview and apply DAG or Wiki page changes, and control runs through the same authenticated server boundary as the REST API.
See the MCP overview and quickstart.
Built-in Actions
Dagu includes built-in actions that run within the Dagu process or on the selected worker. Local shell commands use the run: field; structured work uses action:.
| Action | Purpose |
|---|---|
run: field | Local shell commands and scripts (bash, sh, PowerShell, custom shells) |
exec | Direct process execution without shell parsing |
noop | Output-only or approval-only placeholder step |
log.write | Write structured log messages |
docker.run / container.run | Run containers with registry auth, volume mounts, and resource limits |
kubernetes.run / k8s.run | Execute Kubernetes Jobs with namespace, image, and resource settings |
ssh.run | Remote command execution over SSH |
sftp.upload / sftp.download | File transfer over SFTP |
| `http.reque |
Files in the repo
- .devcontainer
- .github
- .vscode
- api
- assets
- charts
- cmd
- config
- conformance
- deploy
- examples
- internal
- npm
- proto
- schemas
- scripts
- skills
- specs
- ui
- .dockerignore
- .gitattributes
- .gitignore
- .golangci.yml
- .goreleaser.yaml
- .protolint.yaml
- AGENTS.md
- build-windows.sh
- CLAUDE.md
- CODE_OF_CONDUCT.md
- codecov.yml
- CONTRIBUTING.md
- cr.yaml
- doc.go
- Dockerfile
- Dockerfile.alpine
- Dockerfile.dev
- engine_test.go
- engine.go
- entrypoint.sh
- example_test.go
- executor.go
- go.mod
- go.sum
- LICENSE
- LICENSING.md
- llms.txt
- Makefile
- README_SCHEMA.md
- README.md
- SCHEMA_MIGRATION.md
- SECURITY.md
- tools.go
Discussion (0)
Ask about usage, or say what you built with itSign in to join the discussion.
No comments yet. Be the first to say what this is good for.
More tools
The best-benchmarked open-source AI memory system. And it's free.
Orca is the ADE for working with a fleet of parallel agents. Run any coding agent with your own subscription. Available on desktop, mobile and remote runtime.

A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io
Never stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors
Compress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.


