[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-75058":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":23,"hasPages":23,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":41,"readmeContent":42,"aiSummary":43,"trendingCount":16,"starSnapshotCount":16,"syncStatus":44,"lastSyncTime":45,"discoverSource":46},75058,"HolyClaude","CoderLuii\u002FHolyClaude","CoderLuii","AI coding workstation: Claude Code + web UI + 7 AI CLIs + headless browser + 50+ tools","https:\u002F\u002Fholyclaude.coderluii.dev",null,"Dockerfile",2329,246,14,15,0,13,22,86,39,29.18,"MIT License",false,"master",[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"ai","ai-coding","anthropic","claude","claude-code","coding-agent","container","developer-tools","devtools","docker","docker-compose","gemini","headless-browser","openai","playwright","2026-06-12 02:03:32","🌍 **English** | [Español](docs\u002Ftranslations\u002FREADME.es.md) | [Français](docs\u002Ftranslations\u002FREADME.fr.md) | [Italiano](docs\u002Ftranslations\u002FREADME.it.md) | [Português](docs\u002Ftranslations\u002FREADME.pt.md) | [Deutsch](docs\u002Ftranslations\u002FREADME.de.md) | [Русский](docs\u002Ftranslations\u002FREADME.ru.md) | [हिन्दी](docs\u002Ftranslations\u002FREADME.hi.md) | [中文](docs\u002Ftranslations\u002FREADME.zh.md) | [日本語](docs\u002Ftranslations\u002FREADME.ja.md) | [한국어](docs\u002Ftranslations\u002FREADME.ko.md)\n\n# \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fblob\u002Fmaster\u002Fassets\u002Flogo.png?raw=true\" alt=\"HolyClaude\" width=\"39\" valign=\"bottom\"> \u003Ca name=\"top\">\u003C\u002Fa>HolyClaude\n\n\u003Cdiv align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fblob\u002Fmaster\u002Fassets\u002Fhero.png?raw=true\" alt=\"HolyClaude Banner\" width=\"100%\" \u002F>\n\u003C\u002Fdiv>\n\n[![License: MIT](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-MIT-yellow.svg)](https:\u002F\u002Fopensource.org\u002Flicenses\u002FMIT)\n[![Docker Pulls](https:\u002F\u002Fbadgen.net\u002Fdocker\u002Fpulls\u002Fcoderluii\u002Fholyclaude?icon=docker)](https:\u002F\u002Fhub.docker.com\u002Fr\u002Fcoderluii\u002Fholyclaude)\n[![Full Image](https:\u002F\u002Fimg.shields.io\u002Fdocker\u002Fimage-size\u002Fcoderluii\u002Fholyclaude\u002Flatest?label=full&color=blue&logo=docker)](https:\u002F\u002Fhub.docker.com\u002Fr\u002Fcoderluii\u002Fholyclaude)\n[![Slim Image](https:\u002F\u002Fimg.shields.io\u002Fdocker\u002Fimage-size\u002Fcoderluii\u002Fholyclaude\u002Fslim?label=slim&color=green&logo=docker)](https:\u002F\u002Fhub.docker.com\u002Fr\u002Fcoderluii\u002Fholyclaude)\n\u003Cbr>\n[![GitHub Stars](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fstars\u002FCoderLuii\u002FHolyClaude?style=social)](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude)\n[![Twitter Follow](https:\u002F\u002Fimg.shields.io\u002Ftwitter\u002Ffollow\u002FCoderLuii?style=social)](https:\u002F\u002Fx.com\u002FCoderLuii)\n[![PayPal](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDonate-PayPal-blue.svg)](https:\u002F\u002Fwww.paypal.com\u002Fdonate\u002F?hosted_button_id=PM2UXGVSTHDNL)\n[![Buy Me A Coffee](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FBuy%20Me%20A%20Coffee-support-yellow.svg?style=flat&logo=buy-me-a-coffee)](https:\u002F\u002Fbuymeacoffee.com\u002FCoderLuii)\n[![Website](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fwebsite-coderluii.dev-orange?logo=astro)](https:\u002F\u002Fcoderluii.dev)\n[![GitHub Release](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fv\u002Frelease\u002FCoderLuii\u002FHolyClaude?color=369eff&labelColor=black&logo=github&style=flat-square)](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Freleases)\n[![Issues](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fissues\u002FCoderLuii\u002FHolyClaude?color=ff80eb&labelColor=black&style=flat-square)](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fissues)\n[![Contributors](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fcontributors\u002FCoderLuii\u002FHolyClaude?color=c4f042&labelColor=black&style=flat-square)](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fgraphs\u002Fcontributors)\n\n### Stop configuring. Start building.\n\nOne command. Full AI development workstation. Claude Code, web UI, headless browser, 7 AI CLIs, 50+ dev tools — containerized and ready.\n\n**You were going to spend 2 hours setting this up manually. Or you could just `docker compose up`.**\n\n**Works with your existing Claude Code subscription.** Max\u002FPro plan, API key — whatever you have, it just works.\n\n---\n\n## What is this?\n\nYou know the drill. You want Claude Code. But you also want it in a browser. With a headless browser for screenshots and testing. With Playwright configured. With every AI CLI. With TypeScript, Python, deployment tools, database clients, GitHub CLI.\n\nSo you start installing things. One by one. Then Chromium won't launch because Docker's shared memory is 64MB. Then Xvfb isn't configured. Then the UID inside the container doesn't match your host and everything is permission denied. Then you realize Claude Code's installer hangs when WORKDIR is root-owned. Then SQLite locks on your NAS mount. Then—\n\n**HolyClaude is the container I built after solving every single one of those problems.**\n\nI've been running this daily on my own server for weeks. Every bug has been hit, diagnosed, and fixed. Every edge case has been handled. Every \"why doesn't this work in Docker\" has been answered.\n\nYou pull it. You run it. You open your browser. You build.\n\n### :credit_card: Use Your Existing Subscription\n\n**This runs the real Claude Code CLI.** Not a wrapper. Not a proxy. Not a knock-off.\n\nYour existing Anthropic account works directly:\n- **Claude Max\u002FPro plan** — authenticate through the web UI (OAuth), same as desktop Claude Code\n- **Anthropic API key** — set it through the web UI, same billing as always\n- **No extra cost** — HolyClaude is free and open source. You only pay Anthropic for what you use, like you already do.\n\n> HolyClaude doesn't touch your credentials. They're stored locally in your bind-mounted volume (`.\u002Fdata\u002Fclaude\u002F`), same as they would be on bare metal.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## Table of Contents\n\n| | Section |\n|---|---|\n| :zap: | [Quick Start](#zap-quick-start) |\n| :computer: | [Platform Support](#computer-platform-support) |\n| :star2: | [Why HolyClaude](#star2-why-holyclaude) |\n| :credit_card: | [Subscription & Authentication](#credit_card-subscription--authentication) |\n| :package: | [Image Variants](#package-image-variants) |\n| :whale: | [Docker Compose — Quick](#whale-docker-compose--quick) |\n| :whale2: | [Docker Compose — Full](#whale2-docker-compose--full) |\n| :wrench: | [Environment Variables](#wrench-environment-variables) |\n| :rocket: | [What's Inside](#rocket-whats-inside) |\n| :robot: | [AI CLI Providers](#robot-ai-cli-providers) |\n| :llama: | [Using Ollama](#llama-using-ollama) |\n| :building_construction: | [Architecture](#building_construction-architecture) |\n| :file_folder: | [Project Structure](#file_folder-project-structure) |\n| :floppy_disk: | [Data & Persistence](#floppy_disk-data--persistence) |\n| :lock: | [Permissions](#lock-permissions) |\n| :shield: | [Remote Access & Exposure](#shield-remote-access--exposure) |\n| :bell: | [Notifications](#bell-notifications) |\n| :arrows_counterclockwise: | [Upgrading](#arrows_counterclockwise-upgrading) |\n| :construction: | [Troubleshooting](#construction-troubleshooting) |\n| :warning: | [Known Issues](#warning-known-issues) |\n| :hammer_and_wrench: | [Building Locally](#hammer_and_wrench-building-locally) |\n| :bar_chart: | [Alternatives](#bar_chart-alternatives) |\n| :rocket: | [Roadmap](#rocket-roadmap) |\n| :trophy: | [Built with HolyClaude](#trophy-built-with-holyclaude) |\n| :handshake: | [Contributing](#handshake-contributing) |\n| :heart: | [Support](#heart-support) |\n| :scroll: | [Third-Party Software](#scroll-third-party-software) |\n| :page_facing_up: | [License](#page_facing_up-license) |\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :zap: Quick Start\n\n**1.** Create a folder for HolyClaude:\n\n```bash\nmkdir holyclaude && cd holyclaude\n```\n\n**2.** Create a `docker-compose.yaml` file. Copy one of the templates below:\n- [Quick template](#whale-docker-compose--quick) — minimal, zero config, just works\n- [Full template](#whale2-docker-compose--full) — all options, fully documented\n\n**3.** Pull and start:\n\n```bash\ndocker compose up -d\n```\n\n**4.** Open the web UI:\n\n```\nhttp:\u002F\u002Flocalhost:3001\n```\n\n**5.** Create a CloudCLI account (takes 10 seconds), sign in with your Anthropic account, and you're live.\n\n> No `.env` files. No pre-configuration. No reading 40 pages of docs before you can start. It just runs.\n\n> **Want to reach it from outside your network?** Don't port-forward it. See [Remote Access & Exposure](#shield-remote-access--exposure) — use Tailscale or Cloudflare Tunnel instead.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :computer: Platform Support\n\n| Platform | Status | Notes |\n|----------|--------|-------|\n| Linux (amd64) | ✅ Fully supported | Native performance, recommended |\n| Linux (arm64) | ✅ Fully supported | Raspberry Pi 4+, Oracle Cloud, AWS Graviton |\n| macOS (Docker Desktop) | ✅ Fully supported | Apple Silicon & Intel via Docker Desktop |\n| Windows (WSL2 + Docker Desktop) | ✅ Fully supported | Requires WSL2 backend |\n| Synology \u002F QNAP NAS | ✅ Fully supported | Use `CHOKIDAR_USEPOLLING=true` for SMB mounts |\n| Kubernetes | 🔜 Coming soon | Helm chart planned |\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :star2: Why HolyClaude\n\nI built this because I was tired of re-doing the same setup every time. Installing Claude Code, wiring up a web UI, configuring Chromium in Docker, fixing permission issues, debugging process supervision. Every time.\n\nSo I made a container that does all of it. And then I hit every possible bug so you don't have to.\n\n| | HolyClaude | Doing it yourself |\n|---|---|---|\n| **Setup** | 30 seconds | 1-2 hours (if it goes well) |\n| **Claude Code** | Pre-installed, pre-configured, ready | Install, configure, debug installer hanging, fix WORKDIR |\n| **Web UI** | CloudCLI included with plugins | Find a web UI, install it, configure it, wire it to Claude |\n| **Headless browser** | Chromium + Xvfb + Playwright, configured | Install Chromium, install Xvfb, configure display :99, fix shm, fix sandbox, fix seccomp... |\n| **AI CLIs** | 7 providers, one container | Install each one separately across 3 package managers |\n| **Dev tools** | 50+ tools, ready | `apt-get install` \u002F `npm i -g` \u002F `pip install` for the next hour |\n| **Process management** | s6-overlay (auto-restart, graceful shutdown) | Write your own supervisord config or hope Docker restart works |\n| **Persistence** | Bind mounts, credentials survive everything | Figure out Docker volumes, debug \"why is this a directory not a file\" |\n| **Updates** | `docker pull && docker compose up -d` | Update 50 tools manually, pray nothing breaks |\n| **Multi-arch** | AMD64 + ARM64 | Pray your Dockerfile builds on ARM |\n\n**The last row of every manual setup is \"works on my machine.\"** HolyClaude works on every machine.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :credit_card: Subscription & Authentication\n\nHolyClaude runs the **official Claude Code CLI** from Anthropic. Your existing account works out of the box.\n\n### What works:\n\n| Authentication method | How | Cost |\n|----------------------|-----|------|\n| **Claude Max\u002FPro plan** (subscription) | Sign in through CloudCLI web UI — same OAuth flow as desktop | Your existing subscription, no extra charge |\n| **Anthropic API key** | Paste your API key in the web UI | Pay-per-use, same Anthropic billing |\n\n### What doesn't work:\n\n| | Why |\n|---|---|\n| OpenAI API key for Claude | Different company, different API. OpenAI keys work with the **Codex CLI** (also pre-installed) |\n\n> **ChatGPT Plus\u002FPro subscribers:** Your subscription works with the **Codex CLI**. Run `codex login --device-auth` inside the container to authenticate with your ChatGPT account. If you need Codex's browser callback flow from your host, expose port `1455` in the full compose template below.\n\n### Other AI CLIs included:\n\n| CLI | What you need |\n|-----|--------------|\n| Gemini CLI | Google AI API key (`GEMINI_API_KEY`) |\n| OpenAI Codex | OpenAI API key (`OPENAI_API_KEY`) or ChatGPT Plus\u002FPro subscription (`codex login --device-auth`) |\n| Cursor | Cursor API key (`CURSOR_API_KEY`) |\n| TaskMaster AI | Uses your AI provider keys (Anthropic, OpenAI, etc.) |\n| Junie | JetBrains account (JetBrains AI subscription) |\n| OpenCode | Configure via `opencode` TUI (supports multiple providers) |\n\n> **HolyClaude is free and open source.** You only pay your AI providers for usage, same as you already do. We don't proxy, intercept, or touch your credentials. They live in your local bind mount.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :package: Image Variants\n\nTwo flavors. Same quality. Pick your weight class.\n\n| Tag | What you get | Best for |\n|-----|-------------|----------|\n| **`latest`** | Everything pre-installed — every tool, every library, every CLI | Most users. Zero wait time. Claude never has to stop and install something. |\n| **`slim`** | Core tools only — Claude installs extras on-demand | Smaller VPS, limited disk, metered bandwidth |\n| `X.Y.Z` | Full image, pinned version | Production stability — you control when to update |\n| `X.Y.Z-slim` | Slim image, pinned version | Production + small footprint |\n\n```bash\n# Full — batteries included (recommended)\ndocker pull coderluii\u002Fholyclaude\n\n# Slim — lean and mean\ndocker pull coderluii\u002Fholyclaude:slim\n```\n\n> **`latest` is always the full image.** Slim users: don't worry — when you ask Claude to do something that needs a missing tool, it installs it in seconds. You get the same capabilities, just with a smaller initial download.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :whale: Docker Compose — Quick\n\nThe \"I just want it running\" template. Copy this entire block into a `docker-compose.yaml` file:\n\n```yaml\n# ==============================================================================\n# HolyClaude — Quick Start\n# Just run: docker compose up -d\n# Then open: http:\u002F\u002Flocalhost:3001\n# ==============================================================================\n\nservices:\n  holyclaude:\n    image: coderluii\u002Fholyclaude:latest     # Full image (use :slim for smaller download)\n    container_name: holyclaude\n    hostname: holyclaude\n    restart: unless-stopped\n    shm_size: 2g                           # Chromium needs this — don't remove\n    network_mode: bridge\n    cap_add:\n      - SYS_ADMIN                          # Required: Chromium sandboxing\n      - SYS_PTRACE                         # Required: debugging tools\n    security_opt:\n      - seccomp=unconfined                 # Required: Chromium in Docker\n    ports:\n      - \"3001:3001\"                        # CloudCLI web UI\n    volumes:\n      #\n      # .\u002Fdata\u002Fclaude — Your settings, credentials, API keys, and Claude's memory.\n      #                  This is what survives container rebuilds.\n      #                  NEVER delete this folder — your auth lives here.\n      #\n      - .\u002Fdata\u002Fclaude:\u002Fhome\u002Fclaude\u002F.claude\n      #\n      # .\u002Fworkspace — Your code. All projects go here.\n      #               Bind-mounted so you can access files from your host.\n      #\n      - .\u002Fworkspace:\u002Fworkspace\n    environment:\n      - TZ=UTC                             # Your timezone (e.g., America\u002FNew_York, Europe\u002FLondon)\n```\n\nThen:\n\n```bash\ndocker compose up -d\n```\n\nOpen `http:\u002F\u002Flocalhost:3001`. Create a CloudCLI account. Sign in with your Anthropic account. Build something.\n\n**That's the whole setup. You're done.**\n\n> **Why `SYS_ADMIN` + `seccomp=unconfined`?** Chromium needs these to run inside Docker — it's standard for any containerized browser (Playwright docs, Puppeteer docs, every CI pipeline that runs browser tests). Without them, Chromium crashes on startup. This is not a security risk unique to HolyClaude.\n\n> **Why `shm_size: 2g`?** Docker gives containers 64MB of shared memory by default. Chromium uses `\u002Fdev\u002Fshm` heavily for tab rendering. At 64MB, tabs crash randomly. 2GB is the recommended minimum for any Chromium-in-Docker setup.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :whale2: Docker Compose — Full\n\nSame image, every knob exposed. Copy this entire block into a `docker-compose.yaml` file:\n\n```yaml\n# ==============================================================================\n# HolyClaude — Full Configuration\n# All options documented inline.\n# Detailed docs: https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fblob\u002Fmaster\u002Fdocs\u002Fconfiguration.md\n# ==============================================================================\n\nservices:\n  holyclaude:\n    image: coderluii\u002Fholyclaude:latest     # Full image (use :slim for smaller download)\n    container_name: holyclaude\n    hostname: holyclaude\n    restart: unless-stopped\n    shm_size: 2g                           # Chromium shared memory — increase to 4g for heavy browser use\n    network_mode: bridge\n    cap_add:\n      - SYS_ADMIN                          # Required: Chromium sandboxing\n      - SYS_PTRACE                         # Required: debugging tools (strace, lsof)\n    security_opt:\n      - seccomp=unconfined                 # Required: Chromium syscall requirements\n    ports:\n      #\n      # CloudCLI web UI — this is the only port you need.\n      # Override the host-side port from `.env` if 3001 is already in use.\n      #\n      - \"${HOLYCLAUDE_HOST_PORT:-3001}:3001\"\n      #\n      # Dev server ports — uncomment as needed.\n      # These let you access dev servers running inside the container from your host browser.\n      #\n      # - \"3000:3000\"                      # Next.js \u002F Express\n      # - \"4321:4321\"                      # Astro\n      # - \"5173:5173\"                      # Vite\n      # - \"8787:8787\"                      # Wrangler (Cloudflare Workers)\n      # - \"9229:9229\"                      # Node.js debugger\n      # - \"1455:1455\"                      # Codex auth callback port\n    volumes:\n      #\n      # PERSISTENT DATA\n      #\n      # .\u002Fdata\u002Fclaude — Settings, credentials, API keys, Claude's memory file.\n      #                  Survives container rebuilds. NEVER delete this folder.\n      #                  Override the host path from `.env` if you want it elsewhere.\n      #\n      - ${HOLYCLAUDE_HOST_CLAUDE_DIR:-.\u002Fdata\u002Fclaude}:\u002Fhome\u002Fclaude\u002F.claude\n      #\n      # .\u002Fworkspace — Your code and projects. Everything you build goes here.\n      #               Accessible from your host machine.\n      #               Override the host path from `.env` if you want a different root.\n      #\n      - ${HOLYCLAUDE_HOST_WORKSPACE_DIR:-.\u002Fworkspace}:\u002Fworkspace\n    environment:\n      #\n      # TIMEZONE\n      # Full list: https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FList_of_tz_database_time_zones\n      #\n      - TZ=UTC\n      #\n      # PERFORMANCE\n      # Node.js heap memory limit in MB. Increase if you work on large monorepos\n      # and hit out-of-memory errors. 4096 (4GB) is a solid default.\n      #\n      - NODE_OPTIONS=--max-old-space-size=4096\n      #\n      # USER MAPPING\n      # Match these to your host user so files created inside the container\n      # have the right ownership on your host. Run `id -u` and `id -g` on your host.\n      #\n      - PUID=1000\n      - PGID=1000\n      #\n      # SMB\u002FCIFS NETWORK MOUNTS\n      # Only enable these if your volumes are on a NAS, Samba share, or CIFS mount.\n      # They enable polling-based file watching since network mounts don't support inotify.\n      # Leave commented out for local storage — polling uses more CPU.\n      #\n      # - CHOKIDAR_USEPOLLING=1\n      # - WATCHFILES_FORCE_POLLING=true\n      #\n      # NOTIFICATIONS (optional)\n      # Get notified when Claude finishes a task or hits an error.\n      # Uses Apprise — supports 100+ services. Also requires creating a flag file\n      # inside the container: touch ~\u002F.claude\u002Fnotify-on\n      #\n      # - NOTIFY_DISCORD=discord:\u002F\u002Fwebhook_id\u002Fwebhook_token\n      # - NOTIFY_TELEGRAM=tg:\u002F\u002Fbot_token\u002Fchat_id\n      # - NOTIFY_PUSHOVER=pover:\u002F\u002Fuser_key@app_token\n      # - NOTIFY_SLACK=slack:\u002F\u002Ftoken_a\u002Ftoken_b\u002Ftoken_c\n      # - NOTIFY_EMAIL=mailto:\u002F\u002Fuser:pass@gmail.com?to=you@gmail.com\n      # - NOTIFY_GOTIFY=gotify:\u002F\u002Fhostname\u002Ftoken\n      # - NOTIFY_URLS=                                   # catch-all: comma-separated Apprise URLs\n      #\n      # AI PROVIDER KEYS (optional)\n      # Claude Code can authenticate via web UI (OAuth) or ANTHROPIC_API_KEY.\n      # Set these if you want to use additional AI CLIs or API-based auth.\n      #\n      # - GEMINI_API_KEY=your_key\n      # - OPENAI_API_KEY=your_key\n      # - CURSOR_API_KEY=your_key\n```\n\nThen:\n\n```bash\ndocker compose up -d\n```\n\nIf you want to change the host-side port or bind-mount paths without editing compose, copy `.env.example` to `.env` and set:\n\n```dotenv\nHOLYCLAUDE_HOST_PORT=3003\nHOLYCLAUDE_HOST_CLAUDE_DIR=.\u002Fdata\u002Fclaude\nHOLYCLAUDE_HOST_WORKSPACE_DIR=.\u002Fworkspace\n```\n\nThese values are read by Docker Compose on the host. They are not container environment variables.\n\n### What each section controls:\n\n| Section | What it does | When to change it |\n|---------|-------------|-------------------|\n| **Timezone** | Container clock | Always — set to your local TZ |\n| **Performance** | Node.js memory ceiling | Only if you hit OOM errors on large projects |\n| **User mapping** | File permissions between container and host | If you get \"permission denied\" (`id -u` and `id -g` on your host) |\n| **SMB\u002FCIFS** | File watcher polling mode | Only if your volumes live on a NAS or network share |\n| **Notifications** | Push alerts via Apprise (Discord, Telegram, Slack, Email, 100+ services) | If you want to walk away and know when your AI agents are done |\n| **AI providers** | API keys for Gemini, Codex, Cursor, Junie, OpenCode | If you want to use AI CLIs other than Claude |\n\n> **Every single environment variable is optional.** The container runs perfectly with just `TZ=UTC`. Everything else has sensible defaults or is handled through the web UI.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :wrench: Environment Variables\n\nThe complete reference. Every variable, what it defaults to, what it does.\n\n| Variable | Default | What it does |\n|----------|---------|--------------|\n| `TZ` | `UTC` | Container timezone |\n| `PUID` | `1000` | Container user ID — match your host to avoid permission issues |\n| `PGID` | `1000` | Container group ID — match your host to avoid permission issues |\n| `NODE_OPTIONS` | `--max-old-space-size=4096` | Node.js heap memory limit in MB |\n| `GIT_USER_NAME` | `HolyClaude User` | Git commit author (set once on first boot) |\n| `GIT_USER_EMAIL` | `noreply@holyclaude.local` | Git commit email (set once on first boot) |\n| `CHOKIDAR_USEPOLLING` | *(unset)* | Set to `1` for SMB\u002FCIFS — enables polling file watchers |\n| `WATCHFILES_FORCE_POLLING` | *(unset)* | Set to `true` for SMB\u002FCIFS — enables Python polling |\n| `NOTIFY_DISCORD` | *(unset)* | Discord webhook URL for notifications |\n| `NOTIFY_TELEGRAM` | *(unset)* | Telegram bot URL for notifications |\n| `NOTIFY_PUSHOVER` | *(unset)* | Pushover URL for notifications |\n| `NOTIFY_SLACK` | *(unset)* | Slack webhook URL for notifications |\n| `NOTIFY_EMAIL` | *(unset)* | Email (SMTP) URL for notifications |\n| `NOTIFY_GOTIFY` | *(unset)* | Gotify URL for notifications |\n| `NOTIFY_URLS` | *(unset)* | Catch-all — comma-separated [Apprise URLs](https:\u002F\u002Fgithub.com\u002Fcaronc\u002Fapprise\u002Fwiki) |\n| `ANTHROPIC_API_KEY` | *(unset)* | Anthropic API key (alternative to web UI OAuth) |\n| `ANTHROPIC_AUTH_TOKEN` | *(unset)* | Anthropic auth token (alternative to API key, or set to `ollama` for Ollama) |\n| `ANTHROPIC_BASE_URL` | *(unset)* | Custom Anthropic API endpoint (proxies, private deployments, or Ollama's Anthropic-compatible API) |\n| `CLAUDE_CODE_USE_BEDROCK` | *(unset)* | Set to `1` to use Amazon Bedrock backend |\n| `CLAUDE_CODE_USE_VERTEX` | *(unset)* | Set to `1` to use Google Vertex AI backend |\n| `GEMINI_API_KEY` | *(unset)* | Google Gemini API key |\n| `OPENAI_API_KEY` | *(unset)* | OpenAI API key (for Codex CLI, or use `codex login --device-auth` for ChatGPT subscription) |\n| `CURSOR_API_KEY` | *(unset)* | Cursor API key |\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :rocket: What's Inside\n\nThis is not a minimal container. This is an entire development workstation.\n\n### Both variants (full + slim)\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Node.js 22 LTS + npm global packages\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n| Package | What it's for |\n|---------|---------------|\n| `typescript`, `tsx` | TypeScript compilation and execution |\n| `pnpm` | Fast, disk-efficient package manager |\n| `vite`, `esbuild` | Lightning-fast build tools |\n| `eslint`, `prettier` | Code quality and formatting |\n| `serve`, `nodemon` | Static file server, auto-restart dev server |\n| `concurrently` | Run multiple scripts in parallel |\n| `dotenv-cli` | Load env vars from `.env` files |\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Python 3 packages\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n| Package | What it's for |\n|---------|---------------|\n| `requests`, `httpx` | HTTP clients |\n| `beautifulsoup4`, `lxml` | Web scraping and HTML parsing |\n| `Pillow` | Image processing (pre-compiled — no waiting) |\n| `pandas`, `numpy` | Data manipulation (pre-compiled — seriously, you don't want to pip install these at runtime) |\n| `openpyxl` | Read\u002Fwrite Excel files |\n| `python-docx` | Read\u002Fwrite Word documents |\n| `jinja2`, `markdown` | Templating and markdown rendering |\n| `pyyaml`, `python-dotenv` | Config file parsing |\n| `rich`, `click`, `tqdm` | Beautiful CLIs and progress bars |\n| `playwright` | Browser automation (Chromium already configured and ready) |\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>System tools\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n| Tool | What it's for |\n|------|---------------|\n| `git`, `gh` | Version control + GitHub CLI (PRs, issues, releases from the terminal) |\n| `ripgrep` (`rg`), `fd`, `fzf` | Blazing-fast search — Claude uses these constantly |\n| `bat`, `tree`, `jq` | Better cat (syntax highlighting), directory trees, JSON processing |\n| `curl`, `wget` | HTTP downloads |\n| `tmux` | Terminal multiplexer — run things in the background |\n| `htop`, `lsof`, `strace` | Process monitoring and debugging |\n| `imagemagick` | Image conversion (`convert`, `identify`, `mogrify`) |\n| `chromium` | Headless browser — screenshots, Playwright, Lighthouse |\n| `psql`, `redis-cli`, `sqlite3` | Talk to databases directly |\n| `openssh-client` | SSH into things |\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>AI CLIs — every major provider\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n| CLI | Command | What it's for |\n|-----|---------|---------------|\n| **Claude Code** | `claude` | The main event — you're running inside this |\n| **Gemini CLI** | `gemini` | Google's AI coding agent |\n| **OpenAI Codex** | `codex` | OpenAI's coding agent |\n| **Cursor** | `cursor` | Cursor's AI agent |\n| **TaskMaster AI** | `task-master` | Task planning and orchestration |\n| **Junie** | `junie` | JetBrains' AI coding agent |\n| **OpenCode** | `opencode` | Open source AI agent (multiple providers) |\n\nSeven AI CLIs. One container. Switch between them instantly. No other Docker image does this.\n\n\u003C\u002Fdetails>\n\n### Full image only (additional packages)\n\nThe full image includes everything above, plus:\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Additional npm packages — deployment, ORMs, performance\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n| Package | What it's for |\n|---------|---------------|\n| `wrangler`, `@cloudflare\u002Fnext-on-pages` | Cloudflare Workers deployment |\n| `vercel` | Vercel deployment |\n| `netlify-cli` | Netlify deployment |\n| `az` | Azure CLI for cloud deployment and management |\n| `prisma`, `drizzle-kit` | The two most popular Node.js ORMs |\n| `pm2` | Production process manager |\n| `eas-cli` | Expo \u002F React Native builds |\n| `lighthouse`, `@lhci\u002Fcli` | Performance auditing (Chromium is already there) |\n| `sharp-cli` | Image processing CLI |\n| `json-server`, `http-server` | Mock REST APIs, static file serving |\n| `@marp-team\u002Fmarp-cli` | Markdown to presentation slides |\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Additional Python packages — PDFs, data viz, web frameworks\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n| Package | What it's for |\n|---------|---------------|\n| `reportlab`, `weasyprint`, `cairosvg`, `fpdf2`, `PyMuPDF`, `pdfkit`, `img2pdf` | Every major PDF library. Generate them, read them, convert them, merge them. |\n| `xlsxwriter`, `xlrd` | Excel formats beyond what openpyxl covers |\n| `matplotlib`, `seaborn` | Data visualization and charts |\n| `python-pptx` | PowerPoint generation |\n| `fastapi`, `uvicorn` | Python web framework |\n| `httpie` | Human-friendly HTTP client (like curl but readable) |\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Additional system packages — media, documents\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n| Package | What it's for |\n|---------|---------------|\n| `pandoc` | Convert between any document format (markdown, HTML, PDF, docx, epub...) |\n| `ffmpeg` | Video and audio processing (extract, convert, transcode) |\n| `libvips-dev` | High-performance image processing library |\n\n\u003C\u002Fdetails>\n\n> **Slim users:** Missing a package? Ask Claude. It installs npm\u002Fpip packages in seconds. System packages (pandoc, ffmpeg) take 1-2 minutes. You get the same capabilities — the full image just has zero wait time.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :robot: AI CLI Providers\n\nSeven AI CLIs. One container. No other Docker image gives you this.\n\n| Provider | Command | How to authenticate | Subscription works? |\n|----------|---------|--------------------|--------------------|\n| **Claude Code** | `claude` | CloudCLI web UI (OAuth) | **Yes** — Max\u002FPro plan or API key |\n| **Gemini CLI** | `gemini` | `GEMINI_API_KEY` env var | API key (pay-per-use) |\n| **OpenAI Codex** | `codex` | `OPENAI_API_KEY` or `codex login --device-auth` | **Yes** — ChatGPT Plus\u002FPro\u002FTeam\u002FEnterprise or API key |\n| **Cursor** | `cursor` | `CURSOR_API_KEY` env var | API key |\n| **TaskMaster AI** | `task-master` | Uses existing AI provider keys | Works with configured keys |\n| **Junie** | `junie` | JetBrains AI subscription | JetBrains account required |\n| **OpenCode** | `opencode` | Configure via TUI | Supports multiple providers |\n\n> Claude Code is the primary CLI. The others are there because sometimes you want a second opinion, or a specific model's strengths, or you're comparing outputs. Having all of them one `Tab` away is the whole point.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :llama: Using Ollama\n\nHolyClaude works with [Ollama](https:\u002F\u002Follama.com) as an alternative to an Anthropic subscription. The supported setup path is `ANTHROPIC_AUTH_TOKEN=ollama` plus `ANTHROPIC_BASE_URL=\u003Cyour Ollama endpoint>`.\n\nSee the full setup guide: **[docs\u002Follama.md](docs\u002Follama.md)**\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :building_construction: Architecture\n\n```mermaid\ngraph TB\n    subgraph Docker Container\n        EP[\"entrypoint.sh\"] --> BS[\"bootstrap.sh\\n(first boot only)\"]\n        EP --> S6[\"s6-overlay\\n(PID 1)\"]\n        S6 --> CC[\"CloudCLI\\n(:3001)\"]\n        S6 --> XV[\"Xvfb\\n(:99)\"]\n        CC --> CLAUDE[\"Claude Code CLI\"]\n        CLAUDE --> TOOLS[\"Dev Tools\\n(Node, Python, Git...)\"]\n        CLAUDE --> CHROME[\"Chromium\\n(headless)\"]\n        XV -.-> CHROME\n    end\n\n    subgraph Host\n        DATA[\".\u002Fdata\u002Fclaude\"] -.->|bind mount| HOME[\"~\u002F.claude\"]\n        WS[\".\u002Fworkspace\"] -.->|bind mount| WORK[\"\u002Fworkspace\"]\n    end\n\n    USER[\"Browser\"] -->|\":3001\"| CC\n\n    style S6 fill:#2d3748,color:#fff\n    style CC fill:#6366f1,color:#fff\n    style CLAUDE fill:#f59e0b,color:#000\n```\n\n### How the pieces fit together\n\n1. **Container starts** — `entrypoint.sh` runs as root. Remaps UID\u002FGID to match your host user, pre-creates required files (preventing Docker's \"create it as a directory\" bug), checks if this is a first boot.\n\n2. **First boot only** — `bootstrap.sh` runs once. Copies default settings, memory template, configures git identity. Creates a sentinel file (`.holyclaude-bootstrapped`) so it never runs again. Your customizations are safe from that point on.\n\n3. **s6-overlay takes over as PID 1** — This isn't supervisord. It's [s6-overlay](https:\u002F\u002Fgithub.com\u002Fjust-containers\u002Fs6-overlay), purpose-built for Docker. Supervises CloudCLI and Xvfb. Auto-restarts on crash. Forwards signals. Reaps zombies. Shuts down gracefully.\n\n4. **CloudCLI serves the web UI** — Port 3001. Browser-based interface to Claude Code with project management, multiple sessions, and plugins (project stats + web terminal included).\n\n5. **Xvfb provides a virtual display** — Chromium needs a screen to render to, even in \"headless\" mode. Xvfb gives it a 1920x1080 virtual display at `:99`. This is why Playwright, screenshots, and Lighthouse all work out of the box.\n\nSee [docs\u002Farchitecture.md](docs\u002Farchitecture.md) for the full technical deep-dive — including why we chose s6 over supervisord, why plugins are baked into the image, and why `runuser` instead of `su`.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :file_folder: Project Structure\n\n```\nholyclaude\u002F\n├── .github\u002F                 # CI\u002FCD workflows, issue & PR templates\n│   ├── FUNDING.yml          # Sponsor\u002Fdonation links\n│   ├── ISSUE_TEMPLATE\u002F      # Bug report, feature request, package request\n│   ├── pull_request_template.md\n│   ├── SECURITY.md          # Security policy\n│   └── workflows\u002F           # Docker build & push automation\n├── assets\u002F                  # Logo and banner images\n├── config\u002F                  # Claude Code configuration\n│   ├── claude-memory-full.md\n│   ├── claude-memory-slim.md\n│   └── settings.json\n├── docs\u002F                    # Extended documentation\n│   ├── architecture.md\n│   ├── CHANGELOG.md\n│   ├── configuration.md\n│   ├── dockerhub-description.md\n│   ├── ollama.md\n│   └── troubleshooting.md\n├── scripts\u002F                 # Container lifecycle scripts\n│   ├── bootstrap.sh         # First-run setup\n│   ├── entrypoint.sh        # Container entrypoint\n│   └── notify.py            # Notification helper (Apprise)\n├── s6-overlay\u002F              # Process supervision (s6-rc services)\n├── Dockerfile               # Single-stage build\n├── docker-compose.yaml      # Quick start (minimal config)\n├── docker-compose.full.yaml # Full config (all options)\n├── LICENSE\n└── README.md\n```\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :floppy_disk: Data & Persistence\n\n| What | Where (container) | Where (host) | Survives rebuild? |\n|------|-------------------|-------------|-------------------|\n| Settings, credentials, API keys | `\u002Fhome\u002Fclaude\u002F.claude` | `.\u002Fdata\u002Fclaude` | **Yes** |\n| Claude Code session (OAuth, onboarding) | `\u002Fhome\u002Fclaude\u002F.claude.json` | `.\u002Fdata\u002Fclaude\u002F.claude.json.persist` | **Yes** |\n| Your code and projects | `\u002Fworkspace` | `.\u002Fworkspace` | **Yes** |\n| CloudCLI account | `\u002Fhome\u002Fclaude\u002F.cloudcli` | *(container only by default — see below)* | No (opt-in available) |\n\n### What survives `docker compose down && docker compose up`:\n- Your Anthropic authentication and API keys\n- Claude Code settings, memory (`CLAUDE.md`), and OAuth session (no re-login)\n- All your code in `.\u002Fworkspace`\n- Git configuration\n- Codex, Gemini, and Cursor CLI auth (since v1.1.7)\n\n### What you'll redo (10 seconds):\n- CloudCLI web account — quick signup, that's it (unless you opt into persistence below)\n\n### Re-triggering first-boot setup:\n```bash\n# Delete the sentinel file — NOT the whole folder\nrm .\u002Fdata\u002Fclaude\u002F.holyclaude-bootstrapped\ndocker compose restart holyclaude\n```\n\n> **Never delete `.\u002Fdata\u002Fclaude\u002F` entirely.** That's where your credentials live. Delete the sentinel file if you want a fresh bootstrap. Delete specific config files if you want to reset settings. But never nuke the whole folder.\n\n### Persisting the CloudCLI account (optional, local storage only)\n\nBy default, the CloudCLI account database (`~\u002F.cloudcli`) is container-local and gets wiped on rebuild. Re-creating the account takes 10 seconds, so most people leave it as-is.\n\nIf you want it to survive rebuilds, add a **named Docker volume** to your compose file:\n\n```yaml\nservices:\n  holyclaude:\n    volumes:\n      - .\u002Fdata\u002Fclaude:\u002Fhome\u002Fclaude\u002F.claude\n      - .\u002Fworkspace:\u002Fworkspace\n      - cloudcli-data:\u002Fhome\u002Fclaude\u002F.cloudcli   # add this line\n\nvolumes:\n  cloudcli-data:                                # and this block\n```\n\n> **Do NOT bind-mount `.\u002Fdata\u002Fcloudcli` on a network share (NAS, SMB\u002FCIFS, NFS).** CloudCLI stores its account in SQLite, and SQLite's file locking breaks on network mounts. You'll hit `database is locked` errors constantly. Named volumes live on the Docker engine's local filesystem, which is why this works — bind mounts pointing at a NAS will not.\n\nA bind mount to a local SSD path is fine too, just keep it off any network share.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :lock: Permissions\n\nClaude Code runs in **`allowEdits`** mode by default. This is the safest useful setting:\n\n| Action | Allowed? |\n|--------|----------|\n| Read files | Yes |\n| Edit \u002F create files | Yes |\n| Run shell commands | **Asks you first** |\n| Install packages | **Asks you first** |\n\n### Want full bypass? (power users)\n\nThis is how I personally run it. Edit `.\u002Fdata\u002Fclaude\u002Fsettings.json` on your host:\n\n```json\n{\n  \"permissions\": {\n    \"defaultMode\": \"bypassPermissions\"\n  }\n}\n```\n\n> **Bypass mode means Claude executes any command without confirmation.** Fast, powerful, and exactly what you want if you trust what you're building. But `allowEdits` is the safe default for a reason.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :shield: Remote Access & Exposure\n\nHolyClaude binds CloudCLI to port `3001`. By default that's local-only — fine for running on your laptop or a home server you SSH into.\n\n**The moment you want to reach it from outside your network, read this section.**\n\n### Don't port-forward it to the public internet\n\nI'll say it flat out: do not punch a hole in your router and expose `3001` to the open internet. Not even with a password. Here's why:\n\n- CloudCLI exposes a full shell through the web terminal plugin\n- It can run arbitrary code, install packages, and read\u002Fwrite your entire `\u002Fworkspace`\n- It holds your Anthropic OAuth tokens and API keys\n- Basic auth \u002F app-level passwords get brute-forced, credential-stuffed, and scraped out of logs\n- One leaked password = someone else has a paid Claude Code instance running on your box with your money\n\nA password is a speed bump, not a door. Treat HolyClaude like you'd treat an SSH session: never on the open internet without a proper tunnel in front of it.\n\n### Use a proper tunnel instead\n\nThese are the two options I actually recommend:\n\n| Option | Who it's for | Why |\n|--------|-------------|-----|\n| **[Tailscale](https:\u002F\u002Ftailscale.com)** | Personal use, small teams | WireGuard mesh VPN. Install Tailscale on your server + your laptop\u002Fphone, and you reach `http:\u002F\u002Fholyclaude:3001` from anywhere as if you were on the LAN. No ports opened, no DNS, no certs. Free for personal use. |\n| **[Cloudflare Tunnel](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fconnections\u002Fconnect-networks\u002F)** | Sharing with others, public hostname | Cloudflare proxies the connection, so port `3001` stays closed. You get a real domain with HTTPS, and you can put Cloudflare Access (Google\u002FGitHub SSO) in front of it. Free tier covers most personal use. |\n\nBoth give you:\n- Zero open ports on your router\n- Encrypted transport end to end\n- Real identity-based auth (not a shared password)\n- Audit logs\n\n### If you insist on exposing it directly (please don't)\n\nIf you absolutely have to skip the tunnel (self-hosting tutorial, isolated lab network, whatever), at the very minimum:\n\n1. **Put a reverse proxy in front of it** (Caddy, nginx, Traefik) with real TLS\n2. **Add IP allowlisting** at the firewall or proxy level — only your known IPs\n3. **Enable `bypassPermissions: false`** (the default) so shell commands still prompt\n4. **Rotate your Anthropic credentials** if anything looks off\n5. **Run behind Cloudflare Access or similar SSO**, not basic auth\n\nEven with all that, the risk surface is huge. Use Tailscale or Cloudflare Tunnel. They're free, they take five minutes to set up, and they're what I personally use.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :bell: Notifications\n\nWalk away from your computer and know when your AI agents are done. Claude Code, Codex, and Gemini CLI all send notifications when a task completes. Uses [Apprise](https:\u002F\u002Fgithub.com\u002Fcaronc\u002Fapprise) — supports 100+ services including Discord, Telegram, Slack, Email, Pushover, Gotify, and more.\n\n**To enable:**\n\n1. Add one or more `NOTIFY_*` variables to your compose `environment`:\n   ```yaml\n   - NOTIFY_DISCORD=discord:\u002F\u002Fwebhook_id\u002Fwebhook_token\n   - NOTIFY_TELEGRAM=tg:\u002F\u002Fbot_token\u002Fchat_id\n   ```\n2. Inside the container: `touch ~\u002F.claude\u002Fnotify-on`\n\nSee [configuration docs](docs\u002Fconfiguration.md#notifications-apprise) for all supported variables and URL formats.\n\n**To disable:** `rm ~\u002F.claude\u002Fnotify-on`\n\n**Events that trigger notifications:**\n| Event | What happened |\n|-------|--------------|\n| `stop` | Claude Code, Codex, or Gemini finished the current task |\n| `error` | A tool use failure occurred |\n\n> Completely silent when not configured. No `NOTIFY_*` vars set? No flag file? Zero network calls. Zero log spam. Zero overhead.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :arrows_counterclockwise: Upgrading\n\n```bash\n# Pull the latest image\ndocker compose pull\n\n# Recreate the container with the new image\ndocker compose up -d\n```\n\nYour data persists in `.\u002Fdata\u002Fclaude` and `.\u002Fworkspace` — upgrading only replaces the container, not your files.\n\nTo pin a specific version instead of `latest`:\n\n```yaml\nimage: coderluii\u002Fholyclaude:1.1.2   # instead of :latest\n```\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :construction: Troubleshooting\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>CloudCLI shows wrong default directory\u003C\u002Fstrong>\u003C\u002Fsummary>\n\nCloudCLI opens to `\u002Fhome\u002Fclaude` instead of `\u002Fworkspace`.\n\n**Cause:** `WORKSPACES_ROOT` not reaching the CloudCLI process. Docker-compose env vars don't pass through s6-overlay's `s6-setuidgid` — it runs with a clean environment by design (security feature, not a bug).\n\n**Fix:** Already handled in HolyClaude. The s6 run script sets `WORKSPACES_ROOT=\u002Fworkspace` directly in the process environment.\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>SQLite \"database is locked\"\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n**Cause:** SQLite databases on SMB\u002FCIFS network mounts. CIFS doesn't support the file-level locking SQLite requires.\n\n**Fix:** Don't store SQLite databases on network shares. HolyClaude keeps `.cloudcli` in container-local storage for exactly this reason. If you have your own SQLite databases in `\u002Fworkspace` on a NAS, move them to a local path.\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Chromium crashes \u002F blank pages \u002F tab failures\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n**Cause:** Insufficient shared memory. Docker defaults to 64MB.\n\n**Fix:** Ensure `shm_size: 2g` in your compose file. For heavy browser use (many tabs, complex pages), increase to `4g`.\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>File watchers not detecting changes (hot reload broken)\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n**Cause:** SMB\u002FCIFS network mounts don't support `inotify`.\n\n**Fix:** Enable polling in your compose environment:\n```yaml\n- CHOKIDAR_USEPOLLING=1\n- WATCHFILES_FORCE_POLLING=true\n```\nNote: Polling uses more CPU than inotify. Only enable on network mounts.\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Permission denied errors\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n**Cause:** Container UID\u002FGID doesn't match host file ownership.\n\n**Fix:**\n```bash\n# On your host machine\nid -u  # → this is your PUID\nid -g  # → this is your PGID\n```\nSet them in your compose file:\n```yaml\n- PUID=1000\n- PGID=1000\n```\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Docker creates .claude.json as a directory\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n**Cause:** If a bind-mount target file doesn't exist before container start, Docker helpfully creates it as a directory. Thanks, Docker.\n\n**Fix:** Already handled — `entrypoint.sh` pre-creates it as a file.\n\u003C\u002Fdetails>\n\nSee [docs\u002Ftroubleshooting.md](docs\u002Ftroubleshooting.md) for the complete guide including all SMB\u002FCIFS gotchas and the full history of bugs we encountered and fixed.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :warning: Known Issues\n\nThese are not HolyClaude bugs — they're upstream issues or intentional trade-offs.\n\n| Issue | Why | Workaround |\n|-------|-----|------------|\n| \"Continue in Shell\" button broken | CloudCLI upstream bug (race condition in terminal init) | Use the **Web Terminal** plugin instead (pre-installed) |\n| Cursor CLI \"Command timeout\" | No API key configured — cosmetic only, doesn't affect anything | Set `CURSOR_API_KEY` or ignore |\n| CloudCLI account lost on rebuild | SQLite can't persist on network mounts — intentional trade-off | Re-create account (~10 seconds) |\n| Web push notifications \"not supported\" | Browser limitation in CloudCLI, standard behavior | Use Apprise notifications instead (see [Notifications](#bell-notifications)) |\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :hammer_and_wrench: Building Locally\n\nWant to build the image yourself instead of pulling from Docker Hub? Go for it:\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude.git\ncd holyclaude\n\n# Build full image\ndocker build -t holyclaude .\n\n# Build slim image\ndocker build --build-arg VARIANT=slim -t holyclaude:slim .\n\n# Build for ARM (Apple Silicon, Raspberry Pi, AWS Graviton)\ndocker buildx build --platform linux\u002Farm64 -t holyclaude .\n```\n\nThis source release vendors the patched CloudCLI package under `vendor\u002Fartifacts\u002F`, so `docker build` installs that bundled tarball instead of downloading `@siteboon\u002Fclaude-code-ui` from npm.\n\nThen use `image: holyclaude` instead of `image: coderluii\u002Fholyclaude:latest` in your compose file.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :bar_chart: Alternatives\n\nHow does HolyClaude compare to other approaches?\n\n| Approach | Web UI | Multi-AI | Pre-configured tools | Headless browser | One command setup | Persistence |\n|----------|--------|----------|---------------------|-----------------|-------------------|-------------|\n| **HolyClaude** | CloudCLI | 5 CLIs | 50+ tools | Chromium + Xvfb + Playwright | `docker compose up` | Bind mounts |\n| Claude Code (bare metal) | No | No | Install yourself | Install yourself | Multi-step install | Manual |\n| Claude Code + oh-my-openagent | No | Yes (multi-model) | Some | No | npm install | Manual |\n| DIY Docker + Claude Code | Maybe | Maybe | Whatever you add | If you configure it | If you write the Dockerfile | If you set up volumes |\n| Cursor IDE | Built-in | Cursor only | IDE-bundled | No | Download app | App data |\n\nHolyClaude isn't competing with coding agents — it's the **infrastructure layer** that makes them all work better. It's the container you run them inside.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :rocket: Roadmap\n\nWhat's coming next:\n\n| Status | Feature |\n|--------|---------|\n| 🔜 | **ARM-native builds** — optimized native ARM64 images, not just emulated |\n| 🔜 | **VS Code tunnel integration** — built-in VS Code Server or tunnel for connecting from VS Code desktop |\n| 🔜 | **Notification routing** — different notification destinations per event type (errors to Telegram, completions to Discord) |\n\nHave an idea? [Start a discussion](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fdiscussions) or [request a feature](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fissues\u002Fnew?template=feature_request.yml).\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :trophy: Built with HolyClaude\n\nUsing HolyClaude to build something? We'd love to see it.\n\nOpen an issue with the `showcase` label or submit a PR to add your project here:\n\n\u003C!-- Add your project: [Project Name](url) — one-line description -->\n\n*Be the first to add your project here.*\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :handshake: Contributing\n\nContributions welcome. This project was born from real daily usage, and it gets better when more people use it and find edge cases.\n\n1. Fork it\n2. Branch it (`git checkout -b feature\u002Fsomething`)\n3. Commit it\n4. Push it\n5. PR it\n\nBugs, feature requests, questions: [open an issue](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fissues).\n\n### Get in touch\n\n| Channel | Use for |\n|---------|---------|\n| [GitHub Discussions](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fdiscussions) | Questions, show your setup, ideas |\n| [Issues](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fissues) | Bug reports, feature & package requests |\n| [Security Advisories](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fsecurity\u002Fadvisories\u002Fnew) | Vulnerability reports (private) |\n\n### Want a tool added?\n\nUse the [📦 Package Request](https:\u002F\u002Fgithub.com\u002FCoderLuii\u002FHolyClaude\u002Fissues\u002Fnew?template=package_request.yml) issue template. Include the package name, install method, and which variant (full\u002Fslim) it should target.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :heart: Support\n\nHolyClaude is free, open source, and maintained by one developer who uses it every day.\n\nIf it saved you time, here's how you can help:\n\n- **Star this repo** — it's the single biggest thing you can do for visibility\n- **Share it** — tell a friend, post it, tweet it\n- **Open issues** — bug reports and feature requests make HolyClaude better for everyone\n- **Contribute** — PRs are always welcome\n\n[![PayPal](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDonate-PayPal-blue.svg)](https:\u002F\u002Fwww.paypal.com\u002Fdonate\u002F?hosted_button_id=PM2UXGVSTHDNL)\n[![Buy Me A Coffee](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FBuy%20Me%20A%20Coffee-support-yellow.svg?style=flat&logo=buy-me-a-coffee)](https:\u002F\u002Fbuymeacoffee.com\u002FCoderLuii)\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :scroll: Third-Party Software\n\nThe HolyClaude Docker image includes third-party software, each under its own license. Notable components:\n\n| Component | License | Source |\n|-----------|---------|--------|\n| CloudCLI | GPL-3.0 | [siteboon\u002Fclaudecodeui](https:\u002F\u002Fgithub.com\u002Fsiteboon\u002Fclaudecodeui) |\n| s6-overlay | ISC | [just-containers\u002Fs6-overlay](https:\u002F\u002Fgithub.com\u002Fjust-containers\u002Fs6-overlay) |\n| Node.js | MIT | [nodejs\u002Fnode](https:\u002F\u002Fgithub.com\u002Fnodejs\u002Fnode) |\n\nSee [THIRD-PARTY-NOTICES](THIRD-PARTY-NOTICES) for full details including modification notices. HolyClaude's own source code is MIT licensed.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## :page_facing_up: License\n\nMIT — see [LICENSE](LICENSE). Use it however you want.\n\n\u003Cp align=\"right\">\n  \u003Ca href=\"#top\">↑ back to top\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n\u003C!-- Star History -->\n\u003Cdiv align=\"center\">\n\u003Ca href=\"https:\u002F\u002Fstar-history.com\u002F#CoderLuii\u002FHolyClaude&Date\">\n  \u003Cpicture>\n    \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\"https:\u002F\u002Fapi.star-history.com\u002Fsvg?repos=CoderLuii\u002FHolyClaude&type=Date&theme=dark\" \u002F>\n    \u003Csource media=\"(prefers-color-scheme: light)\" srcset=\"https:\u002F\u002Fapi.star-history.com\u002Fsvg?repos=CoderLuii\u002FHolyClaude&type=Date\" \u002F>\n    \u003Cimg alt=\"Star History Chart\" src=\"https:\u002F\u002Fapi.star-history.com\u002Fsvg?repos=CoderLuii\u002FHolyClaude&type=Date\" width=\"600\" \u002F>\n  \u003C\u002Fpicture>\n\u003C\u002Fa>\n\u003C\u002Fdiv>\n\n---\n\n\u003Cdiv align=\"center\">\n\nBuilt by [CoderLuii](https:\u002F\u002Fgithub.com\u002Fcoderluii) · [coderluii.dev](https:\u002F\u002Fcoderluii.dev)\n\nThis container is what I use every day. If it saves you even half the setup time it saved me, a star would be nice.\n\n\u003C\u002Fdiv>\n","HolyClaude 是一个基于 Docker 的 AI 编程工作站，集成了 Claude Code、Web 界面、7 个 AI 命令行工具、无头浏览器和 50 多种开发工具。该项目通过容器化技术将这些工具整合在一起，只需一条命令即可启动完整的开发环境，极大简化了配置过程。它支持多种开发场景，包括代码生成、调试、测试以及自动化任务等，特别适合希望快速搭建高效开发环境的开发者。HolyClaude 与现有的 Claude Code 订阅兼容，无论是 Max\u002FPro 计划还是 API 密钥都能无缝接入。",2,"2026-06-11 03:52:07","high_star"]