
:::note[What you will learn]
By the end of this tutorial you will be able to:

1. Activate a crate and use its commands as if they were natively installed
2. Pipe output between commands running in separate containers
3. Run one-off containerized commands from a script without activating a crate
4. Deactivate a crate and restore your original environment
:::

## How bulker works (30-second version)

A **crate** is a list of command-name-to-container-image mappings, defined in a YAML manifest. When you **activate** a crate, bulker creates a symlink (a "shimlink") for each command pointing to the `bulker` binary, and adds them to your PATH. When you run a shimlink, bulker reads `argv[0]` to identify the command and launches the matching container behind the scenes. You never type `docker run` -- you just type the command name.

## Activate a crate

This tutorial assumes you've [installed bulker](../install/) and that Docker or Apptainer is available on your system.

> **Note:** The first time you run a containerized command, your container engine must be running. Start Docker Desktop (macOS/Windows) or confirm the Docker daemon is active (`docker info`) before proceeding. On HPC systems, Apptainer is available without a daemon.

With bulker, there's no separate load/install step — activate directly:

```bash
bulker activate demo
```

This fetches the `demo` manifest from the registry (if not already cached), creates shimlinks for each command, and puts them on your PATH. Your prompt updates to show the active crate.

## Run commands

Commands from the crate work as if natively installed. The first time you run a command, Docker pulls the image automatically:

```bash
cowsay Hello world!
```

```
 ______________
< Hello world! >
 --------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
```

The `fortune` command is also in the demo crate, so you can pipe between containers:

```bash
fortune | cowsay
```

```
 _________________________________________
/ You are deeply attached to your friends \
\ and acquaintances.                      /
 -----------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
```

Each command runs in its own container — there's no single container with both `fortune` and `cowsay`.

## Deactivate

```bash
bulker deactivate
```

This restores your original PATH.

## One-off commands with exec

For scripts and non-interactive use, `exec` runs a single command without modifying your shell:

```bash
bulker exec demo -- fortune
bulker exec demo -- cowsay "Hello from exec"
```

## Exercise: try it yourself

1. Activate the `demo` crate and run `fortune` by itself. What happens?
2. Deactivate, then run the same command using `bulker exec demo -- fortune`. Compare the experience.
3. Combine both commands in a single pipeline using exec mode: `bulker exec demo -- sh -c 'fortune | cowsay'`. Why does this require `sh -c`?

<details>
<summary>Hint for question 3</summary>

Without `sh -c`, the pipe (`|`) is interpreted by your host shell, which tries to pipe the output of one `bulker exec` call into another command. Wrapping the pipeline in `sh -c '...'` runs the entire pipeline inside a single container shell invocation. In interactive mode (`bulker activate`), piping works naturally because both shimlinks are on your PATH.
</details>

## Key points

- `bulker activate <crate>` puts containerized commands on your PATH. `bulker deactivate` removes them.
- `bulker exec <crate> -- <cmd>` runs a single command without changing your shell -- useful in scripts.
- Each command runs in its own container. Pipes between commands work naturally in an activated crate.
- You never type `docker run`. Bulker handles container orchestration behind shimlinks.

## Next steps

- [Write your own manifest](../../guides/write-a-manifest/) to containerize your own tool collection
- [Manage Crates](../../guides/manage-crates/) to list, inspect, and clean your local crate cache
- [Combine multiple crates](../../guides/import-crates/) to build richer environments
