Merge branch 'main' into commands-list-clean

This commit is contained in:
Luke
2026-01-08 16:22:25 -05:00
committed by GitHub
35 changed files with 847 additions and 201 deletions

View File

@@ -6,62 +6,85 @@ read_when:
---
# Cron jobs (Gateway scheduler)
Cron runs inside the Gateway and schedules background work so Clawdbot can
wake itself up, run isolated agent jobs, and deliver reminders on time.
Cron is the Gateways built-in scheduler. It persists jobs, wakes the agent at
the right time, and can optionally deliver output back to a chat.
## Update checklist (internal)
- [x] Audit cron + heartbeat behavior in code
- [x] Rewrite cron doc as user-facing feature
- [x] Update heartbeat docs + templates
- [x] Update cron links in docs
- [x] Update changelog
- [x] Run full gate (lint/build/test/docs)
If you want *“run this every morning”* or *“poke the agent in 20 minutes”*,
cron is the mechanism.
## What cron is
- **Gateway-owned scheduler** that persists jobs under `~/.clawdbot/cron/`.
- **Two execution modes**:
- **Main session jobs** enqueue `System:` events and rely on the heartbeat runner.
- **Isolated jobs** run a dedicated agent turn in `cron:<jobId>` sessions.
- **Wakeups** are first-class: a job can trigger the next heartbeat or run it now.
## TL;DR
- Cron runs **inside the Gateway** (not inside the model).
- Jobs persist under `~/.clawdbot/cron/` so restarts dont lose schedules.
- Two execution styles:
- **Main session**: enqueue a system event, then run on the next heartbeat.
- **Isolated**: run a dedicated agent turn in `cron:<jobId>`, optionally deliver output.
- Wakeups are first-class: a job can request “wake now” vs “next heartbeat”.
## When to use it
- Recurring reminders: “every weekday at 7:30” or “every 2h.”
- Background chores: summarize inboxes, check dashboards, watch logs.
- Automation that should not pollute the main chat history.
- Scheduled wakeups that drive the heartbeat pipeline.
## Concepts
## Schedules
### Jobs
A cron job is a stored record with:
- a **schedule** (when it should run),
- a **payload** (what it should do),
- optional **delivery** (where output should be sent).
Jobs are identified by a stable `jobId` (used by CLI/Gateway APIs).
In agent tool calls, `jobId` is canonical; legacy `id` is accepted for compatibility.
### Schedules
Cron supports three schedule kinds:
- `at`: one-shot timestamp in ms.
- `at`: one-shot timestamp (ms since epoch).
- `every`: fixed interval (ms).
- `cron`: 5-field cron expression, optional IANA timezone.
- `cron`: 5-field cron expression with optional IANA timezone.
Cron expressions use `croner` under the hood. If a timezone is omitted, the
servers local timezone is used.
Cron expressions use `croner`. If a timezone is omitted, the Gateway hosts
local timezone is used.
## Job types
### Main vs isolated execution
### Main session jobs
#### Main session jobs (system events)
Main jobs enqueue a system event and optionally wake the heartbeat runner.
They **must** use `payload.kind = "systemEvent"`.
They must use `payload.kind = "systemEvent"`.
- **`wakeMode: "next-heartbeat"`** (default): the event waits for the next
scheduled heartbeat.
- **`wakeMode: "now"`**: the event triggers an immediate heartbeat run.
- `wakeMode: "next-heartbeat"` (default): event waits for the next scheduled heartbeat.
- `wakeMode: "now"`: event triggers an immediate heartbeat run.
### Isolated jobs
Isolated jobs run a dedicated agent turn in session `cron:<jobId>` and can
optionally deliver a message.
This is the best fit when you want the normal heartbeat prompt + main-session context.
See [Heartbeat](/gateway/heartbeat).
#### Isolated jobs (dedicated cron sessions)
Isolated jobs run a dedicated agent turn in session `cron:<jobId>`.
Key behaviors:
- Prompt is prefixed with `[cron:<jobId> <job name>]` for traceability.
- A summary is posted to the main session with prefix `Cron` (or
`isolation.postToMainPrefix`).
- A summary is posted to the main session (prefix `Cron`, configurable).
- `wakeMode: "now"` triggers an immediate heartbeat after posting the summary.
- `payload.deliver: true` sends output to a provider; otherwise it stays internal.
- If `payload.deliver: true`, output is delivered to a provider; otherwise it stays internal.
Use isolated jobs for noisy, frequent, or “background chores” that shouldnt spam
your main chat history.
### Delivery (provider + target)
Isolated jobs can deliver output to a provider. The job payload can specify:
- `provider`: `whatsapp` / `telegram` / `discord` / `slack` / `signal` / `imessage` / `last`
- `to`: provider-specific recipient target
If `provider` or `to` is omitted, cron can fall back to the main sessions “last route”
(the last place the agent replied).
#### Telegram delivery targets (topics / forum threads)
Telegram supports forum topics via `message_thread_id`. For cron delivery, you can encode
the topic/thread into the `to` field:
- `-1001234567890` (chat id only)
- `-1001234567890:topic:123` (preferred: explicit topic marker)
- `-1001234567890:123` (shorthand: numeric suffix)
Internal prefixes like `telegram:...` / `telegram:group:...` are also accepted:
- `telegram:group:-1001234567890:topic:123`
## Storage & history
- Job store: `~/.clawdbot/cron/jobs.json` (JSON, Gateway-managed).
- Job store: `~/.clawdbot/cron/jobs.json` (Gateway-managed JSON).
- Run history: `~/.clawdbot/cron/runs/<jobId>.jsonl` (JSONL, auto-pruned).
- Override store path: `cron.store` in config.
@@ -70,16 +93,16 @@ Key behaviors:
```json5
{
cron: {
enabled: true, // default true
enabled: true, // default true
store: "~/.clawdbot/cron/jobs.json",
maxConcurrentRuns: 1 // default 1
maxConcurrentRuns: 1 // default 1
}
}
```
Disable cron entirely:
- `cron.enabled: false` (config)
- or `CLAWDBOT_SKIP_CRON=1` (env)
- `CLAWDBOT_SKIP_CRON=1` (env)
## CLI quickstart
@@ -106,6 +129,19 @@ clawdbot cron add \
--to "+15551234567"
```
Recurring isolated job (deliver to a Telegram topic):
```bash
clawdbot cron add \
--name "Nightly summary (topic)" \
--cron "0 22 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize today; send to the nightly topic." \
--deliver \
--provider telegram \
--to "-1001234567890:topic:123"
```
Manual run (debug):
```bash
clawdbot cron run <jobId> --force
@@ -121,12 +157,19 @@ Immediate wake without creating a job:
clawdbot wake --mode now --text "Next heartbeat: check battery."
```
## API surface (Gateway)
## Gateway API surface
- `cron.list`, `cron.status`, `cron.add`, `cron.update`, `cron.remove`
- `cron.run` (force or due), `cron.runs`
- `wake` (enqueue system event + optional heartbeat)
## Tips
- Use **main session jobs** when you want the heartbeat prompt + existing context.
- Use **isolated jobs** for noisy, frequent, or long-running work.
- Keep messages short; cron turns are full agent runs and can burn tokens.
## Troubleshooting
### “Nothing runs”
- Check cron is enabled: `cron.enabled` and `CLAWDBOT_SKIP_CRON`.
- Check the Gateway is running continuously (cron runs inside the Gateway process).
- For `cron` schedules: confirm timezone (`--tz`) vs the host timezone.
### Telegram delivers to the wrong place
- For forum topics, use `-100…:topic:<id>` so its explicit and unambiguous.
- If you see `telegram:...` prefixes in logs or stored “last route” targets, thats normal;
cron delivery accepts them and still parses topic IDs correctly.

View File

@@ -1176,6 +1176,8 @@ per session key at a time). Default: 1.
Optional **Docker sandboxing** for the embedded agent. Intended for non-main
sessions so they cannot access your host system.
Details: [Sandboxing](/gateway/sandboxing)
Defaults (if enabled):
- scope: `"agent"` (one container + workspace per agent)
- Debian bookworm-slim based image

View File

@@ -23,11 +23,24 @@ clawdbot doctor --yes
Accept defaults without prompting (including restart/service/sandbox repair steps when applicable).
```bash
clawdbot doctor --repair
```
Apply recommended repairs without prompting (repairs + restarts where safe).
```bash
clawdbot doctor --repair --force
```
Apply aggressive repairs too (overwrites custom supervisor configs).
```bash
clawdbot doctor --non-interactive
```
Run without prompts and only apply safe migrations (config normalization + on-disk state moves). Skips restart/service/sandbox actions that require human confirmation.
Legacy state migrations run automatically when detected.
```bash
clawdbot doctor --deep
@@ -47,6 +60,7 @@ cat ~/.clawdbot/clawdbot.json
- Legacy config migration and normalization.
- Legacy on-disk state migration (sessions/agent dir/WhatsApp auth).
- State integrity and permissions checks (sessions, transcripts, state dir).
- Config file permission checks (chmod 600) when running locally.
- Legacy workspace dir detection (`~/clawdis`, `~/clawdbot`).
- Sandbox image repair when sandboxing is enabled.
- Legacy service migration and extra gateway detection.
@@ -117,6 +131,8 @@ Doctor checks:
split between installs).
- **Remote mode reminder**: if `gateway.mode=remote`, doctor reminds you to run
it on the remote host (the state lives there).
- **Config file permissions**: warns if `~/.clawdbot/clawdbot.json` is
group/world readable and offers to tighten to `600`.
### 5) Sandbox image repair
When sandboxing is enabled, doctor checks Docker images and offers to build or
@@ -150,6 +166,13 @@ missing or outdated defaults (e.g., systemd network-online dependencies and
restart delay). When it finds a mismatch, it recommends an update and can
rewrite the service file/task to the current defaults.
Notes:
- `clawdbot doctor` prompts before rewriting supervisor config.
- `clawdbot doctor --yes` accepts the default repair prompts.
- `clawdbot doctor --repair` applies recommended fixes without prompts.
- `clawdbot doctor --repair --force` overwrites custom supervisor configs.
- You can always force a full rewrite via `clawdbot daemon install --force`.
### 12) Gateway runtime + port diagnostics
Doctor inspects the daemon runtime (PID, last exit status) and warns when the
service is installed but not actually running. It also checks for port collisions

View File

@@ -156,6 +156,8 @@ See also: [`docs/presence.md`](/concepts/presence) for how presence is produced/
- StandardOut/Err: file paths or `syslog`
- On failure, launchd restarts; fatal misconfig should keep exiting so the operator notices.
- LaunchAgents are per-user and require a logged-in session; for headless setups use a custom LaunchDaemon (not shipped).
- `clawdbot daemon install` writes `~/Library/LaunchAgents/com.clawdbot.gateway.plist`.
- `clawdbot doctor` audits the LaunchAgent config and can update it to current defaults.
## Daemon management (CLI)

View File

@@ -0,0 +1,94 @@
---
summary: "How Clawdbot sandboxing works: modes, scopes, workspace access, and images"
title: Sandboxing
read_when: "You want a dedicated explanation of sandboxing or need to tune agent.sandbox."
status: active
---
# Sandboxing
Clawdbot can run **tools inside Docker containers** to reduce blast radius.
This is **optional** and controlled by configuration (`agent.sandbox` or
`routing.agents[id].sandbox`). If sandboxing is off, tools run on the host.
The Gateway stays on the host; tool execution runs in an isolated sandbox
when enabled.
This is not a perfect security boundary, but it materially limits filesystem
and process access when the model does something dumb.
## What gets sandboxed
- Tool execution (`bash`, `read`, `write`, `edit`, `process`, etc.).
- Optional sandboxed browser (`agent.sandbox.browser`).
Not sandboxed:
- The Gateway process itself.
- Any tool explicitly allowed to run on the host (e.g. `agent.elevated`).
## Modes
`agent.sandbox.mode` controls **when** sandboxing is used:
- `"off"`: no sandboxing.
- `"non-main"`: sandbox only **non-main** sessions (default if you want normal chats on host).
- `"all"`: every session runs in a sandbox.
## Scope
`agent.sandbox.scope` controls **how many containers** are created:
- `"session"` (default): one container per session.
- `"agent"`: one container per agent.
- `"shared"`: one container shared by all sandboxed sessions.
## Workspace access
`agent.sandbox.workspaceAccess` controls **what the sandbox can see**:
- `"none"` (default): tools see a sandbox workspace under `~/.clawdbot/sandboxes`.
- `"ro"`: mounts the agent workspace read-only at `/agent` (disables `write`/`edit`).
- `"rw"`: mounts the agent workspace read/write at `/workspace`.
Inbound media is copied into the active sandbox workspace (`media/inbound/*`).
## Images + setup
Default image: `clawdbot-sandbox:bookworm-slim`
Build it once:
```bash
scripts/sandbox-setup.sh
```
Sandboxed browser image:
```bash
scripts/sandbox-browser-setup.sh
```
By default, sandbox containers run with **no network**.
Override with `agent.sandbox.docker.network`.
Docker installs and the containerized gateway live here:
[Docker](/install/docker)
## Tool policy + escape hatches
Tool allow/deny policies still apply before sandbox rules. If a tool is denied
globally or per-agent, sandboxing doesnt bring it back.
`agent.elevated` is an explicit escape hatch that runs `bash` on the host.
Keep it locked down.
## Multi-agent overrides
Each agent can override sandbox + tools:
`routing.agents[id].sandbox` and `routing.agents[id].tools`.
See [Multi-Agent Sandbox & Tools](/multi-agent-sandbox-tools) for precedence.
## Minimal enable example
```json5
{
agent: {
sandbox: {
mode: "non-main",
scope: "session",
workspaceAccess: "none"
}
}
}
```
## Related docs
- [Sandbox Configuration](/gateway/configuration#agent-sandbox)
- [Multi-Agent Sandbox & Tools](/multi-agent-sandbox-tools)
- [Security](/gateway/security)

View File

@@ -95,6 +95,14 @@ This is social engineering 101. Create distrust, encourage snooping.
## Configuration Hardening (examples)
### 0) File permissions
Keep config + state private on the gateway host:
- `~/.clawdbot/clawdbot.json`: `600` (user read/write only)
- `~/.clawdbot`: `700` (user only)
`clawdbot doctor` can warn and offer to tighten these permissions.
### 1) DMs: pairing by default
```json5
@@ -138,10 +146,12 @@ We may add a single `readOnlyMode` flag later to simplify this configuration.
## Sandboxing (recommended)
Dedicated doc: [Sandboxing](/gateway/sandboxing)
Two complementary approaches:
- **Run the full Gateway in Docker** (container boundary): [Docker](/install/docker)
- **Tool sandbox** (`agent.sandbox`, host gateway + Docker-isolated tools): [Configuration](/gateway/configuration)
- **Tool sandbox** (`agent.sandbox`, host gateway + Docker-isolated tools): [Sandboxing](/gateway/sandboxing)
Note: to prevent cross-agent access, keep `sandbox.scope` at `"agent"` (default)
or `"session"` for stricter per-session isolation. `scope: "shared"` uses a

View File

@@ -55,6 +55,10 @@ the Gateway likely refused to bind.
- If they dont, youre almost certainly editing one config while the daemon is running another.
- Fix: rerun `clawdbot daemon install --force` from the same `--profile` / `CLAWDBOT_STATE_DIR` you want the daemon to use.
**If `clawdbot daemon status` reports service config issues**
- The supervisor config (launchd/systemd/schtasks) is missing current defaults.
- Fix: run `clawdbot doctor` to update it (or `clawdbot daemon install --force` for a full rewrite).
**If `Last gateway error:` mentions “refusing to bind … without auth”**
- You set `gateway.bind` to a non-loopback mode (`lan`/`tailnet`/`auto`) but left auth off.
- Fix: set `gateway.auth.mode` + `gateway.auth.token` (or export `CLAWDBOT_GATEWAY_TOKEN`) and restart the daemon.

View File

@@ -9,10 +9,18 @@ read_when:
Docker is **optional**. Use it only if you want a containerized gateway or to validate the Docker flow.
## Is Docker right for me?
- **Yes**: you want an isolated, throwaway gateway environment or to run Clawdbot on a host without local installs.
- **No**: youre running on your own machine and just want the fastest dev loop. Use the normal install flow instead.
- **Sandboxing note**: agent sandboxing uses Docker too, but it does **not** require the full gateway to run in Docker. See [Sandboxing](/gateway/sandboxing).
This guide covers:
- Containerized Gateway (full Clawdbot in Docker)
- Per-session Agent Sandbox (host gateway + Docker-isolated agent tools)
Sandboxing details: [Sandboxing](/gateway/sandboxing)
## Requirements
- Docker Desktop (or Docker Engine) + Docker Compose v2
@@ -33,6 +41,11 @@ This script:
- runs the onboarding wizard
- prints optional provider setup hints
- starts the gateway via Docker Compose
- generates a gateway token and writes it to `.env`
After it finishes:
- Open `http://127.0.0.1:18789/` in your browser.
- Paste the token into the Control UI (Settings → token).
It writes config/workspace on the host:
- `~/.clawdbot/`
@@ -92,6 +105,8 @@ pnpm test:docker:qr
## Agent Sandbox (host gateway + Docker tools)
Deep dive: [Sandboxing](/gateway/sandboxing)
### What it does
When `agent.sandbox` is enabled, **non-main sessions** run tools inside a Docker

View File

@@ -18,6 +18,8 @@ This allows you to run multiple agents with different security profiles:
- Family/work agents with restricted tools
- Public-facing agents in sandboxes
For how sandboxing behaves at runtime, see [Sandboxing](/gateway/sandboxing).
---
## Configuration Examples

View File

@@ -13,6 +13,15 @@ Goal: Clawdbot Gateway running on an exe.dev VM, reachable from your laptop via:
This page assumes **Ubuntu/Debian**. If you picked a different distro, map packages accordingly.
If youre on any other Linux VPS, the same steps apply — you just wont use the exe.dev proxy commands.
## Beginner quick path
1) Create VM → install Node 22 → install Clawdbot
2) Run `clawdbot onboard --install-daemon`
3) Tunnel from laptop (`ssh -N -L 18789:127.0.0.1:18789 …`)
4) Open `http://127.0.0.1:18789/` and paste your token
## What you need
- exe.dev account + `ssh exe.dev` working on your laptop

View File

@@ -10,6 +10,16 @@ Clawdbot core is fully supported on Linux. The core is written in TypeScript, so
We do not have a Linux companion app yet. It is planned, and we would love contributions to make it happen.
## Beginner quick path (VPS)
1) Install Node 22+
2) `npm i -g clawdbot@latest`
3) `clawdbot onboard --install-daemon`
4) From your laptop: `ssh -N -L 18789:127.0.0.1:18789 <user>@<host>`
5) Open `http://127.0.0.1:18789/` and paste your token
Step-by-step VPS guide: [exe.dev](/platforms/exe-dev)
## Install
- [Getting Started](/start/getting-started)
- [Install & updates](/install/updating)
@@ -35,12 +45,6 @@ clawdbot daemon install
Or:
```
clawdbot daemon install
```
Or:
```
clawdbot configure
```

View File

@@ -63,6 +63,8 @@ Manager:
Behavior:
- “Clawdbot Active” enables/disables the LaunchAgent.
- App quit does **not** stop the gateway (launchd keeps it alive).
- CLI install (`clawdbot daemon install`) writes the same LaunchAgent; `clawdbot daemon install --force` rewrites it.
- `clawdbot doctor` audits the LaunchAgent config and can update it to current defaults.
Logging:
- launchd stdout/err: `/tmp/clawdbot/clawdbot-gateway.log`

View File

@@ -36,12 +36,6 @@ clawdbot daemon install
Or:
```
clawdbot daemon install
```
Or:
```
clawdbot configure
```

View File

@@ -89,6 +89,10 @@ It also warns if your configured model is unknown or missing auth.
Bun is supported for faster TypeScript execution, but **WhatsApp requires Node** in this ecosystem. The wizard lets you pick the runtime; choose **Node** if you use WhatsApp.
### Is there a dedicated sandboxing doc?
Yes. See [Sandboxing](/gateway/sandboxing). For Docker-specific setup (full gateway in Docker or sandbox images), see [Docker](/install/docker).
## Where things live on disk
### Where does Clawdbot store its data?

View File

@@ -80,6 +80,7 @@ Use these hubs to discover every page, including deep dives and reference docs t
- [Heartbeat](https://docs.clawd.bot/gateway/heartbeat)
- [Doctor](https://docs.clawd.bot/gateway/doctor)
- [Logging](https://docs.clawd.bot/gateway/logging)
- [Sandboxing](https://docs.clawd.bot/gateway/sandboxing)
- [Dashboard](https://docs.clawd.bot/web/dashboard)
- [Control UI](https://docs.clawd.bot/web/control-ui)
- [Remote access](https://docs.clawd.bot/gateway/remote)