From 2b91920ae3c0300a282ce5ca11907844639ee91a Mon Sep 17 00:00:00 2001 From: James Doyle Date: Sun, 15 Feb 2026 13:09:01 -0800 Subject: [PATCH] feat: Add Docker and Docker Compose support --- .gitignore | 2 + Dockerfile | 28 ++++++++++++ README.md | 29 ++++++++++++ clawlet.config.json | 109 ++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 18 ++++++++ 5 files changed, 186 insertions(+) create mode 100644 Dockerfile create mode 100644 clawlet.config.json create mode 100644 docker-compose.yml diff --git a/.gitignore b/.gitignore index 2abf8a2..61ae4cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .tmp .idea dist/ + +.env \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2d826ba --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +# docker run -e OPENROUTER_API_KEY="$OPENROUTER_API_KEY" -p 18790:18790 -it --volume="$PWD:/app" --workdir="/app" --entrypoint=/bin/sh clawlet +FROM golang:1.26-alpine AS builder + +RUN apk add --no-cache gcc musl-dev + +WORKDIR /app + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . + +RUN CGO_ENABLED=1 go build -o clawlet ./cmd/clawlet + +FROM alpine:latest + +RUN apk add --no-cache ca-certificates + +WORKDIR /app + +COPY --from=builder /app/clawlet /usr/local/bin + +RUN clawlet onboard +RUN clawlet status + +EXPOSE 18790 + +ENTRYPOINT ["clawlet", "gateway"] diff --git a/README.md b/README.md index 528ffc0..d433eac 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,35 @@ clawlet status clawlet agent -m "What is 2+2?" ``` +## Docker + +Run clawlet using Docker or Docker Compose instead of installing locally. + +### Dockerfile + +The Dockerfile uses a multi-stage build: it compiles the Go application with CGO enabled (for sqlite-vec), then runs it in a minimal Alpine container. The container automatically runs `clawlet onboard` and `clawlet status` on first build, then starts the gateway. + +### Docker Compose + +```bash +docker-compose up --build +``` + +The gateway will be available at `http://localhost:18790`. + +### Plain Docker + +```bash +# Build the image +docker build -t clawlet . + +# Run the gateway +docker run -e OPENROUTER_API_KEY="$OPENROUTER_API_KEY" \ + -p 18790:18790 \ + -v "$PWD/clawlet.config.json:/root/.clawlet/config.json" \ + clawlet +``` + ## Configuration (`~/.clawlet/config.json`) Config file: `~/.clawlet/config.json` diff --git a/clawlet.config.json b/clawlet.config.json new file mode 100644 index 0000000..06b80ea --- /dev/null +++ b/clawlet.config.json @@ -0,0 +1,109 @@ +{ + "agents": { + "defaults": { + "model": "openrouter/google/gemini-3-flash-preview", + "maxTokens": 8192, + "temperature": 0.2, + "memoryWindow": 50, + "memorySearch": { + "enabled": false, + "provider": "openai", + "model": "text-embedding-3-small", + "remote": { + "baseURL": "https://api.openai.com/v1", + "apiKey": "", + "headers": {} + }, + "store": { + "path": "./memory-store", + "vector": { + "enabled": true + } + }, + "chunking": { + "tokens": 400, + "overlap": 80 + }, + "query": { + "maxResults": 6, + "minScore": 0.35, + "hybrid": { + "vectorWeight": 0.7, + "textWeight": 0.3, + "candidateMultiplier": 4 + } + }, + "cache": { + "enabled": true, + "maxEntries": 1000 + }, + "sync": { + "onSearch": true + } + } + } + }, + "tools": { + "restrictToWorkspace": true, + "exec": { + "timeoutSec": 60 + }, + "web": { + "braveApiKey": "" + } + }, + "cron": { + "enabled": true + }, + "heartbeat": { + "enabled": true, + "intervalSec": 1800 + }, + "gateway": { + "listen": "0.0.0.0:18790" + }, + "channels": { + "discord": { + "enabled": false, + "token": "", + "allowFrom": [ + "123456789" + ], + "gatewayURL": "wss://gateway.discord.gg/?v=10&encoding=json", + "intents": 37377 + }, + "slack": { + "enabled": false, + "allowFrom": [ + "U123ABC", + "U456DEF" + ], + "botToken": "xoxb-...", + "appToken": "xapp-...", + "groupPolicy": "mention", + "groupAllowFrom": [ + "C123CHAN" + ], + "dm": { + "enabled": true + } + }, + "telegram": { + "enabled": false, + "token": "", + "allowFrom": [ + "123456789" + ], + "baseURL": "https://api.telegram.org", + "pollTimeoutSec": 25, + "workers": 2 + }, + "whatsapp": { + "enabled": false, + "allowFrom": [ + "+1234567890" + ], + "sessionStorePath": "./whatsapp-session.db" + } + } +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..dc5cf62 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,18 @@ +services: + clawlet: + build: + context: . + dockerfile: Dockerfile + container_name: clawlet + ports: + - "18790:18790" + environment: + # @see https://github.com/mosaxiv/clawlet?tab=readme-ov-file#supported-providers + # uses your shell ENV OR a `.env` + - OPENROUTER_API_KEY=${OPENROUTER_API_KEY} + volumes: + # copies the local config file to the container + - ./clawlet.config.json:/root/.clawlet/config.json + entrypoint: ["clawlet", "gateway"] + stdin_open: true + tty: true \ No newline at end of file