Files
clawdbot/docs/start/clawd.md
JustYannicc dd06028827 feat(heartbeat): skip API calls when HEARTBEAT.md is effectively empty (#1535)
* feat: skip heartbeat API calls when HEARTBEAT.md is effectively empty

- Added isHeartbeatContentEffectivelyEmpty() to detect files with only headers/comments
- Modified runHeartbeatOnce() to check HEARTBEAT.md content before polling the LLM
- Returns early with 'empty-heartbeat-file' reason when no actionable tasks exist
- Preserves existing behavior when file is missing (lets LLM decide)
- Added comprehensive test coverage for empty file detection
- Saves API calls/costs when heartbeat file has no meaningful content

* chore: update HEARTBEAT.md template to be effectively empty by default

Changed instruction text to comment format so new workspaces benefit from
heartbeat optimization immediately. Users still get clear guidance on usage.

* fix: only treat markdown headers (# followed by space) as comments, not #TODO etc

* refactor: simplify regex per code review suggestion

* docs: clarify heartbeat empty file behavior (#1535) (thanks @JustYannicc)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-01-24 04:19:01 +00:00

236 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
summary: "End-to-end guide for running Clawdbot as a personal assistant with safety cautions"
read_when:
- Onboarding a new assistant instance
- Reviewing safety/permission implications
---
# Building a personal assistant with Clawdbot (Clawd-style)
Clawdbot is a WhatsApp + Telegram + Discord + iMessage gateway for **Pi** agents. Plugins add Mattermost. This guide is the "personal assistant" setup: one dedicated WhatsApp number that behaves like your always-on agent.
## ⚠️ Safety first
Youre putting an agent in a position to:
- run commands on your machine (depending on your Pi tool setup)
- read/write files in your workspace
- send messages back out via WhatsApp/Telegram/Discord/Mattermost (plugin)
Start conservative:
- Always set `channels.whatsapp.allowFrom` (never run open-to-the-world on your personal Mac).
- Use a dedicated WhatsApp number for the assistant.
- Heartbeats now default to every 30 minutes. Disable until you trust the setup by setting `agents.defaults.heartbeat.every: "0m"`.
## Prerequisites
- Node **22+**
- Clawdbot available on PATH (recommended: global install)
- A second phone number (SIM/eSIM/prepaid) for the assistant
```bash
npm install -g clawdbot@latest
# or: pnpm add -g clawdbot@latest
```
From source (development):
```bash
git clone https://github.com/clawdbot/clawdbot.git
cd clawdbot
pnpm install
pnpm ui:build # auto-installs UI deps on first run
pnpm build
pnpm link --global
```
## The two-phone setup (recommended)
You want this:
```
Your Phone (personal) Second Phone (assistant)
┌─────────────────┐ ┌─────────────────┐
│ Your WhatsApp │ ──────▶ │ Assistant WA │
│ +1-555-YOU │ message │ +1-555-CLAWD │
└─────────────────┘ └────────┬────────┘
│ linked via QR
┌─────────────────┐
│ Your Mac │
│ (clawdbot) │
│ Pi agent │
└─────────────────┘
```
If you link your personal WhatsApp to Clawdbot, every message to you becomes “agent input”. Thats rarely what you want.
## 5-minute quick start
1) Pair WhatsApp Web (shows QR; scan with the assistant phone):
```bash
clawdbot channels login
```
2) Start the Gateway (leave it running):
```bash
clawdbot gateway --port 18789
```
3) Put a minimal config in `~/.clawdbot/clawdbot.json`:
```json5
{
channels: { whatsapp: { allowFrom: ["+15555550123"] } }
}
```
Now message the assistant number from your allowlisted phone.
When onboarding finishes, we auto-open the dashboard with your gateway token and print the tokenized link. To reopen later: `clawdbot dashboard`.
## Give the agent a workspace (AGENTS)
Clawd reads operating instructions and “memory” from its workspace directory.
By default, Clawdbot uses `~/clawd` as the agent workspace, and will create it (plus starter `AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`) automatically on setup/first agent run. `BOOTSTRAP.md` is only created when the workspace is brand new (it should not come back after you delete it).
Tip: treat this folder like Clawds “memory” and make it a git repo (ideally private) so your `AGENTS.md` + memory files are backed up. If git is installed, brand-new workspaces are auto-initialized.
```bash
clawdbot setup
```
Full workspace layout + backup guide: [Agent workspace](/concepts/agent-workspace)
Memory workflow: [Memory](/concepts/memory)
Optional: choose a different workspace with `agents.defaults.workspace` (supports `~`).
```json5
{
agent: {
workspace: "~/clawd"
}
}
```
If you already ship your own workspace files from a repo, you can disable bootstrap file creation entirely:
```json5
{
agent: {
skipBootstrap: true
}
}
```
## The config that turns it into “an assistant”
Clawdbot defaults to a good assistant setup, but youll usually want to tune:
- persona/instructions in `SOUL.md`
- thinking defaults (if desired)
- heartbeats (once you trust it)
Example:
```json5
{
logging: { level: "info" },
agent: {
model: "anthropic/claude-opus-4-5",
workspace: "~/clawd",
thinkingDefault: "high",
timeoutSeconds: 1800,
// Start with 0; enable later.
heartbeat: { every: "0m" }
},
channels: {
whatsapp: {
allowFrom: ["+15555550123"],
groups: {
"*": { requireMention: true }
}
}
},
routing: {
groupChat: {
mentionPatterns: ["@clawd", "clawd"]
}
},
session: {
scope: "per-sender",
resetTriggers: ["/new", "/reset"],
reset: {
mode: "daily",
atHour: 4,
idleMinutes: 10080
}
}
}
```
## Sessions and memory
- Session files: `~/.clawdbot/agents/<agentId>/sessions/{{SessionId}}.jsonl`
- Session metadata (token usage, last route, etc): `~/.clawdbot/agents/<agentId>/sessions/sessions.json` (legacy: `~/.clawdbot/sessions/sessions.json`)
- `/new` or `/reset` starts a fresh session for that chat (configurable via `resetTriggers`). If sent alone, the agent replies with a short hello to confirm the reset.
- `/compact [instructions]` compacts the session context and reports the remaining context budget.
## Heartbeats (proactive mode)
By default, Clawdbot runs a heartbeat every 30 minutes with the prompt:
`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`
Set `agents.defaults.heartbeat.every: "0m"` to disable.
- If `HEARTBEAT.md` exists but is effectively empty (only blank lines and markdown headers like `# Heading`), Clawdbot skips the heartbeat run to save API calls.
- If the file is missing, the heartbeat still runs and the model decides what to do.
- If the agent replies with `HEARTBEAT_OK` (optionally with short padding; see `agents.defaults.heartbeat.ackMaxChars`), Clawdbot suppresses outbound delivery for that heartbeat.
- Heartbeats run full agent turns — shorter intervals burn more tokens.
```json5
{
agent: {
heartbeat: { every: "30m" }
}
}
```
## Media in and out
Inbound attachments (images/audio/docs) can be surfaced to your command via templates:
- `{{MediaPath}}` (local temp file path)
- `{{MediaUrl}}` (pseudo-URL)
- `{{Transcript}}` (if audio transcription is enabled)
Outbound attachments from the agent: include `MEDIA:<path-or-url>` on its own line (no spaces). Example:
```
Heres the screenshot.
MEDIA:/tmp/screenshot.png
```
Clawdbot extracts these and sends them as media alongside the text.
## Operations checklist
```bash
clawdbot status # local status (creds, sessions, queued events)
clawdbot status --all # full diagnosis (read-only, pasteable)
clawdbot status --deep # adds gateway health probes (Telegram + Discord)
clawdbot health --json # gateway health snapshot (WS)
```
Logs live under `/tmp/clawdbot/` (default: `clawdbot-YYYY-MM-DD.log`).
## Next steps
- WebChat: [WebChat](/web/webchat)
- Gateway ops: [Gateway runbook](/gateway)
- Cron + wakeups: [Cron jobs](/automation/cron-jobs)
- macOS menu bar companion: [Clawdbot macOS app](/platforms/macos)
- iOS node app: [iOS app](/platforms/ios)
- Android node app: [Android app](/platforms/android)
- Windows status: [Windows (WSL2)](/platforms/windows)
- Linux status: [Linux app](/platforms/linux)
- Security: [Security](/gateway/security)