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

# Run a campaign by hand

> Set up and start a campaign with the piloop CLI, without an agent. First on the enwik8 example, then on your own repo.

Your agent runs these commands for you when you follow the [Quickstart](/quickstart). This page shows the same steps
by hand. Install piloop first (see the [Quickstart](/quickstart)), and log in to at least one coding agent CLI:
run `claude auth login`, or `codex login`, or start `pi` and type `/login`.

## The enwik8 example

This example is a small version of the [Hutter Prize](http://prize.hutter1.net/). The task is to compress the first
10 MB of enwik8, a dump of English Wikipedia, into as few bytes as possible. The agents edit one file,
`compressor.py`. The baseline is zlib at level 9.

<Steps>
  <Step title="Create the project">
    ```bash theme={null}
    piloop init --example enwik8 ~/piloop-enwik8
    cd ~/piloop-enwik8
    ```

    `piloop init` copies the example, downloads `data/enwik8.zip` (about 36 MB, not committed) and makes a git repo
    with a baseline commit. Then it measures the baseline and registers the project. The baseline is about 3.69 MB.
  </Step>

  <Step title="Choose your agents">
    The example uses Claude Code (`harnesses = ["claude"]` in `piloop.toml`). To use Codex or pi as well, or instead,
    edit `harnesses`, for example `harnesses = ["claude", "codex"]`.

    The agents run as background processes, and `piloop watch` shows what they print. To see and steer every agent
    in a terminal pane, install [Herdr](https://herdr.dev) and set `runtime = "herdr"`.

    Run `piloop init` again, so that piloop reads the changed file.

    ```bash theme={null}
    piloop init
    ```
  </Step>

  <Step title="Add an idea">
    ```bash theme={null}
    piloop idea add enwik8 "Try lzma at the highest preset"
    ```

    You do not have to add more. When the backlog is short, the research agent adds ideas.
  </Step>

  <Step title="Start the daemon">
    ```bash theme={null}
    piloop serve --detach
    ```

    The daemon starts a worker for the idea and a research sweep for more ideas. It writes its log to
    `~/.piloop/serve.log`.
  </Step>

  <Step title="Watch the campaign">
    ```bash theme={null}
    piloop watch
    ```

    Press `enter` to open the project. The four panels show the inbox, the agents, the ideas and the candidates. Press
    `q` to quit. The daemon continues to run.
  </Step>
</Steps>

<Note>
  The example stops after 20 scored worker runs (`[stop] max_runs = 20` in `piloop.toml`). A run that ends without a
  scored commit does not count. To run longer or shorter, change `max_runs` and run `piloop init`. `piloop stop`
  stops the daemon, not the campaign: the project stays active, and the next `piloop serve` continues it.
</Note>

### What happens

Each worker edits `compressor.py` and commits. For each commit, the daemon runs `evaluate.py` in a clean worktree. The
script checks that `decompress(compress(data))` gives back the exact input. If it does not, the commit is a crash.
Then the script prints two metrics:

* `bytes`: the compressed size plus the size of `compressor.py`. Lower is better. This is the primary metric. As in
  the Hutter Prize, the size of the decompressor counts.
* `seconds`: the time to compress and decompress. Lower is better. This is a guardrail: a commit may add at most 10 s
  to the time of the head, and the time must stay below 120 s.

```toml theme={null}
[[metrics]]
name = "bytes"
direction = "lower"
role = "primary"

[[metrics]]
name = "seconds"
direction = "lower"
role = "guardrail"
margin = 10
floor = 120
```

A commit with fewer bytes that holds the guardrail is a `keep`, and it becomes the new head. The next runs start from
it. To see the progress at any time, run:

```bash theme={null}
piloop status enwik8
```

### Add an orchestrator

Without an orchestrator, escalations wait in the inbox until you read them. To let an agent answer them, open your
coding agent in `~/piloop-enwik8` and ask:

```text theme={null}
Orchestrate the piloop campaign.
```

The agent follows the `piloop-operate` skill. See [The orchestrator and the inbox](/concepts/orchestrator).

The second example, `piloop init --example titanic-tracks ~/piloop-titanic`, has two objectives. See
[Tracks](/concepts/tracks).

## Your own repo

A campaign needs three files in your repo and a registration:

* `piloop.toml`: the configuration, with the metrics.
* `brief.md`: the instructions that every worker reads.
* An evaluate command that prints `METRIC <name>=<value>` lines.
* A registration, which `piloop init` does.

<Steps>
  <Step title="Create the files">
    ```bash theme={null}
    cd my-repo
    piloop init
    ```

    In a repo without `piloop.toml`, `piloop init` writes `piloop.toml`, `brief.md` and an `evaluate.py` stub. It
    keeps every file that exists already. It runs `git init` when necessary. Then it commits every uncommitted change
    in the repo (`git add -A`), not only the files that it wrote, so commit or stash your own work first. Then it
    stops, because `evaluate.py` is still the stub.

    <Warning>
      If your repo already has an `evaluate.py`, `piloop init` keeps it and does not stop. It goes on to measure the
      baseline with the template's `piloop.toml`, which usually fails, because your script does not print
      `METRIC score=<value>`. Edit `piloop.toml` as in the next steps, then run `piloop init` again.
    </Warning>
  </Step>

  <Step title="Write the evaluate command">
    Make `evaluate.py` measure your code, or set `evaluate` in `piloop.toml` to a command that you have already. See
    [the evaluate command](/concepts/projects#the-evaluate-command) for the contract. Run it once yourself.
  </Step>

  <Step title="Edit piloop.toml">
    Set `name`, `evaluate`, the `[[metrics]]` tables, `harnesses` and `[model]`. The template lists every key. A key
    that is set shows its default, unless its comment says otherwise, and the optional keys are comments. The
    [configuration reference](/reference/configuration) describes each one.

    Put margins and floors in `piloop.toml`, not only in `brief.md`. The daemon enforces only what is in
    `piloop.toml`.
  </Step>

  <Step title="Edit brief.md">
    Write to the worker: what to improve, how to measure it, which files it may edit, which files it must not touch,
    and what needs a human decision. Keep it to one page. The template has a heading for each topic.
  </Step>

  <Step title="Register the project">
    ```bash theme={null}
    piloop init
    ```

    This commits your edits, measures `HEAD` as the baseline and registers the project. Check the baseline value. A
    value that surprises you usually means that the evaluate command is wrong.
  </Step>

  <Step title="Start the campaign">
    ```bash theme={null}
    piloop serve --detach
    piloop idea add my-repo "Cache the parsed input" --hypothesis "Parsing takes 40% of the time" --priority 1
    piloop watch
    ```

    The project name is the `name` in `piloop.toml`. `piloop init` sets it to the name of the directory.
  </Step>
</Steps>

## Change the configuration

Edit `piloop.toml` and run `piloop init` again. piloop reads the file again and keeps the history of the project. The
daemon uses the copy of the file that the last `piloop init` stored, so an edit has no effect until you run
`piloop init`. You can also ask your agent to reconfigure the campaign. It runs the setup interview again, with the
current values as the first options.

A change to the evaluate command, to a metric's name or direction, or to `link` makes a new evaluator. piloop never
compares scores from two evaluators: the daemon measures every kept candidate again under the new evaluator. A change to
a role, a margin, a floor or `confidence` changes how the next candidates are judged, and keeps the scores.

## Next steps

* [Projects and the evaluate command](/concepts/projects)
* [Running for days](/guides/running-for-days)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.