Debian based image to run OpenRig and the AI coding agents it drives inside a container, so the agents can only touch the project directory that is mounted into it.
Note: This image is built to be started through a wrapper script and a Docker Compose setup, which mount the project and the state directories, keep the projects apart and load the environment. The wrapper script and the Compose setup are not published at the moment. The image works without them, but you have to set up the same mounts and options yourself (see Running without the wrapper).
netinventors/openrig:<openrig version>-node<node version>-<debian version>,
e.g. netinventors/openrig:0.6.7-node24-trixie
Every build is also tagged latest. Images are rebuilt regularly, also without
version bumps, to pick up Debian and Node.js security fixes.
| Tool | Command | Source |
|---|---|---|
| Node.js | node, npm | official node:<version>-<debian>-slim image |
| OpenRig | rig, openrig-tui | @openrig/cli |
| Claude Code | claude | @anthropic-ai/claude-code |
| Codex | codex | @openai/codex |
| Pi | pi | @earendil-works/pi-coding-agent |
| Oh My Pi | omp (with bun) | @oh-my-pi/pi-coding-agent |
| Cursor CLI | cursor-agent, agent | cursor.com/cli |
| Grok CLI | grok | @xai-official/grok |
| herdr | herdr | herdrdev/herdr, the tiled view for rig terminal open |
Plus tmux, git, ripgrep, jq, curl, less, unzip, openssh-client, procps and tini.
Why Debian and not Alpine: OpenRig needs the native better-sqlite3 module and
Claude Code needs extra workarounds on musl. Both work out of the box on glibc.
Everything runs as the node user (uid/gid 1000). The tools are installed
into /home/node/.npm-global, /home/node/.bun and /home/node/.local, not as
root (except the static herdr binary in /usr/local/bin). Auto updates of
Claude Code are disabled; updates come with a new image.
Entrypoint: tini → /usr/local/bin/entrypoint.sh. Default command:
tmux new-session -A -s rig. On every start the entrypoint
rig setup (idempotent, output in ~/.openrig/setup.log),herdr server for rig terminal open (log in
~/.openrig/herdr.log),0.0.0.0 when
OPENRIG_AUTH_BEARER_TOKEN is set) and brings the kernel rig back, because
its tmux sessions do not survive the container (log in
~/.openrig/start.log).The daemon needs the tmux server of the default command. If you replace the
command, start tmux yourself or skip the daemon with OPENRIG_SKIP_START=1.
| Variable | Purpose |
|---|---|
ANTHROPIC_API_KEY, OPENAI_API_KEY | use API keys instead of logging in |
OPENRIG_AUTH_BEARER_TOKEN | bearer token for the daemon. Required to bind it to 0.0.0.0, which is needed to reach its UI/API from the host. Also handed to rig tui as OPENRIG_TERMINAL_BEARER_TOKEN |
OPENRIG_SKIP_SETUP=1 | skip rig setup on start |
OPENRIG_SKIP_HERDR=1 | do not start the headless herdr server |
OPENRIG_SKIP_START=1 | do not start the daemon and the kernel |
The image declares no volumes. The wrapper setup bind mounts these directories from the host. They must exist and be writable by uid 1000:
| Container path | Content | Scope |
|---|---|---|
| the project's host path | the project the agents work on | per project |
/home/node/.openrig | OpenRig: rigs, kernel, missions, tasks, logs | per project |
/home/node/.claude | Claude Code login, settings, history (CLAUDE_CONFIG_DIR) | shared |
/home/node/.codex | Codex login and sessions | shared |
/home/node/.pi, /home/node/.omp | Pi / Oh My Pi | shared |
/home/node/.cursor, /home/node/.config/cursor | Cursor CLI and its login | shared |
/home/node/.grok | Grok CLI | shared |
Mount the project at the same path as on the host, not at a fixed path like
/workspace. The agents key their conversation history and memory by the
working directory, so with a fixed path every project would see the history,
memory and tasks of the previous one. For the same reason use a separate
/home/node/.openrig directory per project. The login directories can be
shared.
Never mount your real ~/.claude, ~/.codex etc. from the host: the agents
could write hooks that your host tools execute, and read your host credentials.
7433: OpenRig daemon UI/API. Publish it on the host's loopback only
(127.0.0.1:7433:7433).
Roughly what the wrapper does, for a project in the current directory:
state=~/.local/share/openrig
project="$(basename "$PWD")-$(printf '%s' "$PWD" | sha256sum | cut -c1-8)"
mkdir -p "$state"/{claude,codex,pi,omp,cursor,cursor-config,grok} "$state/workspaces/$project/openrig"
docker run --rm -it \
--hostname openrig \
--cap-drop ALL \
--security-opt no-new-privileges:true \
-p 127.0.0.1:7433:7433 \
-v "$PWD:$PWD" -w "$PWD" \
-v "$state/workspaces/$project/openrig:/home/node/.openrig" \
-v "$state/claude:/home/node/.claude" \
-v "$state/codex:/home/node/.codex" \
-v "$state/pi:/home/node/.pi" \
-v "$state/omp:/home/node/.omp" \
-v "$state/cursor:/home/node/.cursor" \
-v "$state/cursor-config:/home/node/.config/cursor" \
-v "$state/grok:/home/node/.grok" \
-e OPENRIG_AUTH_BEARER_TOKEN="$(openssl rand -hex 32)" \
netinventors/openrig:latest
On first start log in once inside the container; the logins are kept in the state directories:
claude # or: claude auth login
codex login
cursor-agent login # optional
grok login # optional
rig setup # should report no failures now
rig start # later starts do this automatically
To see the kernel's seats as tiles, place them in herdr and attach a herdr
client from a host terminal (not from inside the container's tmux, both use
the ctrl+b prefix):
# inside the container
rig terminal open saved:kernel --provider herdr
# on the host
docker exec -it <container> herdr # ctrl+b q detaches
--provider herdr is required: without it rig tries to open a desktop terminal
window, which the container does not have, and fails with unauthorized.
--cap-drop ALL and no-new-privileges; non-root usersecrets-manager) do not
work. Never mount /var/run/docker.sock: it gives the agents root on the hostContent type
Image
Digest
sha256:727f676e0…
Size
1.1 GB
Last updated
4 days ago
docker pull netinventors/openrig