Skip to content

Run Claude Code as an isolated and containerized A2A agent - orchestrate multiple sessions with full visibility on Claude operations and messages. Configure marketplaces, plugins, MCP servers and more.

License

Notifications You must be signed in to change notification settings

dwmkerr/claude-code-agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

62 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

claude-code-agent

Run Claude Code as an isolated and containerized A2A agent - orchestrate multiple sessions with full visibility on Claude operations and messages. Configure marketplaces, plugins, MCP servers and more.

Quickstart | Sending Messages | Installation | Configuration | Examples | Important

cicd npm docker codecov

Claude Code Agent terminal output

This project lets you deploy and run the Claude Code agent as a self-contained A2A server. This allows you to deploy Claude Code to different environments and interact with it using a standardised protocol. Isolated workspaces, skills, and various other capabilities can easily be extended.

Each Claude Code session runs in its own workspace and sessions can be configured with an .init-session.sh script to install MCP servers, plugins, and customise Claude Code's environment.

I am using this agent extensively in my work on Ark - there are examples on how to build skills, use K8S, playwright, and more, in ./examples/ark.

Quickstart

Run the Claude Code Agent A2A server locally (check important note on managing risk:

# Set your API key. OR use as .env file to set your keys.
export ANTHROPIC_API_KEY="sk-***"
# cp .env.sample .env

# Run in local development / live reload mode.
npm install && npm run dev

# SAFER: Run in local development / live reload mode - but don't inherit the
# user's environment (e.g. sensitive env vars not accessible to claude).
make dev-safe
# Server: http://localhost:2222
# or:
# env -i npm run dev

Or run in a container (event safer and more isolated):

# Run in a container. Also loads the .env file if present.
make docker-run
# Server: http://localhost:2222

Sending Messages

The A2A server takes incoming requests and starts a session for each one. Each session runs Claude Code in an isolated workspace - you can run as many sessions in parallel as you need. There are a few ways to send messages to an A2A server.

Script

Use the a2a-msg.sh script to send an A2A message. You'll see rich output in the A2A server in real time:

./scripts/a2a-msg.sh "Tell me what tools you have access to, test one out."

Example output:

→ Executing: "clone dwmkerr/claude-code-agent and summarise top three issues"
  < system:init session=07898273...
  < assistant: "I'll clone the repository and summarize the top three issues."
  < assistant: Bash {"command":"git clone https://github.com/dwmkerr/claude-..."}
  < assistant: Bash {"command":"gh issue list --limit 3"}
     ... (hidden for brevity in docs)
  ← Response: "Here are the top 3 issues: #22 OTEL session ID..."

This script is just a wrapper around the raw curl command that can be used to message an A2A server (see below).

cURL

You can also just hit the server directly with curl:

# Construct an A2A message and send to the A2A server.
curl -N -X POST http://localhost:2222/ \
  -H "Content-Type: application/json" \
  -d @- << 'EOF'
{
  "jsonrpc": "2.0",
  "method": "message/stream",
  "params": {
    "message": {
      "messageId": "1",
      "contextId": "ctx-1",
      "role": "user",
      "parts": [{"kind": "text", "text": "Tell me what skills you have loaded."}]
    }
  },
  "id": 1
}
EOF

Example output:

{"jsonrpc":"2.0","id":1,"result":{"messageId":"...","contextId":"ctx-1",...}}
{"jsonrpc":"2.0","method":"message/stream","params":{"delta":{"text":"I'll..."}}}
   ... (hidden for brevity in docs)
{"jsonrpc":"2.0","method":"message/stream","params":{"status":"completed"}}

A2A Inspector

You can run the A2A Inspector tool to connect to the server and send messages:

# Clone and run the A2A inspector tool.
git clone https://github.com/a2aproject/a2a-inspector
cd a2a-inspector && ./scripts/run.sh

# Then connect to http://localhost:2222

Installation

See Installation Guide for all installation options, including:

  • Docker - Run in Docker
  • DevSpace - Live-reload in Kubernetes
  • Helm - Deploy to Kubernetes
  • Ark - Deploy on Ark

Configuration

All options are documented in claude-code-agent.example.yaml. Environment variables from .env are loaded on startup (overriding existing vars). The config file .claude-code-agent.yaml is loaded by default if present.

claude-code-agent [options] [-- <claude-code-args>]

Options:
  -p, --port <number>      Server port (default: 2222)
  -H, --host <string>      Server host (default: 0.0.0.0)
  -w, --workspace <path>   Workspace directory
  -c, --config <path>      Path to YAML config file
  --timeout <seconds>      Execution timeout (default: 3600)
  --log-path <path>        Path to write Claude output logs
  --agent-name <name>      Agent name for A2A registration

# Pass any Claude Code args after --
claude-code-agent -- --allowedTools Bash,Read

Environment Variables

Variable Description Default
ANTHROPIC_API_KEY API key (required) -
CLAUDE_TIMEOUT_SECONDS Execution timeout 3600
CLAUDE_CODE_WORKSPACE_DIR Working directory ./workspace (local) or /workspace (docker/helm)
CLAUDE_AGENT_NAME Agent name for A2A registration claude-code
CLAUDE_LOG_PATH File path for JSONL chunk logs - (disabled)
INIT_SESSION Session init script path ./.init-session.sh (auto-detected)
HOST Server host 0.0.0.0
PORT Server port 2222
FORCE_COLOR Enable colors in logs 1

CLI options override environment variables.

Workspaces

Claude operates in ./workspace locally or /workspace in containers. Override with CLAUDE_CODE_WORKSPACE_DIR.

# Mount a specific folder rather than the local ./workspace folder.
CLAUDE_CODE_WORKSPACE_DIR=/tmp/project1 npm run dev

# Docker - mount a local workspace. This folder is automatically mounted when
# make docker-run is used.
docker run -v ./workspace:/workspace ...

# Helm - enable persistence (creates PVC)
helm install ... --set workspace.persistence.enabled=true

Session Setup for MCP, Plugins, etc

You can configure each Claude Code session with a .init-session.sh script. This script runs automatically when a new session starts in a workspace, allowing you to set up MCP servers, marketplace plugins, and project-specific configuration.

Default: ./.init-session.sh (auto-detected if present) Override: --init-session <path> or config file agent.initSession

Example .init-session.sh:

#!/usr/bin/env bash
set -e -o pipefail

echo "Initializing session: $A2A_SESSION_ID"

# Add MCP servers (project scope).
# These may fail locally if already installed at user scope - that's ok.
claude mcp add --scope project shellwright -- npx -y @dwmkerr/shellwright || true

# Add marketplace plugins (project scope).
# These may fail locally if already installed at user scope - that's ok.
claude plugin marketplace add dwmkerr/claude-toolkit || true
claude plugin install --scope project toolkit@claude-toolkit || true

# Set up CLAUDE.md - choose one approach:
# Option 1: Fetch from URL
# curl -s https://example.com/CLAUDE.md > .claude/CLAUDE.md

# Option 2: Heredoc for inline configuration
# mkdir -p .claude
# cat > .claude/CLAUDE.md << 'EOF'
# # Agent Instructions
# Your custom instructions here.
# EOF

The A2A_SESSION_ID environment variable identifies the current session.

Tools

Claude code runs in a container, with a number of tools such as curl, wget, etc installed. Check these tools or extend by editing Dockerfile.

If tools require configuration, config files or env vars can be passed to the container. For example, to ensure that the gh CLI can be used, pass a GH_TOKEN by either setting in .env or explicitly pass the environment variable. See the important note on risk.

Telemetry (OpenTelemetry)

Enable OTEL tracing by setting CLAUDE_CODE_ENABLE_TELEMETRY=1:

# Docker
docker run -e CLAUDE_CODE_ENABLE_TELEMETRY=1 \
  -e OTEL_EXPORTER_OTLP_ENDPOINT=http://phoenix:6006 ...

# Helm
helm install ... --set env.CLAUDE_CODE_ENABLE_TELEMETRY=1

# With envFrom for OTEL secrets (e.g., from Phoenix)
helm install ... \
  --set env.CLAUDE_CODE_ENABLE_TELEMETRY=1 \
  --set envFrom[0].secretRef.name=otel-environment-variables \
  --set envFrom[0].secretRef.optional=true

Examples

See examples/ for usage examples:

  • Ark Testing - Test Ark PRs with Kind clusters, MCP servers (Playwright), and skills

API

Implements A2A protocol:

  • GET /.well-known/agent-card.json - Agent metadata
  • POST / - JSON-RPC messages
  • GET /health - Health check

Development

npm install
npm run dev      # Development with hot-reload
npm test         # Run tests
npm run build    # Build for production

Docker Images

Releases push to GHCR (ghcr.io/dwmkerr/claude-code-agent). For local development, push release candidates to Docker Hub:

# Build and push base image RC
docker build -t dwmkerr/claude-code-agent-base:0.1.2-rc1 -f Dockerfile.base .
docker push dwmkerr/claude-code-agent-base:0.1.2-rc1

# Update Dockerfile and devspace.yaml to use the RC tag, then iterate

Test Prompts

Clone the mckinsey/agents-at-scale-ar repo, build a file called 'issues.md' that has a table of issues/urls/ids/titles and a one line summary for each one. Then suggest a good first issue to work on.

Check out mckinsey/agents-at-scale-ark#531 and test it you need to use ark setup to setup your environment and ark-testing to c heck the dashboard. save screenshots to ./screenshots and let me know when done

Important

Be aware that if you run the agent as a local process with npm, then it will inherit your environment. This presents a significant security risk - for example if you are logged into the GitHub CLI (gh) then the agent will be able to execute GitHub commands with your identity, via the Bash tool.

You can run in local development mode with live-reload using make dev-safe:

# SAFER: Run in local development / live reload mode - but don't inherit the
# user's environment (e.g. sensitive env vars not accessible to claude).
make dev-safe
# Server: http://localhost:2222

Behind the scenes dev-safe explicitly excludes the user's environment (this'll ensure your AWS keys or whatever are not passed to the model), i.e:

# env -i npm run dev

It is highly recommended that you run the agent in a docker container with make docker-run or by checking the Deploy guide. You can also use make dev-safe. Use make help for all recipes.

About

Run Claude Code as an isolated and containerized A2A agent - orchestrate multiple sessions with full visibility on Claude operations and messages. Configure marketplaces, plugins, MCP servers and more.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 2

  •  
  •