Loading...
Loading...
Deploy a full AI coding workstation with Claude Code, web UI, headless browser, and 5 AI CLIs in a single Docker container
npx skill4agent add aradotso/trending-skills holyclaude-ai-workstationSkill by ara.so — Daily 2026 Skills collection.
docker compose upmkdir holyclaude && cd holyclaudedocker-compose.yamlservices:
holyclaude:
image: CoderLuii/HolyClaude:latest
container_name: holyclaude
hostname: holyclaude
restart: unless-stopped
shm_size: 2g
ports:
- "3001:3001"
volumes:
- ./data/claude:/root/.claude
- ./data/config:/root/.config
- ./projects:/workspace
environment:
- PUID=1000
- PGID=1000docker compose up -d
# Open http://localhost:3001# Full image — all tools pre-installed (recommended)
docker pull CoderLuii/HolyClaude:latest
# Slim image — smaller download, tools installed on demand
docker pull CoderLuii/HolyClaude:slim
# Pinned version for production stability
docker pull CoderLuii/HolyClaude:1.2.3
docker pull CoderLuii/HolyClaude:1.2.3-slimservices:
holyclaude:
image: CoderLuii/HolyClaude:latest
container_name: holyclaude
hostname: holyclaude
restart: unless-stopped
shm_size: 2g # Required for Chromium
ports:
- "3001:3001" # CloudCLI web UI
volumes:
- ./data/claude:/root/.claude # Claude credentials & config (persisted)
- ./data/config:/root/.config # App config (persisted)
- ./projects:/workspace # Your project files
environment:
# User/group IDs (match host user to avoid permission issues)
- PUID=1000
- PGID=1000
# AI provider API keys (optional — can also set via web UI)
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- GEMINI_API_KEY=${GEMINI_API_KEY}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- CURSOR_API_KEY=${CURSOR_API_KEY}
# NAS/SMB mount polling (enable if using Synology/QNAP)
- CHOKIDAR_USEPOLLING=true
# Notification webhooks (optional)
- DISCORD_WEBHOOK_URL=${DISCORD_WEBHOOK_URL}
- SLACK_WEBHOOK_URL=${SLACK_WEBHOOK_URL}
security_opt:
- seccomp:unconfined # Required for Chromium sandbox| Variable | Required | Description |
|---|---|---|
| Recommended | Host user ID (run |
| Recommended | Host group ID (run |
| Optional | Anthropic API key (alternative to OAuth login) |
| Optional | Google AI API key for Gemini CLI |
| Optional | OpenAI API key for Codex CLI |
| Optional | Cursor API key |
| NAS only | Set |
| Optional | Discord notifications |
| Optional | Slack notifications |
http://localhost:3001environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}./data/claude/ → /root/.claude/
./data/config/ → /root/.config/# No extra config needed
shm_size: 2g# Works out of the box with Docker Desktop
shm_size: 2g# Requires WSL2 backend enabled in Docker Desktop
shm_size: 2genvironment:
- CHOKIDAR_USEPOLLING=true # Fixes file watching on SMB mounts
volumes:
- /volume1/docker/holyclaude/data/claude:/root/.claude
- /volume1/docker/holyclaude/projects:/workspace# arm64 image is published alongside amd64
image: CoderLuii/HolyClaude:latest # multi-arch manifest auto-selects correct arch| CLI | Invocation | Key Provider |
|---|---|---|
| Claude Code | | Anthropic ( |
| Gemini CLI | | Google ( |
| OpenAI Codex | | OpenAI ( |
| Cursor | | Cursor ( |
| TaskMaster AI | | Uses configured AI provider keys |
:99shm_size: 2gghvolumes:
- ./projects:/workspace
# Or mount a specific project:
- /path/to/my-app:/workspace/my-app# Access the container shell
docker exec -it holyclaude bash
# Navigate to workspace
cd /workspace
# Run Claude Code directly
claude
# Run other AI CLIs
gemini
codex// playwright.config.ts — already works inside the container
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
// Chromium is pre-installed, no download needed
browserName: 'chromium',
launchOptions: {
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage', // Use /tmp instead of /dev/shm
],
},
},
});// Direct Playwright usage inside container
import { chromium } from 'playwright';
const browser = await chromium.launch({
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
],
});
const page = await browser.newPage();
await page.goto('https://example.com');
const screenshot = await page.screenshot({ path: '/workspace/screenshot.png' });
await browser.close();# Run Playwright tests inside container
docker exec -it holyclaude bash -c "cd /workspace && npx playwright test"
# Run with headed mode via Xvfb
docker exec -it holyclaude bash -c "DISPLAY=:99 npx playwright test --headed"# Pull latest image
docker compose pull
# Recreate container with new image (zero data loss — data is in bind mounts)
docker compose up -d
# Or explicit recreation
docker compose down && docker compose up -d# For production: pin to a specific version
image: CoderLuii/HolyClaude:1.2.3
# Update by changing the tag and running:
docker compose up -dholyclaude/
├── docker-compose.yaml
├── data/
│ ├── claude/ # Claude credentials, .claude.json, history
│ └── config/ # CloudCLI and app configuration
└── projects/ # Your workspace (mount your code here)docker compose down && updocker compose pullvolumes:
- ./data/claude:/root/.claude
- ./data/config:/root/.config
- ~/code/project-a:/workspace/project-a
- ~/code/project-b:/workspace/project-b
- ~/code/project-c:/workspace/project-c# .env (never commit this)
ANTHROPIC_API_KEY=sk-ant-...
GEMINI_API_KEY=AIza...
OPENAI_API_KEY=sk-...# docker-compose.yaml
services:
holyclaude:
env_file: .envports:
- "8080:3001" # Access via http://localhost:8080ports:
- "0.0.0.0:3001:3001" # Accessible from network
# Then access via http://your-server-ip:3001
# Recommend putting behind nginx/Caddy with HTTPS for productionservices:
holyclaude:
image: CoderLuii/HolyClaude:latest
# Don't expose ports directly — nginx handles it
expose:
- "3001"
networks:
- web
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./certs:/etc/nginx/certs
networks:
- web
networks:
web:# Check logs
docker compose logs holyclaude
# Check if port 3001 is already in use
lsof -i :3001# Ensure shm_size is set (CRITICAL)
shm_size: 2g
# Ensure seccomp is unconfined
security_opt:
- seccomp:unconfined# Verify display is available inside container
docker exec holyclaude bash -c "echo $DISPLAY"
# Should output: :99environment:
- PUID=1000 # Must match your host user: `id -u`
- PGID=1000 # Must match your host group: `id -g`# Fix existing permissions on host
sudo chown -R 1000:1000 ./data ./projectsenvironment:
- CHOKIDAR_USEPOLLING=true# Ensure WORKDIR is not root-owned before running Claude Code installer
RUN chown -R node:node /app
WORKDIR /appvolumes:
# Move SQLite databases to a local volume, not NAS mount
- holyclaude-db:/root/.local/share/holyclaude
- /nas/mount:/workspace # NAS mount only for project files
volumes:
holyclaude-db:# Ensure this volume is mounted (credentials live here)
volumes:
- ./data/claude:/root/.claudedocker exec holyclaude s6-svstat /run/service/cloudcli
docker exec holyclaude s6-svstat /run/service/xvfbgit clone https://github.com/CoderLuii/HolyClaude.git
cd HolyClaude
# Build full image
docker build -t holyclaude:local .
# Build slim image
docker build -t holyclaude:local-slim --target slim .
# Build for specific platform
docker buildx build --platform linux/arm64 -t holyclaude:arm64 .
# Run your local build
docker run -d \
--name holyclaude \
--shm-size=2g \
-p 3001:3001 \
-v $(pwd)/data/claude:/root/.claude \
holyclaude:local# Start
docker compose up -d
# Stop
docker compose down
# View logs (live)
docker compose logs -f holyclaude
# Shell access
docker exec -it holyclaude bash
# Update to latest
docker compose pull && docker compose up -d
# Restart only the container
docker compose restart holyclaude
# Check resource usage
docker stats holyclaude