---
title: reeval image build, reeval clean
description: Build every sandbox image a run needs, and remove local debug data.
---
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reeval.ai/llms.txt
> Use this file to discover all available pages before exploring further.

`reeval image build` builds the Docker images your evals need before a run. `reeval clean` removes the local debug data runs leave in `.reeval/debug`.

```bash
npx reeval image build --dry-run
npx reeval image build --profile nightly
npx reeval clean --keep 3
```

## reeval image build

[//]: # (generated:cli-help:image-build)

```text
reeval image build [filter...]
                              Build every image the evals' Docker sandboxes need, per harness: reeval's
                              image (bakes in its CLI), from and dockerfile images, install layers.
                              Builds what's missing or stale (a from tag that moved upstream), three
                              at a time, and reports every failure; exit 3 if any image failed
  --profile <name>            Plan with a profile from reeval.config.ts, as reeval run does, so its
                              harness, sandbox and tags pick the images (also REEVAL_PROFILE)
  --force                     Rebuild every image, pulling each base again
  --dry-run                   List the images, how each is made and how each stands, building
                              nothing (a from tag is looked up in its registry, not pulled)
```

[//]: # (/generated:cli-help:image-build)

Filters match as [`reeval run`'s](/reference/cli/run) do: a substring of an eval file's path, an eval's name or a cell. A cell names its harness, so `reeval image build claude-code` builds only the images Claude Code's cells need. A filter that matches nothing exits 2.

It collects the evals with `--config`, `--profile` or `REEVAL_PROFILE`, and filters (not `--tag`), then prepares every image, three at a time, the way `reeval run` does before a run. A profile's `defaults.harness` and `defaults.sandbox` pick the images and its `tags` narrow the evals, as they would for the run; an unknown profile exits 2.

1. reeval's image for each harness the plan uses, `reeval-sandbox:<harness>-<adapter version>` (for example `cursor-0.1.6`), which bakes that agent's CLI onto `reeval-sandbox-base:latest`: built when it's missing or reeval's base changed.
2. Each `docker({ from })` image: built when missing, and rebuilt when its tag has moved upstream since.
3. Each `docker({ dockerfile })` image and `install` layer: built when its content hash (or its base) is new.

`--force` rebuilds all of them and pulls each base again. It keeps going past a failure, then prints a line per image and exits 3 if any failed (2 if the only failures are a missing `docker({ image })`):

```text
✓ docker · cursor: reeval-sandbox:cursor-0.1.0 e04d443bc8e2
✗ docker:bad.Dockerfile · cursor (1 eval): Building evals/bad.Dockerfile failed: a RUN step exited 42
    | broken
  (full log: .reeval/cache/images/reeval-dockerfile-bad-dockerfile-6d9d1a5c9d335eb6.log)
✓ docker:debian:bookworm-slim · cursor: reeval-sandbox:cursor-0.1.0-debian-bookworm-slim-12f2bc40 41f80062675e
…
2 of 4 images failed to build
```

A real `--dry-run` in a project whose evals use several harnesses and images, where `✓` is ready, `+` to build, `~` stale, `✗` missing and `?` unchecked:

```text
images  7 sandbox images (nothing built: --dry-run)
docker · cursor · 23 evals
  + base  reeval-sandbox:cursor-0.1.6  (to build: not built yet)
…
docker+0ab0e263 · cursor + install · 1 eval
  + base               reeval-sandbox:cursor-0.1.6  (to build: not built yet)
  + install 1 command  reeval-install:<base id + commands>  (to build: not built yet)
python · cursor · 1 eval
  + from python:3.12-slim  reeval-sandbox:cursor-0.1.6-python-3-12-slim-375f4a61  (to build: on python:3.12-slim (a6e34c598f24))
…
```

Each block names its sandbox and the harness whose image it builds on. An `install` layer's tag hashes its base image's id, so it reads `reeval-install:<base id + commands>` until the base is built, and its real tag after.

When Docker can't say whether an image is there (the daemon doesn't answer, or `docker` won't start), the step is `?` unchecked, with Docker's error, never "not built yet". `reeval run --dry-run`'s `images` line counts it the same way:

```text
docker · claude-code · 1 eval
  ? base  reeval-sandbox:claude-code-1.0.160-patch.b17cde50  (unchecked: docker image inspect reeval-sandbox:claude-code-1.0.160-patch.b17cde50 couldn't run: spawn docker ENOENT)
```

It needs a `reeval.config.*`, as `reeval run` does: with none found it exits 2 (`No reeval.config.ts … here or above. Run reeval init.`). Rebuild after upgrading reeval.

## reeval clean

[//]: # (generated:cli-help:clean)

```text
reeval clean                  Remove local debug data (.reeval/debug); --keep <n> keeps the newest n runs
  --images                    Also remove the Docker images reeval built that nothing tags any more,
                              and the intermediate -base tags of from builds
```

[//]: # (/generated:cli-help:clean)

`reeval run` already keeps only the newest `debug.keep` runs' debug data (default 20). `reeval clean` removes all of it, or all but the newest `--keep <n>` runs. It never touches `.reeval/runs/` or the history folder.

```text
Removed debug data for 4 runs (106.9 KB) from .reeval/debug
```

## Related

- [Sandboxes and toolchains](/guide/sandboxes)
- [docker()](/reference/sandbox/docker)
- [Debug data](/reference/debug-data)
