Hillclimbing on verifiable rewards.
Use Claude Code and Codex to autonomously search for python programs that optimize a score you define.
Website · Docs · Quickstart · Python SDK · CLI reference · Blog · Discord
hillclimb provides a modular harness, tooling and testbed for exploring and
benchmarking autoresearch algorithms. The aim is to provide a tool to discover better
autoresearch methods, rather than build a single best autoresearcher.
You provide a verifier script, verifier.sh, and (optionally) a starting
solution, solution.py. hillclimb then spends a compute budget running a
search policy — a climber — that
decides which version to build on next and dispatches headless coding agents
to write, debug and improve it. Each version is scored through your verifier,
and hillclimb keeps the one that scores best.
The harness is fixed. The climber — what to try next and how each attempt is prompted — is a block you can swap, edit and share, so two methods can be compared on the same problem under the same budget.
Quickstart
pip install hillclimb # or: uv tool install hillclimb
hillclimb connect claude # or codex, pi, openrouter; add --agent dummy to any run for no LLM at all
hillclimb init # hillclimb.yaml, problems/, runs/ in this folder
hillclimb problem get heilbronn-convex-13 # the verifier is the problem; description.md is the brief
hillclimb verify heilbronn-convex-13 # score the floor solution
hillclimb run heilbronn-convex-13 --budget 10m
hillclimb watch # live coding agents and scores (also: chart, tree)
hillclimb stop --all
hillclimb summit # copy the best solution.py into this folder
Every search also keeps its best in runs/<run-id>/searches/<search-id>/best/.
The walkthrough goes through each step.
Climbers
A climber is five modules, run in this order at every step of a search. Each one is a built-in or a Python file you can edit.
| Module | Decides | Built in |
|---|---|---|
selector_policy |
which candidate the next attempt builds on | best, map-elites |
operator_policy |
which operator to apply to it | greedy |
operators |
how one attempt is made: the prompt the coding agent gets | draft, debug, improve, ensemble |
tuner |
which parameter values to try on a candidate | random, optuna |
memory |
what carries over from one search to the next | files, none |
Together they are one block of config, in a run spec or as the folder's default
in hillclimb.yaml:
climber:
selector_policy: map-elites # which candidate to build on next
operator_policy: greedy # which operator to use on it
operators: [draft, debug, improve, crossover.py:Crossover]
tuner: optuna
memory: files
params: {num_drafts: 5}
Every slot takes a prebuilt module, a .py file of your own, or
package.module:Class. Presets: greedy, openevolve, gepa. Or compose in
Python:
from hillclimb import Budget, Climber, Problem
from hillclimb.policies import Greedy
from hillclimb.selectors import MapElites
problem = Problem("heilbronn-convex-13")
budget = Budget(wall_clock="10m", evaluations=40)
climber = Climber(selector_policy=MapElites(num_drafts=5), operator_policy=Greedy())
climber.search(problem, budget=budget)
climber.best, climber.history, climber.to_frame()
MapElites and the openevolve preset need pip install 'hillclimb[openevolve]',
tuner: optuna needs 'hillclimb[optuna]' and gepa needs 'hillclimb[gepa]'.
climber.start(...) opens the same search to drive by hand, one climber.step() at a
time, and Problem(name, score=my_function, ...) defines a problem from a scoring function.
Runnable scripts are in examples/.
Compare two head to head:
hillclimb run heilbronn-convex-13 --climber greedy --climber openevolve # one search each; --parallel-searches 3 runs three of each
hillclimb experiment report <run-id>
Learn more
Walkthrough →From first run to following and resuming a search. |
Problems →Define your own problem and write its verifier. |
Climbers →The modules a climber is built from. |
Experiments →Compare climbers on the same problem. |
Example problems →Every example problem and its best known value. |
CLI reference →Every |
Python SDK →Build and run searches from Python. |
Blogposts →Blog posts on hillclimbing. |
Questions, results, ideas: join the Discord.
License
Metadata
Release files for hillclimb 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hillclimb-0.8.0.tar.gz | 668.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hillclimb-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.5 MB
Release files / hillclimb-0.8.0.tar.gz
| Download URL | hillclimb-0.8.0.tar.gz |
|---|---|
| Size | 668.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8930acb236f9998527df37ded357abb594231e33d29b83dcd603ee423c9ae66c
|
|
BLAKE2b-256 checksum How to use checksums |
ce6843788bd9c444f8ad04fc6e893fb0eff433ed86edbd1d45d66457769c4484
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.2
|
Release files / hillclimb-0.8.0-py3-none-any.whl
| Download URL | hillclimb-0.8.0-py3-none-any.whl |
|---|---|
| Size | 865.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
324731fda1d3fe6728745d3196c2edd614acc190e6aaa7a255682a28252ad5fa
|
|
BLAKE2b-256 checksum How to use checksums |
db030909916986a3ba0113042060376fcac14b4d381d7e86e16109a0feb5f621
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.2
|