Skip to main content
Your agent runs these commands for you when you follow the Quickstart. This page shows the same steps by hand. Install piloop first (see the 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. 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.
1

Create the project

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.
2

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 and set runtime = "herdr".Run piloop init again, so that piloop reads the changed file.
3

Add an idea

You do not have to add more. When the backlog is short, the research agent adds ideas.
4

Start the daemon

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

Watch the campaign

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.
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.

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.
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:

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:
The agent follows the piloop-operate skill. See The orchestrator and the inbox. The second example, piloop init --example titanic-tracks ~/piloop-titanic, has two objectives. See 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.
1

Create the files

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.
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.
2

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 for the contract. Run it once yourself.
3

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 describes each one.Put margins and floors in piloop.toml, not only in brief.md. The daemon enforces only what is in piloop.toml.
4

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.
5

Register the project

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.
6

Start the campaign

The project name is the name in piloop.toml. piloop init sets it to the name of the directory.

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