Self-hosted service
dagger/dagger avatar
dagger/dagger

Dagger: a programmable CI/CD engine that runs the same way on your laptop and in CI

Automation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud

16,250 stars921 forksGoApache-2.0

At a glance

What is it?
Dagger replaces shell scripts and proprietary CI YAML with a typed, container-based execution engine and SDKs in eight languages. It is a good fit when your delivery pipeline has outgrown copy-pasted YAML, and a poor fit if you only need a handful of steps.
Who is it for?
Adopt Dagger if your delivery logic has outgrown YAML and you want the same pipeline to run on a laptop and in CI. Do not adopt it if your pipeline is a few shell steps that already work, or if you cannot run a Linux container runtime on developer machines.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What Dagger replaces, and who ends up using it

The README frames the problem directly: "Shell scripts and proprietary YAML are no longer acceptable for automating software delivery." That is the gap Dagger targets. Pipeline logic written in a CI vendor's YAML dialect cannot be executed on a developer laptop, cannot be unit tested, and cannot be reused across vendors. Dagger moves that logic into ordinary programs written against a typed API, so the same code path runs locally, in CI, or in the cloud.

The intended user is a platform or build engineer who owns delivery for a codebase, not an application developer who occasionally edits a workflow file. The README lists eight SDKs (Go, Python, TypeScript, PHP, Java, .NET, Elixir, Rust), which means the pipeline author writes in whatever language the team already uses. The repository's primary language is Go, and go.mod pins dagger.io/dagger v0.21.9 with a local replace directive pointing at sdk/go, so the Go SDK is developed in-tree alongside the engine.

One consequence is easy to miss: Dagger does not remove the CI server. It removes the CI-specific language. You still need something to trigger the pipeline, and that trigger is now a thin call into Dagger rather than the place where the logic lives.

The execution model: a GraphQL API, typed artifacts, and content-addressed caching

Dagger's core is an execution engine exposing a system API over GraphQL. The repository layout supports this: dagql/ sits next to core/, and go.mod depends on gqlgen and genqlient, the Go GraphQL code generation pair. Each SDK is generated from that API schema, which is why the README describes the SDKs as giving "idiomatic code with full type safety and editor support" rather than hand-written wrappers that drift from the server.

The API orchestrates concrete resources: containers, filesystems, secrets, git repositories, network tunnels. Operations are keyed by their inputs, so changing one file re-runs only the affected operations. The README calls the cache "content-addressed" and says it works automatically across local runs and CI. That is the mechanism behind the local-first promise: a build performed on a laptop and the same build performed in CI resolve to the same cache keys, provided the inputs match.

Typed artifacts are the second half. The README states that custom object types with encapsulated state and functions are content-addressed and can cross SDK language and module boundaries without serialization. In practice that means a module written by one team can return a typed value that another team's module consumes, even if the two modules are in different languages. The trade-off is that you are adopting a type system, not just a runner. Types that are not modelled in the API have to be modelled by you.

Observability is built into the same path. Every operation emits an OpenTelemetry span, and the CLI includes a live terminal UI. The README names Jaeger and Honeycomb as export targets, along with any OTel-compatible backend.

Installing Dagger and running a first pipeline

The README gives a Homebrew install for macOS and Linux. The repository also carries install.sh and install.ps1 at the top level, and the docs site is the canonical place for other platforms.

bash
brew install dagger/tap/dagger

After installation, the CLI is available as dagger. The engine itself runs in a container, so a Linux container runtime such as Docker must be present. The README is explicit that this is the only dependency.

The repository contains a dagger.toml and a dagger.lock at the top level, which indicates that a project is configured through a manifest plus a lockfile rather than a single workflow file. Because the README does not document the manifest keys, read dagger.toml in the repository before assuming a schema.

For a first real use, the documented path is the quickstart at docs.dagger.io/quickstart. The README also points at the documentation index at docs.dagger.io. Beyond the install command, the README does not include a worked pipeline example, so treat the quickstart as the source of truth for the first module rather than copying anything from this article.

When you do write that first pipeline, the shape to expect is a function that returns a typed artifact (a container, a directory, a file) and a CLI invocation that executes it. The CLI's live TUI shows the OpenTelemetry trace as the pipeline runs, which is the fastest way to see which operation actually executed and which came from cache.

Where Dagger is the wrong tool

Dagger assumes a Linux container runtime on every machine that runs the pipeline. The README states the requirement plainly: natively on Linux, or via Docker Desktop and similar products on macOS and Windows. On a fleet of Windows developer laptops without Docker Desktop, that assumption fails at the first step, and no amount of SDK quality fixes it.

The second limitation is adoption cost. A team that already has a working pipeline of a dozen shell steps in a CI vendor's YAML is trading a known, boring system for a typed API, a module ecosystem, and a cache model that must be reasoned about. The README's claim that caching is automatic is true at the operation level, but it does not tell you how to debug a cache miss, and the README does not document cache invalidation controls beyond the phrase "advanced cache control." That is a real gap for anyone whose build is sensitive to environment differences between local and CI.

The third case is scope. Dagger builds, tests and ships codebases. It is not a deployment orchestrator with opinions about your infrastructure, and it is not a replacement for a scheduler. If your problem is that a Kubernetes rollout is flaky, Dagger is not the layer that fixes it.

Finally, the repository is large and the engine is a substantial piece of software. go.mod shows dependencies on containerd v2, gqlgen, Bubble Tea, and cloud secret managers including AWS Secrets Manager and GCP Secret Manager. That breadth is a sign of how much surface area the engine covers, and also of how much of it you are pulling in to run a build.

Dagger compared with a container-native build tool like BuildKit or a plain Dockerfile pipeline

The closest comparison is not another CI vendor. It is the combination of a Dockerfile plus whatever shell script drives it. That approach is local-first and repeatable in the same sense Dagger claims: docker build runs identically on a laptop and in CI, and layer caching is content-addressed.

The difference is in what can be expressed. A Dockerfile describes how to produce an image. It cannot easily branch on a test result, call an external API, read a secret and feed it into a step, or return a typed value that another pipeline consumes. Dagger's system API covers containers, filesystems, secrets, git repositories and network tunnels in one typed surface, and the SDKs let you write ordinary control flow around them. The README's phrase for this is "programmable," and the REPL and module ecosystem are the practical expression of it.

What you give up is the Dockerfile's ubiquity. Every developer already knows how to read one, and every CI vendor already knows how to build one. A Dagger module is code in one of eight languages, and reviewing it requires reading that language. For a small team with a simple image build, that is a net loss.

Maintenance, releases, and the licence

The repository is not archived, and the last push was on 2026-09-15. The most recent release listed is v0.21.9 from 2026-08-26, with matching TypeScript and Rust SDK releases on the same day. That pattern, where the engine and the SDKs are versioned together, matters for upgrades: bumping the engine implies checking the SDK version in your own go.mod or package manifest, since the Go SDK is pinned to v0.21.9 in the repository's own go.mod.

The version numbering is pre-1.0. Dagger has not declared a stable API, and the repository carries a .changes/ directory and a .changie.yaml, which indicates changelog entries are collected per change. Read CHANGELOG.md before upgrading across minor versions rather than assuming compatibility.

The licence is Apache-2.0, and the repository includes a NOTICE file alongside LICENSE. Apache-2.0 permits commercial use and modification and includes an explicit patent grant, but it also carries attribution and notice-retention obligations. If you redistribute the engine or embed it in a product, read LICENSE and NOTICE together. This is a description of the files present, not legal advice.

Upgrade cost in practice is the SDK version plus any module API changes. The README does not document a rollback procedure or a compatibility policy, so plan to test an upgrade on a branch before moving your CI to it.

Editorial conclusion

Adopt Dagger if your delivery logic has outgrown YAML and you want the same pipeline to run on a laptop and in CI. Do not adopt it if your pipeline is a few shell steps that already work, or if you cannot run a Linux container runtime on developer machines. Before committing, verify that a container runtime is available on every machine that will run the pipeline, and check the licence and NOTICE files in the repository against how you plan to redistribute the engine.

Frequently asked questions

What is Dagger in CI/CD?

Dagger is a platform for automating software delivery that can build, test and ship any codebase. It runs locally, in a CI server, or in the cloud, and exposes a typed system API with SDKs in eight languages so pipeline logic is written as code rather than vendor YAML.

How do I use Dagger?

Install the CLI, for example with brew install dagger/tap/dagger, then write a pipeline against one of the SDKs and run it with the dagger CLI. The README points to docs.dagger.io/quickstart for the first working example.

What does Dagger need to run?

The README states that the only requirement is a Linux container runtime, running natively on Linux or via Docker Desktop and similar products on macOS and Windows. Local and CI behavior are described as identical.

Which languages does Dagger have SDKs for?

The README lists native SDKs for Go, Python, TypeScript, PHP, Java, .NET, Elixir and Rust. Each SDK is generated from the API schema, so the types match the engine.

What licence is Dagger released under?

The repository carries an Apache-2.0 licence, with a NOTICE file alongside LICENSE. Apache-2.0 allows commercial use and modification and includes a patent grant, with attribution and notice-retention obligations.

Official sources

  1. dagger/dagger on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Community notes

Community notes