Docker
Run the hb CLI anywhere Docker runs — no Python required. The official
image is published to GitHub Container Registry on every release:
Pin a tag in CI. :X.Y.Z, :X.Y, and :X are published for every
release; :latest is for interactive experimentation, not pipelines.
Un-tagged and :latest always point at the newest release; :2 tracks the
newest 2.x.y and is re-pointed with every release in that major line;
:2.7 and :2.7.0 freeze to progressively narrower versions.
Quick start (local mode — no login)
docker run --rm \
-v "$PWD":/workspace \
-e HB_PROVIDER=openai -e HB_API_KEY=$OPENAI_API_KEY -e HB_MODEL=gpt-4o-mini \
ghcr.io/humanbound/humanbound \
test --endpoint ./endpoint.json --wait --fail-on high
--rm— the container runs one command, exits withhb's exit code (0pass /1findings at or above--fail-on/2error), and removes itself.-v "$PWD":/workspace— mounts your project at the image's working directory. Inputs are read through it and results are written back through it.
Two different keys
| Variable | What it is |
|---|---|
HB_API_KEY |
Your LLM provider key (OpenAI, Anthropic, …) — powers the attacker/judge models in local mode |
HUMANBOUND_API_KEY |
Your Humanbound platform project key — headless platform auth (coming soon) |
Files in, results out
All file options (--endpoint, --scope, --prompt, --context,
--repo) are read inside the container. The rule: mount your project at
/workspace and use relative paths — --scope ./scope.yaml resolves to the
mounted host file. Absolute host paths do not exist inside the container, and
what happens next depends on the option: --scope, --prompt, and --repo
fail fast with a "does not exist" error; --endpoint falls through to "must
be a JSON string or path to a JSON file"; --context does neither — a
nonexistent path is silently treated as the literal context string. Double
check --context in particular, since a typo'd path won't error, it'll just
send the wrong text to the judge.
Results persist to ./.humanbound/results/exp-*/ on your host through the
same mount. Reports too:
Inline escape hatches (no files needed): --endpoint accepts a JSON string
and --context accepts a plain string — useful for templating from CI
secrets.
Two different .humanbound directories. <project>/.humanbound/results/
is written relative to your workdir and persists on the host through the
/workspace mount above — that's the test results and reports. ~/.humanbound/
in the container's home directory is a separate thing entirely: platform
credentials, config, and the telemetry identity. It only exists inside the
container if you mount it yourself, as shown in Platform commands.
Reaching an agent on your host
Inside a container, localhost is the container. If the agent under test
runs on your machine:
- macOS / Windows: use
http://host.docker.internal:<port>in your endpoint config. - Linux: add
--add-host=host.docker.internal:host-gatewaytodocker run, or use--network host.
Platform commands
hb status, project-scoped hb logs, and platform-mode hb test need platform auth:
- Today: log in on the host, then mount your credentials (read-write — the CLI refreshes tokens):
hb login # on the host, once
docker run --rm -v ~/.humanbound:/home/hb/.humanbound \
ghcr.io/humanbound/humanbound status
- Coming soon:
-e HUMANBOUND_API_KEY=<project-key>— headless project-key auth, no browser involved.
Using the image in CI
For ready-made GitLab and CircleCI snippets that run this image in your pipeline, see CI/CD Integration.
Notes
- Linux bind-mount permissions: the container runs as uid 1000; add
--user $(id -u):$(id -g)if your uid differs and result files come out root-owned or unwritable. - Telemetry follows the CLI's normal rules — auto-disabled when a CI
environment variable is set, and
-e HB_TELEMETRY_DISABLED=1or-e DO_NOT_TRACK=1always works. It's also auto-disabled whenever the container has no TTY, which is everydocker runwithout-it— including all of the example commands on this page — so scripted and CI runs never send anything. The fresh-machine caveat (a new anonymous ID andinstallevent per container) only applies to interactive-itruns without a mounted~/.humanbound; mounting it as shown in Platform commands keeps the telemetry identity stable. - Commands that open a browser (
hb login,hb docs) don't work inside a container — run them on the host.