feat(dev): add containerized development environment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Argenis 2026-02-15 11:10:45 -05:00 committed by GitHub
parent 128b30cdf1
commit 20f857a55a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 385 additions and 24 deletions

71
dev/README.md Normal file
View file

@ -0,0 +1,71 @@
# ZeroClaw Development Environment
A fully containerized development sandbox for ZeroClaw agents. This environment allows you to develop, test, and debug the agent in isolation without modifying your host system.
## Directory Structure
- **`agent/`**: (Merged into root Dockerfile)
- The development image is built from the root `Dockerfile` using the `dev` stage (`target: dev`).
- Based on `debian:bookworm-slim` (unlike production `distroless`).
- Includes `bash`, `curl`, and debug tools.
- **`sandbox/`**: Dockerfile for the simulated user environment.
- Based on `ubuntu:22.04`.
- Pre-loaded with `git`, `python3`, `nodejs`, `npm`, `gcc`, `make`.
- Simulates a real developer machine.
- **`docker-compose.yml`**: Defines the services and `dev-net` network.
- **`cli.sh`**: Helper script to manage the lifecycle.
## Usage
Run all commands from the repository root using the helper script:
### 1. Start Environment
```bash
./dev/cli.sh up
```
Builds the agent from source and starts both containers.
### 2. Enter Agent Container (`zeroclaw-dev`)
```bash
./dev/cli.sh agent
```
Use this to run `zeroclaw` CLI commands manually, debug the binary, or check logs internally.
- **Path**: `/zeroclaw-data`
- **User**: `nobody` (65534)
### 3. Enter Sandbox (`sandbox`)
```bash
./dev/cli.sh shell
```
Use this to act as the "user" or "environment" the agent interacts with.
- **Path**: `/home/developer/workspace`
- **User**: `developer` (sudo-enabled)
### 4. Development Cycle
1. Make changes to Rust code in `src/`.
2. Rebuild the agent:
```bash
./dev/cli.sh build
```
3. Test changes inside the container:
```bash
./dev/cli.sh agent
# inside container:
zeroclaw --version
```
### 5. Persistence & Shared Workspace
The local `playground/` directory (in repo root) is mounted as the shared workspace:
- **Agent**: `/zeroclaw-data/workspace`
- **Sandbox**: `/home/developer/workspace`
Files created by the agent are visible to the sandbox user, and vice versa.
The agent configuration lives in `target/.zeroclaw` (mounted to `/zeroclaw-data/.zeroclaw`), so settings persist across container rebuilds.
### 6. Cleanup
Stop containers and remove volumes and generated config:
```bash
./dev/cli.sh clean
```
**Note:** This removes `target/.zeroclaw` (config/DB) but leaves the `playground/` directory intact. To fully wipe everything, manually delete `playground/`.

114
dev/cli.sh Executable file
View file

@ -0,0 +1,114 @@
#!/bin/bash
set -e
# Detect execution context (root or dev/)
if [ -f "dev/docker-compose.yml" ]; then
BASE_DIR="dev"
HOST_TARGET_DIR="target"
elif [ -f "docker-compose.yml" ] && [ "$(basename "$(pwd)")" == "dev" ]; then
BASE_DIR="."
HOST_TARGET_DIR="../target"
else
echo "❌ Error: Run this script from the project root or dev/ directory."
exit 1
fi
COMPOSE_FILE="$BASE_DIR/docker-compose.yml"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
function ensure_config {
CONFIG_DIR="$HOST_TARGET_DIR/.zeroclaw"
CONFIG_FILE="$CONFIG_DIR/config.toml"
WORKSPACE_DIR="$CONFIG_DIR/workspace"
if [ ! -f "$CONFIG_FILE" ]; then
echo -e "${YELLOW}⚙️ Config file missing in target/.zeroclaw. Creating default dev config from template...${NC}"
mkdir -p "$WORKSPACE_DIR"
# Copy template
cat "$BASE_DIR/config.template.toml" > "$CONFIG_FILE"
fi
}
function print_help {
echo -e "${YELLOW}ZeroClaw Development Environment Manager${NC}"
echo "Usage: ./dev/cli.sh [command]"
echo ""
echo "Commands:"
echo -e " ${GREEN}up${NC} Start dev environment (Agent + Sandbox)"
echo -e " ${GREEN}down${NC} Stop containers"
echo -e " ${GREEN}shell${NC} Enter Sandbox (Ubuntu)"
echo -e " ${GREEN}agent${NC} Enter Agent (ZeroClaw CLI)"
echo -e " ${GREEN}logs${NC} View logs"
echo -e " ${GREEN}build${NC} Rebuild images"
echo -e " ${GREEN}clean${NC} Stop and wipe workspace data"
}
if [ -z "$1" ]; then
print_help
exit 1
fi
case "$1" in
up)
ensure_config
echo -e "${GREEN}🚀 Starting Dev Environment...${NC}"
# Build context MUST be set correctly for docker compose
docker compose -f "$COMPOSE_FILE" up -d
echo -e "${GREEN}✅ Environment is running!${NC}"
echo -e " - Agent: http://127.0.0.1:3000"
echo -e " - Sandbox: running (background)"
echo -e " - Config: target/.zeroclaw/config.toml (Edit locally to apply changes)"
;;
down)
echo -e "${YELLOW}🛑 Stopping services...${NC}"
docker compose -f "$COMPOSE_FILE" down
echo -e "${GREEN}✅ Stopped.${NC}"
;;
shell)
echo -e "${GREEN}💻 Entering Sandbox (Ubuntu)... (Type 'exit' to leave)${NC}"
docker exec -it zeroclaw-sandbox /bin/bash
;;
agent)
echo -e "${GREEN}🤖 Entering Agent Container (ZeroClaw)... (Type 'exit' to leave)${NC}"
docker exec -it zeroclaw-dev /bin/bash
;;
logs)
docker compose -f "$COMPOSE_FILE" logs -f
;;
build)
echo -e "${YELLOW}🔨 Rebuilding images...${NC}"
docker compose -f "$COMPOSE_FILE" build
ensure_config
docker compose -f "$COMPOSE_FILE" up -d
echo -e "${GREEN}✅ Rebuild complete.${NC}"
;;
clean)
echo -e "${RED}⚠️ WARNING: This will delete 'target/.zeroclaw' data and Docker volumes.${NC}"
read -p "Are you sure? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
docker compose -f "$COMPOSE_FILE" down -v
rm -rf "$HOST_TARGET_DIR/.zeroclaw"
echo -e "${GREEN}🧹 Cleaned up (playground/ remains intact).${NC}"
else
echo "Cancelled."
fi
;;
*)
print_help
exit 1
;;
esac

12
dev/config.template.toml Normal file
View file

@ -0,0 +1,12 @@
workspace_dir = "/zeroclaw-data/workspace"
config_path = "/zeroclaw-data/.zeroclaw/config.toml"
# This is the Ollama Base URL, not a secret key
api_key = "http://host.docker.internal:11434"
default_provider = "ollama"
default_model = "llama3.2"
default_temperature = 0.7
[gateway]
port = 3000
host = "[::]"
allow_public_bind = true

59
dev/docker-compose.yml Normal file
View file

@ -0,0 +1,59 @@
# Development Environment for ZeroClaw Agentic Testing
#
# Use this for:
# - Running the agent in a sandboxed environment
# - Testing dangerous commands safely
# - Developing new skills/integrations
#
# Usage:
# cd dev && ./cli.sh up
# or from root: ./dev/cli.sh up
name: zeroclaw-dev
services:
# ── The Agent (Development Image) ──
# Builds from source using the 'dev' stage of the root Dockerfile
zeroclaw-dev:
build:
context: ..
dockerfile: Dockerfile
target: dev
container_name: zeroclaw-dev
restart: unless-stopped
environment:
- API_KEY
- PROVIDER
- ZEROCLAW_MODEL
- ZEROCLAW_GATEWAY_PORT=3000
- SANDBOX_HOST=zeroclaw-sandbox
volumes:
# Mount single config file (avoids shadowing other files in .zeroclaw)
- ../target/.zeroclaw/config.toml:/zeroclaw-data/.zeroclaw/config.toml
# Mount shared workspace
- ../playground:/zeroclaw-data/workspace
ports:
- "127.0.0.1:3000:3000"
networks:
- dev-net
# ── The Sandbox (Ubuntu Environment) ──
# A fully loaded Ubuntu environment for the agent to play in.
sandbox:
build:
context: sandbox # Context relative to dev/
dockerfile: Dockerfile
container_name: zeroclaw-sandbox
hostname: dev-box
command: ["tail", "-f", "/dev/null"]
working_dir: /home/developer/workspace
user: developer
environment:
- TERM=xterm-256color
- SHELL=/bin/bash
volumes:
- ../playground:/home/developer/workspace # Mount local playground
networks:
- dev-net
networks:
dev-net:
driver: bridge

34
dev/sandbox/Dockerfile Normal file
View file

@ -0,0 +1,34 @@
FROM ubuntu:22.04
# Prevent interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive
# Install common development tools and runtimes
# - Node.js: Install v20 (LTS) from NodeSource
# - Core: curl, git, vim, build-essential (gcc, make)
# - Python: python3, pip
# - Network: ping, dnsutils
RUN apt-get update && apt-get install -y curl && \
curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
apt-get install -y \
nodejs \
wget git vim nano unzip zip \
build-essential \
python3 python3-pip \
sudo \
iputils-ping dnsutils net-tools \
&& rm -rf /var/lib/apt/lists/* \
&& node --version && npm --version
# Create a non-root user 'developer' with UID 1000
# Grant passwordless sudo to simulate a local dev environment (using safe sudoers.d)
RUN useradd -m -s /bin/bash -u 1000 developer && \
echo "developer ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/developer && \
chmod 0440 /etc/sudoers.d/developer
# Set up the workspace
USER developer
WORKDIR /home/developer/workspace
# Default command
CMD ["/bin/bash"]