| name | dagger |
| description | Use when building CI/CD pipelines as code with Dagger. Covers Dagger Functions, modules, container-based execution, caching, and SDK usage in TypeScript, Python, and Go.
USE FOR: CI/CD pipelines as code, Dagger Functions and modules, container-based build steps, reproducible pipelines
DO NOT USE FOR: cloud infrastructure provisioning (use terraform or pulumi), container image authoring (use docker), Kubernetes deployment (use kubernetes)
|
| license | MIT |
| metadata | {"displayName":"Dagger","author":"Tyler-R-Kendrick"} |
| compatibility | claude, copilot, cursor |
| references | [{"title":"Dagger Documentation","url":"https://docs.dagger.io"},{"title":"Dagger GitHub Repository","url":"https://github.com/dagger/dagger"}] |
Dagger
Overview
Dagger is an open-source runtime for composable software workflows. It lets you write CI/CD pipelines in real programming languages (TypeScript, Python, Go) that run in containers, providing automatic caching, reproducibility, and portability across local dev and CI environments.
Core Concepts
- Functions — typed, cacheable units of work that run in containers
- Modules — collections of related functions, shareable and composable
- Dagger Engine — runs functions in containers with automatic caching
TypeScript Example
import { dag, Container, Directory, object, func } from "@dagger.io/dagger";
@object()
class MyPipeline {
@func()
async build(source: Directory): Promise<Container> {
return dag
.container()
.from("node:22")
.withDirectory("/app", source)
.withWorkdir("/app")
.withExec(["npm", "ci"])
.withExec(["npm", "run", "build"]);
}
@func()
async test(source: Directory): Promise<string> {
return this.build(source)
.then(ctr => ctr.withExec(["npm", "test"]).stdout());
}
@func()
async publish(source: , : ): <> {
built = .(source);
built
.([, ])
.();
}
}
Python Example
import dagger
from dagger import dag, function, object_type
@object_type
class MyPipeline:
@function
async def build(self, source: dagger.Directory) -> dagger.Container:
return (
dag.container()
.from_("python:3.12")
.with_directory("/app", source)
.with_workdir("/app")
.with_exec(["pip", "install", "-r", "requirements.txt"])
)
@function
async def test(self, source: dagger.Directory) -> str:
return await (
(await self.build(source))
.with_exec(["pytest"])
.stdout()
)
CLI Usage
dagger init --sdk=typescript
dagger call build --source=.
dagger call test --source=.
dagger call publish --source=. --tag=latest
Key Features
| Feature | Description |
|---|
| Automatic caching | Every function result is cached by inputs; unchanged steps are skipped |
| Container isolation | Functions run in containers, ensuring reproducibility |
| Type safety | Full type checking from your language's SDK |
| Composability | Call functions from other modules |
| Local + CI parity | Same pipeline runs identically on your laptop and in CI |
Using Existing Modules
dagger call -m github.com/dagger/dagger/modules/wolfi container --packages=curl,git
Best Practices
- Write functions as small, composable units — each function should do one thing.
- Use
withDirectory to pass source code into containers rather than bind-mounting.
- Leverage automatic caching — structure functions so unchanged inputs skip work.
- Use
dagger call locally to test pipelines before pushing to CI.
- Use Dagger modules from the community instead of reimplementing common tasks (linting, testing, publishing).
- Keep secrets out of function arguments — use Dagger's
Secret type for sensitive values.