Skip to main content

hillclimb

Hillclimbing on verifier-defined problems. You give it a problem — a folder whose verifier.sh scores a solution.py — and a budget. It spawns coding agents (Claude Code, Codex or pi) as operators that draft, debug and improve solutions, scores every candidate through your verifier, and keeps the best. The harness is fixed. The climber — what to try next and how each attempt is prompted — is a bundle you can swap, edit and share, so two methods can be compared on the same problem under the same budget.

Get started

Eight commands, ten minutes. Each step says what you should see.

1. Install and connect an agent.

pip install hillclimb
hillclimb connect claude       # logs in; operator calls bill your Claude subscription

connect codex and connect pi do the same for the other agents. No agent yet? Add --agent dummy to any run below: it climbs with no LLM at all.

2. Make a hillclimb dir, get a problem, read it.

hillclimb init                         # this folder: hillclimb.yaml, problems/, runs/
hillclimb problem list                 # the bundled example problems, with the best known value
hillclimb problem get heilbronn-11

Everything hillclimb writes lives beside hillclimb.yaml (hillclimb init hillclimb keeps it all in a subfolder instead). The problem lands in problems/heilbronn-11/. Open verify.py: the verifier is the problem. Everything the agents will be told is in description.md.

3. Check the verifier.

hillclimb verify heilbronn-11 --repeat 3

Scores the problem's floor three times and prints the spread. Example problems are exact, so the spread is 0 and any improvement is real. On a noisy problem of your own, this number is the noise floor the search must beat.

4. Climb.

hillclimb run heilbronn-11 --budget 10m

The search starts as a detached engine and the terminal comes straight back with the run id: a baseline, then drafts, debugs and improves, each scored as it lands. (--no-detach keeps it in this terminal; Ctrl-C then stops it.)

5. Watch it.

hillclimb watch      # every agent, what it is doing, its candidate's score
hillclimb chart      # best score so far against time, every candidate a dot
hillclimb tree       # the exploration tree: what was expanded, what was left

The result is runs/<run-id>/searches/heilbronn-11/best/: solution.py and the submission.csv it wrote.

6. Stop everything.

hillclimb stop --all

7. Next.

  • Your own problem. Copy a bundled problem and edit verify.py. See docs/problems.md.
  • Another climber. hillclimb run heilbronn-11 --climber openevolve. hillclimb climber show openevolve prints it as the block it is; hillclimb climber new mine --from greedy copies greedy's source into climbers/mine.py for editing. See docs/climbers.md.
  • Compare two. hillclimb run heilbronn-11 --climber greedy --climber openevolve --parallel-searches 2, then hillclimb experiment report <run-id>. See docs/experiments.md.

Example problems

Construction problems in one shape: the submission is a small CSV of numbers, the verifier checks the constraints and computes the score exactly, there is no dataset, no holdout split and no noise. Each ships with the best known value as a reference line on the chart, and each family is a ladder, so a ten-minute run visibly climbs on the small instance and an hour does not saturate the large one.

Family Instances Score
Circle packing (AlphaEvolve's benchmark) circle-packing (26), circle-packing-32 sum of radii, maximize
Heilbronn triangles heilbronn-11, -14, -17, heilbronn-convex-13 smallest triangle area, maximize
Low-autocorrelation binary sequences labs-40, labs-60 sidelobe energy, minimize
Tammes (points on a sphere) tammes-30, tammes-50 minimum angle, maximize
Thomson (charges on a sphere) thomson-50, thomson-100 Coulomb energy, minimize
Autocorrelation inequalities (AlphaEvolve) autocorr-1, autocorr-3, erdos-overlap the inequality's constant
Kissing configuration in dimension 11 kissing-11 number of points, maximize
Golomb rulers golomb-20, golomb-27 ruler length, minimize
Travelling salesman on a fixed instance tsp-200 tour length, minimize
Multidimensional knapsack (Chu & Beasley instances) mknap-100-5, mknap-250-10 total value, maximize

hillclimb problem list prints the catalog with the best known value and who found it. Problems that need data, a hidden split or a provider (Kaggle competitions through MLE-bench, energy forecasting through emflow) are documented in docs/providers.md.

Climbers

A climber is one block of config, defined where the run is defined — in a run spec, or in hillclimb.yaml as the folder's default:

climber:
  policy: greedy                  # what to try next (or `loop:` for the whole control flow)
  select: map-elites              # which candidate it expands
  operators: [draft, debug, improve, crossover.py:Crossover]
  tuner: optuna
  memory: files
  params: {num_drafts: 5}

Every slot names a prebuilt module, a .py file of your own, or package.module:Class. Three presets stand for whole blocks: greedy (debug failing tips, draft a few branches, improve the best), openevolve (the same schedule over a MAP-Elites archive) and gepa (reflective Pareto search, brings its own loop). The same building blocks compose in Python:

import hillclimb as hc

climber = hc.Climber(policy=hc.policies.Greedy(num_drafts=5), select=hc.selectors.MapElites(), tuner="optuna")
hc.run("heilbronn-11", climber=climber, budget="10m")

A run records the block it ran, a search snapshots its climber (so editing the live files never changes a running search), and hillclimb climber check replays recorded journals through an edited climber before an agent hour is spent on it.

What is where

Path What it is
src/hillclimb/harness/ The fixed core every search runs on: core.py (the Harness), the loop, evaluation and the executor, the journal, candidates and the store, budgets, slots and the control queue. Never a research surface.
src/hillclimb/modules/ What a climber is built from, one subpackage per kind, each with its contract in base.py: policies/ (what to try next), selectors/ (which candidate to expand), operators/ (how one attempt is made), tuners/ (which parameter values), memory/ (what a search knows from others, and the graph module that indexes it), similarity/ (how alike two solutions are). refs.py resolves a module's name, spec.py is the climber: block. Implementations import only hillclimb.sdk.
src/hillclimb/sdk/ The one import a climber needs: the contracts and the read-only views of the search.
src/hillclimb/climbers/ Climber libraries that bring more than one module: gepa/ (its loop, its operator, its scoring view).
src/hillclimb/{policies,selectors,operators,tuners,memory,loops}.py The prebuilt building blocks by name, for composing in Python (hillclimb.policies.Greedy): lazy windows onto modules/.
src/hillclimb/tui/ Every terminal view (watch, chart, tree, archive, surface, similarity, graph) and the layout it draws. Reads the store, imported by nothing else.
src/hillclimb/cli/ The hillclimb command, one module per command group.
src/hillclimb/agents/ The agents that write code: Claude Code, Codex, pi, and the dummy and fake agents for tests.
src/hillclimb/providers/ Problem providers: emflow, MLE-bench, Einstein Arena.
src/hillclimb/prompts/ The operator prompt templates. A climber may shadow them by name.
src/hillclimb/runtime/ The managed venv the verifier and the solution run in, and the shim that makes hillclimb.spaces importable there.
src/hillclimb/demo/ The example problems as package data, so hillclimb problem get works from a bare install.
src/hillclimb/spaces.py The output-format contract a problem's interface.py is written in, and the params.json contract. Stdlib only, byte-copied into runtime venvs.
src/hillclimb/{api,config,problem,climber,experiment,connect}.py The public surface: run a search (run, run_spec), the config schema, load a problem, compose or resolve a climber, experiments, and connecting an agent.
problems/ The example problems' source of truth, one make_<family>.py generator per family; the bundled copies under demo/ are stamped from here.
hillclimb.yaml, experiments/, knowledge/ This repo is itself a hillclimb dir: its config, experiment specs and seeds, and learning (the graph, cards, credit, playbooks), beside problems/ and runs/.
tests/ The suite (uv run pytest). test_layout.py pins which package may import which, test_sdk_imports.py that climber code imports only the sdk, golden/ the prompt bytes and every --help screen.
docs/ The topic docs linked below, and the dated design plans.

Docs

  • Problems — the verifier contract, floors, unit tests, tunable parameters, per-instance scores, noise
  • Climbers — the climber: block, presets, your own policy / selector / operator / loop, composing in Python, climber check, mixed fleets, GEPA
  • Agents — Claude Code, Codex, pi; connect; billing through OpenRouter; sampling
  • The sandbox — what agents and solutions can write, read and reach; agents without internet
  • Experiments — studies of experiments, repeats, matched budgets, the report
  • Providers — emflow, MLE-bench, Einstein Arena
  • Operators and memory — operator scaffolds, model routing, the knowledge graph
  • The hillclimb dir — config precedence, run specs, how runs are laid out, the store, pruning
  • Commands — every command, the TUIs, the demo suite
  • Development
  • Changelog

Metadata

Release files for hillclimb 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hillclimb 0.6.0
File Size Uploaded
hillclimb-0.6.0.tar.gz 564.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hillclimb 0.6.0
File Interpreter ABI Platform
hillclimb-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.3 MB

Release files / hillclimb-0.6.0.tar.gz

Download URL hillclimb-0.6.0.tar.gz
Size 564.2 kB
Tags Source
SHA-256 checksum
How to use checksums
0f561a0684e5df0114210794f21534062450ac55125ca845ca3cc9f86078fba4
BLAKE2b-256 checksum
How to use checksums
f5248898b479d0bb0d8ce5be659686b77ca940d8e4953b9e32d0566c67ec6fd3
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.6.0-py3-none-any.whl

Download URL hillclimb-0.6.0-py3-none-any.whl
Size 743.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d3e3ca8fe29eaf980b8f18078f245bad09a70e161785237b344306b7620ab5c4
BLAKE2b-256 checksum
How to use checksums
44bf81da91e0a50dc3eb80d741558db51af03d690a4b1e7cc6d9c191b2892547
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.2

Release history Release notifications | RSS feed

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.1

2 release files

0.7.0

2 release files

This release

0.6.0 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page