-
Notifications
You must be signed in to change notification settings - Fork 534
Add Docker support for Windows and cross-platform execution #173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # Git | ||
| .git | ||
|
|
||
| # Node modules | ||
| node_modules/ | ||
|
|
||
| # Ralph state files (rebuilt at runtime) | ||
| .ralph/.call_count | ||
| .ralph/.last_reset | ||
| .ralph/.exit_signals | ||
| .ralph/.response_analysis | ||
| .ralph/.circuit_breaker_state | ||
| .ralph/.circuit_breaker_history | ||
| .ralph/.json_parse_result | ||
| .ralph/.last_output_length | ||
| .ralph/.ralph_session | ||
| .ralph/.ralph_session_history | ||
| .ralph/.claude_session_id | ||
| .ralph/status.json | ||
| .ralph/logs/ | ||
|
|
||
| # Coverage and test artifacts | ||
| coverage/ | ||
| *.log | ||
|
|
||
| # OS files | ||
| .DS_Store | ||
| Thumbs.db | ||
|
|
||
| # IDE files | ||
| .vscode/ | ||
| .idea/ | ||
| *.swp | ||
| *.swo |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # Force LF line endings for all shell scripts and test files | ||
| # Prevents Windows CRLF corruption of bash scripts | ||
| *.sh text eol=lf | ||
| *.bats text eol=lf | ||
| *.bash text eol=lf | ||
|
|
||
| # Docker files | ||
| Dockerfile text eol=lf | ||
| docker-compose.yml text eol=lf | ||
| docker-entrypoint.sh text eol=lf | ||
|
|
||
| # Keep markdown and other text files as auto | ||
| *.md text | ||
| *.yml text | ||
| *.yaml text | ||
| *.json text | ||
|
|
||
| # Binary files | ||
| *.png binary | ||
| *.jpg binary | ||
| *.gif binary |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| name: Docker Build | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ main, develop ] | ||
| paths: | ||
| - 'Dockerfile' | ||
| - 'docker/**' | ||
| - '.dockerignore' | ||
| - 'install.sh' | ||
| - 'lib/**' | ||
| - 'ralph_loop.sh' | ||
| pull_request: | ||
| branches: [ main ] | ||
| paths: | ||
| - 'Dockerfile' | ||
| - 'docker/**' | ||
| - '.dockerignore' | ||
| - 'install.sh' | ||
| - 'lib/**' | ||
| - 'ralph_loop.sh' | ||
|
|
||
| jobs: | ||
| build: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v3 | ||
|
|
||
| - name: Build Docker image | ||
| run: docker build -t ralph-claude-code:test . | ||
|
|
||
| - name: Verify Ralph is installed | ||
| run: docker run --rm ralph-claude-code:test ralph --help | ||
|
|
||
| - name: Verify dependencies | ||
| run: | | ||
| docker run --rm ralph-claude-code:test bash -c ' | ||
| echo "=== Checking dependencies ===" | ||
| bash --version | head -1 | ||
| node --version | ||
| npm --version | ||
| jq --version | ||
| git --version | ||
| tmux -V | ||
| timeout --version | head -1 | ||
| echo "=== All dependencies OK ===" | ||
| ' | ||
|
|
||
| - name: Run tests inside Docker | ||
| run: docker run --rm ralph-claude-code:test bash -c 'cd /opt/ralph-claude-code && npm test' | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,9 @@ target/ | |
| *.swp | ||
| *.swo | ||
|
|
||
| # Docker | ||
| docker/tmp/ | ||
|
|
||
| # Claude Code local settings | ||
| .claude/settings.local.json | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,46 @@ | ||||||||||||||||||
| FROM debian:bookworm-slim | ||||||||||||||||||
|
|
||||||||||||||||||
| # System dependencies | ||||||||||||||||||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||||||||||||||||||
| bash \ | ||||||||||||||||||
| jq \ | ||||||||||||||||||
| git \ | ||||||||||||||||||
| tmux \ | ||||||||||||||||||
| coreutils \ | ||||||||||||||||||
| curl \ | ||||||||||||||||||
| ca-certificates \ | ||||||||||||||||||
| gosu \ | ||||||||||||||||||
| procps \ | ||||||||||||||||||
| && rm -rf /var/lib/apt/lists/* | ||||||||||||||||||
|
|
||||||||||||||||||
| # Install Node.js 20 LTS | ||||||||||||||||||
| RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ | ||||||||||||||||||
| && apt-get install -y --no-install-recommends nodejs \ | ||||||||||||||||||
| && rm -rf /var/lib/apt/lists/* | ||||||||||||||||||
|
Comment on lines
+16
to
+19
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: Node.js 20.x (Iron) reaches End-of-Life (EOL) on April 30, 2026—after that date, the Node.js project ends official maintenance/security support for the 20.x line. [1][2] 🌐 Web query:
💡 Result: Node.js LTS support timeline (v22 vs v24) in/around 2026 Node.js 22.x (“Jod”)
Node.js 24.x (“Krypton”)
Practical takeaway for 2026:
Sources: official Node.js releases page [1] and the Node.js Release Working Group schedule [2]. Upgrade to Node.js 24 LTS instead — Node.js 20 reaches end-of-life April 30, 2026. Node.js 20 maintenance support ends April 30, 2026. Node.js 22 is currently in Maintenance LTS. For better long-term support, use Node.js 24, which is the current Active LTS and will remain supported through October 2026. -RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
+RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| # Install Claude Code CLI globally | ||||||||||||||||||
| RUN npm install -g @anthropic-ai/claude-code | ||||||||||||||||||
|
|
||||||||||||||||||
| # Create ralph user | ||||||||||||||||||
| RUN groupadd -g 1000 ralph \ | ||||||||||||||||||
| && useradd -m -u 1000 -g ralph -s /bin/bash ralph | ||||||||||||||||||
|
|
||||||||||||||||||
| # Copy Ralph source | ||||||||||||||||||
| COPY . /opt/ralph-claude-code/ | ||||||||||||||||||
|
|
||||||||||||||||||
| # Install Ralph as the ralph user | ||||||||||||||||||
| USER ralph | ||||||||||||||||||
| RUN cd /opt/ralph-claude-code && bash install.sh | ||||||||||||||||||
| ENV PATH="/home/ralph/.local/bin:${PATH}" | ||||||||||||||||||
|
|
||||||||||||||||||
| # Switch back to root for entrypoint (handles UID remapping) | ||||||||||||||||||
| USER root | ||||||||||||||||||
|
|
||||||||||||||||||
| # Copy entrypoint | ||||||||||||||||||
| COPY docker/docker-entrypoint.sh /usr/local/bin/ | ||||||||||||||||||
| RUN chmod +x /usr/local/bin/docker-entrypoint.sh | ||||||||||||||||||
|
|
||||||||||||||||||
| WORKDIR /workspace | ||||||||||||||||||
|
|
||||||||||||||||||
| ENTRYPOINT ["docker-entrypoint.sh"] | ||||||||||||||||||
| CMD ["ralph", "--help"] | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| services: | ||
| ralph: | ||
| build: | ||
| context: . | ||
| dockerfile: Dockerfile | ||
| image: ralph-claude-code:latest | ||
| container_name: ralph | ||
| stdin_open: true | ||
| tty: true | ||
| working_dir: /workspace | ||
| environment: | ||
| - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} | ||
| - RALPH_UID=${RALPH_UID:-1000} | ||
| - RALPH_GID=${RALPH_GID:-1000} | ||
| volumes: | ||
| - ./:/workspace | ||
| # Optional: mount git config for commits | ||
| # - ~/.gitconfig:/home/ralph/.gitconfig:ro | ||
| # Optional: mount SSH keys for git push | ||
| # - ~/.ssh:/home/ralph/.ssh:ro | ||
| command: ["ralph", "--help"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| #!/bin/bash | ||
| set -e | ||
|
|
||
| # Default UID/GID matching typical Linux/macOS user | ||
| RALPH_UID=${RALPH_UID:-1000} | ||
| RALPH_GID=${RALPH_GID:-1000} | ||
|
|
||
| # Remap ralph user UID/GID to match host user (avoids file permission issues on bind mounts) | ||
| if [ "$(id -u ralph)" != "$RALPH_UID" ] || [ "$(id -g ralph)" != "$RALPH_GID" ]; then | ||
| groupmod -g "$RALPH_GID" ralph 2>/dev/null || true | ||
| usermod -u "$RALPH_UID" -g "$RALPH_GID" -d /home/ralph ralph 2>/dev/null || true | ||
| chown -R ralph:ralph /home/ralph 2>/dev/null || true | ||
| fi | ||
|
|
||
| # Git safe.directory for mounted workspace | ||
| gosu ralph git config --global --add safe.directory /workspace 2>/dev/null || true | ||
|
|
||
| # Warn if API key is missing | ||
| if [ -z "$ANTHROPIC_API_KEY" ]; then | ||
| echo "WARNING: ANTHROPIC_API_KEY is not set. Ralph will not be able to call Claude." | ||
| echo "Set it with: docker run -e ANTHROPIC_API_KEY=your-key ..." | ||
| echo "" | ||
| fi | ||
|
|
||
| # Execute command as ralph user | ||
| exec gosu ralph "$@" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #!/bin/bash | ||
| # ralph-docker - Convenience wrapper for running Ralph in Docker | ||
| # | ||
| # Usage: | ||
| # ./docker/ralph-docker [ralph-options] | ||
| # | ||
| # Examples: | ||
| # ./docker/ralph-docker --help | ||
| # ./docker/ralph-docker --monitor | ||
| # ./docker/ralph-docker --live --verbose | ||
| # | ||
| # Environment: | ||
| # ANTHROPIC_API_KEY Required. Your Anthropic API key. | ||
| # RALPH_IMAGE Optional. Docker image name (default: ralph-claude-code:latest) | ||
|
|
||
| set -e | ||
|
|
||
| IMAGE_NAME="${RALPH_IMAGE:-ralph-claude-code:latest}" | ||
|
|
||
| if [ -z "$ANTHROPIC_API_KEY" ]; then | ||
| echo "Error: ANTHROPIC_API_KEY environment variable is not set." | ||
| echo "Export it first: export ANTHROPIC_API_KEY=sk-ant-..." | ||
| exit 1 | ||
| fi | ||
|
|
||
| EXTRA_VOLUMES=() | ||
|
|
||
| # Mount git config if available | ||
| if [ -f "$HOME/.gitconfig" ]; then | ||
| EXTRA_VOLUMES+=(-v "$HOME/.gitconfig:/home/ralph/.gitconfig:ro") | ||
| fi | ||
|
|
||
| # Mount SSH keys if available | ||
| if [ -d "$HOME/.ssh" ]; then | ||
| EXTRA_VOLUMES+=(-v "$HOME/.ssh:/home/ralph/.ssh:ro") | ||
| fi | ||
|
|
||
| docker run -it --rm \ | ||
| -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \ | ||
| -e RALPH_UID="$(id -u)" \ | ||
| -e RALPH_GID="$(id -g)" \ | ||
| -v "$(pwd):/workspace" \ | ||
| "${EXTRA_VOLUMES[@]}" \ | ||
| "$IMAGE_NAME" \ | ||
| ralph "$@" |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,40 @@ | ||||||||||||||||||||||||||||||
| # ralph-docker.ps1 - Convenience wrapper for running Ralph in Docker on Windows | ||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||
| # Usage: | ||||||||||||||||||||||||||||||
| # .\docker\ralph-docker.ps1 [ralph-options] | ||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||
| # Examples: | ||||||||||||||||||||||||||||||
| # .\docker\ralph-docker.ps1 --help | ||||||||||||||||||||||||||||||
| # .\docker\ralph-docker.ps1 --monitor | ||||||||||||||||||||||||||||||
| # .\docker\ralph-docker.ps1 --live --verbose | ||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||
| # Environment: | ||||||||||||||||||||||||||||||
| # ANTHROPIC_API_KEY Required. Your Anthropic API key. | ||||||||||||||||||||||||||||||
| # RALPH_IMAGE Optional. Docker image name (default: ralph-claude-code:latest) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| param( | ||||||||||||||||||||||||||||||
| [Parameter(ValueFromRemainingArguments = $true)] | ||||||||||||||||||||||||||||||
| [string[]]$RalphArgs | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| $ImageName = if ($env:RALPH_IMAGE) { $env:RALPH_IMAGE } else { "ralph-claude-code:latest" } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if (-not $env:ANTHROPIC_API_KEY) { | ||||||||||||||||||||||||||||||
| Write-Error "ANTHROPIC_API_KEY environment variable is not set." | ||||||||||||||||||||||||||||||
| Write-Host 'Set it first: $env:ANTHROPIC_API_KEY = "sk-ant-..."' | ||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| $DockerArgs = @( | ||||||||||||||||||||||||||||||
| "run", "-it", "--rm", | ||||||||||||||||||||||||||||||
| "-e", "ANTHROPIC_API_KEY=$env:ANTHROPIC_API_KEY", | ||||||||||||||||||||||||||||||
| "-v", "${PWD}:/workspace", | ||||||||||||||||||||||||||||||
| $ImageName, | ||||||||||||||||||||||||||||||
| "ralph" | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if ($RalphArgs) { | ||||||||||||||||||||||||||||||
| $DockerArgs += $RalphArgs | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| & docker @DockerArgs | ||||||||||||||||||||||||||||||
|
Comment on lines
+36
to
+40
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing exit code propagation from If Proposed fix if ($RalphArgs) {
$DockerArgs += $RalphArgs
}
& docker `@DockerArgs`
+$exitCode = $LASTEXITCODE
+if ($exitCode -ne 0) {
+ exit $exitCode
+}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update
actions/checkoutfrom v3 to v4.As flagged by actionlint,
actions/checkout@v3uses Node.js 16 which is deprecated on GitHub Actions. Update to v4.📝 Committable suggestion
🧰 Tools
🪛 actionlint (1.7.10)
[error] 28-28: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🤖 Prompt for AI Agents