Skip to content

[Feature]: Claude Configuration Injection for Docker Sandboxes #242

Description

@mg-dev25

[Feature]: Claude Configuration Injection for Docker Sandboxes

Feature Description

Enable Claude Code to work seamlessly inside Docker containers by automatically injecting Claude configuration files and MCP server settings from the host system.


Problem Statement

Without this feature, Claude Code works inside VibeKit containers but with severely limited functionality:

  1. Missing User-Level Instructions: User's ~/.claude/CLAUDE.md doesn't exist in containers, losing personal coding preferences and standards
  2. No Custom Tools: .claude/{agents,commands,scripts} directories (user and project-level) aren't available, removing custom workflow automation
  3. Broken MCP Servers: Model Context Protocol servers fail because required environment variables (API keys, credentials) aren't injected, making tools like Brave Search, context7, etc. unusable
  4. File Permission Issues: Container runs as root, creating files with root ownership that cause permission conflicts on host

User Impact: Claude Code runs but is significantly less useful. Developers won't manually recreate configurations inside containers—they'll simply avoid using containers or find the AI assistance inadequate and abandon the product


Solution

Automatically inject Claude configuration from host → container at startup. Five NEW components:

1. File Injection (docker-sandbox.js:167-270)

Injects Claude configuration files from host → container:

NEW Mappings:

~/.claude/CLAUDE.md                      → /home/vibekit/.claude/CLAUDE.md
~/.claude/{agents,commands,scripts}/*    → /home/vibekit/.claude/*/
./.claude/{agents,commands,scripts}/*    → /workspace/.claude/*/

Note: Project CLAUDE.md already exists via project directory mount (/workspace)

Method: Base64-encoded script mounted into container (avoids E2BIG limit for large files)

2. MCP Environment Variables (docker-sandbox.js:127-165)

Security Model: Only injects environment variables explicitly referenced in MCP configs

Example .mcp.json:

{
  "mcpServers": {
    "brave": {
      "env": { "BRAVE_API_KEY": "${BRAVE_API_KEY}" }
    }
  }
}

Process:

  1. Scan .mcp.json for ${ENV_VAR} patterns
  2. Extract referenced variables (e.g., BRAVE_API_KEY)
  3. Inject only those variables: docker run -e BRAVE_API_KEY=$BRAVE_API_KEY

Critical: We do not blindly inject all environment variables or credentials. Only MCP-required vars are passed.

3. Project MCP Server Extraction (claude-auth-helper.js:174-203)

NEW function extractProjectMcpServers() extracts MCP servers from project-level .mcp.json and merges with host-level servers (project takes precedence).

4. Executable Permissions (docker-sandbox.js:264-267)

Auto-chmod +x for .sh files and scripts in /commands/, /scripts/ directories

5. Non-Root User Execution (Dockerfile:23-44)

NEW Feature: Container runs as vibekit user (UID/GID matched to host) instead of root.

Problem Solved: Files created inside container were owned by root, causing permission errors when accessed from host.

Implementation:

ARG HOST_UID=1000
ARG HOST_GID=1001

RUN groupadd -g ${HOST_GID} vibekit && \
    useradd -m -u ${HOST_UID} -g ${HOST_GID} -s /bin/bash vibekit

USER vibekit

Path Changes:

  • /root/.claude/home/vibekit/.claude
  • /root/.local/home/vibekit/.local
  • /root/.bun/home/vibekit/.bun

Benefits:

  • ✅ Files in /workspace have correct ownership (matches host user)
  • ✅ Injected .claude/ configs owned by correct user
  • ✅ No sudo required to edit files created in container
  • ✅ Better security (principle of least privilege)

Why This Approach?

Key Design Decisions

1. File Mounting (not env vars)

  • Docker's E2BIG limit (~128KB) breaks with large CLAUDE.md files
  • Mounted scripts avoid command-line length limits

2. Selective Env Injection

  • Security: Only inject env vars explicitly referenced in .mcp.json
  • No blind credential exposure
  • MCP servers declare their requirements

3. Automatic (not opt-in)

  • Zero user friction
  • Fails gracefully if configs don't exist

4. Non-Root Execution

  • Matches host UID/GID to prevent permission conflicts
  • Follows Docker security best practices

Benefits

  • Zero setup: Claude Code works immediately in containers
  • Security: Only MCP-required environment variables injected, non-root execution
  • Consistency: Same config/behavior across host and containers
  • Flexibility: Project-level configs override user-level defaults
  • File Ownership: Container files match host user (no permission conflicts)

Implementation

Branch: feat/claude-injection

Commits:

  • 921a975 - Core injection system
  • 3101ed2 - Sanitize MCP logging (security)
  • 38c0a39 - Auto-chmod for scripts

Files Changed:

  • packages/cli/src/sandbox/docker-sandbox.js (+185 lines)
  • packages/cli/src/auth/claude-auth-helper.js (+65 lines)
  • packages/cli/Dockerfile (+23/-4 lines)
    • Added non-root user creation with host UID/GID mapping
    • Updated all paths from /root/ to /home/vibekit/
    • Added Node.js for MCP server support

Questions for Reviewers

  1. Should this be opt-out instead of always-on?
  2. Any security concerns with the selective env var injection model?
  3. Need separate documentation file?
  4. Should UID/GID be configurable or use fixed defaults?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions