Upgrading to Workspaces
If you're new to Dagger, you can skip this page. It's for existing users encountering changes.
What changed
In previous versions, dagger.json served double duty: it defined both your module's code and your project's configuration (toolchains, blueprints, customizations). These are now separate:
- Module (
dagger-module.toml) - A package of code. - Workspace (
dagger.toml) - Your project's Dagger configuration: which modules to use, how to configure them.
What happened to toolchains?
They're now just modules installed in your workspace. dagger install github.com/foo/bar adds a module to dagger.toml. Same functionality, simpler model.
What happened to blueprints?
They're now workspace modules marked as entrypoint = true in dagger.toml. The concept of "blueprint" as a distinct thing is gone; it's just a configuration flag.
What happened to customizations?
The customizations array in legacy dagger.json is deprecated. Workspace module settings now use settings in dagger.toml:
[modules.go]
source = "github.com/dagger/go"
[modules.go.settings]
goVersion = "1.22"
Do I need to migrate right now?
No. Backwards compatibility will infer a workspace from your existing dagger.json. You'll see a warning, but everything will continue to work. When you're ready:
dagger setup
dagger setup prompts before each step. Its migration step converts workspace fields from your legacy dagger.json into dagger.toml, and converts module-shaped dagger.json files to dagger-module.toml in place — module files are never moved, and only the root dagger.json plus the local dependencies and toolchains it references are touched. If anything needs manual attention, it creates .dagger/migration-report.md with instructions.
A few migration behaviors worth knowing:
- If your repo is a dagger module — the root
dagger.jsondescribes a module whose source lives at the repo root — migration converts the config in place and writes a minimaldagger.tomlthat only pins the module's SDK. The module is not installed into the workspace, so load it explicitly:dagger -m . call --help. - Running
dagger setupfrom a module subdirectory — adagger.jsonbelow the repository root — migrates just that module:dagger.jsonbecomesdagger-module.tomlin place (along with any local dependencies it references) and no workspace is created. Module recommendations are skipped in this case. - Nested
dagger.tomlfiles are never created. If a subdirectorydagger.jsonlists toolchains, migration installs them into adagger.tomlat the repository root, with local source paths rebased; the module itself is not installed into that workspace. A subdirectorydagger.jsonwith ablueprintis left as legacy with a warning. - Modules now commit their generated code (e.g.
dagger.gen.go) instead of regenerating it at runtime. Migration removes the legacy.gitignorerules that ignored those files — after migrating, rundagger generateand commit the output. - Applying a migration ends the setup run; run
dagger setupagain to see module recommendations for the migrated workspace.
What happened to module-management commands?
Workspace modules are managed with the top-level commands. Use dagger search to find modules, dagger install <module> and dagger uninstall <module> to update dagger.toml.
Module source metadata moves to dagger-module.toml. Create or edit that file directly when authoring a module or adding code dependencies.
Quick reference
| Before | Now |
|---|---|
dagger -m <ref> (with toolchains) | dagger -W <ref> |
dagger toolchain install <module> | dagger install <module> |
dagger install <dep> (module code dependency) | Add the dependency to [[dependencies]] in dagger-module.toml |
toolchains array in dagger.json | [modules.*] in dagger.toml |
blueprint in dagger.json | entrypoint = true in dagger.toml |
customizations in dagger.json | [modules.*.settings] in dagger.toml |
.env for constructor defaults | [modules.*.settings] in dagger.toml |