Python 3 has been unconditionally present since the Debian trixie upgrade (e58962a, Apr 13) — python3 3.13 ships as a transitive dependency of the trixie base image. python3-pip (e1029bb) and python3-venv (3a7ec45) were later added to the base layer on Apr 23 so Mason could install Python-based LSPs (ruff, ansible-lint) into venvs on nvim startup. MemPalace's pip install (b9c08c3) just piggybacks on what was already there. In other words, INSTALL_PYTHON=true has been a no-op reinstall of already-installed packages for two weeks before MemPalace existed. The flag is dead weight and the docs that advertise it as meaningful are misleading. Remove it everywhere. Users who want Python tooling should use the pre-installed uv/uvx.
22 KiB
opencode-devbox — Docker Hub
Portable AI developer environment for opencode. Debian-based, with git, SSH, Node.js, AWS CLI v2, and common dev tools pre-installed.
Image Variants
Two image variants are published for each release:
| Tag | Description |
|---|---|
latest / vX.Y.Z |
Base image — opencode, Node.js, AWS CLI, dev tools |
latest-omos / vX.Y.Z-omos |
Base + oh-my-opencode-slim multi-agent orchestration and Bun |
Both variants support linux/amd64 and linux/arm64.
Quick Start
docker run -it --rm \
-e ANTHROPIC_API_KEY=your-key \
-e OPENCODE_PROVIDER=anthropic \
-e GIT_USER_NAME="Your Name" \
-e GIT_USER_EMAIL="you@example.com" \
-v ~/projects:/workspace \
-v ~/.ssh:/home/developer/.ssh:ro \
joakimp/opencode-devbox:latest
This drops you straight into opencode with your project mounted at /workspace.
Interactive Shell
To get a shell first (useful for AWS SSO login or running other commands):
docker run -it --rm \
-e ANTHROPIC_API_KEY=your-key \
-e OPENCODE_PROVIDER=anthropic \
-v ~/projects:/workspace \
-v ~/.ssh:/home/developer/.ssh:ro \
joakimp/opencode-devbox:latest bash
Then run opencode when ready.
Running Multiple Shells
Once opencode is running it takes over the terminal. To have a separate shell for aws, git, or other commands, run the container in the background and attach multiple times:
# Start in background
docker run -d --name devbox \
-e ANTHROPIC_API_KEY=your-key \
-e OPENCODE_PROVIDER=anthropic \
-v ~/projects:/workspace \
-v ~/.ssh:/home/developer/.ssh:ro \
joakimp/opencode-devbox:latest sleep infinity
# Shell 1: run opencode
docker exec -it -u developer devbox opencode
# Shell 2 (separate terminal): aws, git, etc.
docker exec -it -u developer devbox bash
# When done
docker rm -f devbox
Note: Always use
-u developerwithdocker exec— the container starts as root for UID adjustment, then drops todeveloper. Without-u developer, exec runs as root.
Environment Variables
All configuration is done via environment variables, typically stored in a .env file.
Provider Configuration
| Variable | Description | Default |
|---|---|---|
OPENCODE_PROVIDER |
LLM provider (anthropic, openai, amazon-bedrock) |
anthropic |
OPENCODE_MODEL |
Model override | Provider default |
API Keys
Set the key matching your provider:
| Variable | Provider |
|---|---|
ANTHROPIC_API_KEY |
Anthropic |
OPENAI_API_KEY |
OpenAI |
AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY |
AWS Bedrock (static creds) |
AWS Bedrock
| Variable | Description | Default |
|---|---|---|
AWS_REGION |
AWS region | us-east-1 |
AWS_PROFILE |
AWS SSO profile name | default |
Git
| Variable | Description |
|---|---|
GIT_USER_NAME |
Git commit author name |
GIT_USER_EMAIL |
Git commit author email |
User ID Mapping
The container runs as user developer (UID 1000 by default). If your host user has a different UID, file permission mismatches can occur on mounted volumes.
The entrypoint automatically detects the owner of /workspace and adjusts the container user's UID/GID to match. You can also set it explicitly:
| Variable | Description | Default |
|---|---|---|
USER_UID |
Container user UID | Auto-detect from /workspace owner |
USER_GID |
Container user GID | Auto-detect from /workspace owner |
Locale and Editor
The container defaults to English (en_US.UTF-8) and neovim as the editor. Override via environment variables:
| Variable | Description | Default |
|---|---|---|
LANG |
System locale | en_US.UTF-8 |
LANGUAGE |
Language priority list | en_US:en |
LC_ALL |
Override all locale settings | en_US.UTF-8 |
EDITOR |
Default text editor | nvim |
Pre-generated locales: en_US, en_GB, sv_SE, da_DK, nb_NO, fi_FI, de_DE, fr_FR, es_ES, it_IT, pt_BR, nl_NL, pl_PL, ja_JP, ko_KR, zh_CN (all UTF-8).
Example for Swedish:
LANG=sv_SE.UTF-8
LANGUAGE=sv_SE:sv
LC_ALL=sv_SE.UTF-8
To add a locale not in the list, run inside the container:
sudo sed -i '/xx_XX.UTF-8/s/^# //g' /etc/locale.gen
sudo locale-gen
Replace xx_XX with the desired locale (e.g. ru_RU, tr_TR). This change does not persist across container restarts — for permanent additions, build from source and modify the Dockerfile.
Initial Setup
1. Create host directories
Bind-mounted directories must exist on the host before starting the container. Docker creates missing directories as root-owned, which causes permission issues.
# Required
mkdir -p ~/projects
# If mounting opencode config (recommended for persistent settings)
mkdir -p ~/.config/opencode
# If using AWS Bedrock
# mkdir -p ~/.aws
# If mounting neovim config
# mkdir -p ~/.config/nvim
2. Create a .env file
Create a .env file with your configuration. Examples for each provider:
Anthropic:
OPENCODE_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com
OpenAI:
OPENCODE_PROVIDER=openai
OPENAI_API_KEY=sk-...
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com
AWS Bedrock (SSO):
OPENCODE_PROVIDER=amazon-bedrock
OPENCODE_MODEL=amazon-bedrock/eu.anthropic.claude-opus-4-6-v1
AWS_REGION=eu-west-1
AWS_PROFILE=your-profile-name
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com
3. AWS SSO setup (Bedrock users only)
AWS SSO requires a ~/.aws/config file on the host with your SSO session configuration. If you already have this on another machine, copy it:
scp -r user@other-machine:~/.aws ~/.aws
Or configure from scratch:
aws configure sso
You'll be prompted for:
- SSO session name
- SSO start URL
- SSO region
- Registration scopes (typically
sso:account:access)
The ~/.aws directory must be mounted into the container (see docker-compose example below).
Data Storage and Persistence
Understanding what survives container restarts and what doesn't:
| Path in container | Source | Survives restart? | Contains |
|---|---|---|---|
/workspace |
Host bind mount | ✅ Yes — lives on host | Your project files |
/home/developer/.ssh |
Host bind mount (ro) | ✅ Yes — lives on host | SSH keys |
/home/developer/.aws |
Host bind mount | ✅ Yes — lives on host | AWS credentials/SSO cache |
/home/developer/.local/share/opencode |
Named volume (if configured) | ✅ Yes — Docker volume | Session history, memory, auth tokens |
/home/developer/.local/state/opencode |
Named volume (if configured) | ✅ Yes — Docker volume | TUI settings (theme, toggles) |
/home/developer/.cache/bash |
Named volume devbox-shell-history |
✅ Yes — Docker volume | Bash history ($HISTFILE) — survives container recreate |
/home/developer/.local/share/zoxide |
Named volume devbox-zoxide |
✅ Yes — Docker volume | Zoxide directory history (z <fragment> jump targets) |
/home/developer/.local/share/nvim |
Named volume devbox-nvim-data |
✅ Yes — Docker volume | Neovim plugins, Mason LSP installs, Lazy plugin cache |
/home/developer/.mempalace |
Named volume devbox-palace (if configured) |
✅ Yes — Docker volume | MemPalace conversation memory, knowledge graph, embeddings |
/home/developer/.cache/chroma |
Named volume devbox-chroma-cache (if configured) |
✅ Yes — Docker volume | ChromaDB ONNX embedding model (~79 MB, downloaded on first use) |
/home/developer/.local/share/uv |
Named volume (if configured) | ✅ Yes — Docker volume | Python installs, uv tool installs |
/home/developer/.rustup |
Named volume (if configured) | ✅ Yes — Docker volume | Rust toolchains |
/home/developer/.cargo |
Named volume (if configured) | ✅ Yes — Docker volume | Cargo binaries, registry cache |
/home/developer/.vscode-server |
Named volume (if configured) | ✅ Yes — Docker volume | VS Code server and extensions |
/home/developer/.config/opencode |
Host bind mount (if configured) | ✅ Yes — lives on host | opencode.json, skills, plus oh-my-opencode-slim.json on the OMOS variant |
Key points
- Project files (
/workspace) are always safe — they're your host filesystem. - opencode config is auto-generated from
OPENCODE_PROVIDERenv var on each start if no existing config is found. To persist config changes, mount the config directory from the host (see Custom opencode Config below). - opencode data (session history, memory) is lost on container recreation unless you add a named volume.
- TUI settings (theme, toggles) are lost on container recreation unless you add the
devbox-statenamed volume. - Bash history persists via the
devbox-shell-historyvolume mounted at~/.cache/bash.HISTFILEis pre-configured; no setup required. - Python installs via
uv python installare lost on container recreation unless you add thedevbox-uvnamed volume. - Rust toolchains via
rustup-initare lost on container recreation unless you add thedevbox-rustupanddevbox-cargonamed volumes. - AWS SSO tokens persist across restarts when
~/.awsis mounted (recommended for Bedrock users).
Custom opencode Config
For full control over opencode settings (MCP servers, custom models, and — on the OMOS variant — oh-my-opencode-slim agents), mount the entire config directory from the host:
docker run -it --rm \
-v ~/.config/opencode:/home/developer/.config/opencode \
... \
joakimp/opencode-devbox:latest
This persists all configuration changes across container restarts. When an existing opencode.json is found, the OPENCODE_PROVIDER auto-config is skipped.
Portability note: The mounted config runs inside a Linux container. Any absolute paths inside
opencode.json(for example, host-specificpluginentries likefile:///usr/local/lib/node_modules/...orfile:///opt/homebrew/...) will not resolve inside the container. Prefer bare package specifiers (e.g."oh-my-opencode-slim") that resolve vianode_moduleslookup, which works on both macOS and Linux hosts.
Neovim Configuration
The image includes neovim 0.12 with EDITOR=nvim set by default. To use your own neovim config (and have plugins auto-install via lazy.nvim on first start), mount it from the host:
docker run -it --rm \
-v ~/.config/nvim:/home/developer/.config/nvim:ro \
... \
joakimp/opencode-devbox:latest
Python Development with uv
The image includes Python 3.13 (from Debian Trixie) and uv, a fast Python package manager that replaces pip, venv, and pyenv:
# Python 3.13 is available out of the box
python3 --version
# Use uv for package management
uv venv
uv pip install -r requirements.txt
# Or use uv's project workflow (reads pyproject.toml)
uv sync
# Run a Python script
uv run python script.py
# Install standalone Python tools
uvx ruff check .
# Install a newer Python version (persists with devbox-uv volume)
uv python install 3.14
To persist Python installs across container restarts, add a named volume:
docker run -it --rm \
-v devbox-uv:/home/developer/.local/share/uv \
... \
joakimp/opencode-devbox:latest
Project virtual environments (.venv) are stored in your workspace directory and persist automatically via the /workspace bind mount.
Rust Development with rustup
The image includes rustup-init, the Rust toolchain installer. Rust is not pre-installed but can be bootstrapped on demand:
# One-time setup: install Rust toolchain (~300MB, persists with volumes)
rustup-init -y
source ~/.cargo/env
# Now use Rust normally
cargo new my-project
cargo build
cargo run
To persist Rust toolchains and cargo data across container restarts, add named volumes:
docker run -it --rm \
-v devbox-rustup:/home/developer/.rustup \
-v devbox-cargo:/home/developer/.cargo \
... \
joakimp/opencode-devbox:latest
JavaScript and TypeScript
The base image includes Node.js 22 and npm — sufficient for most JavaScript and TypeScript development:
# Initialize a new project
npm init -y
# Install dependencies
npm install
# Run TypeScript (via tsx, ts-node, etc.)
npx tsx src/index.ts
The OMOS image variant also includes Bun, a faster JavaScript runtime and package manager:
bun init
bun install
bun run src/index.ts
Node modules are stored in your project directory under /workspace and persist automatically.
VS Code Integration
VS Code can connect directly to a running opencode-devbox container for a full IDE experience with IntelliSense, debugging, and extensions running inside the container.
Requirements: Install the Dev Containers extension. For remote Docker hosts, also install Remote - SSH.
Steps:
- Start the container:
docker compose up -d - In VS Code:
Ctrl+Shift+P→ "Dev Containers: Attach to Running Container" → selectopencode-devbox
For remote Docker hosts (e.g. connecting to a server via SSH), first connect to the remote host with Remote-SSH, then attach to the container from there.
VS Code extensions installed inside the container persist as long as the container exists. For persistent extension storage across container recreations, add a named volume:
docker run -it --rm \
-v devbox-vscode:/home/developer/.vscode-server \
... \
joakimp/opencode-devbox:latest
Using docker-compose
Create a directory with a docker-compose.yml and a .env file:
mkdir opencode-devbox && cd opencode-devbox
.env — your settings (never commit this):
OPENCODE_PROVIDER=amazon-bedrock
OPENCODE_MODEL=amazon-bedrock/eu.anthropic.claude-opus-4-6-v1
AWS_REGION=eu-west-1
AWS_PROFILE=your-profile-name
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com
docker-compose.yml:
services:
devbox:
image: joakimp/opencode-devbox:latest
# For multi-agent orchestration, use the omos variant instead:
# image: joakimp/opencode-devbox:latest-omos
container_name: opencode-devbox
stdin_open: true
tty: true
env_file:
- .env
environment:
- TERM=xterm-256color
- GITHUB_PERSONAL_ACCESS_TOKEN=${GITHUB_PERSONAL_ACCESS_TOKEN:-}
- GITEA_ACCESS_TOKEN=${GITEA_ACCESS_TOKEN:-}
- GITEA_HOST=${GITEA_HOST:-}
volumes:
- ~/projects:/workspace
- ~/.ssh:/home/developer/.ssh:ro
- devbox-data:/home/developer/.local/share/opencode
- devbox-state:/home/developer/.local/state/opencode
- devbox-shell-history:/home/developer/.cache/bash
- devbox-zoxide:/home/developer/.local/share/zoxide
- devbox-nvim-data:/home/developer/.local/share/nvim
- devbox-uv:/home/developer/.local/share/uv
# Optional: persist MemPalace data (conversation memory, knowledge graph)
# - devbox-palace:/home/developer/.mempalace
# Optional: persist ChromaDB embedding model cache (~79 MB)
# - devbox-chroma-cache:/home/developer/.cache/chroma
# Optional: persist Rust toolchains and cargo data
# - devbox-rustup:/home/developer/.rustup
# - devbox-cargo:/home/developer/.cargo
# Optional: persist VS Code server and extensions
# - devbox-vscode:/home/developer/.vscode-server
# Mount AWS config for Bedrock SSO (required for amazon-bedrock provider)
# - ~/.aws:/home/developer/.aws
# Optional: mount opencode config directory (persists config changes across restarts)
# - ~/.config/opencode:/home/developer/.config/opencode
# Optional: mount opencode agent skills from host
# - ~/.agents/skills:/home/developer/.agents/skills:ro
# Optional: mount neovim config from host (plugins auto-install on first start)
# - ~/.config/nvim:/home/developer/.config/nvim:ro
volumes:
devbox-data:
devbox-state:
devbox-shell-history:
devbox-zoxide:
devbox-nvim-data:
devbox-uv:
# devbox-palace:
# devbox-chroma-cache:
# devbox-rustup:
# devbox-cargo:
# devbox-vscode:
Docker Compose loads .env automatically from the same directory. All variables from .env are passed to the container via env_file. Do not hardcode provider settings in the environment: section — use .env instead.
Then:
# Start in background
docker compose up -d
# Open a shell (always use -u developer with exec)
docker compose exec -u developer devbox bash
# For Bedrock: authenticate, then start opencode
aws sso login --sso-session <your-session> --use-device-code
opencode
# Or run opencode directly (if no SSO needed)
docker compose exec -u developer devbox opencode
# One-shot mode (creates and removes container)
docker compose run --rm devbox # direct to opencode
docker compose run --rm devbox bash # interactive shell
Shell defaults
The image ships baked .bash_aliases and .inputrc in /etc/skel-devbox/. On first container start the entrypoint copies them to /home/developer/ only if the target file does not already exist, so your host bind-mounts or any in-container customization are preserved across upgrades.
- Prefix history search on Up/Down arrows (type
git, press Up, walk back through priorgit ...commands only). Ctrl-Up / Ctrl-Down still step through full history. - Persistent history via
$HISTFILE=~/.cache/bash/history, backed by thedevbox-shell-historynamed volume. Survives container recreate. 100 000 entries, time-stamped, dedup. - Case-insensitive tab completion and coloured completion lists.
- Aliases —
ls/ll/la→eza,cat→bat,gs/gd/glfor git, interactiverm/mv/cp. - Integrations —
zoxide(z <fragment>),fzfkey bindings (Ctrl-R,Ctrl-T). [devbox]prompt prefix so you always know you're in the container.
To override with your host's own files, uncomment the matching bind-mount lines in docker-compose.yml. To restore the baked defaults any time: cp /etc/skel-devbox/.bash_aliases ~/ (or delete the file and recreate the container).
What's Included
Base image (latest)
- Debian trixie-slim — glibc, full terminal/PTY support
- opencode — AI coding assistant
- Node.js 22 — for npx-based MCP servers
- AWS CLI v2 — SSO and Bedrock authentication
- Dev tools — git, git-lfs, git-crypt, age, ssh, ripgrep, fd, fzf, bat, eza, zoxide, uv, rustup, mempalace, gitea-mcp, jq, make, gcc, g++, curl, wget, neovim 0.12, tmux, htop, tree, rsync
- Non-root user — runs as
developerwith UID auto-matched to workspace owner (sudo available)
OMOS image (latest-omos)
Everything in the base image, plus:
- oh-my-opencode-slim — multi-agent orchestration plugin
- Bun — JavaScript runtime required by oh-my-opencode-slim
- 6 specialized agents — Orchestrator, Explorer, Oracle, Librarian, Designer, Fixer
Additional runtimes (build from source)
When building from source, additional runtimes are available via build args:
- Go (
INSTALL_GO=true) — Go toolchain
oh-my-opencode-slim (OMOS variant)
The -omos image variant includes oh-my-opencode-slim, which adds a multi-agent layer on top of opencode. An Orchestrator delegates tasks to specialized agents, each configurable with different models and providers.
Quick start with OMOS
docker run -it --rm \
-e OPENAI_API_KEY=your-key \
-e OPENCODE_PROVIDER=openai \
-e ENABLE_OMOS=true \
-v ~/projects:/workspace \
-v ~/.ssh:/home/developer/.ssh:ro \
joakimp/opencode-devbox:latest-omos
On first start, the entrypoint configures oh-my-opencode-slim automatically. The default preset uses OpenAI models.
OMOS environment variables
| Variable | Default | Description |
|---|---|---|
ENABLE_OMOS |
false |
Activate oh-my-opencode-slim on container start |
OMOS_TMUX |
false |
Enable tmux pane integration (watch agents in split panes) |
OMOS_SKILLS |
true |
Install recommended skills (simplify, agent-browser, cartography) |
OMOS_RESET |
false |
Force regenerate config on next start (backs up existing config) |
Custom OMOS configuration
If you mount the opencode config directory (see Custom opencode Config above), the oh-my-opencode-slim.json file is included and persists across restarts. Edit it directly to control which models power each agent, fallback chains, council setup, and more.
See the oh-my-opencode-slim configuration docs for the full reference.
Verifying agents
After starting opencode with OMOS enabled, run inside the opencode session:
ping all agents
All six agents should respond if your provider authentication is working.
Multi-User Setup
This guide covers single-user setup. For running multiple opencode-devbox instances in parallel — whether each user has their own OS account or everyone shares one login — see the Multi-user setup section in the source repository. It covers volume isolation, the docker-compose.shared.yml layout, and the SIGNUM / $USER auto-detection mechanism.
Source
Build from source or contribute: opencode-devbox on Gitea
See the Changelog for a full release history.