---
slug: /sdk/cue/934917/action
displayed_sidebar: 'current'
---

# Actions

Actions are the basic building block of the Dagger CUE SDK.
An action encapsulates an arbitrarily complex automation into a simple
software component that can be safely shared, and repeatably executed by any Dagger Engine.

Actions can be executed directly with `dagger-cue do`, or integrated as a component of a more complex action.

There are two types of actions: _core actions_ and _composite actions_.

## Core Actions

Core Actions are primitives implemented by the Dagger CUE SDK and Dagger Engine itself. They can be combined into higher-level composite actions. Their definitions can be imported in the `dagger.io/dagger/core` package.

To learn more about core actions, see [the core action reference](../references/565505-core-actions-reference.md).

## Composite Actions

Composite Actions are actions made of other actions. Arbitrary nesting of actions is supported, so a composite action can be assembled from any combination of core and composite actions.

One consequence of arbitrary nesting is that there is no distinction between "pipelines" and "steps": everything is an action. Some actions are just more complex and powerful than others.

### Universe packages

Universe packages are ready-to-use composite actions with embedded domain logic.

They are abstractions on top of other actions, aiming to:

1. Promote code reusability
2. Enforce good practices
3. Abstract complexity

For example, the [netlify](https://github.com/dagger/dagger/blob/v0.2.28/pkg/universe.dagger.io/netlify/netlify.cue) package is based on the [docker](https://github.com/dagger/dagger/blob/v0.2.28/pkg/universe.dagger.io/docker/build.cue) and the [bash](https://github.com/dagger/dagger/blob/v0.2.28/pkg/universe.dagger.io/bash/bash.cue) actions. It is a composite action that we rely on internally whenever we need to deploy code on this platform.

## Lifecycle of an Action

A composite action's lifecycle has 4 stages:

1. Definition
2. Integration
3. Discovery
4. Execution

### Definition

A new action is _defined_ in a declarative template called a [CUE definition](https://cuetorials.com/overview/foundations/#definitions). This definition describes the action's inputs, outputs and its domain logic.

Here is an example of a simple action definition:

```cue
package main

import (
    "dagger.io/dagger"
    "dagger.io/dagger/core"
)

// Write a greeting to a file, and add it to a directory
#AddHello: {
    // The input directory
    dir: dagger.#FS

    // The name of the person to greet
    name: string | *"world"

    write: core.#WriteFile & {
        input: dir
        path: "hello-\(name).txt"
        contents: "hello, \(name)!"
    }

    // The directory with greeting message added
    result: write.output
}
```

Note the free-form structure: an action definition is not structured by a rigid schema. It is simply a CUE struct with fields of various types.

- "inputs" are simply fields which are not complete, and therefore can receive an external value at integration. For example, `dir` and `name` are inputs.
- "outputs" are simply fields which produce a value that can be referenced externally at integration. For example, `result` is an output.
- The "domain logic" is implemented via the wiring of any number of sub-actions. Sub-actions are pre-existing core actions, universe packages or any composite actions containing parts of the domain logic.

For example, this composite action includes one sub-action: `core.#WriteFile`, at the heart of the domain logic of `#AddHello`, and referenced by the `write` field.

There are no constraints to an action's field names or types.

### Integration

Action definitions cannot be executed directly: they must be integrated into a plan.

A plan is an execution context for actions. It specifies:

- What actions to present to the end user
- Dependencies between those tasks, if any
- Interactions between the tasks and the client system, if any

Actions are integrated into a plan by _merging_ their CUE definition into the plan's CUE definition.

Here is an example of a plan:

```cue
package main

import (
    "dagger.io/dagger"
)

dagger.#Plan & {
    // Say hello by writing to a file
    actions: hello: #AddHello & {
        dir: client.filesystem.".".read.contents
    }
    client: filesystem: ".": {
        read: contents: dagger.#FS
        write: contents: actions.hello.result
    }
}
```

Note that `#AddHello` was integrated _directly_ into the plan, whereas `core.#WriteFile` was integrated _indirectly_, by virtue of being a sub-action of `#AddHello`.

To learn more about the structure of a plan, see [it all begins with a plan](./347598-plan.md).

### Discovery

Once integrated into a plan, actions can be discovered by end users, by using the familiar convention of usage messages:

```bash
$ dagger-cue do --help
Execute a dagger action.

Available Actions:
 hello   Say hello by writing to a file

Usage:
  dagger-cue do [OPTIONS] ACTION [SUBACTION...] [flags]

Flags:
  [...]
```

### Execution

Once the end user has discovered the action that they need, they can execute it with `dagger-cue do`. For example:

```bash
dagger-cue do hello
```

#### Example

Given this representative CUE plan:

```cue
dagger.#Plan & {
    actions: {
        build: {...}
        deploy: {
            local: {...}
            cloud: {...}
        }
    }
}
```

Running:

- `dagger-cue do build` will run the `build` action
- `dagger-cue do deploy` will run both the `local` and `cloud` actions
- `dagger-cue do deploy local` will run the `local` sub-action
- `dagger-cue do deploy cloud` will run the `cloud` sub-action

If you specify the key path to an action regrouping several sub-actions, all of the sub-actions will run. When you specify the key path to a single action/sub-action, only one will run.

There is no depth limit to the key path you specify: it can be useful for debugging purposes.
