Provider docs used

This tutorial follows Docker's guidance for Dockerfiles, bind mounts, and Compose secrets. Dockerfiles define the runner image. Bind mounts share source code with the container. Compose secrets mount sensitive values into /run/secrets on a per-service basis. Keep the provider docs open: Dockerfile overview, Bind mounts, and Compose secrets.

Step 1: Create the runner image

Create a Dockerfile at the root of a runner project, not inside every repository you want Autohand Code to inspect.

FROM node:22-bookworm

RUN apt-get update \
  && apt-get install -y --no-install-recommends git openssh-client ca-certificates build-essential \
  && rm -rf /var/lib/apt/lists/*

RUN npm install -g autohand-cli

WORKDIR /workspace
ENTRYPOINT ["autohand"]
docker build -t autohand-runner:local .

Step 2: Run against a local repository

Mount the repository into /workspace. Docker bind mounts can write to the host by default, so use readonly for review-only jobs.

cd /path/to/your-repo

docker run --rm -it \
  --mount type=bind,src="$PWD",dst=/workspace,readonly \
  -e OPENROUTER_API_KEY \
  -e AUTOHAND_MODEL="anthropic/claude-sonnet-4" \
  autohand-runner:local \
  -p "Review this repository and summarize the highest-risk issues" --restricted

Remove readonly only for trusted write jobs that need to update files in the mounted repository.

Step 3: Keep secrets out of the image

Do not bake model provider keys into the Dockerfile. Pass them at runtime, or use Compose secrets for long-running runner services.

services:
  autohand:
    image: autohand-runner:local
    working_dir: /workspace
    volumes:
      - ./your-repo:/workspace
    secrets:
      - openrouter_api_key
    environment:
      AUTOHAND_MODEL: anthropic/claude-sonnet-4
    entrypoint: ["/bin/bash", "-lc"]
    command: >
      export OPENROUTER_API_KEY="$(cat /run/secrets/openrouter_api_key)" &&
      autohand -p "Review this repository and write a risk summary" --restricted --output-format stream-json

secrets:
  openrouter_api_key:
    file: ./secrets/openrouter_api_key.txt

Step 4: Give the container Git access

For private repositories, mount a read-only deploy key and known hosts file. Avoid mounting your entire personal ~/.ssh directory.

docker run --rm -it \
  --mount type=bind,src="$PWD",dst=/workspace \
  --mount type=bind,src="$HOME/.ssh/github-autohand",dst=/home/node/.ssh/id_ed25519,readonly \
  --mount type=bind,src="$HOME/.ssh/known_hosts",dst=/home/node/.ssh/known_hosts,readonly \
  -e OPENROUTER_API_KEY \
  autohand-runner:local \
  -p "Update docs for the latest CLI changes, then summarize the diff" --output-format stream-json

Step 5: Use Docker on a remote host

When the Docker daemon is remote, bind mounts refer to paths on the remote daemon host, not your local laptop. Clone the repository on the remote host first, then run the container there.

ssh [email protected]
cd ~/work/your-repo

docker run --rm \
  --mount type=bind,src="$PWD",dst=/workspace \
  --env-file ~/.autohand/env \
  autohand-runner:local \
  -p "Run tests and fix straightforward failures" --output-format stream-json

Operations checklist

  • Keep runner images small and rebuild them when Node.js or Autohand Code changes.
  • Use read-only mounts for analysis jobs.
  • Mount only the Git keys needed for the job.
  • Use Compose secrets or runtime environment injection, not Dockerfile ENV, for provider keys.
  • Pin image tags in production runner scripts.