Skip to content

Commit c64db55

Browse files
Add AI agents and cloud CLIs to container image
- Claude Code, OpenAI Codex, Cursor, Gemini CLI - AWS, GCP, Azure, GitHub CLIs - Config file support (~/.coderunner.config) - Credential mount options (--with-ssh-agent, --with-credentials) - 48h auto-update via GitHub Actions cron - Trivy vulnerability scanning
1 parent ae745a3 commit c64db55

4 files changed

Lines changed: 257 additions & 24 deletions

File tree

.github/workflows/docker-build.yml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ on:
77
branches: [ main ]
88
release:
99
types: [ published ]
10+
schedule:
11+
# Every 48 hours at midnight UTC
12+
- cron: '0 0 */2 * *'
13+
workflow_dispatch:
14+
# Manual trigger
1015

1116
env:
1217
REGISTRY: docker.io
@@ -61,7 +66,18 @@ jobs:
6166
labels: ${{ steps.meta.outputs.labels }}
6267
cache-from: type=gha
6368
cache-to: type=gha,mode=max
64-
69+
70+
- name: Scan image for vulnerabilities
71+
if: github.event_name != 'pull_request'
72+
uses: aquasecurity/trivy-action@master
73+
with:
74+
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:docker-latest
75+
format: 'table'
76+
exit-code: '0'
77+
ignore-unfixed: true
78+
vuln-type: 'os,library'
79+
severity: 'CRITICAL,HIGH'
80+
6581
- name: Generate build summary
6682
run: |
6783
echo "## Docker Build Summary" >> $GITHUB_STEP_SUMMARY

Dockerfile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,47 @@ ENV PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
107107
RUN npm install playwright@1.53.0 -g
108108
RUN npx playwright@1.53.0 install
109109

110+
# --- AI Coding Agents ---
111+
# Claude Code CLI (pinned to major version 1.x)
112+
RUN npm install -g @anthropic-ai/claude-code@1
113+
114+
# OpenAI Codex CLI
115+
RUN npm install -g @openai/codex
116+
117+
# Gemini CLI
118+
RUN npm install -g @anthropic-ai/claude-code@1 && \
119+
pip install --no-cache-dir google-generativeai
120+
121+
# Cursor CLI (installs as 'agent' at ~/.local/bin)
122+
RUN curl -fsSL https://cursor.com/install | bash && \
123+
ln -sf /root/.local/bin/agent /usr/local/bin/cursor
124+
125+
# --- Cloud CLIs ---
126+
# AWS CLI v2
127+
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "awscliv2.zip" && \
128+
unzip -q awscliv2.zip && \
129+
./aws/install && \
130+
rm -rf awscliv2.zip aws
131+
132+
# Google Cloud CLI
133+
RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | \
134+
tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \
135+
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
136+
gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg && \
137+
apt-get update && apt-get install -y google-cloud-cli && \
138+
apt-get clean && rm -rf /var/lib/apt/lists/*
139+
140+
# GitHub CLI (gh)
141+
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | \
142+
dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \
143+
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | \
144+
tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
145+
apt-get update && apt-get install -y gh && \
146+
apt-get clean && rm -rf /var/lib/apt/lists/*
147+
148+
# Azure CLI
149+
RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash
150+
110151
# Copy the entrypoint script into the image
111152
COPY entrypoint.sh /entrypoint.sh
112153

README.md

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,52 @@
66

77
# CodeRunner
88

9-
Sandboxed Python execution for Mac. Local files, local processing.
9+
Sandboxed code execution for Mac using [Apple containers](https://github.com/apple/container).
1010

11-
CodeRunner runs Python code in an isolated container on your Mac using [Apple's native container technology](https://github.com/apple/container). Process your local files without uploading them anywhere.
11+
- Python execution in persistent Jupyter kernels
12+
- AI coding agents: Claude Code, OpenAI Codex, Cursor, Gemini CLI
13+
- Cloud CLIs: AWS, GCP, Azure, GitHub
14+
- Browser automation via Playwright
15+
- Data science stack: pandas, numpy, scipy, matplotlib
1216

13-
- Execute Python in a persistent Jupyter kernel
14-
- Pre-installed data science stack (pandas, numpy, matplotlib, etc.)
15-
- Files stay on your machine
16-
- Optional browser automation via Playwright
17-
18-
**Requirements:** macOS, Apple Silicon (M1+), Python 3.10+
17+
**Requirements:** macOS 15+, Apple Silicon
1918

2019
## Install
2120

22-
### Homebrew (coming soon)
2321
```bash
2422
brew install instavm/cli/coderunner
2523
```
2624

27-
### Manual
25+
Server starts automatically at `http://coderunner.local:8222`
26+
27+
### Manual Install
28+
2829
```bash
2930
git clone https://github.com/instavm/coderunner.git
3031
cd coderunner
31-
chmod +x install.sh
32-
sudo ./install.sh
32+
./install.sh
3333
```
3434

35-
Server runs at: `http://coderunner.local:8222`
35+
### Commands
36+
37+
```bash
38+
coderunner status # Check if running
39+
coderunner stop # Stop server
40+
coderunner start # Start server
41+
coderunner run claude # Run Claude Code
42+
coderunner run codex # Run OpenAI Codex
43+
coderunner run cursor # Run Cursor
44+
coderunner exec bash # Shell into container
45+
coderunner logs # View logs
46+
```
47+
48+
### Start Options
49+
50+
```bash
51+
coderunner start --with-ssh-agent # Forward SSH agent for git
52+
coderunner start --with-credentials # Mount ~/.claude, ~/.aws, ~/.config/gh
53+
coderunner start --env-file ~/.env # Load environment from file
54+
```
3655

3756
## Usage
3857

@@ -211,9 +230,42 @@ CodeRunner includes a skills system for common tasks.
211230

212231
See [SKILLS-README.md](SKILLS-README.md) for details.
213232

214-
## Pre-installed Libraries
233+
## Configuration
234+
235+
Create `~/.coderunner.config` with your API keys:
236+
237+
```
238+
ANTHROPIC_API_KEY=sk-ant-xxx
239+
OPENAI_API_KEY=sk-xxx
240+
GITHUB_TOKEN=ghp_xxx
241+
AWS_ACCESS_KEY_ID=AKIA...
242+
AWS_SECRET_ACCESS_KEY=xxx
243+
GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
244+
```
245+
246+
Keys are loaded automatically on `coderunner start`. CLI params override config file values.
247+
248+
### Credential Locations
249+
250+
| Tool | Config Directory | Environment Variable |
251+
|------|-----------------|---------------------|
252+
| Claude Code | `~/.claude/` | `ANTHROPIC_API_KEY` |
253+
| OpenAI Codex | `~/.codex/` | `OPENAI_API_KEY` |
254+
| Cursor | `~/.cursor/` | `CURSOR_API_KEY` |
255+
| GitHub CLI | `~/.config/gh/` | `GITHUB_TOKEN` |
256+
| AWS CLI | `~/.aws/` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` |
257+
| GCP CLI | `~/.config/gcloud/` | `GOOGLE_APPLICATION_CREDENTIALS` |
258+
| Azure CLI | `~/.azure/` | `AZURE_CREDENTIALS` |
259+
260+
Use `--with-credentials` to mount these directories into the container (read-only).
261+
262+
## Pre-installed Tools
263+
264+
**Python:** pandas, numpy, scipy, matplotlib, seaborn, scikit-learn, pillow, pypdf, python-docx, openpyxl, beautifulsoup4, requests, httpx, playwright
265+
266+
**AI Agents:** Claude Code, OpenAI Codex, Cursor, Gemini CLI
215267

216-
The sandbox includes: pandas, numpy, scipy, matplotlib, seaborn, pillow, pypdf, python-docx, openpyxl, beautifulsoup4, requests, httpx, and more.
268+
**Cloud CLIs:** aws, gcloud, az, gh
217269

218270
## Security
219271

install.sh

Lines changed: 132 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,91 @@
11
#!/bin/bash
22

3+
# CodeRunner Install Script
4+
# Installs and starts the CodeRunner sandbox container
5+
6+
set -e
7+
8+
# --- Configuration ---
9+
CONFIG_FILE="${CODERUNNER_CONFIG:-$HOME/.coderunner.config}"
10+
CODERUNNER_HOME="${CODERUNNER_HOME:-$HOME/.coderunner}"
11+
12+
# --- Default options ---
13+
WITH_SSH_AGENT=false
14+
WITH_CREDENTIALS=false
15+
ENV_FILE=""
16+
17+
# --- Parse command line arguments ---
18+
while [[ $# -gt 0 ]]; do
19+
case $1 in
20+
--with-ssh-agent)
21+
WITH_SSH_AGENT=true
22+
shift
23+
;;
24+
--with-credentials)
25+
WITH_CREDENTIALS=true
26+
shift
27+
;;
28+
--env-file)
29+
ENV_FILE="$2"
30+
shift 2
31+
;;
32+
--config)
33+
CONFIG_FILE="$2"
34+
shift 2
35+
;;
36+
-h|--help)
37+
echo "Usage: install.sh [OPTIONS]"
38+
echo ""
39+
echo "Options:"
40+
echo " --with-ssh-agent Forward SSH agent for git operations"
41+
echo " --with-credentials Mount config directories (~/.claude, ~/.config/gh, etc.)"
42+
echo " --env-file FILE Load environment variables from file"
43+
echo " --config FILE Use custom config file (default: ~/.coderunner.config)"
44+
echo ""
45+
echo "Config file format (~/.coderunner.config):"
46+
echo " ANTHROPIC_API_KEY=sk-xxx"
47+
echo " OPENAI_API_KEY=sk-xxx"
48+
echo " GITHUB_TOKEN=ghp_xxx"
49+
exit 0
50+
;;
51+
*)
52+
echo "Unknown option: $1"
53+
exit 1
54+
;;
55+
esac
56+
done
57+
58+
# --- Load config file if exists ---
59+
declare -a ENV_VARS
60+
if [[ -f "$CONFIG_FILE" ]]; then
61+
echo "Loading config from $CONFIG_FILE"
62+
while IFS='=' read -r key value; do
63+
# Skip comments and empty lines
64+
[[ "$key" =~ ^#.*$ ]] && continue
65+
[[ -z "$key" ]] && continue
66+
# Trim whitespace
67+
key=$(echo "$key" | xargs)
68+
value=$(echo "$value" | xargs)
69+
if [[ -n "$key" && -n "$value" ]]; then
70+
ENV_VARS+=("--env" "$key=$value")
71+
fi
72+
done < "$CONFIG_FILE"
73+
fi
74+
75+
# --- Load env file if specified ---
76+
if [[ -n "$ENV_FILE" && -f "$ENV_FILE" ]]; then
77+
echo "Loading environment from $ENV_FILE"
78+
while IFS='=' read -r key value; do
79+
[[ "$key" =~ ^#.*$ ]] && continue
80+
[[ -z "$key" ]] && continue
81+
key=$(echo "$key" | xargs)
82+
value=$(echo "$value" | xargs)
83+
if [[ -n "$key" && -n "$value" ]]; then
84+
ENV_VARS+=("--env" "$key=$value")
85+
fi
86+
done < "$ENV_FILE"
87+
fi
88+
389
# Function to get current macOS version
490
get_macos_version() {
591
sw_vers -productVersion | awk -F. '{print $1 "." $2}'
@@ -105,8 +191,8 @@ if ! container image pull instavm/coderunner; then
105191
exit 1
106192
fi
107193

108-
echo "→ Ensuring coderunner assets directories"
109-
ASSETS_SRC="$HOME/.coderunner/assets"
194+
echo "→ Ensuring coderunner directories..."
195+
ASSETS_SRC="$CODERUNNER_HOME/assets"
110196
mkdir -p "$ASSETS_SRC/skills/user"
111197
mkdir -p "$ASSETS_SRC/outputs"
112198

@@ -115,19 +201,57 @@ echo "Stopping any existing coderunner container..."
115201
container stop coderunner 2>/dev/null || true
116202
sleep 2
117203

118-
# Run the command to start the sandbox container
119-
echo "Running: container run --name coderunner --detach --rm --cpus 8 --memory 4g instavm/coderunner"
204+
# --- Build volume mounts ---
205+
declare -a VOLUME_MOUNTS
206+
VOLUME_MOUNTS+=("--volume" "$ASSETS_SRC/skills/user:/app/uploads/skills/user")
207+
VOLUME_MOUNTS+=("--volume" "$ASSETS_SRC/outputs:/app/uploads/outputs")
208+
209+
# SSH Agent forwarding
210+
if [[ "$WITH_SSH_AGENT" == true && -n "$SSH_AUTH_SOCK" ]]; then
211+
echo "Enabling SSH agent forwarding..."
212+
VOLUME_MOUNTS+=("--volume" "$SSH_AUTH_SOCK:/ssh-agent")
213+
ENV_VARS+=("--env" "SSH_AUTH_SOCK=/ssh-agent")
214+
fi
215+
216+
# Credential directory mounts (read-only)
217+
if [[ "$WITH_CREDENTIALS" == true ]]; then
218+
echo "Mounting credential directories..."
219+
# AI CLIs
220+
[[ -d "$HOME/.claude" ]] && VOLUME_MOUNTS+=("--volume" "$HOME/.claude:/root/.claude:ro")
221+
[[ -d "$HOME/.cursor" ]] && VOLUME_MOUNTS+=("--volume" "$HOME/.cursor:/root/.cursor:ro")
222+
[[ -d "$HOME/.codex" ]] && VOLUME_MOUNTS+=("--volume" "$HOME/.codex:/root/.codex:ro")
223+
# Cloud CLIs
224+
[[ -d "$HOME/.config/gh" ]] && VOLUME_MOUNTS+=("--volume" "$HOME/.config/gh:/root/.config/gh:ro")
225+
[[ -d "$HOME/.config/gcloud" ]] && VOLUME_MOUNTS+=("--volume" "$HOME/.config/gcloud:/root/.config/gcloud:ro")
226+
[[ -d "$HOME/.aws" ]] && VOLUME_MOUNTS+=("--volume" "$HOME/.aws:/root/.aws:ro")
227+
[[ -d "$HOME/.azure" ]] && VOLUME_MOUNTS+=("--volume" "$HOME/.azure:/root/.azure:ro")
228+
fi
229+
230+
# Run the container
231+
echo "Starting coderunner container..."
120232
if container run \
121-
--volume "$ASSETS_SRC/skills/user:/app/uploads/skills/user" \
122-
--volume "$ASSETS_SRC/outputs:/app/uploads/outputs" \
233+
"${VOLUME_MOUNTS[@]}" \
234+
"${ENV_VARS[@]}" \
123235
--name coderunner \
124236
--detach \
125237
--rm \
126238
--cpus 8 \
127239
--memory 4g \
128240
instavm/coderunner; then
129-
echo "✅ Setup complete. MCP server is available at http://coderunner.local:8222/mcp"
241+
echo ""
242+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
243+
echo "CodeRunner is running"
244+
echo ""
245+
echo " Server: http://coderunner.local:8222"
246+
echo " MCP: http://coderunner.local:8222/mcp"
247+
echo " Health: http://coderunner.local:8222/health"
248+
echo ""
249+
echo "Commands:"
250+
echo " coderunner status Check server status"
251+
echo " coderunner stop Stop the server"
252+
echo " coderunner run Run AI agents (claude, codex, cursor)"
253+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
130254
else
131-
echo "Failed to start coderunner container. Please check the logs with: container logs coderunner"
255+
echo "Failed to start container. Check logs: container logs coderunner"
132256
exit 1
133257
fi

0 commit comments

Comments
 (0)