Linux:
curl -fsSL https://bubblehub.ai/install.sh | bashWindows PowerShell, through WSL:
irm https://bubblehub.ai/install.ps1 | iexCheck it:
bubblehub --helpOpen the app:
bubblehub appDocker image:
docker pull ghcr.io/bublhub/bubblehub:latestUse a release image as a base:
FROM ghcr.io/bublhub/bubblehub:v0.1.0Ask the local model a question:
bubblehub prompt --text "Say hello from BubbleHub"Run an agent in the sandbox:
bubblehub run --root-dir ./examples/basic --binary ./examples/basic/basic_agent.py --memory 16GName an agent for bubblehub ps, the shell prompt, and the Control Center:
bubblehub shell --name reviewer --root-dir ./workspace
bubblehub ps --kill agt-...Start the OpenAI-compatible local endpoint (optional):
bubblehub servePick or inspect models:
bubblehub models
bubblehub models list
bubblehub models stopOpen app:
bubblehub app- Runs local LLMs.
- Exposes an OpenAI-compatible endpoint at
http://127.0.0.1:8000/v1. - Keeps warm model backends shared across agents.
- Runs agents in a Linux sandbox with restricted filesystem and network access.
- Injects local inference into agents as
OPENAI_BASE_URLandOPENAI_API_KEY. - Provides the BubbleHub Control Center desktop app for graphical monitoring, manifest review, and base-model selection.
bubblehub run starts the shared inference endpoint before launching an agent and injects:
OPENAI_BASE_URL=http://127.0.0.1:8000/v1
OPENAI_API_KEY=bubblehub-local
BUBBLEHUB_API_BASE_URL=http://127.0.0.1:8000
BUBBLEHUB_SANDBOX_INFERENCE_HOST=127.0.0.1
BUBBLEHUB_SANDBOX_INFERENCE_PORT=8000Sandboxed agents only get access to the local inference endpoint by default. HTTP clients see a loopback policy proxy at http://127.0.0.1:18080, and BubbleHub injects HTTP_PROXY, HTTPS_PROXY, http_proxy, and https_proxy for isolated sandboxes. The proxy is owned by libbubblehub: it checks the persistent sandbox access manifest under ~/.local/state/bubblehub/sandboxes/<agent-id>/access-manifest.json (or BUBBLEHUB_STATE_DIR) and either forwards allowed requests or returns a logged 403. Unknown requests fail closed; when no host prompt is available, BubbleHub records them as pending in the manifest for later dashboard review. Use --allow-network with bubblehub run or bubblehub shell when an agent setup step needs general outbound network access.
When bubblehub run or bubblehub shell is connected to a real terminal, first access to a new host pauses the agent and prompts on the host for always, never, or ask every time (approve now). Non-interactive runs fail closed and print a reminder to run bubblehub dashboard; the dashboard resolves pending sandbox access requests before the live resource view opens. Use bubblehub manifest --root-dir <dir> or bubblehub manifest --agent-id <agent> to inspect and edit persisted policies. Manifest policies are exactly always, never, or ask; HTTP policies match domains plus the visible HTTP method/path, while HTTPS CONNECT can only be matched at the host/port level.
When --root-dir is provided, non-system binaries must live inside that root and BubbleHub mounts the root as the sandbox workspace. System binaries from /usr, /bin, /sbin, or /opt/bubblehub can still be used with a root directory, which lets bubblehub shell --root-dir <dir> open a shell inside the workspace sandbox. When --root-dir is omitted, non-system binaries are copied into a temporary workspace before the sandbox starts. Inside the sandbox, BubbleHub Python prompt/shim calls detect BUBBLEHUB_SANDBOX=1 and use the forwarded inference endpoint instead of loading the native shared library.
Installed sandboxes run over an Ubuntu 26.04 root filesystem using a per-agent overlay. The Ubuntu lower filesystem stays unchanged; writes outside the workspace copy up into .bubblehub/agents/<agent-id>/overlay/upper and persist with that agent. Use --force-new-sandbox or --overwrite-sandbox to discard the persistent home and private overlay for the current workspace.
For implementation details, security assumptions, and known gaps, see docs/sandbox.md.
OpenClaw can be installed entirely from inside the sandbox. The persistent agent home keeps nvm, npm global packages, and OpenClaw config across runs.
bubblehub shell --allow-network --root-dir openclawInside the sandbox shell:
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash
export NVM_DIR="$HOME/.nvm"
. "$NVM_DIR/nvm.sh"
nvm install 22.19.0
npm install -g openclaw@latest
openclaw onboard --install-daemonBubbleHub ships source install assets from GitHub Releases and runtime images from GHCR.
Push a v* tag. The release workflow runs unit tests, runs local-inference integration tests, then publishes:
install.shinstall.ps1BubbleHub-<version>-x64.debBubbleHub-<version>-x64.exebubblehub-source.tar.gzcontainer-image.txtSHA256SUMS
For Cursor-written release notes, ask Cursor to use the BubbleHub release-notes skill before tagging.
It writes .github/releases/<tag>.md from commits since the previous release, and the release workflow uses that file when present.
Install a specific tag:
curl -fsSL https://bubblehub.ai/download/linux/v0.1.0/install.sh | BUBBLEHUB_VERSION=v0.1.0 bashDownload a specific Debian package:
curl -LO https://bubblehub.ai/download/linux/v0.1.0/BubbleHub-0.1.0-x64.deb
sudo apt install ./BubbleHub-0.1.0-x64.debUse the matching runtime image:
docker pull ghcr.io/bublhub/bubblehub:v0.1.0- Create and activate a virtual environment
python3 -m venv .venv
source .venv/bin/activateInstall dependencies and build BubbleHub. The build installs the native bubblehub-sandbox helper under /usr/local/bin with the permissions required for sandbox setup, creates the Ubuntu 26.04 rootfs on first install, and preserves it on later local rebuilds for a faster development loop.
./scripts/install-deps.sh
./scripts/build.shRun the same Docker test targets that CI uses before pushing:
docker build -f docker/Dockerfile --target unit-test -t bubblehub:unit .
docker run --rm --privileged --security-opt seccomp=unconfined bubblehub:unitCI enforces line coverage through Codecov (45% project target for libbubblehub and bubblehub). See CONTRIBUTING.md for the local coverage command and HTML report locations.
Integration tests also need persistent caches for the model and OpenClaw dependencies. Use Docker named volumes instead of $PWD bind mounts, which can fail on remote/NFS workspaces:
docker volume create bubblehub-cache-local
docker volume create bubblehub-openclaw-local
docker build -f docker/Dockerfile --target integration-test -t bubblehub:integration .
docker run --rm --privileged --security-opt seccomp=unconfined \
-v bubblehub-cache-local:/cache/bubblehub \
-v bubblehub-openclaw-local:/cache/openclaw \
bubblehub:integrationTo explore the integration image interactively instead of running pytest:
docker run -it --rm \
--privileged \
--security-opt seccomp=unconfined \
-e BUBBLEHUB_CACHE=/cache/bubblehub \
-e BUBBLEHUB_MODELS_CONFIG=/cache/bubblehub/ci-models.yaml \
-e BUBBLEHUB_INTEGRATION_WORKSPACE_DIR=/cache/bubblehub/integration-workspaces \
-e OPENCLAW_CACHE_DIR=/cache/openclaw \
-v bubblehub-cache-local:/cache/bubblehub \
-v bubblehub-openclaw-local:/cache/openclaw \
bubblehub:integration \
bashInside the container:
scripts/ci/write-ci-model-config.sh
scripts/ci/prepare-openclaw.sh
mkdir -p /cache/bubblehub/integration-workspaces/dev-playground
bubblehub shell --allow-network --root-dir /cache/bubblehub/integration-workspaces/dev-playgroundApache License 2.0. See LICENSE for details.
See CONTRIBUTING.md for contribution guidelines, testing requirements, and pull request expectations.