> ## 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 its own files: the ones
    it wrote, and its template's files that you changed. It never commits other changes in the repo, which may be
    another agent's work in progress. 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.