Upstream Hive's contributor runtime packaged as an isolated, distroless container, driven by OMP.
This appliance packages Hive's contributor runtime (contributor-agent.sh + contributor-relay.js) with OMP as the agent CLI, so a contributor needs no agent toolchain of their own. Hive owns task selection, assignment, prompts, leases, and output capture; OMP owns agent execution, model choice, thinking effort, and tool boundaries. This repository owns the isolation boundary, the credentials that cross it, and the single configuration file.
The Hive runtime inside is tracked directly from upstream's v5 branch and is never pinned to a static commit in this repository. Every image build resolves the branch to a commit, stamps it into /usr/share/hive/contribute/HIVE_COMMIT, records it in the image labels (io.hivecommons.contribute.hive.ref) and SBOM, and registration clones that same branch, so setup and runtime follow one release line. They are not pinned to the same commit: setup reads v5 live while the image carries the SHA resolved when it was last built, so they can differ. The daily rebuild is meant to bound that gap, not to guarantee it.
# Run the worker in the foreground (Ctrl-C stops it)
hive-contribute
# Or through just from a checkout
just contributehive-contribute requires a Linux host environment. Both isolation tiers (KVM microVMs via krun and standard Podman containers) rely on Linux kernel facilities (/dev/kvm and unprivileged user namespaces). macOS and Windows hosts are supported by running inside a Linux virtual machine.
| Host | Support | Provisioning Command |
|---|---|---|
| Linux | Native | Direct execution (requires Podman; /dev/kvm recommended for krun hardware isolation) |
| macOS | Linux VM via Lima | limactl start (or install via brew install lima && limactl start), then run inside the VM |
| Windows | Linux VM via WSL2 | wsl --install (e.g., Ubuntu distro), then run inside the WSL2 distro |
On macOS and Windows, provision the Linux VM, install Podman and the required prerequisites inside the guest, and run hive-contribute from within that environment. Native execution directly on macOS or Windows command prompts is not supported.
Install hive-contribute onto your PATH or run directly from a checkout.
From a repository checkout:
git clone https://github.com/projectbluefin/contribute.git
cd contributeThe launcher executable is bin/hive-contribute. You can symlink or copy it to ~/.local/bin/hive-contribute (or anywhere on your PATH).
The launcher is bin/hive-contribute:
| Command | Description |
|---|---|
hive-contribute / hive-contribute run |
Launch the worker in the foreground (Ctrl-C stops it) |
hive-contribute hives |
Pick which hives to contribute to (interactive; applies to a running worker immediately) |
hive-contribute switch [name] |
Pick which followed hive the worker asks first (applies immediately) |
hive-contribute doctor |
Read-only preflight diagnostics; starts no agent |
hive-contribute setup |
Register this machine with a hive through upstream's own setup |
hive-contribute config |
Print the resolved appliance configuration |
From a checkout, just provides thin wrappers: just contribute, just hives, just switch, just doctor, just setup, just config, and just contribute-build.
Run hive-contribute hives. It lists the hives you already follow (ticked), the hives Hive knows your GitHub account by, and every online hive in the Commons registry. Tick a hive with x (or Tab) — not space — and press Enter; it registers the newly ticked ones and drops the ones you untick. A dropped hive's token cannot be recovered, so it asks first. A self-hosted hive that is in no list is the last row: tick it and type its address once, e.g. reef.tunaos.org (a full wss:// URL also works); it is checked to answer as a Hive hub before anything registers, and it is an ordinary tick from then on. With more than one hive it also asks which one the worker asks first and how it chooses between them (ranked, spread, or neediest). hive-contribute switch changes only the first hive. If any choice does not take effect, it says which and exits non-zero.
Nothing needs editing by hand, and a running worker picks every change up without a restart. Every change goes through upstream's hivectl hives: the profiles live in ~/.config/hive/profiles.yml, and contributor.env is generated from them. The launcher fetches hivectl from Hive's newest v5 release image through upstream's own bootstrap the first time you use it. hive-contribute hives <args> passes any other hivectl hives subcommand straight through, for example hive-contribute hives list or hive-contribute hives rename <old> <new>. The pickers use gum when it is installed and plain numbered prompts otherwise.
All site configuration lives in one file:
${XDG_CONFIG_HOME:-~/.config}/hive-contribute.yml
The launcher creates it on first run, seeding hub from an existing ~/.config/hive/contributor.env if present. You can point HIVE_CONTRIBUTE_CONFIG at another path to run a second configuration.
The configuration has nine flat keys:
# hive-contribute — the whole appliance configuration.
#
# hub the hive this machine contributes to (wss://<host>/contribute)
# registration Hive's own credential file, written by its contribute-setup
# image contributor runtime image to run
# backend agent CLI Hive drives inside the container
# memory RAM ceiling for the worker (also the microVM's size); none = no limit
# cpus CPU ceiling for the worker (also the microVM's vCPUs); none = no limit
# llmman OpenAI-compatible base URL of YOUR llmman daemon; empty = cloud only
# llmman_token file holding that daemon's API key (0600); empty = unauthenticated
# llmman_model model the daemon must serve; 'doctor' checks it is loaded there
hub: wss://hive.example.org/contribute
registration: ~/.config/hive/contributor.env
image: ghcr.io/projectbluefin/contribute:stable
backend: omp
memory: 4g
cpus: 2
llmman:
llmman_token:
llmman_model:| Key | Meaning | Default |
|---|---|---|
hub |
The hive WebSocket endpoint to join (wss://<host>/contribute) |
Seeded from registration or set via setup |
registration |
Path to Hive's credential file | ~/.config/hive/contributor.env |
image |
Contributor runtime image reference (registry location) | ghcr.io/projectbluefin/contribute:stable |
backend |
Agent CLI Hive drives inside the container | omp |
memory |
RAM ceiling, swap pinned to it; none removes it |
4g (upstream's contributor envelope) |
cpus |
CPU ceiling; none removes it |
2 (upstream's contributor envelope) |
llmman |
OpenAI-compatible base URL of your own llmman daemon | empty — the worker uses cloud providers only |
llmman_token |
File holding that daemon's API key | empty — the endpoint is contacted unauthenticated |
llmman_model |
Model the daemon must serve, verified by doctor |
empty — doctor lists what is served instead |
memory and cpus are enforced on Podman runs, where they size the microVM.
Warning
WSL2 credential-mode hazard: When running under WSL2, keep registration: on the Linux filesystem (e.g., ~/.config/hive/contributor.env), never on a Windows drive mount (such as /mnt/c/...). Windows DrvFs mounts do not preserve Linux file modes (0600) without explicit metadata configuration, silently exposing the contributor registration credential.
Every worker invocation runs inside an isolated container:
- libkrun microVM preferred: When Podman,
krun, and/dev/kvmare available, the launcher starts a hardware-isolated KVM microVM (podman run --runtime=krun). When KVM is unavailable, it runs standard Podman containers. - Read-only credential mount: Each worker gets a private copy of Hive's
0600registration in a launcher-owned directory under$XDG_RUNTIME_DIR, mounted read-only at/home/hive/.config/hive.hive-contribute hivesandswitchreplace that copy and signal the worker, whose relay reloads its hive list; the copy is removed when the worker stops. In WSL2 environments, keep the registration on the Linux filesystem rather than a/mnt/cmount to preserve the0600permission mode. - No host home mount: The user's host
$HOMEis never mounted. The container runs as unprivileged userhive(uid/gid 65532) with its own isolated home volume. - Foreground attach: The container remains attached to the terminal in the foreground. Detached runs are unsupported; Ctrl-C stops the invocation cleanly.
- GitHub identity: Passed by environment as
GH_TOKEN(resolved from$GH_TOKEN,$GITHUB_TOKEN, orgh auth token). Host~/.config/ghis never mounted into the container. - The hives lookup uses your token off-GitHub:
hive-contribute hives(andswitch, for labeling) asks the Hive Commons directory athttps://hive.hivecommons.dev/api/saas/my-hiveswhich hives know your GitHub account, authenticating that one request with your github.com token as a bearer header — the same lookup upstream'scontribute-setuppicker performs. The token rides stdin, never the command line, and the flow says so before it happens. If you do not want your token sent there, skiphivesand type the hive's address directly. ghis Hive's, not raw: Inside the container,ghis upstream'sgh-wrapper.shwith the real binary at/opt/hive/bin/gh-real, and contributor mode is a root-owned marker file the agent cannot forge. An assigned task cannot rungh auth, cannot issue a mutatinggh api, and cannot reach any subcommand outside Hive's allowlist; read-only lookups stay available, and created issues and PRs are labelledcontributor/<login>andcli/omp.- Provider keys: Only allowlisted provider environment variables (
COPILOT_GITHUB_TOKEN,ANTHROPIC_API_KEY,OPENAI_API_KEY,OPENROUTER_API_KEY,GEMINI_API_KEY,GOOGLE_API_KEY,AWS_BEARER_TOKEN_BEDROCK, etc.) are forwarded. - Credential validity is Hive's: The hub issues and rotates registration tokens, and its relay is what authenticates one. This launcher mounts the credential and nothing more — it does not validate, reissue, or relaunch on a rejected token. Repair a rejected registration with upstream's
contribute-move.
Bluefin's Agent Mode runs llmman as a rootless user service bound to the host's loopback address, which an isolated container cannot reach by default. The appliance can run its assigned work against that daemon — but only when you explicitly select it.
Local inference is off until you select it. With llmman empty, the launch is byte-for-byte what it was: whatever cloud provider keys you have configured, and nothing else. Writing an endpoint into the config file is the selection:
llmman: http://127.0.0.1:17434/v1
llmman_token: ~/.config/llmman/api.key # optional; 0600
llmman_model: qwen3-coder-30b # optional; verified by doctor and selected in OMPThen check it before you run a worker:
hive-contribute doctordoctor reports the endpoint and the transport, reads the key, and makes one read-only GET of the OpenAI-compatible model list — so reachability, authentication, and whether llmman_model is actually loaded are all answered before an assignment arrives, not after one fails.
What crosses the isolation boundary when local inference is selected:
- The transport: For a loopback endpoint, the run adds
--network slirp4netns:allow_host_loopback=true, which makes the host loopback reachable from the container at10.0.2.2. Important:allow_host_loopback=trueexposes the entire host loopback interface (127.0.0.1) to the worker at10.0.2.2, not just thellmmanport. Operators should consider what other services are listening on127.0.0.1. A routable network endpoint is passed through unchanged with no custom network mode. Either way, the appliance publishes no ports of its own and starts no listeners. OPENAI_BASE_URL, by value — it is an address, not a secret, and a recorded one is how you prove afterwards which endpoint the worker used.OPENAI_API_KEY, by name, holding the contents ofllmman_token. It is never written into the image, never placed on a command line, and never read from a mounted host home. With nollmman_token, the appliance sends its own placeholder rather than your cloud OpenAI key — an endpoint of your own does not get a credential minted for someone else.- Model selection: When
llmman_modelis configured, it is passed into the appliance and configured as OMP's default model selection (openai/<model>andllmman/<model>). The OpenAI provider slot is repurposed for the local endpoint, while other configured cloud providers (Anthropic, Gemini, Copilot, Bedrock, OpenRouter) remain available.
Two different things share the word "local", and this appliance does exactly one of them:
- Donating worker capacity (this repository): you run the contributor appliance, Hive assigns it work, and with
llmmanset that work is inferred on your own machine instead of a cloud provider. The appliance is a client of the endpoint you named. - llmman peer aggregation (llmman's own feature): one machine consumes another machine's llmman daemon over the network. That is configured in llmman with
llmman config set, it is not something this launcher does, and nothing here advertises your daemon as a peer or opens it to the LAN.
If you want your workstation's GPU to serve your laptop, that is llmman's aggregation, configured in llmman. If you want Hive's assigned work to run on hardware you own, that is the llmman key above.
The Hive contributor runtime inside the image is never pinned to a static commit. The build resolves the upstream v5 tracking branch, packages the resolved runtime assets, and stamps the commit into:
/usr/share/hive/contribute/HIVE_COMMITinside the image- The OCI image label
io.hivecommons.contribute.hive.ref - The image SBOM at
/usr/share/hive/contribute/sbom.spdx.json
hive-contribute setup clones that same upstream tracking branch during registration, ensuring registration protocol and container runtime stay synchronized.
Third-party release binaries (OMP, Node.js, GitHub CLI, tmux) remain digest-pinned and tracked via Renovate.
hive-contributeThat is the whole flow. On a machine with nothing configured it writes its
config, hands off to upstream Hive's contribute-setup to pick a hive and
register, records the hub it registered against, and starts the worker. Choose
provider, model, and reasoning effort inside OMP.
First run needs a host toolchain, because registration is upstream's and
runs on the host: just, gh, git, curl, jq, and node. The launcher
names any that are missing before it touches the network or a credential. Log
in to GitHub first, since upstream's setup reads that identity:
gh auth login --web --hostname github.com --scopes repo,read:orgOnce a registration exists, the setup tools (just, git, curl, jq,
node) are needed only to register again; hive-contribute hives uses gh,
git, curl, and jq. Every run still needs a container runtime —
Podman with krun — and a GitHub token, either from gh or exported as GH_TOKEN.
hive-contribute doctor # read-only preflight; starts no agent
hive-contribute setup # re-run registration through upstream on its own
hive-contribute config # print the resolved configurationThe default contributor runtime image is published to GitHub Container Registry at ghcr.io/projectbluefin/contribute:stable (used here as a container registry location). Build locally with:
just contribute-buildTo run the container directly with podman (preserving host access to the 0600 registration file):
podman run --rm -it \
--userns keep-id:uid=65532,gid=65532 \
-v ~/.config/hive/contributor.env:/home/hive/.config/hive/contributor.env:ro,z \
-v hive-home:/home/hive:rw \
-e GH_TOKEN \
ghcr.io/projectbluefin/contribute:stableA direct run reads the registration once: after hive-contribute hives or switch, restart it. Only launcher-started workers get the staged copy that changes live.
For environments using Docker, map your host user ID and bind-mount a dedicated host-owned directory for /home/hive so the container process can read the 0600 registration file and write to its home and workspace:
mkdir -p ~/.local/state/hive-contribute/home/{.config/hive,workspace}
docker run --rm -it \
--user "$(id -u):$(id -g)" \
-v "${HOME}/.local/state/hive-contribute/home:/home/hive" \
-v "${HOME}/.config/hive/contributor.env:/home/hive/.config/hive/contributor.env:ro" \
-w /home/hive/workspace \
-e GH_TOKEN \
ghcr.io/projectbluefin/contribute:stable- Launcher:
docs/skills/launcher.md - Runtime contract:
docs/skills/hive-runtime.md - Triage & troubleshooting:
docs/skills/hive-triage.md - Image build & development:
docs/image-and-development.md - Agent contract:
AGENTS.md - All documentation:
docs/SKILL.md
Licensed under Apache 2.0.