> ## Documentation Index
> Fetch the complete documentation index at: https://tally.wharflab.com/llms.txt
> Use this file to discover all available pages before exploring further.

# tally/shell-run-in-scratch

> Detects shell-form RUN instructions in scratch stages where no shell exists.

Detects shell-form RUN instructions in scratch stages where no shell exists.

| Property | Value       |
| -------- | ----------- |
| Severity | Warning     |
| Category | Correctness |
| Default  | Enabled     |

## Description

Detects shell-form `RUN` instructions (e.g., `RUN echo "hello"`) in `FROM scratch` stages.
Shell-form RUN requires a shell (`/bin/sh` by default) in the container's root filesystem.
Since `scratch` is an empty image with no shell, these instructions will always fail at build time.

If you explicitly set a `SHELL` instruction in the scratch stage, this rule is suppressed because
it assumes you have bootstrapped a shell binary into the stage (e.g., via `COPY --from` or `ADD`).

Common causes:

* Changing `FROM alpine` to `FROM scratch` to shrink the image without reworking `RUN` instructions
* An AI patch replacing the base image without adjusting command forms

## Examples

### Bad

```dockerfile theme={null}
FROM scratch
RUN echo "hello"
```

### Good (exec-form)

```dockerfile theme={null}
FROM scratch
RUN ["/myapp", "--init"]
```

### Good (explicit SHELL after bootstrapping)

```dockerfile theme={null}
FROM scratch
COPY --from=builder /bin/sh /bin/sh
SHELL ["/bin/sh", "-c"]
RUN echo "hello"
```

### Good (different base image)

```dockerfile theme={null}
FROM alpine:3.19
RUN echo "hello"
```

## Related rules

* [`tally/copy-from-empty-scratch-stage`](./copy-from-empty-scratch-stage) — if a scratch stage
  contains only a shell-form `RUN`, this rule fires but `copy-from-empty-scratch-stage` does not
  (because any `RUN` counts as file-producing). If you remove the failing `RUN` in response to this
  warning, the stage becomes truly empty and `copy-from-empty-scratch-stage` will then fire on any
  downstream `COPY --from`.

## Configuration

```toml theme={null}
[rules.tally.shell-run-in-scratch]
severity = "warning"  # Options: "off", "error", "warning", "info", "style"
```
