diff --git a/Dockerfile b/Dockerfile index 883f55b5..ae297a95 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,7 +58,7 @@ ARG USER_UID=1000 ARG USER_GID=1000 WORKDIR /app COPY --chown=node:node --from=build /app /app -RUN npm install --global --omit=dev @anthropic-ai/claude-code@latest @openai/codex@latest opencode-ai \ +RUN npm install --global --omit=dev @anthropic-ai/claude-code@latest @openai/codex@latest opencode-ai @google/gemini-cli@latest \ && apt-get update \ && apt-get install -y --no-install-recommends openssh-client jq \ && rm -rf /var/lib/apt/lists/* \ @@ -80,7 +80,8 @@ ENV NODE_ENV=production \ PAPERCLIP_CONFIG=/paperclip/instances/default/config.json \ PAPERCLIP_DEPLOYMENT_MODE=authenticated \ PAPERCLIP_DEPLOYMENT_EXPOSURE=private \ - OPENCODE_ALLOW_ALL_MODELS=true + OPENCODE_ALLOW_ALL_MODELS=true \ + GEMINI_SANDBOX=false VOLUME ["/paperclip"] EXPOSE 3100 diff --git a/docs/deploy/docker.md b/docs/deploy/docker.md index 9fc2dbfe..d741b86c 100644 --- a/docs/deploy/docker.md +++ b/docs/deploy/docker.md @@ -48,12 +48,14 @@ All data is persisted under the bind mount (`./data/docker-paperclip`): - Local secrets key - Agent workspace data -## Claude and Codex Adapters in Docker +## Local Adapter CLIs in Docker -The Docker image pre-installs: +The Docker image pre-installs these agent CLIs so their `*_local` adapters can run inside the container: -- `claude` (Anthropic Claude Code CLI) -- `codex` (OpenAI Codex CLI) +- `claude` (Anthropic Claude Code CLI) — `claude_local` +- `codex` (OpenAI Codex CLI) — `codex_local` +- `opencode` (OpenCode multi-provider CLI) — `opencode_local` +- `gemini` (Google Gemini CLI) — `gemini_local` (experimental) Pass API keys to enable local adapter runs inside the container: @@ -64,8 +66,15 @@ docker run --name paperclip \ -e PAPERCLIP_HOME=/paperclip \ -e OPENAI_API_KEY=sk-... \ -e ANTHROPIC_API_KEY=sk-... \ + -e GEMINI_API_KEY=... \ -v "$(pwd)/data/docker-paperclip:/paperclip" \ paperclip-local ``` +Each adapter reads its provider's standard credentials — for example `ANTHROPIC_API_KEY` (Claude), `OPENAI_API_KEY` (Codex), and `GEMINI_API_KEY` or `GOOGLE_API_KEY` (Gemini). OpenCode is multi-provider and uses whichever provider key you supply. + +> **Gemini key restrictions:** Google requires Gemini API keys to be *restricted* to the Gemini API (scoped in the Google Cloud console); unrestricted keys are blocked and `gemini_local` runs will fail with an auth error. Create a restricted key, or authenticate with `gemini auth login` (OAuth) and persist `~/.gemini` via the data volume so the credential survives container restarts. + +The image sets `GEMINI_SANDBOX=false` so the Gemini CLI does not try to launch its own (Docker-in-Docker) sandbox inside the container. The `gemini_local` adapter already passes `--sandbox=none` per run, so this env var only matters if you invoke `gemini` manually inside the container; override it if you have nested-container support and want CLI-level sandboxing. + Without API keys, the app runs normally — adapter environment checks will surface missing prerequisites.