← Back to Plugins
Tools

CI OpenClaw

companionintelligence By companionintelligence 👁 33 views ▲ 0 votes

A Docker image for running OpenClaw on the Companion Intelligence (CI) marketplace.

Homepage GitHub

Install

npm install -g`

Configuration Example

services:
  openclaw:
    environment:
      APP_SEED: ${APP_SEED:-dev}
      CI_SERVER_URL: ${CI_SERVER_URL}
      CI_SERVER_TOKEN: ${CI_SERVER_TOKEN}

README

<h1 align="center">CI-OpenClaw</h1>

<p align="center"><strong>A Docker image for running OpenClaw on the Companion Intelligence (CI) marketplace.</strong></p>

[![release](https://img.shields.io/github/v/release/companionintelligence/CI-OpenClaw?style=flat-square&color=0a6358&label=release)](https://github.com/companionintelligence/CI-OpenClaw/releases/latest)
[![platform](https://img.shields.io/badge/platform-Docker%20%C2%B7%20Companion%20Hub-0a6358?style=flat-square)](https://github.com/companionintelligence/CI-OpenClaw)
[![License](https://img.shields.io/badge/license-PolyForm%20NC%201.0-0a6358?style=flat-square)](LICENSE)
[![Discord](https://img.shields.io/badge/chat-Discord-5865F2?style=flat-square&logo=discord&logoColor=white)](https://discord.com/invite/yQp9hwpzAa)

<p align="center"><a href="https://hub.ci.computer/store/openclaw">Website</a> · <a href="LICENSE">License</a> · <a href="https://docs.ci.computer/docs/reference/open-source-systems">Systems map</a> · <a href="README.md#deployment-boundary">Documentation</a></p>

<p align="center">
  <a href="https://hub.ci.computer/store/openclaw"><img src="https://img.shields.io/badge/Install%20OpenClaw%20in%20Hub-Install%20OpenClaw%20in%20Hub-0a6358?style=for-the-badge&logo=docker&logoColor=white" alt="Install OpenClaw in Hub" height="30"></a>
</p>

⚠️ WARNING: Running this on systems other than the CI marketplace is likely very insecure. This configuration is only secure when running behind the CI app proxy.


## Features

| Feature | What it provides |
|---|---|
| **OpenClaw runtime** | Run the agent gateway and workspace inside the Hub app container. |
| **First-run setup** | Configure providers, keys and the gateway through the Companion install flow. |
| **Memory plugin** | Add optional Memory capture and retrieval through a bundled plugin. |
| **Hub integration** | Use Hub MCP through the authenticated app proxy when enabled. |


## What is this?

This is a containerized version of OpenClaw with seamless onboarding on the CI marketplace. It provides:

- A simple setup UI to configure your API keys (no interactive onboarding CLI)
- Headless browser setup and configured out of the box
- Sandboxing so OpenClaw runs in its own environment that can't mess up other CI apps
- Automatic gateway token management
- Homebrew pre-installed for OpenClaw to install additional tools configured in a way that will persist between app updates
- apt/apt-get disabled with a message pointing OpenClaw at the package managers the sandbox does have (brew, pip/venv/uv, npm)
- A complete Python 3 toolchain for coding tasks — `python3`, `pip`, `venv`, `uv`, with `pytest` and `httpx` preinstalled — see [Sandbox toolchain](#sandbox-toolchain)
- Globally installed node modules persisted between app updates
- A bundled `companionintelligence` memory plugin that can use CI-Server as OpenClaw's active memory backend when `CI_SERVER_URL` and `CI_SERVER_TOKEN` are configured
- Automatic Hub MCP tool access via a native `mcp.servers.ci-hub` entry in `openclaw.json` (Streamable HTTP), registered when the Hub injects `HUB_URL` / `HUB_MCP_API_KEY` (default on CI marketplace installs with MCP enabled). A bundled `ci-hub` plugin additionally provides the wake endpoint (it also implements app-event SSE, disabled by default). The `ci-hub` model provider is written to `openclaw.json` by the setup server (`config-reconcile.cjs`), not by the plugin — see the note below.
- Security features that complicate setup disabled which are not required on the CI marketplace due to OpenClaw already being protected when running behind the CI app proxy

This creates a seamless one-click install experience for OpenClaw on the CI marketplace.

## Sandbox toolchain

The agent runs its shell commands inside this container, as the unprivileged `node` user with
`HOME=/data` (the app's persistent volume). The image is meant to be self-sufficient for common
coding tasks without root:

| Need | What is there | Where installs land |
|---|---|---|
| Python | `python3` / `python` 3.13, `pip`, `python3 -m venv`, `uv` / `uvx`; `pytest` and `httpx` preinstalled | a project venv (`.venv` in the workspace), or `/data/.local` for `pip install` / `uv tool install` |
| Node | `node` 22, `npm` | `/data/.npm-global` for `npm install -g` |
| System tools | Homebrew (`brew install jq ffmpeg ripgrep …`) | `/home/linuxbrew`, its own persistent mount, filled from the image on first start (`seed-linuxbrew.sh`) |
| Browser | headless Chromium | — |

Everything under `/data` survives app updates; anything installed with `sudo` outside it
(`sudo pip install`, `sudo apt` is shimmed away) is lost on the next image.

Typical Python flow the agent can run as-is:

```bash
# system interpreter already has pytest + httpx, no network needed
python3 -m pytest

# per-project environment in the workspace
python3 -m venv .venv && . .venv/bin/activate && pip install -r requirements.txt pytest httpx
# or, with uv (faster, resolves against the same system interpreter)
uv venv && uv pip install -r requirements.txt pytest httpx && uv run pytest
```

Debian's PEP 668 "externally managed" marker is removed in this image, so a plain
`pip install <pkg>` as `node` falls back to a user install under `/data/.local` instead of
erroring. `/data/.local/bin` is on `PATH` so the entry points it (and `uv tool install`)
creates are runnable. The per-project venv is still the recommended route — it keeps a
task's dependencies out of the shared user site.

`uv` is copied from `ghcr.io/astral-sh/uv` (pinned by version and digest in the `Dockerfile`)
so the multi-arch build gets the right static binary per platform. `pytest`/`httpx` are the
Debian trixie packages (`python3-pytest`, `python3-httpx`), which keeps them apt-managed and
importable from the system interpreter.

## Gateway health

The setup server stays up when the OpenClaw gateway behind it exits, and starts the gateway
again only when the next request arrives. So the container's state says nothing about the
agent. Ask the setup server instead:

```bash
docker compose exec openclaw curl -s http://127.0.0.1:18789/__ci_health
docker inspect --format '{{.State.Health.Status}}' openclaw
```

`/__ci_health` answers 503 after three failed starts in a row (runs that died within a minute
of their spawn), even while the next attempt runs, and 200 otherwise: while the gateway runs or
starts, while the app waits for setup, and while the gateway is stopped. A stopped gateway
counts as up because the next request starts it again, and an unhealthy container loses its
Traefik routes, which would keep that request from arriving on a Public Web install. The body
says which state it is and, after an exit, the exit code or signal. Asking does not restart the
gateway.

The image's `HEALTHCHECK` runs `healthcheck.sh`, which fails only on that 503. A gateway that
cannot start reaches three failed starts within seconds once someone opens OpenClaw, because
its loading page reloads every 2.5 seconds and each reload restarts the gateway. The container
turns `unhealthy` about a minute and a half later, and the Hub's app page shows
**Needs attention**. A gateway that failed at boot and that nobody has asked for since stays
`healthy`.

## Companion Intelligence memory setup

CI-OpenClaw ships with a bundled OpenClaw memory plugin named `companionintelligence`. When CI-Server credentials are available, startup selects it as OpenClaw's active memory backend and routes memory reads/writes through CI-Server.

The same plugin is published to npm as [`@companionintelligence/openclaw-memory`](https://www.npmjs.com/package/@companionintelligence/openclaw-memory), so anyone running a stock `openclaw` can add it with `openclaw plugins install npm:@companionintelligence/openclaw-memory` — no appliance and no fork. Its user-facing documentation lives with the source, in [`openclaw-context/plugins/companionintelligence/README.md`](openclaw-context/plugins/companionintelligence/README.md); releases are cut by `.github/workflows/npm-publish.yml` off the same tags that publish the image.

### Required CI-Server configuration

Provide these environment variables to the OpenClaw container:

```bash
CI_SERVER_URL=http://ci-server:8642
CI_SERVER_TOKEN=<ci-server-api-key>
```

For local Docker Compose outside the CI marketplace, `CI_SERVER_URL` is often:

```bash
CI_SERVER_URL=http://host.docker.internal:8642
```

If using the repo-level `.env` file for local development, also pass the values through `docker-compose.yml`:

```yaml
services:
  openclaw:
    environment:
      APP_SEED: ${APP_SEED:-dev}
      CI_SERVER_URL: ${CI_SERVER_URL}
      CI_SERVER_TOKEN: ${CI_SERVER_TOKEN}
```

### First-run flow

1. Start OpenClaw with the CI-Server env vars present:

   ```bash
   docker compose up --build
   ```

2. Open the setup UI:

   ```text
   http://localhost:18789
   ```

3. Complete OpenClaw onboarding for the model provider/API key.

4. Restart once if the CI-Server env vars were added after onboarding:

   ```bash
   docker compose restart openclaw
   ```

On startup, `/app/bootstrap-ci-memory.sh` and the setup server reconcile the persistent OpenClaw config at `/data/.openclaw/openclaw.json`.

### Expected OpenClaw config

When CI memory is active, the reconciled config should contain:

```json
{
  "plugins": {
    "slots": {
      "memory": "companionintelligence"
    },
    "entries": {
      "companionintelligence": {
        "enabled": true,
        "hooks": {
          "allowConversationAccess": true
        }
      }
    }
  },
  "tools": {
    "alsoAllow": ["memory_store"]
  },
  "hooks": {
    "internal": {
      "entries": {
        "session-memory": {
          "enabled": false
        }
      }
    }
  }
}
```

`memory_store` is explicitly allowed because OpenClaw's `group:memory` profile includes `memory_search` and `memory_get`, but not memory writes.

`hooks.allowConversationAccess: true` is required for the plugin's automatic
turn-sync (s

... (truncated)
tools

Comments

Sign in to leave a comment

Loading comments...