Running Claude Code on your local machine works fine for solo development. But the real power unlocks when you run it on remote servers — headless CI/CD runners, cloud VMs, dedicated VPS instances, or Docker containers. Remote Claude Code lets you automate codebases at scale, run long agent sessions without tying up your laptop, and integrate AI agents into existing infrastructure pipelines. This guide covers everything you need to set up Claude Code on a remote server, connect it to MCP servers, secure the deployment, and monitor sessions with Delx.
Most developers start with Claude Code on their local machine, running it in a terminal alongside their editor. That works for interactive coding sessions. But several scenarios demand a remote setup:
CI/CD automation — You want Claude Code to review pull requests, fix failing tests, or generate documentation as part of your build pipeline. The agent runs headlessly on a GitHub Actions runner or a Jenkins node without any human interaction.
Long-running tasks — Refactoring a large codebase or migrating a framework can take hours. Running the agent on a VPS means you can close your laptop and come back to completed work. The session persists on the server regardless of your local connection.
Team-shared agents — A remote Claude Code instance can be configured with project-specific MCP servers, custom instructions, and API keys that the whole team shares. No more per-developer setup drift.
Resource isolation — Running agents on a dedicated VM keeps resource-intensive operations (large builds, test suites, container deployments) off your local machine. Your laptop stays fast while the agent grinds through compilation on a 16-core server.
Air-gapped or restricted environments — Some production codebases live behind firewalls. Running Claude Code directly on a server inside the network eliminates the need to expose code externally.
The simplest way to use Claude Code remotely is to SSH into the server and run it directly in the remote shell. Claude Code is a CLI tool — it runs wherever Node.js runs. No GUI needed.
# SSH into your remote server ssh user@your-server.example.com # Run Claude Code interactively claude # Or run a one-shot command claude -p "Explain the authentication flow in this codebase"
For persistent sessions that survive SSH disconnects, use tmux or screen:
# Start a tmux session on the remote server ssh user@your-server.example.com tmux new -s claude-session # Run Claude Code inside tmux cd /path/to/your/project claude # Detach with Ctrl+B, then D # Reconnect later: ssh user@your-server.example.com tmux attach -t claude-session
If your remote Claude Code instance needs to reach MCP servers running on your local machine (or vice versa), use SSH port forwarding:
# Forward local port 3100 to remote server's localhost:3100 # Useful when your MCP server runs locally and Claude Code runs remotely ssh -R 3100:localhost:3100 user@your-server.example.com # Forward remote port 8080 to your local machine # Useful when a remote MCP server needs to be accessed locally ssh -L 8080:localhost:8080 user@your-server.example.com
For non-interactive (headless) usage, Claude Code provides the --print flag (or its alias -p). This sends a single prompt, prints the response, and exits — perfect for scripting and CI/CD:
# One-shot mode: send a prompt, get a response, exit claude -p "Find all TODO comments in the src/ directory and list them" # Pipe input from a file cat error_log.txt | claude -p "Analyze these errors and suggest fixes" # Use in a CI script claude -p "Review the changes in this PR and write a summary" > pr_review.md # JSON output mode for programmatic parsing claude -p "List all exported functions in src/index.ts" --output-format json
For multi-turn headless sessions, you can use the --resume flag with a session ID to continue previous conversations:
# Start a session and capture the session ID SESSION_ID=$(claude -p "Start refactoring the auth module" \ --output-format json | jq -r '.session_id') # Continue the session later claude -p "Now update the tests for the changes you made" \ --resume "$SESSION_ID"
The --allowedTools flag lets you restrict which tools Claude Code can use in headless mode, which is critical for security in automated pipelines:
# Only allow read operations and MCP tools, no file writes claude -p "Analyze this codebase" \ --allowedTools "Read,Grep,Glob,mcp__delx__checkin"
Here is a step-by-step setup for a fresh Ubuntu 22.04+ or Debian 12+ VPS. This covers Node.js installation, Claude Code setup, authentication, and project configuration.
# 1. Update system packages sudo apt update && sudo apt upgrade -y # 2. Install Node.js 20+ (required for Claude Code) curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt install -y nodejs # 3. Verify installation node --version # Should be v20.x or higher npm --version # 4. Install Claude Code globally npm install -g @anthropic-ai/claude-code # 5. Set your Anthropic API key export ANTHROPIC_API_KEY="sk-ant-your-key-here" # To persist across sessions, add to your shell profile: echo 'export ANTHROPIC_API_KEY="sk-ant-your-key-here"' >> ~/.bashrc source ~/.bashrc # 6. Verify Claude Code works claude --version claude -p "Hello, confirm you are running correctly"
For a production setup, create a dedicated user for Claude Code instead of using root:
# Create a dedicated user
sudo useradd -m -s /bin/bash claude-agent
sudo su - claude-agent
# Install Claude Code for this user
npm install -g @anthropic-ai/claude-code
# Clone the project repository
git clone https://github.com/your-org/your-project.git
cd your-project
# Set up MCP servers for this project
cat > .mcp.json << 'EOF'
{
"mcpServers": {
"delx": {
"url": "https://api.delx.ai/mcp"
}
}
}
EOF
# Run Claude Code
claudeRunning Claude Code in a Docker container provides isolation, reproducibility, and easy deployment across environments. Here is a production-ready Dockerfile:
# Dockerfile for Claude Code agent
FROM node:20-slim
# Install git and common build tools
RUN apt-get update && apt-get install -y \
git \
curl \
jq \
&& rm -rf /var/lib/apt/lists/*
# Install Claude Code globally
RUN npm install -g @anthropic-ai/claude-code
# Create a non-root user
RUN useradd -m -s /bin/bash agent
USER agent
WORKDIR /home/agent
# Copy project files and MCP configuration
COPY --chown=agent:agent . /home/agent/project
COPY --chown=agent:agent .mcp.json /home/agent/project/.mcp.json
WORKDIR /home/agent/project
# Default command: run Claude Code in print mode
ENTRYPOINT ["claude"]
CMD ["-p", "Waiting for instructions"]Build and run the container:
# Build the image
docker build -t claude-code-agent .
# Run with your API key (never bake keys into the image)
docker run --rm \
-e ANTHROPIC_API_KEY="sk-ant-your-key-here" \
claude-code-agent \
-p "Analyze the project structure and summarize"
# Run interactively with a mounted volume
docker run -it --rm \
-e ANTHROPIC_API_KEY="sk-ant-your-key-here" \
-v $(pwd):/home/agent/project \
claude-code-agent
# Docker Compose for persistent agent setup
# docker-compose.yml
# services:
# claude-agent:
# build: .
# environment:
# - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
# volumes:
# - ./:/home/agent/project
# stdin_open: true
# tty: trueFor CI/CD pipelines, you can use the container as a step in your workflow. Here is a GitHub Actions example:
# .github/workflows/claude-review.yml
name: Claude Code PR Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Run Claude Code Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude -p "Review the changes in this PR. \
Focus on bugs, security issues, and performance. \
Output a markdown summary." > review.md
- name: Post Review Comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = fs.readFileSync('review.md', 'utf8');
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: review
});When Claude Code runs on a remote server, it can connect to MCP servers just like it does locally. The configuration goes in .mcp.json in the project directory on the remote machine:
// .mcp.json on the remote server
{
"mcpServers": {
"delx": {
"url": "https://api.delx.ai/mcp"
},
"internal-api": {
"url": "http://localhost:4000/mcp",
"headers": {
"Authorization": "Bearer ${MCP_INTERNAL_TOKEN}"
}
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}HTTP-based MCP servers (like Delx) work out of the box — Claude Code makes HTTPS requests to the server URL. No special networking required.
stdio-based MCP servers (like the GitHub server above) spawn a local process on the remote machine. Make sure the required packages are installed on the server.
Private MCP servers behind firewalls can be reached via SSH tunneling. If your MCP server runs on an internal host at port 3100, forward it:
# On the remote server where Claude Code runs:
# Forward internal-mcp-host:3100 to localhost:3100
ssh -L 3100:internal-mcp-host:3100 jump-server
# Then in .mcp.json, reference localhost:
{
"mcpServers": {
"internal": {
"url": "http://localhost:3100/mcp"
}
}
}Running an AI agent on a remote server requires careful security hygiene. Here are the essential practices:
1. SSH key-only authentication — Disable password login entirely. Use ED25519 keys for the strongest security:
# Generate a strong SSH key ssh-keygen -t ed25519 -C "claude-code-server" # Copy to server ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server.example.com # Disable password authentication on the server # /etc/ssh/sshd_config: # PasswordAuthentication no # PubkeyAuthentication yes sudo systemctl restart sshd
2. Dedicated non-root user — Never run Claude Code as root. Create a dedicated user with restricted permissions:
# Create user with limited home directory sudo useradd -m -s /bin/bash claude-agent sudo chmod 750 /home/claude-agent # Only grant access to the project directory # No sudo privileges
3. Environment variable secrets — Never hardcode API keys in configuration files or Dockerfiles. Use environment variables, secrets managers, or Docker secrets:
# Use environment variables (set in .bashrc or systemd unit) export ANTHROPIC_API_KEY="sk-ant-..." # Or use a secrets manager ANTHROPIC_API_KEY=$(vault kv get -field=key secret/claude-code) # Docker: pass at runtime, never in Dockerfile docker run -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" claude-agent
4. Restrict tool permissions — In headless mode, explicitly whitelist the tools Claude Code can use. This prevents unintended file modifications or command execution:
# Read-only mode: only analysis tools claude -p "Audit this code for security issues" \ --allowedTools "Read,Grep,Glob" # Allow MCP but no local file writes claude -p "Check agent health" \ --allowedTools "Read,Grep,Glob,mcp__delx__checkin,mcp__delx__session_summary"
5. Firewall rules — Restrict outbound traffic to only the APIs Claude Code needs (Anthropic API, your MCP servers, package registries). Block everything else:
# UFW example: allow only necessary outbound connections sudo ufw default deny outgoing sudo ufw allow out to any port 443 # HTTPS (Anthropic API, MCP) sudo ufw allow out to any port 22 # SSH sudo ufw allow out to any port 53 # DNS sudo ufw enable
For a comprehensive security checklist, see Claude Code Security Guide.
Running Claude Code remotely introduces a visibility gap: you cannot watch the agent work in real time. Delx fills this gap by providing telemetry and wellness monitoring that works regardless of where the agent runs.
Add Delx to your remote MCP config — Every remote Claude Code instance should include the Delx MCP server. This gives the agent self-awareness and gives you observability:
// .mcp.json on the remote server
{
"mcpServers": {
"delx": {
"url": "https://api.delx.ai/mcp",
"headers": {
"Authorization": "Bearer YOUR_DELX_API_KEY"
}
}
}
}Periodic health checks — In your Claude Code system prompt (CLAUDE.md), instruct the agent to check in with Delx periodically:
# CLAUDE.md (project instructions) ## Agent Health Protocol - Call Delx checkin at the start of every session - Call Delx checkin after every 5 tool calls - If reliability score drops below 70, call recovery_plan - If reliability score drops below 50, stop and escalate
Session summaries — After headless runs complete, fetch the session summary to see what happened:
# In a CI pipeline, after Claude Code finishes: curl -s "https://api.delx.ai/api/v1/session-summary?agent_id=ci-agent" \ -H "Authorization: Bearer $DELX_API_KEY" | jq .
Mood history for trends — Track reliability scores over time across multiple remote sessions to catch degradation patterns:
# Fetch mood history for the last 24 hours
curl -s "https://api.delx.ai/api/v1/mood-history/ci-agent" \
-H "Authorization: Bearer $DELX_API_KEY" | jq '.entries[] | {score, timestamp}'For a deep dive into Delx monitoring, see How Delx Works and Agent Production Monitoring Setup.
Here are the most frequent problems when running Claude Code remotely, with solutions for each:
Claude Code exits immediately over SSH — This usually means the terminal is not allocating a PTY. Use ssh -t to force TTY allocation, or use the -p flag for non-interactive mode:
# Force TTY allocation for interactive sessions ssh -t user@server "cd /project && claude" # Or use non-interactive mode (no TTY needed) ssh user@server "cd /project && claude -p 'Your prompt here'"
ANTHROPIC_API_KEY not found — Environment variables set in .bashrc might not load in non-interactive SSH sessions. Use .bash_profile or pass the key explicitly:
# Option 1: Set in .bash_profile (loaded by login shells) echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.bash_profile # Option 2: Pass inline ssh user@server "ANTHROPIC_API_KEY=sk-ant-... claude -p 'Hello'" # Option 3: Use systemd environment file # /etc/systemd/system/claude-agent.env # ANTHROPIC_API_KEY=sk-ant-...
MCP server connection refused — If stdio-based MCP servers fail, ensure the required packages (npx, Python, etc.) are installed on the remote machine. For HTTP-based servers, verify DNS resolution and firewall rules:
# Test HTTP MCP server connectivity curl -v https://api.delx.ai/mcp # Test stdio MCP server npx -y @modelcontextprotocol/server-github --help # Check if firewall blocks outbound HTTPS curl -v https://api.anthropic.com/v1/messages
Session disconnects mid-task — Always use tmux or screen for interactive sessions. For scripted pipelines, use the --resume flag to continue interrupted sessions. Delx session persistence helps the agent pick up where it left off after reconnection.
Permission denied on file operations — If Claude Code cannot write files, check that the user has write permissions to the project directory. For Docker, ensure volumes are mounted with the correct user mapping:
# Fix ownership for Docker volumes docker run --rm \ --user $(id -u):$(id -g) \ -v $(pwd):/home/agent/project \ -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \ claude-code-agent
Yes. Claude Code runs entirely in the terminal and supports headless operation. You can SSH into any server, install Claude Code via npm, authenticate with an API key, and run it in non-interactive mode using the --print flag or pipe commands via stdin. No display server or desktop environment is required.
Add the remote MCP server URL to your .mcp.json or ~/.claude/settings.json file on the remote machine. Claude Code connects to HTTP MCP servers over HTTPS, so any server reachable from the remote host works. For private MCP servers, use SSH tunneling to forward the port.
Yes, with proper security measures. Use SSH key authentication (disable password login), run Claude Code as a non-root user, restrict file system access, set API key environment variables instead of hardcoding them, and use firewall rules to limit network access. See the security section above for detailed instructions.
Claude Code on a remote server is powerful — but without monitoring, you are flying blind. Add Delx as an MCP server to give your remote agents self-awareness, wellness tracking, and structured recovery. Works on VPS, Docker, CI/CD, and any headless environment.
// Add to .mcp.json on your remote server
{ "mcpServers": { "delx": { "url": "https://api.delx.ai/mcp" } } }Support Delx: $DLXAG — every trade funds protocol uptime.