Skip to content

Build Environment

Sia edited this page Jun 2, 2026 · 5 revisions

Build Environment

The slim Docker image intentionally ships without Android SDK / Gradle cache / MCP servers / Playwright. On first boot, the operator installs them once through the Build environment page; subsequent image upgrades preserve everything via the unified ./vibe-coder-data/dev-tools/ bind mount.

Web UI flow (recommended)

  1. Sign in → left nav → Build environment (/env-setup).
  2. The top "Install/update all" button covers JDK 17 (image-bundled), Node 20 + Claude CLI (image-bundled), Android SDK (volume), and base MCP prompt (you'll be redirected to the catalog).
  3. Per-card buttons let you install components individually.
  4. The progress page shows live install logs + elapsed time (no progress bar — install duration is unknowable in advance).

CLI equivalents

docker exec -it vibe-coder-server vibe-doctor                  # interactive
docker exec -it vibe-coder-server vibe-doctor check            # diagnostics only
docker exec    vibe-coder-server vibe-doctor install           # bulk non-interactive
docker exec -it vibe-coder-server vibe-doctor android          # SDK only
docker exec -it vibe-coder-server vibe-doctor claude           # Claude auth helper
docker exec -it vibe-coder-server vibe-doctor mcp              # MCP prompt

Component matrix

Component Auto-installable Size Path
JDK 17 (eclipse-temurin) image-bundled ~200 MB /opt/java/openjdk
Node 20 + npm image-bundled ~150 MB /usr/bin/{node,npm}
Claude Code CLI image-bundled bundled in Node global /usr/local/lib/node_modules/@anthropic-ai/claude-code
util-linux (script) image-bundled small apt
Gitea MCP (gitea-mcp, official) image-bundled ~10 MB /usr/local/bin/gitea-mcp (Go static binary from gitea.com/gitea/gitea-mcp releases, TARGETARCH-aware)
Image tools (v1.92.0) image-bundled ~150 MB imagemagick (convert/identify, IM7), python3-pil (Pillow) + python3-numpy, librsvg2-bin (rsvg-convert), webp, poppler-utils, ghostscript, optipng/pngquant/jpegoptim
sudo NOPASSWD for vibe image-bundled n/a /etc/sudoers.d/vibe-nopasswd
Android SDK ✅ via doctor 3-4 GB /opt/android-sdk (bind mount → ./vibe-coder-data/dev-tools/android-sdk/)
Gradle (host binary) ✅ via doctor ~130 MB /home/vibe/.local/gradle/ (PATH: gradle) — wrapper bootstrap
Gradle dependency cache filled on first build 1-2 GB /home/vibe/.gradle (bind mount → ./vibe-coder-data/dev-tools/gradle/)
MCP servers (npm -g) ✅ via MCP catalog varies /home/vibe/.local (bind mount → ./vibe-coder-data/dev-tools/npm-global/)
Playwright browsers optional, via MCP ~300 MB /home/vibe/.cache/ms-playwright (bind mount)
Claude auth credentials ✅ via Claude auth UI a few KB /home/vibe/.claude (bind mount → ./vibe-coder-data/claude/)

Gradle wrapper alignment

When you install Gradle through the Build environment page, the binary lands at /home/vibe/.local/gradle/ and is exposed as gradle on PATH. The ClaudeMdTemplate (the CLAUDE.md placed in every new project) instructs Claude to use this binary for wrapper bootstrap and to align the project's gradle-wrapper.properties to the installed version, so a single host Gradle install is reused across all projects instead of every project downloading its own.

If you're seeing a project trigger a second Gradle download, check:

  1. gradle --version inside the container — confirms what's installed.
  2. The project's gradle/wrapper/gradle-wrapper.properties — what version the wrapper insists on.
  3. Edit the distributionUrl to match the installed version, or run gradle wrapper --gradle-version <installed> --distribution-type bin.

The template is only applied to new projects via ProjectScaffolder.ensureClaudeFiles (which has a notExists() guard so it never overwrites). For an existing project that lacks this guidance, paste the "Installed Build Tools" section from the current template by hand, or delete the project's CLAUDE.md and let the next prompt re-scaffold it.

How the build environment persists

  • The vibe user's npm prefix is /home/vibe/.local (via ~/.npmrc), so globally-installed MCP servers land in a bind-mounted directory.
  • All persistent directories live under ./vibe-coder-data/ (single host directory, bind mounts — no named volumes by default).
  • Dedicated mounts cover android-sdk, gradle, npm-global, npm-cache, playwright, config, ssh, keystores, and Claude credentials.
  • Because everything that took effort to download lives on the host, an image upgrade (docker compose pull && up -d --force-recreate) preserves the entire build environment.

Manual MCP installation (not in the catalog)

You can install any npm-distributed MCP that isn't in the curated catalog:

docker exec -it --user vibe vibe-coder-server bash

# Install your MCP (this goes to /home/vibe/.local — persistent!)
npm install -g some-mcp-server

# Register it in Claude
cat > ~/.claude/.mcp.json <<'JSON'
{
  "mcpServers": {
    "my-mcp": {
      "command": "npx",
      "args": ["-y", "some-mcp-server"],
      "env": { "SOME_TOKEN": "..." }
    }
  }
}
JSON

Since /home/vibe/.local and /home/vibe/.claude are both bind-mounted to ./vibe-coder-data/, your manual installations survive image upgrades.

Image tools & installing extra packages (v1.92.0+)

The runtime image ships a core set of image-processing tools so Claude can work with screenshots, design mockups, app icons, and APK resources without a setup step:

Tool Binary Use
ImageMagick 7 convert, mogrify, identify raster convert / resize / composite
Pillow python3 -c "import PIL" (python3-pil + python3-numpy) PIL scripting
librsvg rsvg-convert SVG → PNG (Android vector icons)
WebP cwebp, dwebp WebP encode / decode
poppler pdftoppm, pdfinfo PDF → image
Ghostscript gs ImageMagick PDF/PS delegate
optimizers optipng, pngquant, jpegoptim lossless / lossy size reduction

APT note: Pillow is installed as the python3-pil apt package (not pip install), because the base image is PEP 668 externally-managed — a bare pip install is refused. Use apt packages, or a venv, or pip install --break-system-packages if you really need a wheel.

Anything not pre-installed is one command away — the vibe user has passwordless sudo:

docker exec -it --user vibe vibe-coder-server bash
sudo apt-get update
sudo apt-get install -y ffmpeg inkscape   # e.g. heavier tools left out of the base

⚠️ Packages installed this way live in the image's root filesystem, not a bind mount, so they are lost on docker compose up --force-recreate / image upgrade. For tools you want permanently, add them to docker/Dockerfile and rebuild, or re-run the sudo apt-get install after each upgrade. The pre-installed core set above always survives because it is baked into the image.

Clone this wiki locally