[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:
- Missing User-Level Instructions: User's
~/.claude/CLAUDE.md doesn't exist in containers, losing personal coding preferences and standards
- No Custom Tools:
.claude/{agents,commands,scripts} directories (user and project-level) aren't available, removing custom workflow automation
- 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
- 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:
- Scan
.mcp.json for ${ENV_VAR} patterns
- Extract referenced variables (e.g.,
BRAVE_API_KEY)
- 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
- Should this be opt-out instead of always-on?
- Any security concerns with the selective env var injection model?
- Need separate documentation file?
- Should UID/GID be configurable or use fixed defaults?
[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:
~/.claude/CLAUDE.mddoesn't exist in containers, losing personal coding preferences and standards.claude/{agents,commands,scripts}directories (user and project-level) aren't available, removing custom workflow automationUser 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:
Note: Project
CLAUDE.mdalready 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:
.mcp.jsonfor${ENV_VAR}patternsBRAVE_API_KEY)docker run -e BRAVE_API_KEY=$BRAVE_API_KEYCritical: 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.jsonand merges with host-level servers (project takes precedence).4. Executable Permissions (
docker-sandbox.js:264-267)Auto-
chmod +xfor.shfiles and scripts in/commands/,/scripts/directories5. Non-Root User Execution (
Dockerfile:23-44)NEW Feature: Container runs as
vibekituser (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:
Path Changes:
/root/.claude→/home/vibekit/.claude/root/.local→/home/vibekit/.local/root/.bun→/home/vibekit/.bunBenefits:
/workspacehave correct ownership (matches host user).claude/configs owned by correct usersudorequired to edit files created in containerWhy This Approach?
Key Design Decisions
1. File Mounting (not env vars)
CLAUDE.mdfiles2. Selective Env Injection
.mcp.json3. Automatic (not opt-in)
4. Non-Root Execution
Benefits
Implementation
Branch:
feat/claude-injectionCommits:
921a975- Core injection system3101ed2- Sanitize MCP logging (security)38c0a39- Auto-chmod for scriptsFiles 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)/root/to/home/vibekit/Questions for Reviewers