这是indexloc提供的服务,不要输入任何密码
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions packages/cli/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
FROM oven/bun:1

# Build arguments for user/group creation
ARG HOST_UID=1000
ARG HOST_GID=1001

# Install system dependencies including build tools for native modules
RUN apt-get update && apt-get install -y \
bash \
Expand All @@ -11,26 +15,41 @@ RUN apt-get update && apt-get install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*

# Create non-root user and group with host UID/GID
# Remove existing user/group if they conflict, then create vibekit user
RUN (getent passwd ${HOST_UID} && userdel -r $(getent passwd ${HOST_UID} | cut -d: -f1) || true) && \
(getent group ${HOST_GID} && groupdel $(getent group ${HOST_GID} | cut -d: -f1) || true) && \
groupadd -g ${HOST_GID} vibekit && \
useradd -m -u ${HOST_UID} -g ${HOST_GID} -s /bin/bash vibekit

# Install Node.js for MCP server support
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \
&& apt-get install -y nodejs

# Set up Bun environment
ENV BUN_INSTALL="/home/.bun"
ENV BUN_INSTALL="/home/vibekit/.bun"
ENV PATH="$BUN_INSTALL/bin:$PATH"

# Install coding agents globally
RUN bun add -g @anthropic-ai/claude-code@latest || echo "Claude CLI install failed"
RUN bun add -g @openai/codex@latest || echo "Codex CLI install failed"
RUN bun add -g @openai/codex@latest || echo "Codex CLI install failed"
RUN bun add -g @google/gemini-cli@latest || echo "Gemini CLI install failed"
RUN bun add -g opencode-ai@latest || echo "OpenCode CLI install failed"
RUN bun add -g @vibe-kit/grok-cli@latest || echo "Grok CLI install failed"

# Try alternative Claude installation
RUN curl -sSL https://install.anthropic.com | bash || echo "Alternative Claude install failed"
ENV PATH="/root/.local/bin:$BUN_INSTALL/bin:$PATH"
ENV PATH="/home/vibekit/.local/bin:$BUN_INSTALL/bin:$PATH"

# Install vibekit CLI globally and create symlink
RUN bun add -g vibekit || echo "Vibekit install failed"

# Create workspace directory
RUN mkdir -p /workspace
# Create workspace directory and Claude directories, set ownership
RUN mkdir -p /workspace /home/vibekit/.claude && \
chown -R vibekit:vibekit /workspace /home/vibekit

# Switch to non-root user
USER vibekit
WORKDIR /workspace

# Expose common local development ports
Expand Down
55 changes: 48 additions & 7 deletions packages/cli/src/auth/claude-auth-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class ClaudeAuthHelper {
* @returns {Object} Command modification object
*/
static createClaudeWrapper(credentials, args) {
// Create bash wrapper that deep merges our settings into /root/.claude.json
// Create bash wrapper that deep merges our settings into /home/vibekit/.claude.json
const settingsJson = JSON.stringify(credentials.settings);

// Use base64 encoding to avoid shell escaping issues with JSON content
Expand Down Expand Up @@ -170,6 +170,38 @@ MERGE_EOF
};
}

/**
* Extract project-specific MCP server configurations from .mcp.json file
* @param {string} projectPath - Path to the project directory
* @returns {Object} Project MCP server configurations or empty object
*/
static async extractProjectMcpServers(projectPath) {
try {
const mcpJsonFile = path.join(projectPath, '.mcp.json');

console.log(chalk.blue(`[auth] 🔍 Looking for project MCP servers in: ${mcpJsonFile}`));

if (await fs.pathExists(mcpJsonFile)) {
console.log(chalk.blue('[auth] 📁 Project .mcp.json file exists, reading...'));
const mcpConfig = await fs.readJson(mcpJsonFile);

if (mcpConfig.mcpServers && typeof mcpConfig.mcpServers === 'object') {
console.log(chalk.green(`[auth] ✅ Found ${Object.keys(mcpConfig.mcpServers).length} project-level MCP servers`));
return mcpConfig.mcpServers;
} else {
console.log(chalk.yellow('[auth] ⚠️ No mcpServers found in project .mcp.json'));
}
} else {
console.log(chalk.blue('[auth] 📝 No project .mcp.json file found'));
}
} catch (error) {
console.log(chalk.red(`[auth] ❌ Error extracting project MCP servers: ${error.message}`));
}

console.log(chalk.blue('[auth] 📤 Returning empty project mcpServers object: {}'));
return {};
}

/**
* Extract MCP server configurations from host .claude.json file
* @returns {Object} MCP server configurations or empty object
Expand All @@ -189,7 +221,7 @@ MERGE_EOF

// Extract user-scope MCP server configs
if (hostConfig.mcpServers && typeof hostConfig.mcpServers === 'object') {
console.log(chalk.green(`[auth] ✅ Found root-level mcpServers: ${JSON.stringify(hostConfig.mcpServers)}`));
console.log(chalk.green(`[auth] ✅ Found ${Object.keys(hostConfig.mcpServers).length} root-level MCP servers`));
return hostConfig.mcpServers;
} else {
console.log(chalk.yellow('[auth] ⚠️ No root-level mcpServers found in host .claude.json'));
Expand All @@ -205,7 +237,6 @@ MERGE_EOF
} catch (error) {
// Log more detailed error information
console.log(chalk.red(`[auth] ❌ Error extracting MCP servers from host .claude.json: ${error.message}`));
console.log(chalk.red(`[auth] 📍 Error stack: ${error.stack}`));
}

console.log(chalk.blue('[auth] 📤 Returning empty mcpServers object: {}'));
Expand All @@ -215,11 +246,21 @@ MERGE_EOF
/**
* Generate Claude CLI settings for onboarding bypass
* @param {Object} tokenData - Raw token data from ClaudeAuth
* @param {string} projectPath - Project directory path (defaults to process.cwd())
* @returns {Promise<Object>} Settings object for Claude CLI
*/
static async generateClaudeSettings(tokenData) {
// Extract MCP server configurations from host file
static async generateClaudeSettings(tokenData, projectPath = null) {
// Use current working directory if no project path provided
const workingDir = projectPath || process.cwd();

// Extract MCP server configurations from host file and project file
const hostMcpServers = await this.extractHostMcpServers();
const projectMcpServers = await this.extractProjectMcpServers(workingDir);

// Merge host and project MCP servers (project takes precedence)
const mergedMcpServers = { ...hostMcpServers, ...projectMcpServers };

console.log(chalk.green(`[auth] 🔗 Merged ${Object.keys(mergedMcpServers).length} MCP server(s)`));

return {
hasCompletedOnboarding: true, // Skip first-time setup
Expand All @@ -231,8 +272,8 @@ MERGE_EOF
'new-user-warmup': 1
},
firstStartTime: new Date().toISOString(),
// Always inject user-scope MCP server configurations from host (even if empty)
mcpServers: hostMcpServers,
// Always inject merged MCP server configurations (host + project)
mcpServers: mergedMcpServers,
// Project-level configuration for /workspace
projects: {
"/workspace": {
Expand Down
Loading
Loading