holyclaude-ai-workstation

759installs25stars

Install to Claude Code

npx -y skills add https://github.com/aradotso/trending-skills --skill holyclaude-ai-workstation

Description

holyclaude ai workstation

SKILL.md

---
name: holyclaude-ai-workstation
description: Deploy a full AI coding workstation with Claude Code, web UI, headless browser, and 5 AI CLIs in a single Docker container
triggers:
  - set up HolyClaude
  - run Claude Code in Docker
  - AI coding workstation container
  - Claude Code web UI setup
  - deploy HolyClaude with docker compose
  - configure HolyClaude environment
  - headless browser with Claude Code
  - HolyClaude troubleshooting
---

# HolyClaude AI Workstation

> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.

HolyClaude is a containerized AI development workstation that bundles Claude Code CLI, a CloudCLI web UI, Chromium headless browser with Playwright, 5 AI CLIs (Claude, Gemini, OpenAI Codex, Cursor, TaskMaster AI), and 50+ dev tools into a single Docker image. One `docker compose up` replaces hours of manual setup.

---

## Installation

### Prerequisites
- Docker + Docker Compose installed
- Existing Anthropic account (Max/Pro subscription or API key)

### Quick Start

```bash
mkdir holyclaude && cd holyclaude
```

Create `docker-compose.yaml`:

```yaml
services:
  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=1000
```

```bash
docker compose up -d
# Open http://localhost:3001
```

### Image Variants

```bash
# 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-slim
```

---

## Full Docker Compose Configuration

```yaml
services:
  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
```

### Environment Variable Reference

| Variable | Required | Description |
|---|---|---|
| `PUID` | Recommended | Host user ID (run `id -u` to find yours) |
| `PGID` | Recommended | Host group ID (run `id -g` to find yours) |
| `ANTHROPIC_API_KEY` | Optional | Anthropic API key (alternative to OAuth login) |
| `GEMINI_API_KEY` | Optional | Google AI API key for Gemini CLI |
| `OPENAI_API_KEY` | Optional | OpenAI API key for Codex CLI |
| `CURSOR_API_KEY` | Optional | Cursor API key |
| `CHOKIDAR_USEPOLLING` | NAS only | Set `true` for SMB/NFS mounts |
| `DISCORD_WEBHOOK_URL` | Optional | Discord notifications |
| `SLACK_WEBHOOK_URL` | Optional | Slack notifications |

---

## Authentication

### Method 1: OAuth (Claude Max/Pro Subscription)
1. Open `http://localhost:3001`
2. Create a CloudCLI account (10 seconds)
3. Sign in with your Anthropic account via OAuth
4. No API key needed — uses your existing subscription

### Method 2: API Key
```yaml
environment:
  - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
```
Or paste the key directly in the CloudCLI web UI settings.

### Credential Persistence
Credentials are stored in the bind-mounted volume:
```
./data/claude/     →  /root/.claude/
./data/config/     →  /root/.config/
```
Credentials survive container restarts, updates, and recreation.

---

## Platform-Specific Configuration

### Linux (amd64/arm64) — Default
```yaml
# No extra config needed
shm_size: 2g
```

### macOS (Docker Desktop)
```yaml
# Works out of the box with Docker Desktop
shm_size: 2g
```

### Windows (WSL2 + Docker Desktop)
```yaml
# Requires WSL2 backend enabled in Docker Desktop
shm_size: 2g
```

### Synology / QNAP NAS
```yaml
environment:
  - CHOKIDAR_USEPOLLING=true    # Fixes file watching on SMB mounts
volumes:
  - /volume1/docker/holyclaude/data/claude:/root/.claude
  - /volume1/docker/holyclaude/projects:/workspace
```

### Kubernetes (ARM64 / Oracle Cloud Graviton)
```yaml
# arm64 image is published alongside amd64
image: CoderLuii/HolyClaude:latest   # multi-arch manifest auto-selects correct arch
```

---

## What's Inside the Container

### AI CLIs

| CLI | Invocation | Key Provider |
|---|---|---|
| Claude Code | `claude` | Anthropic (`ANTHROPIC_API_KEY` or OAuth) |
| Gemini CLI | `gemini` | Google (`GEMINI_API_KEY`) |
| OpenAI Codex | `codex` | OpenAI (`OPENAI_API_KEY`) |
| Cursor | `cursor` | Cursor (`CURSOR_API_KEY`) |
| TaskMaster AI | `task-master` | Uses configured AI provider keys |

### Headless Browser Stack
- **Chromium** — pre-installed and configured
- **Xvfb** — virtual display on `:99`
- **Playwright** — configured and ready
- **Shared memory** — `shm_size: 2g` pre-configured (fixes the 64MB Docker default)

### Dev Tools (50+)
- **Languages**: Node.js, Python 3, TypeScript, Bun, Deno
- **Package managers**: npm, yarn, pnpm, pip, cargo
- **Database clients**: PostgreSQL, MySQL, SQLite, Redis CLI
- **Cloud CLIs**: AWS CLI, Google Cloud SDK, Azure CLI
- **Dev tools**: GitHub CLI (`gh`), Git, curl, jq, ripgrep, fd
- **Process manager**: s6-overlay (auto-restart, graceful shutdown)

---

## Working with Projects

### Mount your project directory
```yaml
volumes:
  - ./projects:/workspace
  # Or mount a specific project:
  - /path/to/my-app:/workspace/my-app
```

### Inside the container
```bash
# 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 / Headless Browser Usage

Playwright is pre-configured. Use it from Claude Code tasks or directly:

```typescript
// 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
      ],
    },
  },
});
```

```typescript
// 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();
```

```bash
# 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"
```

---

## Updating HolyClaude

```bash
# 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
```

### Pinned Version Strategy
```yaml
# For production: pin to a specific version
image: CoderLuii/HolyClaude:1.2.3

# Update by changing the tag and running:
docker compose up -d
```

---

## Data & Persistence

```
holyclaude/
├── docker-compose.yaml
├── data/
│   ├── claude/          # Claude credentials, .claude.json, history
│   └── config/          # CloudCLI and app configuration
└── projects/            # Your workspace (mount your code here)
```

**All credentials and config survive:**
- Container restarts
- `docker compose down && up`
- Image updates via `docker compose pull`
- Container recreation

---

## Common Patterns

### Pattern: Multiple Projects
```yaml
volumes:
  - ./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
```

### Pattern: Read-only API Keys via .env file
```bash
# .env (never commit this)
ANTHROPIC_API_KEY=sk-ant-...
GEMINI_API_KEY=AIza...
OPENAI_API_KEY=sk-...
```

```yaml
# docker-compose.yaml
services:
  holyclaude:
    env_file: .env
```

### Pattern: Custom Port
```yaml
ports:
  - "8080:3001"    # Access via http://localhost:8080
```

### Pattern: Remote Server Access
```yaml
ports:
  - "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 production
```

### Pattern: Nginx Reverse Proxy
```yaml
services:
  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:
```

---

## Troubleshooting

### Container won't start
```bash
# Check logs
docker compose logs holyclaude

# Check if port 3001 is already in use
lsof -i :3001
```

### Chromium crashes / headless browser fails
```yaml
# Ensure shm_size is set (CRITICAL)
shm_size: 2g

# Ensure seccomp is unconfined
security_opt:
  - seccomp:unconfined
```

```bash
# Verify display is available inside container
docker exec holyclaude bash -c "echo $DISPLAY"
# Should output: :99
```

### Permission denied errors on bind mounts
```yaml
environment:
  - PUID=1000    # Must match your host user: `id -u`
  - PGID=1000    # Must match your host group: `id -g`
```

```bash
# Fix existing permissions on host
sudo chown -R 1000:1000 ./data ./projects
```

### File watching broken on NAS / SMB mounts
```yaml
environment:
  - CHOKIDAR_USEPOLLING=true
```

### Claude Code installer hangs
This is pre-solved in HolyClaude — the container sets the correct WORKDIR ownership. If you're building a custom image on top:
```dockerfile
# Ensure WORKDIR is not root-owned before running Claude Code installer
RUN chown -R node:node /app
WORKDIR /app
```

### SQLite locks on NAS mount
```yaml
volumes:
  # 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:
```

### Claude Code authentication lost after restart
```yaml
# Ensure this volume is mounted (credentials live here)
volumes:
  - ./data/claude:/root/.claude
```

### Process keeps dying / not restarting
HolyClaude uses s6-overlay for process supervision. Check service status:
```bash
docker exec holyclaude s6-svstat /run/service/cloudcli
docker exec holyclaude s6-svstat /run/service/xvfb
```

---

## Building Locally

```bash
git 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
```

---

## Quick Reference

```bash
# 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
```