# Minimal Dependency Strategy

GoClaw is designed to run as a **single binary** with **no runtime to install** — from a full Linux workstation to a headless Raspberry Pi.

The Linux release binaries are built with cgo (SQLite and tree-sitter are C libraries) and link glibc dynamically: they need **glibc 2.34 or later** (Ubuntu 22.04, Debian 12 / Raspberry Pi OS Bookworm, RHEL 9 and up). On a musl system such as Alpine, run the Docker image, which is built for it.

## Design Philosophy

```mermaid
flowchart TD
    subgraph BIN["goclaw binary"]
        direction LR
        LLM["<b>LLM API</b><br/>net/http"]
        TOOLS["<b>Tools</b><br/>pure Go"]
        SKILLS["<b>Skills System</b><br/>auto-detect deps"]
        MEM["<b>Memory</b><br/>SQLite"]
        SESS["<b>Sessions</b><br/>SQLite"]
        HOOKS["<b>Hooks + Plugins</b><br/>Go interfaces"]
        CACHE["<b>Caching</b><br/>SQLite"]
        CFG["<b>Config</b><br/>YAML"]
        GW["<b>Gateway / Auth</b><br/>net/http mux"]
    end

    BIN --> BUILD["<b>go build (cgo)</b> → single binary"]
    BUILD --> DEPLOY["<b>scp to device → run</b>"]
```

## Why?

| Problem (OpenClaw) | Solution (GoClaw) |
|----|----|
| Node.js 22+ runtime required | Go compiles to native binary |
| `npm install` pulls 500+ packages | Zero runtime dependencies |
| 200MB+ disk footprint | One binary, about 110–155 MB depending on the platform |
| RAM: 200-500MB idle | One native process, no language runtime to load |
| curl, jq, etc. expected by tools | All built-in as Go tools |
| Breaks on minimal/embedded OS | Runs on glibc 2.34+ Linux, macOS and Windows; Docker image for musl systems |

## Target Environments

| Environment | CPU | RAM | OS | Status |
|---|---|---|---|---|
| Linux workstation | x86_64 | 4GB+ | Ubuntu/Arch/Fedora | Fully supported |
| macOS | arm64/x86 | 4GB+ | macOS 13+ | Fully supported |
| Windows | x86_64 | 4GB+ | Windows 10+ | Fully supported |
| Raspberry Pi 4/5 | arm64 / armv7 | 2GB+ | Raspberry Pi OS Lite (Bookworm or later) | Target (minimal) |
| Raspberry Pi Zero 2W | arm64 / armv7 | 512MB | Raspberry Pi OS Lite (Bookworm or later) | Target (ultra-minimal) |
| Docker (Alpine) | any | 256MB+ | Alpine Linux | Fully supported |
| Cloud VM (cheap) | any | 512MB+ | Linux with glibc 2.34+ | Fully supported |
| NAS (Synology/QNAP) | arm64/x86 | 1GB+ | DSM/QTS | Target |

Release binaries are published for linux-amd64, linux-arm64, linux-armv7,
darwin-arm64, darwin-amd64 and windows-amd64. There is no MIPS build, and an
OpenWrt router (musl, no bash) cannot run the release binaries.

## Tool Dependency Matrix

### Pure Go (zero external dependencies)

These tools work with just the GoClaw binary:

| Tool | Go Library | External Binary | Raspberry Pi |
|------|-----------|-----------------|-------------|
| `file_read` | `os` | None | Yes |
| `file_write` | `os` | None | Yes |
| `file_edit` | `os` | None | Yes |
| `http_request` | `net/http` | None | Yes |
| `web_fetch` | `net/http` | None | Yes |
| `web_search` | `net/http` (API) | None | Yes |
| `calc` | `go/ast` | None | Yes |
| `datetime` | `time` | None | Yes |
| `text_utils` | `crypto`, `encoding` | None | Yes |
| `memory_get` | SQLite (GORM) | None | Yes |
| `memory_write` | SQLite (GORM) | None | Yes |
| `memory_search` | SQLite (GORM) + embeddings API | None | Yes |
| `memory_consolidate` | SQLite (GORM) | None | Yes |
| `image` | `os` + `net/http` | None | Yes |
| `pdf` | built-in parser (uses `pdftotext` instead when it is installed) | None | Yes |
| `sessions_list` | SQLite | None | Yes |
| `sessions_history` | SQLite | None | Yes |
| `db_query` | Go SQL drivers | None | Yes |
| `mongo_query` | Go driver | None | Yes |
| `cron` | `robfig/cron` | None | Yes |
| `message` | `net/http` | None | Yes |

The archive (`archive_search`, `archive_get`) and wiki (`wiki_read`, `wiki_write`) tools work the same way, on the database.

### OS-Level (usually present)

| Tool | External Binary | Fallback | Notes |
|------|----------------|----------|-------|
| `shell_exec` | `bash` (PowerShell on Windows) | None: there is no `sh` fallback | Present on most Linux distributions and macOS. A busybox-only system (Alpine without bash, OpenWrt) needs `bash` installed; the Docker image includes it |
| `process` | OS process API | Always present | Core OS component |

### Optional Enhancement (graceful degradation)

| Tool | External Binary | Without It | Severity |
|------|----------------|-----------|----------|
| `git` | `git` | Returns "git binary not found on this system" | Low — install with `apt install git` |
| `browser` | Chrome/Chromium | Returns "failed to start browser: …" | Low — niche use case |
| `pdf` | `pdftotext` (poppler-utils) | Uses the built-in parser | Low — layout may be poorer |
| `analyze_pcap` | `tshark`, else `tcpdump` | With only `tcpdump`, the summary view only; with neither, returns install instructions | Low |
| `run_code_linter` | `golangci-lint`, `ruff`, `dart` | Returns "<linter> not found" | Low — developer hosts only |
| `run_sast_scanner` | `gosec`, `bandit` | Returns "<scanner> not found" | Low — developer hosts only |
| `clipboard` | `pbcopy`/`pbpaste` (macOS), `xclip` (Linux), PowerShell (Windows) | Returns the command's error | Low — desktop hosts only |

## Skill Auto-Detection

Skills with `bins` in frontmatter are checked when skills are loaded; a skill is
available when at least one of its listed binaries is on the `PATH`. Among the
built-in skills only `github` (`gh`), `tmux` (`tmux`) and `gh-issues` (`gh`,
`git`) list any. On a host without `gh` and `tmux`:

```
$ goclaw skills check

Skill Dependency Check:

  [ok] git                  (no external deps — pure Go)
  [ok] web-search           (no external deps — pure Go)
  …
  [--] github               (missing: gh)
  [--] tmux                 (missing: tmux)
  [ok] weather              (no external deps — pure Go)
  [ok] gh-issues            (found: git)
  …
  [ok] mcp                  (no external deps — pure Go)
  …

Summary: <n> ready, 2 unavailable, <n> pure Go (no deps)

Unavailable skills are auto-skipped at runtime.
Install missing binaries to enable them.
```

**Unavailable skills are silently excluded from the system prompt.** The LLM never receives instructions for tools that don't exist — no confusion, no wasted tokens.

## Build Targets

GoClaw needs cgo: `mattn/go-sqlite3` and `go-tree-sitter` are C code, and a
`CGO_ENABLED=0` build does not compile. Cross-compiling therefore needs a C
cross-compiler for the target, given as `CC`. The release workflow builds the
Linux and Windows binaries this way on Ubuntu:

```bash
# Native build (the host's own OS and architecture)
CGO_ENABLED=1 CGO_CFLAGS="-DSQLITE_ENABLE_FTS5" go build -o goclaw ./cmd/gateway/

# Linux ARM64 (64-bit Raspberry Pi OS), from Debian/Ubuntu x86_64
sudo apt-get install gcc-aarch64-linux-gnu
CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc CGO_CFLAGS="-DSQLITE_ENABLE_FTS5" CGO_LDFLAGS="-lm" \
  GOOS=linux GOARCH=arm64 go build -o goclaw ./cmd/gateway/

# Linux ARMv7 (32-bit Raspberry Pi OS)
sudo apt-get install gcc-arm-linux-gnueabihf
CGO_ENABLED=1 CC=arm-linux-gnueabihf-gcc CGO_CFLAGS="-DSQLITE_ENABLE_FTS5" CGO_LDFLAGS="-lm" \
  GOOS=linux GOARCH=arm GOARM=7 go build -o goclaw ./cmd/gateway/

# Windows x86_64
sudo apt-get install mingw-w64
CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CGO_CFLAGS="-DSQLITE_ENABLE_FTS5" CGO_LDFLAGS="-lm" \
  GOOS=windows GOARCH=amd64 go build -o goclaw.exe ./cmd/gateway/

# macOS: build on a Mac (the releases are built natively on macOS runners)
CGO_ENABLED=1 CGO_CFLAGS="-DSQLITE_ENABLE_FTS5" GOARCH=arm64 go build -o goclaw ./cmd/gateway/

# Alpine Linux (musl): build the Docker image, which compiles inside golang:alpine
docker build -t goclaw .
```

A binary links the glibc of the machine that built it, so build on a system at
least as old as the oldest one it has to run on.

## Raspberry Pi Quick Start

Use a release binary rather than building one: `goclaw-linux-arm64` for 64-bit
Raspberry Pi OS, `goclaw-linux-armv7` for 32-bit. The install script picks the
right one, checks it against the release's `checksums.json` and installs it:

```bash
# On the Pi (Raspberry Pi OS Bookworm or later)
curl -fsSL https://goclaw.ulab.mn/install.sh | sh
goclaw setup             # interactive setup
goclaw                   # start gateway

# Optional: install as service
goclaw service install
```

To use a binary you built yourself (see [Build Targets](#build-targets)), copy it
over with `scp goclaw pi@raspberrypi:~/` and run it from there.

**Requirements: Network connection (for LLM API calls). That's it.**

## Comparison with OpenClaw

| Aspect | OpenClaw | GoClaw |
|--------|---------|-------|
| Runtime | Node.js 22+ | None (native binary) |
| Install | `npm i -g openclaw` (500+ deps) | Copy single binary |
| Disk | ~200MB | ~110–155 MB (one binary) |
| Process | Node.js runtime | One native process |
| Startup | 2-5 seconds | <1 second |
| curl needed | By many skills | Never (http_request) |
| Python needed | Optional tools | Only for optional tools (`bandit`) |
| Minimum OS | Full Linux/macOS | Linux with glibc 2.34+ (or Docker), macOS, Windows; `bash` for `shell_exec` |
| Cross-compile | N/A (needs Node per arch) | cgo with a C cross-compiler (see [Build Targets](#build-targets)) |

## Rules for Contributors

1. **Never add an external binary dependency to a core tool.** If you need HTTP, use `net/http`. If you need JSON, use `encoding/json`. If you need crypto, use `crypto/`.

2. **Skills can reference external binaries** (via `bins` field) — these are auto-detected and gracefully skipped if not present.

3. **Tools must degrade gracefully** when optional binaries are missing. Return a clear error message suggesting install, don't crash.

4. **Prefer Go standard library** over third-party packages. Only use third-party for complex domains (SQL drivers, WebSocket, Discord API).

5. **Keep binary size small.** Avoid importing large packages for minor features.

6. **Test on minimal environments.** The CI should include a Raspberry Pi-like build target (linux/arm64, no extras).
