Setup guide · Tools and services
Run agent tasks with Harbor
Harbor installed with uv, the hello-world task passing with the oracle agent, your own task scaffolded, and Claude Code running inside a Harbor container on your Claude subscription.
Harbor runs agent tasks in containers. A task is a directory: an instruction, an environment, a test script that writes a reward, and a reference solution. Harbor runs an agent on each task in a fresh sandbox, grades the result and keeps every trajectory. It's the official harness for Terminal-Bench, and the exercises in Agent Benchmarks and Simulations use it to package their own tasks and to run Claude Code on your subscription. The ideas behind the task format are in Task specs, harnesses and sandboxes.
Before you start
- Docker running. Harbor uses Docker as its default sandbox. Follow Docker and Docker Compose first and check that
docker run --rm hello-worldworks. - uv, from Python with uv. Harbor needs Python 3.12 or newer, which uv installs for you.
- Claude Code signed in with your own Pro, Max or Ultra plan (Install Claude Code). You only need it for step 4.
- Disk and time. Each task builds an image, and agent trials install the agent in the container. The first run of a task takes minutes, later runs reuse the cached layers. Keep 10 GB free.
1. Install Harbor
Install Harbor as a uv tool, so the harbor command is available everywhere without touching your projects:
uv tool install harbor
harbor --helpTo upgrade to the current release later, reinstall it:
uv tool uninstall harbor
uv tool install harborIf you don't use uv, pip install harbor works too.
2. Run the oracle on a sample task
The oracle agent runs a task's reference solution instead of a model, so it costs nothing and tells you that Docker, the task and the verifier all work:
mkdir harbor-sandbox && cd harbor-sandbox
harbor run -t hello-world/hello-world -a oracleHarbor pulls the task, builds its image, runs the solution, runs the tests, and writes everything under ./jobs/. Each trial gets its own folder with a result.json (rewards and any exception), the agent's logs and the verifier's output. Open the local viewer to browse them:
harbor view jobsIt prints a local URL (the first free port from 8080). Keep the command running while you look.
The other built-in control is nop, an agent that does nothing. On a sound task it scores 0:
harbor run -t hello-world/hello-world -a nop3. Scaffold your own task
harbor task init my-taskThis creates instruction.md, task.toml, environment/Dockerfile, solution/solve.sh and tests/. The test script must write a number to /logs/verifier/reward.txt (or labelled numbers to /logs/verifier/reward.json). New tasks are set up with a separate verifier: tests run in a fresh container, and only files you list as artifacts in task.toml are copied across from the agent's container.
Check the task with both controls, and lint it:
harbor run -p my-task -a oracle # must score 1
harbor run -p my-task -a nop # must score 0
harbor lint my-task-p also accepts a folder of task directories, which Harbor runs as a local dataset.
4. Run Claude Code on your subscription
Harbor's claude-code agent installs Claude Code inside the task container. To bill your Claude subscription rather than an API key, give it a long-lived OAuth token. Create one on your machine:
claude setup-tokenIt opens the same browser sign-in as /login and prints a token valid for one year. It doesn't save the token anywhere. Export it in the shell you run Harbor from:
export CLAUDE_CODE_OAUTH_TOKEN=your-tokenThen run the agent, with three independent attempts and two trials at a time:
harbor run -p my-task -a claude-code -m anthropic/claude-sonnet-5-5 \
--ae CLAUDE_FORCE_OAUTH=1 -k 3 -n 2--ae sets an environment variable for the agent. CLAUDE_FORCE_OAUTH=1 tells Harbor's Claude Code integration to drop any API key it finds, so the run can't fall back to API billing. Without it, Harbor uses ANTHROPIC_API_KEY whenever both are set.
Each attempt is a full Claude Code session and counts against your plan's usage limits, so start with a few tasks and -k 3.
Flags you'll use
| Flag | What it does |
|---|---|
-p PATH, -t ORG/TASK, -d ORG/DATASET | A local task or folder, a Hub task, a Hub dataset |
-a AGENT, -m MODEL | The agent (oracle, nop, claude-code, codex, …) and its model |
-k N, -n N, -r N | Attempts per task, trials at once, retries for retryable errors |
--ae K=V, --ak K=V, --effort | Agent environment variable, agent option (for example max_turns=25), reasoning effort |
-o DIR, --job-name NAME | Where jobs go and what this one is called |
--override-cpus, --override-memory-mb, --timeout-multiplier | Change resources or time limits for the whole job |
harbor run --help lists the rest, and the full list of agents.
Check it works
harbor run -t hello-world/hello-world -a oracle --job-name check && \
find jobs/check -mindepth 2 -maxdepth 2 -name result.json | xargs catExpected: one trial's JSON, in which verifier_result.rewards shows a reward of 1 and exception_info is null.
Troubleshooting
harbor: command not found after installing. uv's tool folder isn't on your PATH. Run uv tool update-shell, then open a new terminal.
Cannot connect to the Docker daemon, or the environment never starts. Docker Desktop or OrbStack isn't running. Start it and wait until it says it's running; on Linux run sudo systemctl start docker. A trial that fails here is recorded as a sandbox error, not as a failed attempt.
Claude Code trials fail on authentication, or usage shows up on an API account. Check that echo $CLAUDE_CODE_OAUTH_TOKEN prints the token in the shell you run harbor from, and pass --ae CLAUDE_FORCE_OAUTH=1. Unset ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN and ANTHROPIC_BASE_URL if you don't need them.
The first agent run is slow. Harbor builds the image and installs the agent before the first attempt. Install the agent's dependencies in your Dockerfile (Claude Code needs curl), and keep -n low on a laptop so trials don't compete for CPU and memory.
Going further
- Run evals with Inspect, for model evals through an API with sandboxed tools
- MCP servers in Claude Code: Harbor registers servers declared under
[[environment.mcp_servers]]intask.tomlfor agents that support them - Simulate a user:
--user-agent,--user-modeland--bridge acprun a second agent that holds the instruction and talks the agent under test through the task - Noise, reproducibility and eval infrastructure, on what concurrency, retries and resource limits do to the results
Sources
- Harbor: InstallationDocs · Harbor Framework`uv tool install harbor`, upgrading, nightly builds, and the Docker requirement for local runs.
- Harbor: Create a taskDocs · Harbor Framework`harbor task init`, the task layout, and checking a task with the oracle agent before running a real one.
- Harbor: Run a jobDocs · Harbor FrameworkThe `harbor run` flags for tasks, datasets, agents, attempts, concurrency, retries, sandboxes and resources.
- Harbor: Agent auth resolutionDocs · Harbor FrameworkWhich host variables each agent receives, including `CLAUDE_CODE_OAUTH_TOKEN` for `claude-code`.
- Claude Code: AuthenticationDocs · Anthropic`claude setup-token`, the one-year subscription token, and the order in which Claude Code picks a credential.
Exercises that use this
- Package five Quillmoor tasks for Harbor and run the controlsAgent Benchmarks and Simulations · Task specs, harnesses and sandboxes
- Re-annotate a Quillmoor suite with planted flawsAgent Benchmarks and Simulations · Contamination, saturation and broken tasks
- Red-team your Quillmoor benchmarkAgent Benchmarks and Simulations · Auditing benchmarks for exploits