From 20227f1f04ea195ec681477f03905f4954cc9f9a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Feb 2026 08:55:21 +0000 Subject: [PATCH 1/7] feat: add Dockerfile with uv-based installation Add a Dockerfile using the official uv Python image (python3.12-bookworm-slim) for fast dependency installation. Includes Node.js 20 for the WhatsApp bridge, dependency layer caching, and exposes the gateway port (18790). https://claude.ai/code/session_011C1h1NERqqZp4ht3Pqpwkc --- .dockerignore | 13 +++++++++++++ Dockerfile | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..020b9ec --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +__pycache__ +*.pyc +*.pyo +*.pyd +*.egg-info +dist/ +build/ +.git +.env +.assets +node_modules/ +bridge/dist/ +workspace/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..21a502a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim + +# Install Node.js 20 for the WhatsApp bridge +RUN apt-get update && \ + apt-get install -y --no-install-recommends curl ca-certificates gnupg && \ + mkdir -p /etc/apt/keyrings && \ + curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" > /etc/apt/sources.list.d/nodesource.list && \ + apt-get update && \ + apt-get install -y --no-install-recommends nodejs && \ + apt-get purge -y gnupg && \ + apt-get autoremove -y && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +# Install Python dependencies first (cached layer) +COPY pyproject.toml README.md LICENSE ./ +RUN mkdir -p nanobot && touch nanobot/__init__.py && \ + uv pip install --system --no-cache . && \ + rm -rf nanobot + +# Copy the full source and install +COPY nanobot/ nanobot/ +COPY bridge/ bridge/ +RUN uv pip install --system --no-cache . + +# Build the WhatsApp bridge +WORKDIR /app/bridge +RUN npm install && npm run build +WORKDIR /app + +# Create config directory +RUN mkdir -p /root/.nanobot + +# Gateway default port +EXPOSE 18790 + +ENTRYPOINT ["nanobot"] +CMD ["gateway"] From 6df4a56586d5411389f985d63b1b4b17b6d5960b Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Feb 2026 08:59:57 +0000 Subject: [PATCH 2/7] test: add script to verify Dockerfile builds and nanobot status works Builds the image, runs onboard + status inside the container, and validates that the expected output fields (Config, Workspace, Model, API keys) are present. https://claude.ai/code/session_011C1h1NERqqZp4ht3Pqpwkc --- test_docker.sh | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100755 test_docker.sh diff --git a/test_docker.sh b/test_docker.sh new file mode 100755 index 0000000..a90e080 --- /dev/null +++ b/test_docker.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +set -euo pipefail + +IMAGE_NAME="nanobot-test" + +echo "=== Building Docker image ===" +docker build -t "$IMAGE_NAME" . + +echo "" +echo "=== Running 'nanobot onboard' ===" +docker run --name nanobot-test-run "$IMAGE_NAME" onboard + +echo "" +echo "=== Running 'nanobot status' ===" +STATUS_OUTPUT=$(docker commit nanobot-test-run nanobot-test-onboarded > /dev/null && \ + docker run --rm nanobot-test-onboarded status 2>&1) || true + +echo "$STATUS_OUTPUT" + +echo "" +echo "=== Validating output ===" +PASS=true + +check() { + if echo "$STATUS_OUTPUT" | grep -q "$1"; then + echo " PASS: found '$1'" + else + echo " FAIL: missing '$1'" + PASS=false + fi +} + +check "nanobot Status" +check "Config:" +check "Workspace:" +check "Model:" +check "OpenRouter API:" +check "Anthropic API:" +check "OpenAI API:" + +echo "" +if $PASS; then + echo "=== All checks passed ===" +else + echo "=== Some checks FAILED ===" + exit 1 +fi + +# Cleanup +echo "" +echo "=== Cleanup ===" +docker rm -f nanobot-test-run 2>/dev/null || true +docker rmi -f nanobot-test-onboarded 2>/dev/null || true +docker rmi -f "$IMAGE_NAME" 2>/dev/null || true +echo "Done." From fa25856d8cefda9f0e8559d71006f72bdcb614ed Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Feb 2026 09:07:23 +0000 Subject: [PATCH 3/7] fix: create stub bridge/ dir in dependency caching layer Hatchling's force-include requires bridge/ to exist at build time. The dependency caching step now stubs both nanobot/ and bridge/. https://claude.ai/code/session_011C1h1NERqqZp4ht3Pqpwkc --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 21a502a..5244f1a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,9 +16,9 @@ WORKDIR /app # Install Python dependencies first (cached layer) COPY pyproject.toml README.md LICENSE ./ -RUN mkdir -p nanobot && touch nanobot/__init__.py && \ +RUN mkdir -p nanobot bridge && touch nanobot/__init__.py && \ uv pip install --system --no-cache . && \ - rm -rf nanobot + rm -rf nanobot bridge # Copy the full source and install COPY nanobot/ nanobot/ From f7e8e73c5414c1e1bdb600da56ec1bc168b3b65b Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Feb 2026 09:17:24 +0000 Subject: [PATCH 4/7] fix: add git to Dockerfile for npm bridge dependency install A bridge npm dependency requires git to be present at install time. https://claude.ai/code/session_011C1h1NERqqZp4ht3Pqpwkc --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5244f1a..4287944 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim # Install Node.js 20 for the WhatsApp bridge RUN apt-get update && \ - apt-get install -y --no-install-recommends curl ca-certificates gnupg && \ + apt-get install -y --no-install-recommends curl ca-certificates gnupg git && \ mkdir -p /etc/apt/keyrings && \ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" > /etc/apt/sources.list.d/nodesource.list && \ From 7fced16e4c73b08e2cb632542735de9ec63fd6d0 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Feb 2026 09:22:13 +0000 Subject: [PATCH 5/7] docs: add Docker build/run instructions to README https://claude.ai/code/session_011C1h1NERqqZp4ht3Pqpwkc --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 167ae22..71d425b 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,16 @@ nanobot agent -m "What is 2+2?" That's it! You have a working AI assistant in 2 minutes. +## 🐳 Docker + +```bash +docker build -t nanobot . +docker run --rm nanobot onboard +docker run -v ~/.nanobot:/root/.nanobot -p 18790:18790 nanobot +``` + +Mount `~/.nanobot` so your config and workspace persist across runs. Edit `~/.nanobot/config.json` on the host to add API keys, then restart the container. + ## 🖥️ Local Models (vLLM) Run nanobot with your own local models using vLLM or any OpenAI-compatible server. From ae1830acddf6efe997bfac48af5b227caf80d0cd Mon Sep 17 00:00:00 2001 From: Peter van Eijk Date: Mon, 2 Feb 2026 16:36:22 +0700 Subject: [PATCH 6/7] feat: change default command to status --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4287944..8132747 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,4 +37,4 @@ RUN mkdir -p /root/.nanobot EXPOSE 18790 ENTRYPOINT ["nanobot"] -CMD ["gateway"] +CMD ["status"] From 99339c7be93cdcc3cdee5dd0bdf48645bbcb12c7 Mon Sep 17 00:00:00 2001 From: Re-bin Date: Tue, 3 Feb 2026 07:17:47 +0000 Subject: [PATCH 7/7] docs: improve README with provider info and Docker examples --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3440fdc..55c6091 100644 --- a/README.md +++ b/README.md @@ -130,16 +130,6 @@ nanobot agent -m "What is 2+2?" That's it! You have a working AI assistant in 2 minutes. -## 🐳 Docker - -```bash -docker build -t nanobot . -docker run --rm nanobot onboard -docker run -v ~/.nanobot:/root/.nanobot -p 18790:18790 nanobot -``` - -Mount `~/.nanobot` so your config and workspace persist across runs. Edit `~/.nanobot/config.json` on the host to add API keys, then restart the container. - ## 🖥️ Local Models (vLLM) Run nanobot with your own local models using vLLM or any OpenAI-compatible server. @@ -257,6 +247,20 @@ nanobot gateway ## ⚙️ Configuration +Config file: `~/.nanobot/config.json` + +### Providers + +| Provider | Purpose | Get API Key | +|----------|---------|-------------| +| `openrouter` | LLM (recommended, access to all models) | [openrouter.ai](https://openrouter.ai) | +| `anthropic` | LLM (Claude direct) | [console.anthropic.com](https://console.anthropic.com) | +| `openai` | LLM (GPT direct) | [platform.openai.com](https://platform.openai.com) | +| `groq` | LLM + **Voice transcription** (Whisper) | [console.groq.com](https://console.groq.com) | +| `gemini` | LLM (Gemini direct) | [aistudio.google.com](https://aistudio.google.com) | + +> **Note**: Groq provides free voice transcription via Whisper. If configured, Telegram voice messages will be automatically transcribed. +
Full config example @@ -270,6 +274,9 @@ nanobot gateway "providers": { "openrouter": { "apiKey": "sk-or-v1-xxx" + }, + "groq": { + "apiKey": "gsk_xxx" } }, "channels": { @@ -323,6 +330,30 @@ nanobot cron remove
+## 🐳 Docker + +Build and run nanobot in a container: + +```bash +# Build the image +docker build -t nanobot . + +# Initialize config (first time only) +docker run -v ~/.nanobot:/root/.nanobot --rm nanobot onboard + +# Edit config on host to add API keys +vim ~/.nanobot/config.json + +# Run gateway (connects to Telegram/WhatsApp) +docker run -v ~/.nanobot:/root/.nanobot -p 18790:18790 nanobot gateway + +# Or run a single command +docker run -v ~/.nanobot:/root/.nanobot --rm nanobot agent -m "Hello!" +docker run -v ~/.nanobot:/root/.nanobot --rm nanobot status +``` + +> **Tip**: Mount `~/.nanobot` so your config and workspace persist across container restarts. + ## 📁 Project Structure ```