zclaw docs

chapter 1

Getting Started

Fast path from blank machine to a live ESP32 agent. Defaults are safe, and explicit flags keep runs repeatable.

Basic Hardware

  • Tested targets: ESP32-C3, ESP32-S3, and ESP32-C6.
  • Recommended starter board: Seeed XIAO ESP32-C3 (USB-C, small footprint, low cost).
  • Use a real data USB cable (not charge-only), then connect board to host.
  • zclaw's setup scripts will generally find the right serial port without you having to do anything.

One-Line Bootstrap

bash <(curl -fsSL https://raw.githubusercontent.com/tnm/zclaw/main/scripts/bootstrap.sh)

Optional checksum-verified bootstrap (same flow):

ZCLAW_BOOTSTRAP_SHA256="<sha256-from-release-notes>" \
bash <(curl -fsSL https://raw.githubusercontent.com/tnm/zclaw/main/scripts/bootstrap.sh)

Integrity check: when ZCLAW_BOOTSTRAP_SHA256 (or --sha256) is set, bootstrap.sh hashes its own downloaded contents with SHA-256 and compares to your expected value before it clones/updates or runs ./install.sh. Any mismatch exits immediately.

Bootstrap clones or updates the repo, then runs ./install.sh.

  • Installer remembers answers in ~/.config/zclaw/install.env (disable with --no-remember).
  • Interactive flashing defaults to standard mode; encrypted flashing is opt-in with --flash-mode secure.
  • On Linux, dependency installs auto-detect apt-get, pacman, dnf, or zypper; unsupported distros fall back to manual package install guidance.

Want non-interactive install? Use -y and explicit no/yes flags: ./install.sh -y --build --flash --provision --no-qemu --no-cjson. Without -y, unanswered non-interactive prompts default to no.

Common Install Patterns

# Interactive default path
./install.sh

# Non-interactive provisioning path
./install.sh -y --build --flash --provision --monitor

# Explicit secure flash mode
./install.sh -y --build --flash --flash-mode secure

First Boot Flow

  1. Flash firmware (./scripts/flash.sh or ./scripts/flash-secure.sh). Flash scripts auto-detect chip target and can prompt for idf.py set-target <chip> on mismatch.
  2. Provision credentials (./scripts/provision.sh --port <serial-port>).
  3. Enter WiFi SSID, LLM provider, and model. Use API key for Anthropic/OpenAI/OpenRouter, or API URL for Ollama. Optional Telegram fields can be filled now or later.
  4. Reboot and inspect logs with ./scripts/monitor.sh.

ESP32-WROOM/ESP32 DevKit boards run target esp32; local chat uses UART0 automatically on targets without USB Serial/JTAG (no manual CONFIG_ZCLAW_CHANNEL_UART toggle needed).

LLM Provisioning Options

Backend/model/API settings are runtime credentials in NVS, so you can change them any time without reflashing firmware. The install flow prompts for the same values when you run ./install.sh with provisioning enabled.

  • anthropic, openai, openrouter: require --api-key.
  • ollama: requires --api-url; API key is optional.
  • Use --model to override defaults on any backend.
# OpenAI
./scripts/provision.sh --port /dev/cu.usbmodem1101 --backend openai --model gpt-5.2 --api-key sk-...

# OpenRouter
./scripts/provision.sh --port /dev/cu.usbmodem1101 --backend openrouter --model minimax/minimax-m2.5 --api-key or-...

# Ollama (LAN host)
./scripts/provision.sh --port /dev/cu.usbmodem1101 --backend ollama --model qwen3:8b --api-url http://192.168.1.50:11434

For Ollama, use a LAN-reachable host/IP; 127.0.0.1 points to the ESP32 itself and will not reach your laptop/server.

To switch model/provider later, re-run provisioning with new --backend/--model values, or update ZCLAW_BACKEND/ZCLAW_MODEL in provision-dev.sh profile and re-run.

Telegram Path

  1. Create bot via @BotFather.
  2. Get chat ID via @userinfobot.
  3. Provide Telegram credentials during provisioning: use --tg-token and --tg-chat-id (single ID or comma-separated allowlist, up to 4 IDs) for non-interactive runs, or enter them when prompted in interactive provisioning.

Runtime accepts messages only from the configured chat ID allowlist.

To change authorized Telegram chats later, re-run provisioning with a new --tg-chat-id value (either provision.sh or provision-dev.sh).

Telegram control commands: /start//help (help), /settings (status), /stop (pause message intake), /resume (resume message intake).

If old queued messages keep replaying during local dev, run ./scripts/telegram-clear-backlog.sh --show-config once on your host.

First Conversation

Talk to zclaw in normal language. You do not need command syntax.

what are all GPIO states
turn GPIO 5 on
remind me daily at 8:15 to water plants
remember that GPIO 4 controls the arcade machine
create a tool called arcade_on that turns GPIO 4 on
turn the arcade on in 10 minutes

Example flow:

You: create a tool called arcade_on that turns GPIO 4 on
zclaw: Created tool "arcade_on". Say "run arcade_on" anytime.

You: turn the arcade on in 10 minutes
zclaw: Scheduled it. I will run arcade_on once in 10 minutes.

Persona options are neutral, friendly, technical, and witty.

switch to witty persona
what persona are you using

Persona only changes wording/tone, not tool behavior or safety decisions. Persona is saved on-device until changed or reset.

Fast Re-Provision (Local Dev)

# One-time: create local profile template
./scripts/provision-dev.sh --write-template

# Edit ~/.config/zclaw/dev.env once, then:
./scripts/provision-dev.sh --show-config
./scripts/provision-dev.sh

This keeps your WiFi/API/Telegram values in a local profile for repeat dev flashes. Output is redacted; only Telegram bot ID is shown as a safe identifier.

What Re-Provision Updates

Both ./scripts/provision.sh and ./scripts/provision-dev.sh write the same runtime config in NVS:

  • WiFi: SSID + password
  • LLM: backend + model + API key (or Ollama API URL)
  • Telegram: bot token + authorized chat ID allowlist

For Ollama, point --api-url to a LAN host (for example http://192.168.1.50:11434), not 127.0.0.1.

No firmware reflash is required for these changes. provision-dev.sh is a convenience wrapper around provision.sh --yes with a local profile.

Web Relay Path

# Device connected
./scripts/web-relay.sh --serial-port /dev/cu.usbmodem1101 --host 127.0.0.1 --port 8787

# No hardware (mock agent)
./scripts/web-relay.sh --mock-agent --host 127.0.0.1 --port 8787

If you bind to a non-loopback host (for example 0.0.0.0), set ZCLAW_WEB_API_KEY first.

Only one process should own the serial port at a time.

# No-clone bootstrap path
ZCLAW_WEB_API_KEY='long-random-secret' \
bash <(curl -fsSL https://raw.githubusercontent.com/tnm/zclaw/main/scripts/bootstrap-web-relay.sh) -- --serial-port /dev/cu.usbmodem1101 --host 0.0.0.0 --port 8787

Serial Port Conflicts

# Release ESP-IDF monitor/holders
./scripts/release-port.sh

# Relay helper can stop monitor holders automatically
./scripts/web-relay.sh --serial-port /dev/cu.usbmodem1101 --kill-monitor --host 127.0.0.1 --port 8787

Reset / Erase

# Erase only saved credentials/settings (keeps firmware)
./scripts/erase.sh --nvs --port /dev/cu.usbmodem1101

# Full factory wipe (firmware + settings)
./scripts/erase.sh --all --port /dev/cu.usbmodem1101

Guardrails: you must explicitly choose --nvs or --all. Full erase requires confirmation (or --yes in non-interactive runs).

Advanced Board Config

source ~/esp/esp-idf/export.sh
idf.py menuconfig

Adjust GPIO safety range/allowlist under zclaw Configuration -> GPIO Tool Safety.

Other Board Notes

Most boards work with the generic target flow, but some need explicit board-safe pin/reset defaults.

If you move between chips (for example, C3/S3 to WROOM), accept the flash-script prompt to run idf.py set-target <chip> (or run it manually once).

# ESP32-S3-BOX-3 preset
./scripts/build.sh --box-3
./scripts/flash.sh --box-3 /dev/cu.usbmodem1101
# or encrypted flash:
./scripts/flash-secure.sh --box-3 /dev/cu.usbmodem1101

--box-3 applies esp32s3 target, board-safe GPIO allowlist, and factory-reset pin defaults.

If Something Breaks

# ESP-IDF repair
cd ~/esp/esp-idf
./install.sh esp32,esp32c3,esp32c6,esp32s3

# Build/test routines
./scripts/build.sh
./scripts/test.sh host