docs/current_docs/introduction/features/shell.mdx
import VideoPlayer from '@components/VideoPlayer';
The Dagger CLI includes an interactive shell that translates the familiar Bash syntax to Dagger API requests. It's the simplest and fastest way to run Dagger workflows directly from the command-line.
You can use it for builds, tests, ephemeral environments, deployments, or any other task you want to automate from the terminal.
:::important Dagger Shell commands run as sandboxed functions, accessing host resources (files, secrets, services) only when explicitly provided as arguments. This can make commands slightly more verbose, but also more repeatable, giving you confidence to iterate quickly without second-guessing. :::
Here's an example of Dagger Shell in action:
container | from alpine | with-exec apk add curl | with-exec -- curl -L https://dagger.io | stdout
Here's another, more complex example:
container |
from cgr.dev/chainguard/wolfi-base |
with-exec apk add go |
with-directory /src https://github.com/golang/example#master |
with-workdir /src/hello |
with-exec -- go build -o hello . |
file ./hello |
export ./hello-from-dagger
Dagger Shell uses the Bash syntax as a frontend, but its behavior is quite different in the backend:
foo | bar really means foo().bar(). (similar to SQLite)Besides these differences, all the features of the Bash syntax are available in Dagger Shell, including:
container=$(container | from alpine)container() { container | from alpine; }frontend | test & backend | test & .waitDagger Shell supports multiple ways to input commands:
<Tabs groupId="shell"> <TabItem value="Inline execution"> ```shell dagger -c 'container | from alpine | terminal' ``` </TabItem> <TabItem value="Standard input"> ```shell title="First type 'dagger' for interactive mode." dagger <<EOF container | from alpine | terminal EOF ``` </TabItem> <TabItem value="Script"> ```shell #!/usr/bin/env daggercontainer | from alpine | with-exec cat /etc/os-release | stdout
</TabItem>
<TabItem value="Interactive REPL">
```shell title="First type 'dagger' for interactive mode."
container | from alpine | terminal
Dagger Shell can load modules, inspect their types, and run their functions. This works for both local and remote modules.
<VideoPlayer src="/img/current_docs/introduction/features/shell-module.webm" alt="Dagger Shell module loading" />For example, try running this command:
dagger -m github.com/dagger/dagger/[email protected]
This loads the module github.com/dagger/dagger/docs at version v0.18.5. Wait for the Dagger Shell interactive prompt, then:
.help
We see new commands available, loaded from the module. Let's try running one:
server | up
This builds the docs server defined in the module, and runs it as an ephemeral service on your machine.
You can load multiple modules in the same session, each scoped to a single pipeline, then combine those pipelines into a bigger pipeline. For example:
dagger <<.
github.com/dagger/dagger/modules/wolfi |
container --packages=nginx |
with-directory /var/www $(
github.com/dagger/dagger/docs | site
)
.
This loads github.com/dagger/dagger/docs into one pipeline, github.com/dagger/dagger/modules/wolfi into another, then combines them.
This works by executing the module's constructor function. It works exactly like executing any other function:
.help MODULEMODULE --foo=bar --bazfoo=$(MODULE)MODULE | foo | barfoo --bar=$(MODULE | foo | bar)Dagger Shell lets you save the result of any command to a variable, using the standard bash syntax. Values of any type can be saved to a variable, including objects.
Here's an example:
<Tabs groupId="shell"> <TabItem value="System shell"> ```shell dagger <<'.' repo=$(git https://github.com/dagger/hello-dagger | head | tree) env=$(container | from node:23 | with-directory /app $repo | with-workdir /app) build=$($env | with-exec npm install | with-exec npm run build | directory ./dist) container | from nginx | with-directory /usr/share/nginx/html $build | terminal --cmd=/bin/bash . ``` </TabItem> <TabItem value="Dagger Shell"> ```shell title="First type 'dagger' for interactive mode." repo=$(git https://github.com/dagger/hello-dagger | head | tree) env=$(container | from node:23 | with-directory /app $repo | with-workdir /app) build=$($env | with-exec npm install | with-exec npm run build | directory ./dist) container | from nginx | with-directory /usr/share/nginx/html $build | terminal --cmd=/bin/bash ``` </TabItem> </Tabs> <VideoPlayer src="/img/current_docs/introduction/features/shell-variables.webm" alt="Dagger Shell variables" />