Skip to content

Headless agents & setups

Hive can run an agent without the desktop app, using the hive CLI — on a cloud VM, a spare box, or as a background process on your own machine. This page covers the ways to wire that up and which one fits your situation.

The command reference for the CLI lives in crates/hive-cli/README.md. This page is about topology — where the agent runs and how it reaches your workspace.

Install the CLI

One line — macOS + Linux, Apple Silicon and x86_64:

curl -fsSL https://raw.githubusercontent.com/honeyhive-ai/hive/main/install.sh | sh

It drops the prebuilt hive binary from the latest release onto your PATH (override the dir with HIVE_INSTALL_DIR, pin a tag with HIVE_VERSION). Or build from source: cargo install --path crates/hive-cli.

The CLI is the same runtime as the desktop app, without the window — so it can host agents, drive chats, and sync from a terminal or a background service. Even if you live in the GUI, installing it locally is worth it when you want agents to keep working while the app is closed, or to script Hive from cron / a git hook / CI (setup 1 below).

The one rule that decides your setup

Hive state is a per-device, end-to-end-encrypted event log — a local hive.db. Anything participating in a workspace must either

  • share that file (same machine), or
  • sync it over a relay (different machines or processes).

Everything below follows from that.

The four setups

1 — Personal agent, one machine, no relay

The most common local case: you already run the desktop app and want your agents to keep answering @mentions even when the app is closed — with zero infrastructure. Point the CLI at the app's own data dir so both read/write the same hive.db:

# macOS app data dir shown; adjust per-OS. `hive agent` is a local, personal
# responder — gated so it never runs unattended by accident.
HIVE_ALLOW_PERSONAL_AGENT=1 \
HIVE_DATA_DIR="$HOME/Library/Application Support/com.hive.desktop" \
  hive agent bot

Run it as a background service — launchd on macOS, systemd on Linux — and the agent stays responsive after you quit the app or shut the lid.

The same data-dir trick lets you script Hive from a terminal, cron, a git hook, or CI without the GUI: hive send @agent "…", hive new, hive tail, hive queue, hive sync.

Trade-offs: the agent signs as you (shared identity, not a distinct agent account); the app refreshes on window focus rather than instantly; and it's a single-writer-ish SQLite file (fine for one agent, don't pile on writers). For a distinct agent identity, instant updates, and multiple concurrent writers, add a relay (setup 2+).

2 — Personal agent, local relay

Run the relay (the standalone Go service — docker run -p 8443:8443 …) on localhost and point both the app and the CLI at it. Now the agent has its own identity (a distinct member), you get live updates, and concurrency is clean. Cost: one extra process to run. See Self-hosting a relay.

3 — Remote agent / always-on worker

The agent lives on a remote machine (cloud VM, container, an office box). Here a relay is required — there is no shared filesystem across machines — but it can be self-hosted. This is the setup that lets an agent keep working while your laptop is closed: the relay's store-and-forward holds the agent's events, and your app catches up when it next comes online.

Provision the relay URL, token, room, and workspace key out-of-band, then run the worker daemon — it registers the box as a host and runs every agent bound to it on a workspace-owned credential (never your personal key):

export HIVE_RELAY_URL=  HIVE_RELAY_ACCESS_TOKEN=  HIVE_WORKSPACE=acme  HIVE_WORKSPACE_KEY=export HIVE_WS_SECRET_acme=sk-…
hive register-worker --label prod-box        # → this box's host id
hive add-agent reviewer ws-claude --host <host-id>
hive sync
hive worker --label prod-box                 # always-on; @reviewer is now answered here

The worker enforces the §12.5 rule — a detached agent must use a workspace runtime, so it never falls back to a personal key. It also drains queued work: an unanswered @mention waits for its agent's host, and the worker answers every one bound to it — backlog included — so it catches up on mentions addressed while it was down. hive queue shows what's waiting and whether each agent's host is online; if a member's device host is offline, hive set-agent-host <agent> <worker> reassigns the agent to a worker to drain it ("run on worker instead"). See the CLI README for the full daemon behaviour.

The desktop app surfaces the same queue without the CLI: the Review pane lists every unanswered agent mention with its host's live status, and an offline or device-bound agent gets a Run on worker button that reassigns it to an online worker — the GUI equivalent of hive set-agent-host. See Right Rail — Review.

Give the worker tools. A worker (or hive agent) can reach external boards like Linear or GitHub through MCP tools: point HIVE_MCP_CONFIG at a TOML listing MCP servers and provision each server's token via the environment (never in the file). With no config it runs tool-free, exactly as before. See the CLI README — MCP tools for headless agents.

Tools are gated on the requester's role. A synced message only drives the worker's MCP tools if its author holds at least HIVE_MCP_MIN_ROLE (viewer|contributor|admin|owner, default contributor). Below that bar the agent still replies — it just runs tool-free, so a Viewer can't provoke a write to Linear or GitHub through a headless agent. Raise the bar with HIVE_MCP_MIN_ROLE=admin. See the CLI README — requester-role gate.

Do not try to substitute a network filesystem (SSHFS/NFS) for the relay — SQLite over a network mount is corruption-prone. Use the relay.

4 — A team

Everyone joins the same room on a shared relay (self-hosted or hosted) with the workspace key. The relay is content-blind (E2EE), channels organize the work, and configuration is hoisted to the workspace so every chat inherits the same agents, skills, vaults, and runtimes. Members' apps and any workers all sync through the one room.

Which setup?

You want… Setup
A personal agent, no infra 1 — shared data dir
A personal agent, live + clean identity 2 — local relay
An agent that runs while you're away / on a server 3 — remote worker + relay
A team 4 — shared relay

Constraints that apply to every setup

  • E2EE key. The workspace key is shared out-of-band. The relay never sees plaintext and cannot help you recover a lost key.
  • The relay is content-blind and self-hostable — it stores and forwards sealed envelopes only. It is not a required cloud service.
  • Retention. A device fetches events after its cursor; if you're offline longer than the relay retains events, you miss anything pushed beyond retention (you keep everything you'd already synced).
  • Headless credentials — relay token, workspace key, and any provider or workspace-runtime secret — are provisioned out-of-band (env / secret mount).

Why a remote agent doesn't need your API key

A detached agent runs on a workspace-owned runtime (spec §12.5): a provider/model the workspace owns, synced to every member and worker, with a credential the workspace provides. Your personal key never leaves your device.

Define one, share it, provision its secret on the worker, then point the agent at it:

hive add-runtime ws-claude "Team Claude" anthropic claude-sonnet-4-5 --secret-ref acme
hive sync                                          # share it with the workspace
HIVE_WS_SECRET_acme=sk-…  hive agent bot --runtime ws-claude
  • --secret-ref <name> keeps the key off the synced log — the worker holds it in env HIVE_WS_SECRET_<name>. hive runtimes shows when it's present.
  • --secret <value> carries the key E2EE on the log (zero worker provisioning; use only for trusted workspaces).

Concurrency: worker pools + isolated edits

Several people can drive the same shared agents from different channels at once, and the work stays correct:

  • Per-request correlation. Each reply is tagged with the exact mention it answers, so two concurrent tasks to one agent never collapse onto a single reply — one task showing "answered" while its work never ran.
  • Isolated, review-gated edits. A file-mutating agent turn (Claude Code with write access / aider / pi) runs in its own git worktree cut from HEAD, so concurrent turns can't clobber each other's uncommitted work. On completion its diff is captured as a FileDiff proposal in the Review pane — approve it and Implement applies the patch to the workspace. Nothing lands silently. (Isolated turns start from the last commit, not the main tree's uncommitted WIP.)
  • Worker pool for throughput. Run several hive worker processes to drain the backlog in parallel — claim_turn de-dups so no two answer the same mention, and per-turn worktrees keep their file edits from colliding even on a shared checkout:
# run workers from inside the repo checkout they should edit
HIVE_WORKER_PERMISSION_MODE=acceptEdits hive worker --label prod-1 &
HIVE_WORKER_PERMISSION_MODE=acceptEdits hive worker --label prod-2 &
# each claims distinct mentions; each write turn isolates its own worktree

A single worker drains serially, so add processes to scale throughput.

Write access is opt-in. A worker's claude agents are read-only by default (they answer but don't edit). Set HIVE_WORKER_PERMISSION_MODE=acceptEdits (write files) or bypassPermissions (also run shell commands) to let them edit — only then does a worker turn isolate a worktree and produce a review-gated proposal. Run the worker from within the repo checkout it should work on (its cwd is the base for the worktree). A headless worker with bypassPermissions is powerful — grant it only on trusted boxes.

Coming updates you see on reconnect

Whatever a headless agent does while you're offline — reply in a chat, create a channel, change workspace config — rides the same synced event log, so your app pulls it on the next sync and the UI (chats and the channel tree) refreshes. The only requirement is that both sides share the same relay, room, and workspace key. On a local-only workspace (no relay), there's nothing to sync through — use setup 1 (shared data dir) instead.