Skill: arn0ld87/openclaw-expert (version 1.1.0)

--- name: openclaw-expert description: > OpenClaw self-hosted AI agent framework expert. Trigger for: openclaw.json, gateway, channels, models, skills, agents, secrets, cron, sandbox, memory, multi-agent, bindings, dmPolicy, SecretRef, session config, workspace files (AGENTS.md, SOUL.md, MEMORY.md), troubleshooting, security hardening. Covers installation, configuration, channel setup, memory tuning, Docker deployment. --- # OpenClaw Expert Skill ## Kernprinzip: Docs-First + Backup-First OpenClaw verwendet CalVer-Versioning (YYYY.M.D-N) und ändert sich häufig. **Vor jeder Änderung** diese Checkliste abarbeiten: 1. **Version prüfen**: `openclaw --version` 2. **Live-Docs holen** — `web_fetch` auf relevante Docs-Seiten (URLs in Referenzdateien) 3. **Community-Tipps suchen** — `web_search` nach aktuellen Workarounds 4. **Backup anlegen** — Niemals Konfig ohne Backup ändern 5. **Änderung durchführen** 6. **Validieren** — `openclaw doctor` vor und nach jeder Änderung 7. **Gateway neu starten** — `systemctl --user restart openclaw-gateway` 8. **Testen** — `openclaw status` + Kanal-Test --- ## Architektur auf einen Blick ``` Messaging-Kanäle (WhatsApp, Telegram, Slack, Discord, Signal, iMessage, Teams, Matrix, Google Chat, Zalo, WebChat…) │ ▼ ┌───────────────────────────────┐ │ Gateway │ ← ws://127.0.0.1:18789 │ (Control-Plane, RPC) │ ← Config: ~/.openclaw/openclaw.json (JSON5) │ systemd user service │ ← Dashboard: http://127.0.0.1:18789 └──────────────┬────────────────┘ │ ┌──────┴──────┐ │ Agent(s) │ ← Workspace: ~/.openclaw/workspace/ │ Runtime │ ← Sessions: ~/.openclaw/agents/<id>/sessions/ └──────┬──────┘ │ ┌──────┴──────────────────────────┐ │ Nodes (optional) │ │ iOS / Android / macOS / Pi │ │ + Canvas / A2UI │ └─────────────────────────────────┘ ``` ### Verzeichnisstruktur ``` ~/.openclaw/ ├── openclaw.json # Haupt-Config (JSON5 – Kommentare + trailing commas!) ├── credentials/ # API-Keys (chmod 600!) │ ├── anthropic │ ├── openai │ └── openrouter ├── agents/ │ └── <agentId>/ │ ├── agent/ # Auth-Profile, Model-Registry │ └── sessions/ # Session-Logs (*.jsonl) ├── skills/ # Managed/lokale Skills ├── cron/ # Cron-Jobs (jobs.json, runs/) └── workspace/ # Agent-Workspace (= das "Gehirn") ├── AGENTS.md # Betriebsanweisungen (in JEDER Session geladen) ├── SOUL.md # Persönlichkeit, Ton, Grenzen (jede Session) ├── USER.md # Nutzerprofil (jede Session) ├── TOOLS.md # Tool-Hinweise (jede Session) ├── IDENTITY.md # Name, Emoji, Vibe ├── HEARTBEAT.md # Scheduled-Tasks / Cron-Checkliste ├── MEMORY.md # Langzeit-Gedächtnis (nur private Sessions!) ├── BOOT.md # Startup-Checkliste (bei Gateway-Restart) ├── BOOTSTRAP.md # Einmal-Setup (nach Ausführung gelöscht) ├── memory/ # Tages-Logs (YYYY-MM-DD.md) └── skills/ # Workspace-Skills ``` --- ## ⚡ Quick-Start: Häufige Aufgaben ### Neuinstallation ```bash pnpm add -g openclaw@latest && pnpm approve-builds -g openclaw onboard # Interaktiver Wizard openclaw doctor # Gesundheitscheck ``` ### Channel einrichten (WhatsApp) ```bash openclaw channels login --channel whatsapp --account personal openclaw pairing list whatsapp openclaw pairing approve whatsapp <CODE> ``` ### Multi-Agent Setup ```bash openclaw agents add work # Neuer Agent openclaw agents bind work "whatsapp:biz" # Routing-Regel ``` ### Memory mit Semantic Search ```json5 // In openclaw.json: agents: { defaults: { memorySearch: { provider: "openai", model: "text-embedding-3-small", query: { hybrid: { enabled: true }, mmr: { enabled: true, lambda: 0.7 }, temporalDecay: { enabled: true, halfLifeDays: 30 } } } } } ``` ### Sandbox aktivieren ```json5 agents: { defaults: { sandbox: { mode: "non-main", scope: "agent", workspaceAccess: "ro", docker: { image: "openclaw-sandbox:bookworm-slim" } } } } ``` ### Cron-Job erstellen ```bash openclaw cron add --name "Tageszusammenfassung" \ --cron "0 7 * * *" \ --message "Fasse die wichtigsten Ereignisse zusammen" \ --announce ``` ### Config-Problem debuggen ```bash openclaw config validate openclaw doctor --fix systemctl --user restart openclaw-gateway ``` --- ## Referenzdateien — Wann was lesen Dieses Skill-Paket enthält detaillierte Referenzdateien. **Lies die relevante Datei BEVOR du eine Aktion durchführst.** Die Dateien liegen unter `references/` im Skill-Verzeichnis. | Aufgabe | Referenzdatei | Inhalt | |---|---|---| | **Schnellnachschlage** | `references/quick-reference.md` | Einseitige Referenz: Verzeichnisse, Minimal-Config, CLI-Einzeiler, Troubleshooting-Patterns | | Installation & erste Schritte | `references/installation.md` | npm/pnpm, Docker, VPS-Setup, Onboarding-Wizard | | openclaw.json bearbeiten | `references/config-reference.md` | Vollständige Feld-Referenz (agents, models, channels, session, secrets, bindings, $include…) | | Dashboard (Control UI) | `references/dashboard.md` | Alle Dashboard-Bereiche, Zugriff, Troubleshooting | | Workspace-Dateien schreiben | `references/workspace-files.md` | AGENTS.md, SOUL.md, USER.md, HEARTBEAT.md, MEMORY.md Templates | | Channels einrichten | `references/channels.md` | Telegram (komplett!), WhatsApp, Discord, Slack, Signal + Troubleshooting | | Memory & Compaction tunen | `references/memory-system.md` | memoryFlush, memorySearch, Compaction, Semantic Search, Decay | | Docker-Deployment | `references/docker-setup.md` | docker-compose, Sandbox, alpine/openclaw, Permissions | | Security-Hardening | `references/security-hardening.md` | dmPolicy, SecretRef, Token-Rotation, Allowlists, Sandboxing, CIS-Style | | Skills entwickeln/installieren | `references/skills-guide.md` | SKILL.md-Format, ClawHub, Workspace-Skills, Security-Review | | Multi-Agent-Routing | `references/multi-agent.md` | agents.list, bindings, accountId, agentId, Isolation, Per-Agent Sandbox/Tools | | CLI-Referenz | `references/cli-reference.md` | Alle Befehle mit Syntax und Beispielen (agents, browser, cron, secrets, sandbox…) | | Dashboard / Control UI | `references/dashboard.md` | Sidebar-Navigation, Bereiche, CORS, Config, Troubleshooting | | Nodes & Remote-Zugriff | `references/nodes-and-remote.md` | Node-Typen, Pairing, Headless-Nodes, Bonjour/mDNS, Exec-Approval | | Tailscale-Integration | `references/tailscale-integration.md` | Serve vs Funnel vs Tailnet-Bind, SSH-Tunnel, Auth, Config-Beispiele | | Praxis-Beispiele | `references/examples.md` | 7 vollständige Setup-Szenarien (Einsteiger → Multi-Agent → Kosten-optimiert) | | Troubleshooting | `references/troubleshooting.md` | Häufige Fehler, Logs, Diagnose-Schritte, SecretRef, Sandbox, Skill-Gating | | Tricks & Power-User | `references/tricks-and-hacks.md` | Community-Tipps, Cost-Saving, Obsidian, Surge, Watchdog | > **Companion Skill**: Für Cognee Knowledge-Graph-Memory (Docker-Setup, LLM/Embedding-Config, > Ollama Cloud + OpenAI Hybrid, Plugin-Troubleshooting) → den **`cognee-openclaw-memory` Skill** nutzen. --- ## Schnellreferenz: Wichtigste CLI-Befehle ```bash # Status & Diagnose openclaw --version # CalVer-Version openclaw doctor # Gesundheitscheck (IMMER!) openclaw doctor --fix # Auto-Fix openclaw status # Kurzer Status openclaw dashboard # Browser-UI (Port 18789) # Gateway openclaw gateway start|stop|restart|status openclaw gateway install # systemd user service openclaw gateway log # Logs (= journalctl --user -u openclaw-gateway -f) # Agents (Multi-Agent) openclaw agents list # Agent-Liste openclaw agents add <id> # Neuen Agent erstellen openclaw agents bind <agent> <binding> # Binding hinzufügen openclaw agents unbind <agent> <binding> # Binding entfernen # Channels openclaw channels list|add|remove|restart openclaw channels status --probe # Live-Check openclaw channels login --channel whatsapp --account <id> # WhatsApp Account # Models openclaw models list|set <provider/model> openclaw models auth setup-token # Interaktiver Auth-Setup # Skills openclaw skills list|reload clawhub search|install|update <name> # Secrets (Secure Credential Management) openclaw secrets audit # Plaintext-Scan openclaw secrets configure # Interaktiver Wizard openclaw secrets reload # Runtime-Refresh # Cron Jobs openclaw cron list # Alle Jobs openclaw cron add --name "..." --cron "0 7 * * *" --message "..." --announce openclaw cron runs --id <jobId> # Run-History # Browser Automation openclaw browser start|stop|status # Sandbox openclaw sandbox list|status # Memory & Sessions openclaw sessions list|clean openclaw memory flush # Security openclaw [REDACTED_SECRET] --force --length 64 openclaw security audit --deep # Nodes & Devices openclaw nodes status # Verbundene Nodes anzeigen openclaw nodes describe --all # Node-Capabilities auflisten openclaw nodes run --node <id> -- <cmd> # Befehl auf Node ausführen openclaw devices list # Pairing-Requests anzeigen openclaw devices approve <requestId> # Node-Pairing genehmigen # Channel-Pairing openclaw pairing list|approve <channel> <code> # Config openclaw config list|get|set|validate # Hooks openclaw hooks list|test # Webhooks openclaw webhooks list|test # DNS (für Nodes) openclaw dns setup|status # Update pnpm add -g openclaw@latest && pnpm approve-builds -g && openclaw doctor ``` --- ## Sicherheits-Grundregeln (IMMER beachten!) 1. **Gateway bind: `loopback`** — Niemals `lan` oder `0.0.0.0` ohne Tailscale/VPN 2. **dmPolicy: `allowlist` oder `pairing`** — Niemals `open` in Produktion 3. **[REDACTED_SECRET] 64 Zeichen** — `openclaw [REDACTED_SECRET] --force --length 64` 4. **Secrets mit SecretRef** — API-Keys nie im Plaintext in Config, `openclaw secrets configure` 5. **Credentials: `chmod 600`** — `chmod 600 ~/.openclaw/credentials/*` 6. **Skills reviewen** — Vor Installation Quellcode prüfen, ClawHub "Hide Suspicious" nutzen 7. **Kein root** — OpenClaw als eigener User betreiben 8. **Workspace = privat** — Git-Backup in **privates** Repo, MEMORY.md nie in Groups laden 9. **API-Spending-Limits** — Beim Provider setzen, bevor Heartbeat aktiviert wird 10. **Sandbox für Tools** — `agents.defaults.sandbox.mode: "all"` wenn möglich --- ## Workflow: Docs nachschlagen ### Offizielle Docs-URLs (für web_fetch) ``` https://docs.openclaw.ai # Hauptseite https://docs.openclaw.ai/install/docker # Docker https://docs.openclaw.ai/concepts/agent-workspace # Workspace https://docs.openclaw.ai/concepts/memory # Memory https://docs.openclaw.ai/concepts/multi-agent # Multi-Agent https://docs.openclaw.ai/concepts/session # Session Management https://docs.openclaw.ai/automation/cron-jobs # Cron Jobs https://docs.openclaw.ai/gateway/secrets # Secrets Management https://docs.openclaw.ai/gateway/configuration # Config https://docs.openclaw.ai/channels/<name> # Channel-Guides https://docs.openclaw.ai/models # Models https://docs.openclaw.ai/tools/skills # Skills https://docs.openclaw.ai/security # Security ``` Alternative Docs-Mirror: `https://openclaw.im/docs/` ### Community-Suche (für web_search) ``` "openclaw <Thema> 2026 tips" "openclaw <Problem> fix workaround github issue" "openclaw.json <Section> advanced configuration" ``` Quellen-Priorität: 1. `github.com/openclaw/openclaw` (Issues, Discussions, AGENTS.md) 2. `docs.openclaw.ai` / `openclaw.im/docs` 3. Community-Guides (Simon Willison TIL, Substack, Medium) 4. Reddit r/selfhosted, Hacker News --- ## Backup-Strategie (IMMER vor Änderungen) ```bash # Snapshot der Config cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak # Versioniertes Backup tar czf ~/openclaw-backup-$(date +%Y%m%d_%H%M%S).tar.gz ~/.openclaw/ # Git-Backup des Workspace (empfohlen) cd ~/.openclaw/workspace && git add -A && git commit -m "backup: $(date +%Y%m%d_%H%M%S)" ``` --- ## Protokoll: Sichere Config-Änderung 1. `openclaw --version` → Version notieren 2. Relevante Referenzdatei lesen (siehe Tabelle oben) 3. Live-Docs fetchen (URLs oben) 4. `cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak` 5. Änderung durchführen 6. `openclaw doctor` 7. `systemctl --user restart openclaw-gateway` 8. `openclaw status` + Funktionstest im Channel 9. Bei Fehler: `cp ~/.openclaw/openclaw.json.bak ~/.openclaw/openclaw.json && systemctl --user restart openclaw-gateway` --- ## Wichtige Konzepte (Kurzreferenz) ### Multi-Agent-Routing ```json5 { agents: { list: [ { id: "home", default: true, workspace: "~/.openclaw/workspace-home" }, { id: "work", workspace: "~/.openclaw/workspace-work" }, ], }, bindings: [ { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } }, { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } }, ], } ``` ### Session-DmScope - `main` — Alle DMs teilen eine Session (Single-User) - `per-channel-peer` — DMs pro Channel+Sender isolieren (Multi-User empfohlen) - `per-account-channel-peer` — DMs pro Account+Channel+Sender (Multi-Account) ### Config-Hot-Reload | Modus | Verhalten | |---|---| | `hybrid` | Auto-Applie + Auto-Restart für Kritisches | | `hot` | Nur Hot-Applie, Warnung bei Restart-Bedarf | | `restart` | Immer Restart bei Änderung | | `off` | Kein File-Watching | ### SecretRef ```json5 // Env-Variable { source: "env", provider: "default", id: "OPENAI_API_KEY" } // File { source: "file", provider: "filemain", id: "/providers/openai/apiKey" } // Exec (1Password, Vault, sops) { source: "exec", provider: "vault", id: "providers/openai/apiKey" } ```

path: references/channels.md
content: # Channels — Messaging-Kanäle einrichten & troubleshooten

## Übersicht

| Kanal | Adapter | Schwierigkeit | Besonderheiten |
|---|---|---|---|
| **Telegram** | grammY | ⭐ Einfach | Streaming, Reactions, Forum-Topics, Empfohlen |
| **WhatsApp** | Baileys | ⭐⭐ Mittel | QR-Pairing, selfChatMode, globale dmPolicy |
| **Discord** | discord.js | ⭐⭐ Mittel | Message Content Intent nötig |
| **Slack** | Bolt | ⭐⭐ Mittel | Socket Mode oder Events API |
| **Signal** | signal-cli | ⭐⭐⭐ Schwer | Java-Dependency, CLI-basiert |
| **iMessage** | BlueBubbles | ⭐⭐⭐ Schwer | Braucht Mac mit Messages-Login |
| **Teams** | Extension | ⭐⭐⭐ Schwer | Entra ID App-Registration |
| **Google Chat** | Chat API | ⭐⭐ Mittel | Google Cloud Projekt nötig |
| **Matrix** | Extension | ⭐⭐ Mittel | Homeserver + Access-Token |
| **WebChat** | Built-in | ⭐ Einfach | Im Dashboard integriert |

---

## Telegram — Vollständige Anleitung

### 1. Bot erstellen
1. `@BotFather` öffnen → `/newbot`
2. Name + Username (muss auf `bot` enden)
3. **Token sicher kopieren** (kein trailing Space!)
4. BotFather-Einstellungen:
```
/setdescription   → Kurzbeschreibung
/setabouttext      → About-Text
/setuserpic        → Profilbild
/setcommands       → start, new, status, help
/setprivacy        → Disable (für Gruppen ohne @mention)
/setjoingroups     → Enable
```

### 2. Minimal-Config
```json5
{
  channels: {
    telegram: {
      enabled: true,
      botToken: "123456789:AAH...",
      dmPolicy: "pairing",           // Default: Pairing-Flow
      groups: { "*": { requireMention: true } },
    },
  },
}
```

Env-Fallback: `TELEGRAM_BOT_TOKEN=...` (nur für Default-Account).
Telegram nutzt NICHT `openclaw channels login telegram`!

### 3. Vollständige Config (alle Felder)
```json5
{
  channels: {
    telegram: {
      enabled: true,
      botToken: "123:abc",
      dmPolicy: "allowlist",          // "pairing" | "allowlist" | "open" | "disabled"
      allowFrom: [7403482253],        // Numerische User-IDs! NICHT @username
      groupPolicy: "allowlist",       // "allowlist" | "open" | "disabled"
      groupAllowFrom: [7403482253],   // Separat von allowFrom (seit 2026.2.25)

      // Streaming
      streaming: "partial",           // "off" | "partial" | "block" | "progress"

      // Nachrichten-Formatierung
      textChunkLimit: 4000,           // Telegram-Limit (max 4096)
      chunkMode: "newline",           // "newline" = Absatz-Grenzen bevorzugen

      // Media
      mediaMaxMb: 50,                 // Default: 5 MB — erhöhen!

      // Timeouts & Retries
      timeoutSeconds: 30,             // Telegram API Timeout
      retry: { maxRetries: 3 },       // Outbound-API-Retries

      // History
      historyLimit: 50,               // Gruppen-Context-History (0 = aus)
      dmHistoryLimit: 100,            // DM-History

      // Reactions
      // ackReaction: "👀",           // Bestätigungs-Emoji beim Verarbeiten
      // "" = deaktiviert

      // Webhook (optional, statt Long-Polling)
      // webhookUrl: "https://yourdomain.com/telegram-webhook",
      // webhookSecret: "<secret>",
      // webhookPort: 8787,           // Default, lokal
      // webhookHost: "0.0.0.0",      // Nur wenn externer Ingress nötig

      // Sonstiges
      // linkPreview: false,          // Link-Vorschau deaktivieren
      // proxy: "http://proxy:8080",  // IPv6-Workaround
      // configWrites: true,          // Channel kann Config schreiben (Default)
    },
  },
}
```

### 4. Pairing-Workflow
```bash
# Gateway starten
openclaw gateway start

# Bot anschreiben → Pairing-Code erhalten
# Format: "Your Telegram user id: 123456789 Pairing code: ABCD1234"

# Genehmigen:
openclaw pairing approve telegram ABCD1234
# ODER mit User-ID:
openclaw pairing approve telegram:123456789 ABCD1234

# Code verfällt nach 1 Stunde!
```

Danach: Auf `allowlist` wechseln und User-ID in `allowFrom` eintragen.

### 5. User-ID herausfinden
```bash
# Methode 1: Logs lesen
openclaw logs --follow
# → "from.id" in Log-Ausgabe

# Methode 2: Updates API
curl "https://api.telegram.org/bot<TOKEN>/getUpdates" | jq '.result[-1].message.from.id'

# Methode 3: @userinfobot oder @getidsbot anschreiben
```

### 6. Gruppen einrichten

**Privacy Mode** (WICHTIG):

| Privacy Mode | Bot sieht in Gruppen |
|---|---|
| Enabled (Default) | Nur /commands und @mentions |
| Disabled | Alle Nachrichten |
| Bot ist Admin | Alle Nachrichten (unabhängig) |

```
@BotFather → /setprivacy → Disable
# DANN: Bot aus Gruppe entfernen + neu hinzufügen!
```

**Gruppen-Config**:
```json5
{
  channels: {
    telegram: {
      groups: {
        "*": { requireMention: true },       // Alle Gruppen: nur @mention
        "-1001234567890": {                   // Spezifische Gruppe
          requireMention: false,
          groupPolicy: "open",                // Jeder in dieser Gruppe
          allowFrom: [7403482253],
        },
      },
    },
  },
}
```

**Gruppen-ID finden**:
- Nachricht in Gruppe senden → `openclaw logs --follow` → Chat-ID ablesen
- Reguläre Gruppe: `-123456789`
- Supergruppe: `-1001234567890` (100-Prefix nach dem Minus!)
- **ID ändert sich bei Upgrade** auf Supergruppe! → Neues Pairing nötig

**Forum-Gruppen (Topics)**:
- Jedes Topic wird isoliert mit Thread-ID
- Per-Topic-Config-Overrides möglich
- General-Topic = `:topic:1`

### 7. Gruppen-Auth (seit 2026.2.25)
- `groupAllowFrom` ist separat von `allowFrom`
- Gruppen-Auth erbt NICHT DM-Pairing-Approvals
- Commands brauchen Auth auch bei `groupPolicy: "open"`

### 8. Streaming-Modi

| Modus | Verhalten |
|---|---|
| `off` | Keine Vorschau |
| `partial` | Nachricht wird progressiv editiert |
| `block` | Chunked als komplette Blöcke |
| `progress` | = `partial` (Kompatibilität) |

Reasoning-Stream: `/reasoning stream` → Reasoning in Live-Preview, finale Antwort ohne.

### 9. Long-Polling vs. Webhook

| | Long-Polling (Default) | Webhook |
|---|---|---|
| Setup | Kein public URL nötig | HTTPS-Endpoint nötig |
| NAT/Firewall | Funktioniert überall | Braucht offenen Port |
| Latenz | Etwas höher | Niedriger |
| Config | Keine | webhookUrl + webhookSecret |
| Empfehlung | ✅ Für die meisten | Produktion mit Tailscale |

### 10. Telegram Troubleshooting

| Problem | Ursache | Lösung |
|---|---|---|
| 401 Unauthorized | Token falsch/abgelaufen | BotFather → neuen Token → Config → restart |
| Token mit Space kopiert | Trailing Space | Token trimmen, neu einfügen |
| Bot antwortet nicht | User nicht autorisiert | User-ID zu `allowFrom` (als Zahl!) |
| `@username` statt User-ID | Falsches Format | Numerische ID nutzen, nicht @handle |
| Bot schweigt in Gruppen | Privacy Mode enabled | `/setprivacy` Disable → Bot re-adden |
| "plugin not found: telegram" | Falsche Config-Stelle | In `channels.telegram`, NICHT `plugins.entries` |
| Pairing-Code läuft ab | 1h Timeout | Erneut anschreiben → neuer Code |
| Gruppen-ID geändert | Upgrade auf Supergruppe | Neue -100-ID in Config/Pairing |
| `TypeError: fetch failed` | IPv6-Problem auf VPS | IPv4 erzwingen (s.u.) |
| Nachrichten abgeschnitten | 4000-Zeichen-Limit | `chunkMode: "newline"` |
| Bot nach Update tot | Alter Prozess läuft noch | `ps aux \| grep openclaw` → killen |
| Migration Clawdbot→OpenClaw | Alte Config/Prozesse | `cp -r ~/.clawdbot/* ~/.openclaw/` + alte stoppen |
| "access not configured" | Pairing OK, aber nicht autorisiert | `dmPolicy: "allowlist"` + `allowFrom` setzen |

**IPv6-Problem fix**:
```bash
# Prüfen:
dig +short api.telegram.org A
dig +short api.telegram.org AAAA

# Fix: IPv4 erzwingen via /etc/hosts
echo "$(dig +short api.telegram.org A | head -1) api.telegram.org" | sudo tee -a /etc/hosts

# Oder: proxy in Config setzen
```

---

## WhatsApp — Vollständige Anleitung

WhatsApp nutzt WhatsApp Web (Baileys) als Channel-Adapter. Der Gateway besitzt die verknüpfte Session.

### 1. Schnell-Setup

```json5
{
  channels: {
    whatsapp: {
      enabled: true,
      dmPolicy: "pairing",           // Default für unbekannte Sender
      allowFrom: ["+15551234567"],   // E.164 MIT + !
      groupPolicy: "allowlist",
      groupAllowFrom: ["+15551234567"],
    },
  },
}
```

```bash
# QR-Code anzeigen
openclaw channels login --channel whatsapp

# Für spezifischen Account:
openclaw channels login --channel whatsapp --account work

# Gateway starten
openclaw gateway

# Pairing genehmigen (falls pairing mode)
openclaw pairing list whatsapp
openclaw pairing approve whatsapp <CODE>
```

**Empfehlung:** Separate Nummer für OpenClaw nutzen (saubereres Routing, weniger self-chat-Konfusion).

### 2. Deployment-Muster

| Muster | Beschreibung |
|---|---|
| **Dedizierte Nummer** | Sauberste Option, eigene WhatsApp-Identität für OpenClaw |
| **Personal-Nummer** | Onboarding schreibt `selfChatMode: true`, `allowFrom` inkludiert eigene Nummer |

### 3. Access Control & DM-Policy

**DM-Policy (`channels.whatsapp.dmPolicy`)** steuert Direkt-Chat-Zugriff:

| Modus | Verhalten |
|---|---|
| `pairing` | Default — User muss pairing anfragen und genehmigt werden |
| `allowlist` | Nur `allowFrom`-Nummern dürfen schreiben |
| `open` | Erfordert `allowFrom: ["*"]` — jeder darf schreiben (gefährlich!) |
| `disabled` | Keine DMs erlaubt |

```json5
{
  channels: {
    whatsapp: {
      dmPolicy: "allowlist",
      allowFrom: ["+4915568920209", "+4917212345678"],
      // Multi-Account-Override:
      accounts: {
        work: {
          dmPolicy: "pairing",  // Override für "work"-Account
        },
      },
    },
  },
}
```

**Wichtig:** `allowFrom` akzeptiert E.164-Nummern (werden intern normalisiert).

**Self-Chat-Verhalten:**
- Wenn die verknüpfte Nummer auch in `allowFrom` steht:
  - Read-Receipts für Self-Chat werden übersprungen
  - Mention-JID Auto-Trigger verhindert Selbst-Ping
  - `messages.responsePrefix` defaultet zu `[{identity.name}]` oder `[openclaw]`

### 4. Group Access (zweilagig)

**Schicht 1: Gruppen-Mitgliedschafts-Allowlist (`channels.whatsapp.groups`)**
- Wenn weggelassen: Alle Gruppen sind berechtigt
- Wenn vorhanden: Wirkt als Gruppen-Allowlist (`"*"` erlaubt alle)

**Schicht 2: Gruppen-Sender-Policy (`groupPolicy` + `groupAllowFrom`)**

| groupPolicy | Verhalten |
|---|---|
| `open` | Sender-Allowlist wird umgangen |
| `allowlist` | Sender muss `groupAllowFrom` entsprechen (oder `*`) |
| `disabled` | Alle Gruppen-Nachrichten blockieren |

**Fallback-Logik:**
- Wenn `groupAllowFrom` nicht gesetzt → Fallback auf `allowFrom`
- Sender-Allowlists werden VOR Mention/Reply-Aktivierung geprüft

```json5
{
  channels: {
    whatsapp: {
      groups: {
        "*": { requireMention: true },      // Alle Gruppen: nur @mention
        "[REDACTED_SECRET]": {                  // Spezifische Gruppe
          groupPolicy: "open",                // Jeder in dieser Gruppe
        },
      },
      groupPolicy: "allowlist",
      groupAllowFrom: ["+4915568920209"],
    },
  },
}
```

**Wichtig:** Wenn KEIN `channels.whatsapp` Block existiert, ist der groupPolicy-Fallback `allowlist` (mit Warning-Log), selbst wenn `channels.defaults.groupPolicy` gesetzt ist.

### 5. Mention-Aktivierung & /activation

Gruppen-Antworten erfordern Mention by default. Mention-Erkennung:
- Explizite WhatsApp-Mentions der Bot-Identität
- Konfigurierte Mention-Regex (`agents.list[].groupChat.mentionPatterns`)
- Implizite Reply-to-Bot-Erkennung (Reply-Sender = Bot-Identität)

**Sicherheits-Hinweis:** Reply/Quote erfüllt nur Mention-Gating, gewährt aber KEINE Sender-Autorisierung. Bei `groupPolicy: "allowlist"` werden nicht-allowlisted Sender auch beim Reply auf allowlisted User blockiert.

**Session-Level Aktivierung:**
- `/activation mention` — Nur bei Mention antworten
- `/activation always` — Immer antworten (Override)

`activation` aktualisiert Session-State (nicht global), Owner-gegate.

### 6. Config-Referenz

```json5
{
  channels: {
    whatsapp: {
      enabled: true,
      dmPolicy: "allowlist",
      allowFrom: ["+4915568920209"],
      selfChatMode: true,          // Self-Chat als Bot-Befehle

      groupPolicy: "allowlist",
      groupAllowFrom: ["+4915568920209"],
      groups: {
        "*": { requireMention: true },
      },

      // Delivery
      textChunkLimit: 4000,
      chunkMode: "newline",        // "length" | "newline"
      mediaMaxMb: 50,
      sendReadReceipts: true,      // Default

      // Ack-Reactions
      ackReaction: {
        emoji: "👀",
        direct: true,
        group: "mentions",         // "always" | "mentions" | "never"
      },

      // Debounce
      debounceMs: 0,               // 0 = sofort

      // Multi-Account
      accounts: {
        work: {
          enabled: true,
          authDir: "~/.openclaw/credentials/whatsapp/work",
          dmPolicy: "pairing",
        },
      },
    },
  },
}
```

### 7. Pairing-Workflow

```bash
# 1. Gateway starten
openclaw gateway start

# 2. QR-Code scannen (WhatsApp → Verknüpfte Geräte)
# QR erscheint in Terminal oder Dashboard → Channels

# 3. Bei pairing mode: Code genehmigen
openclaw pairing list whatsapp
openclaw pairing approve whatsapp ABCD1234

# Danach auf allowlist wechseln:
# allowFrom in Config eintragen + dmPolicy: "allowlist"
```

Pairing-Requests verfallen nach 1 Stunde. Max 3 pending Requests pro Channel.

### 8. Multi-Account & Credentials

**Account-Selection:**
- Account-IDs kommen aus `channels.whatsapp.accounts`
- Default: `default` falls vorhanden, sonst erster Account (sortiert)
- IDs werden intern normalisiert

**Credential-Paths:**
- Aktuell: `~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
- Backup: `creds.json.bak`
- Legacy-Default-Auth in `~/.openclaw/credentials/` wird noch erkannt/migriert

**Logout:**
```bash
openclaw channels logout --channel whatsapp           # Default-Account
openclaw channels logout --channel whatsapp --account work  # Spezifisch
```

### 9. Troubleshooting

| Problem | Ursache | Lösung |
|---|---|---|
| "Not linked" | Keine Session | `openclaw channels login` + QR scannen |
| Reconnect-Loop | Verbindung instabil | `openclaw doctor` + Logs prüfen |
| "No active listener" | Gateway nicht läuft | Gateway starten, Account verknüpfen |
| Gruppen ignoriert | `groupPolicy`, `groupAllowFrom`, `groups` prüfen | Mention-Gating + Duplicate-Keys checken |
| Gruppen-Nachrichten blockiert | Sender nicht in Allowlist | `groupAllowFrom` oder `groupPolicy: "open"` |
| Duplicate Keys | Spätere Keys überschreiben frühere | JSON5: nur EIN `groupPolicy` pro Scope |
| Gruppen-ID nicht gefunden | Nachricht senden → `openclaw logs --follow` | Chat-ID ablesen |
| Baileys-Warnung | Runtime nicht Node | Node nutzen (nicht Bun) für WhatsApp/Telegram |

### 10. WhatsApp-Eigenheiten

- **dmPolicy ist GLOBAL** für den WhatsApp-Account (nicht per-Agent!)
- **selfChatMode**: Nachrichten an sich selbst = Bot-Befehle
- **Max 4 verknüpfte Geräte** (WhatsApp-Limit)
- **Baileys** = Reverse-Engineered, kein offizielles API → kann brechen
- **Status/Broadcast-Chats** werden ignoriert (`@status`, `@broadcast`)
- **Read-Receipts** standardmäßig aktiviert, Self-Chat überspringt sie

---

## Discord

```json5
{
  channels: {
    discord: {
      enabled: true,
      botToken: "<discord-bot-token>",
      dmPolicy: "allowlist",
    },
  },
}
```

**PFLICHT**: Discord Developer Portal → Bot → Privileged Gateway Intents → **Message Content Intent** aktivieren!

---

## Slack

```json5
{
  channels: {
    slack: {
      enabled: true,
      appToken: "xapp-...",    // Socket Mode Token
      botToken: "xoxb-...",    // Bot OAuth Token
    },
  },
}
```

---

## Signal

```json5
{
  channels: {
    signal: { enabled: true },
    // signal-cli muss installiert + registriert sein
    // Java 17+ nötig
  },
}
```

---

## iMessage (BlueBubbles)

```json5
{
  channels: {
    imessage: {
      enabled: true,
      adapter: "bluebubbles",
      host: "http://<mac-tailscale-ip>:1234",
      [REDACTED_SECRET]",
    },
  },
}
```
Mac mit Messages eingeloggt + BlueBubbles-Server nötig.

---

## CLI: Channels verwalten

```bash
openclaw channels status              # Alle Channels
openclaw channels status --probe      # Mit Live-Check
openclaw channels restart telegram
openclaw channels restart whatsapp

# Nachricht senden
openclaw message send --channel telegram --target 7403482253 --message "Test"
openclaw message send --channel telegram --target @username --message "Test"
openclaw message send --channel whatsapp --target "+4915568920209" --message "Test"

# Logs
openclaw logs --follow --channel telegram
```

---

## Verwandte Docs

- **Quick-Ref**: `references/quick-reference.md` — Channel-Quick-Setup
- **Security**: `references/security-hardening.md` — dmPolicy, Allowlists, Access Control
- **Multi-Agent**: `references/multi-agent.md` — Per-Channel Bindings
- **CLI**: `references/cli-reference.md` — `openclaw channels` und `openclaw pairing` Befehle


path: references/cli-reference.md
content: # OpenClaw CLI-Referenz (Vollständig)

> Stand: März 2026. OpenClaw ändert sich häufig — bei unbekannten Flags `openclaw <command> --help` nutzen.

## Inhaltsverzeichnis
1. [Setup & Onboarding](#setup--onboarding)
2. [Gateway](#gateway)
3. [Doctor & Diagnose](#doctor--diagnose)
4. [Channels](#channels)
5. [Agents (Multi-Agent)](#agents-multi-agent)
6. [Models](#models)
7. [Skills & Plugins](#skills--plugins)
8. [Nodes & Devices](#nodes--devices)
9. [Browser](#browser)
10. [Sandbox](#sandbox)
11. [Cron (Scheduled Jobs)](#cron-scheduled-jobs)
12. [Config](#config)
13. [Secrets](#secrets)
14. [Sessions](#sessions)
15. [Memory](#memory)
16. [Security](#security)
17. [Pairing & Devices](#pairing--devices)
18. [Hooks & Webhooks](#hooks--webhooks)
19. [Update & Versioning](#update--versioning)
20. [Dashboard & TUI](#dashboard--tui)

---

## Setup & Onboarding

### `openclaw setup`

Initialisiert Config + Workspace.

```bash
openclaw setup                              # Workspace erstellen
openclaw setup --workspace <dir>           # Eigenes Workspace-Verzeichnis
openclaw setup --wizard                     # Onboarding-Wizard
openclaw setup --non-interactive            # Headless-Setup
openclaw setup --mode <local|remote>        # Setup-Modus
```

### `openclaw onboard` (empfohlen)

Interaktiver Onboarding-Wizard für Gateway, Workspace und Skills.

```bash
openclaw onboard                            # Vollständiger Wizard
openclaw onboard --install-daemon           # + systemd Service installieren
openclaw onboard --reset                    # Config + Credentials + Sessions zurücksetzen
openclaw onboard --reset-scope full         # Auch Workspace löschen
openclaw onboard --non-interactive          # Headless (alle Flags erforderlich)
openclaw onboard --mode <local|remote>      # Lokal oder Remote-Gateway
openclaw onboard --flow <quickstart|advanced|manual>
openclaw onboard --auth-choice <provider>   # Auth-Provider wählen
# Auth-Options: setup-token|token|chutes|openai-codex|openai-api-key|
#               openrouter-api-key|ollama|ai-gateway-api-key|moonshot-api-key|
#               kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|
#               zai-api-key|mistral-api-key|apiKey|minimax-api|minimax-api-lightning|
#               opencode-zen|opencode-go|custom-api-key|skip
openclaw onboard --gateway-port <port>      # Gateway-Port (default 18789)
openclaw onboard --gateway-bind <bind>      # loopback|lan|tailnet|auto|custom
openclaw onboard --gateway-token <token>    # Gateway-Token setzen
openclaw onboard --tailscale <off|serve|funnel>  # Tailscale-Integration
openclaw onboard --skip-channels            # Channel-Setup überspringen
openclaw onboard --skip-skills              # Skill-Setup überspringen
```

### `openclaw configure`

Interaktiver Konfigurations-Wizard (Modelle, Channels, Skills, Gateway).

### `openclaw config`

Nicht-interaktive Config-Helfer.

```bash
openclaw config get <path>                  # Wert lesen (Dot/Bracket-Notation)
openclaw config set <path> <value>          # Wert setzen (JSON5 oder String)
openclaw config unset <path>                # Wert entfernen
openclaw config file                        # Config-Dateipfad anzeigen
openclaw config validate                    # Config validieren (ohne Gateway-Start)
openclaw config validate --json             # JSON-Ausgabe
```

---

## Gateway

```bash
openclaw gateway                           # Gateway starten (Vordergrund)
openclaw gateway --port 18789               # Port wählen
openclaw gateway --bind <loopback|lan|tailnet|auto|custom>
openclaw gateway --token <token>            # Auth-Token
openclaw gateway --password <password>     # Auth-Passwort
openclaw gateway --tailscale <off|serve|funnel>
openclaw gateway --dev                      # Dev-Modus
openclaw gateway --reset                    # Dev-Config zurücksetzen
openclaw gateway --force                    # Existierenden Listener killen

# Gateway Service (systemd)
openclaw gateway install                    # systemd user service installieren
openclaw gateway uninstall                  # Service entfernen
openclaw gateway start                      # Service starten
openclaw gateway stop                       # Service stoppen
openclaw gateway restart                    # Service neu starten
openclaw gateway status                     # Gateway-Status (probes RPC by default)
openclaw gateway status --no-probe           # Nur Service-Status, kein RPC
openclaw gateway status --deep               # Tiefes System-Scan
openclaw gateway status --json               # JSON-Ausgabe

# Gateway RPC
openclaw gateway health                      # Health-Check
openclaw gateway probe                      # Live-Gateway-Check
openclaw gateway discover                    # Verfügbare Gateways finden
openclaw gateway call <method> [--params '<json>']  # RPC-Methode aufrufen
```

**Wichtige RPC-Methoden:**
```bash
openclaw gateway call config.get --params '{}'
openclaw gateway call config.apply --params '{"raw": "...", "baseHash": "<hash>"}'
openclaw gateway call config.patch --params '{"raw": "...", "baseHash": "<hash>"}'
openclaw gateway call update.run --params '{}'
```

### Logs

```bash
openclaw logs                               # Gateway-Logs (file)
openclaw logs --follow                      # Live-Logs
openclaw logs --limit 200                   # Letzte 200 Zeilen
openclaw logs --json                         # JSON-Ausgabe
openclaw logs --plain                        # Klartext
```

---

## Doctor & Diagnose

```bash
openclaw doctor                             # Vollständiger Gesundheitscheck
openclaw doctor --fix                       # Auto-Fix versuchen
openclaw doctor --yes                       # Headless (keine Prompts)
openclaw doctor --deep                      # System-Level Scan
openclaw doctor --run doctor                # DM-Policy prüfen
openclaw doctor --no-workspace-suggestions  # Workspace-Hints deaktivieren
openclaw status                             # Kompakter Status
openclaw status --deep                      # Channel-Status + Probes
openclaw status --usage                     # Model-Provider Usage/Quota
openclaw health                             # Health vom laufenden Gateway
```

**GOLDENE REGEL**: `openclaw doctor` VOR und NACH jeder Config-Änderung ausführen.

---

## Channels

```bash
openclaw channels list                      # Alle Kanäle + Auth-Profile
openclaw channels status                     # Gateway-Erreichbarkeit + Channel-Health
openclaw channels status --probe             # Live-Channel-Check
openclaw channels logs                       # Channel-Logs
openclaw channels logs --channel whatsapp    # Logs für spezifischen Channel
openclaw channels logs --lines 500          # Letzte 500 Zeilen
openclaw channels add                        # Interaktiver Wizard
openclaw channels add --channel telegram --account alerts --name "Alerts Bot" --token $TOKEN
openclaw channels remove --channel discord --account work --delete
openclaw channels login                      # WhatsApp QR-Login
openclaw channels login --channel whatsapp --account work
openclaw channels logout --channel whatsapp --account personal
```

**Unterstützte Kanäle (Stand 03/2026):**
WhatsApp, Telegram, Discord, Slack, Signal, iMessage, Google Chat,
Mattermost (Plugin), MS Teams, Matrix, Zalo, Zalo Personal,
BlueBubbles, WebChat, LINE, IRC, Feishu, Nostr

### Channel-Login (WhatsApp)

```bash
openclaw channels login                     # Interaktiver QR-Login
openclaw channels login --channel whatsapp --account work
openclaw channels login --verbose           # Debug-Output
```

---

## Agents (Multi-Agent)

Multi-Agent-Routing für isolierte Workspaces und Sessions.

```bash
openclaw agents list                        # Alle Agenten anzeigen
openclaw agents list --bindings            # Mit Routing-Bindings
openclaw agents add [name]                  # Neuen Agent anlegen
openclaw agents add --workspace <dir>       # Workspace-Pfad
openclaw agents add --model <id>            # Standard-Modell
openclaw agents add --bind <channel[:account]>  # Routing-Binding
openclaw agents add --non-interactive        # Headless
openclaw agents bind --agent <id> --bind <channel[:account]>  # Binding hinzufügen
openclaw agents unbind --agent <id> --bind <channel[:account]>  # Binding entfernen
openclaw agents unbind --agent <id> --all   # Alle Bindings entfernen
openclaw agents delete <id>                 # Agent löschen (Workspace + State)
openclaw agents delete <id> --force         # Ohne Bestätigung
```

**Bindings-Syntax:**
- `whatsapp` → Kanal-Default (Default-Account)
- `whatsapp:personal` → Kanal + Account
- `--bind whatsapp --bind telegram` → Mehrere Kanäle

---

## Models

```bash
openclaw models                             # Alias für models status
openclaw models list                        # Verfügbare Modelle
openclaw models list --all                  # Alle Modelle
openclaw models list --local                # Nur lokale Modelle
openclaw models list --provider <name>      # Nach Provider filtern
openclaw models status                      # Auth-Status + Modelle
openclaw models status --check              # Exit-Code bei expired/missing
openclaw models status --probe              # Live-Provider-Check
openclaw models set <model-id>              # Primary-Modell setzen
openclaw models set-image <model-id>        # Image-Modell setzen

# Aliases
openclaw models aliases list                 # Alle Aliases
openclaw models aliases add <alias> <model>  # Alias hinzufügen
openclaw models aliases remove <alias>      # Alias entfernen

# Fallbacks
openclaw models fallbacks list              # Fallback-Modelle anzeigen
openclaw models fallbacks add <model>        # Fallback hinzufügen
openclaw models fallbacks remove <model>    # Fallback entfernen
openclaw models fallbacks clear             # Alle Fallbacks entfernen

# Image-Fallbacks
openclaw models image-fallbacks list
openclaw models image-fallbacks add <model>
openclaw models image-fallbacks remove <model>
openclaw models image-fallbacks clear

# Scan
openclaw models scan                        # Model-Parameter scannen
openclaw models scan --set-default          # Gefundenes als Default setzen

# Auth
openclaw models auth add                    # Interaktiv API-Key hinzufügen
openclaw models auth setup-token --provider anthropic  # Claude Code OAuth
openclaw models auth paste-token --provider <id> --profile-id <id> --expires-in <duration>
openclaw models auth order get --provider <name>  # Auth-Reihenfolge
openclaw models auth order set --provider <name> <profileIds...>
openclaw models auth order clear --provider <name>
```

**Model-ID-Format:**
```
provider/model-name
```

Beispiele:
```
anthropic/claude-sonnet-4-6
anthropic/claude-opus-4-6
openai-codex/gpt-5.3-codex
openai/gpt-4.1
google/gemini-3-pro-preview
ollama/kimi-k2.5:cloud
openrouter/moonshotai/kimi-k2     # Bei / im Model-Name: Provider-Prefix!
```

---

## Skills & Plugins

```bash
openclaw skills list                        # Verfügbare Skills
openclaw skills info <name>                 # Skill-Details
openclaw skills check                        # Readiness-Check

# ClawHub (Skill-Marktplatz)
clawhub search <query>                      # Skills suchen
clawhub install <name>                      # Skill installieren
clawhub update <name>                        # Skill updaten
clawhub update --all                        # Alle Skills updaten

# Plugins
openclaw plugins list                        # Verfügbare Plugins
openclaw plugins info <id>                   # Plugin-Details
openclaw plugins install <path|.tgz|npm-spec>  # Plugin installieren
openclaw plugins marketplace list <marketplace>  # Marketplace durchsuchen
openclaw plugins enable <id>                # Plugin aktivieren
openclaw plugins disable <id>                # Plugin deaktivieren
openclaw plugins doctor                      # Plugin-Load-Errors
```

**Skill-Verzeichnisse:**
```
~/.openclaw/skills/             # Managed Skills (clawhub install)
~/.openclaw/workspace/skills/   # Workspace Skills (manuell)
```

---

## Nodes & Devices

```bash
# Nodes (verbundene Geräte)
openclaw nodes status                        # Verbundene Nodes
openclaw nodes describe --node <id|name|ip>  # Node-Capabilities
openclaw nodes list --connected              # Nur verbundene
openclaw nodes pending                       # Ausstehende Pairing-Requests
openclaw nodes approve <requestId>           # Node-Pairing genehmigen
openclaw nodes reject <requestId>            # Node-Pairing ablehnen
openclaw nodes rename --node <id> --name <name>  # Node umbenennen
openclaw nodes invoke --node <id> --command <cmd> [--params '<json>']  # RPC aufrufen
openclaw nodes run --node <id> <cmd...>      # Befehl auf Node ausführen

# Node Host (Headless)
openclaw node run --host <gateway-host> --port 18789
openclaw node status
openclaw node install [--host <host>] [--port <port>]
openclaw node uninstall
openclaw node start
openclaw node stop
openclaw node restart

# Devices (Gateway Device Pairing)
openclaw devices list                        # Paired Devices
openclaw devices approve <requestId>         # Device-Pairing genehmigen
openclaw devices approve --latest            # Letzten Request genehmigen
openclaw devices reject <requestId>          # Device ablehnen
openclaw devices remove <deviceId>          # Device entfernen
openclaw devices clear --yes                # Alle Devices entfernen
openclaw devices rotate --device <id> --role <role>  # Token rotieren
openclaw devices revoke --device <id> --role <role>  # Token widerrufen

# Kamera (Node)
openclaw nodes camera list --node <id>
openclaw nodes camera snap --node <id> [--facing front|back|both]
openclaw nodes camera clip --node <id> [--duration 10s]

# Canvas (Node)
openclaw nodes canvas snapshot --node <id>
openclaw nodes canvas present --node <id> [--target <url>]
openclaw nodes canvas hide --node <id>
openclaw nodes canvas navigate <url> --node <id>
openclaw nodes canvas eval [<js>] --node <id>

# Location (Node)
openclaw nodes location get --node <id> [--max-age 60s]
```

---

## Browser

Browser-Steuerung für agentische Workflows.

```bash
openclaw browser status                     # Browser-Status
openclaw browser start                      # Browser starten
openclaw browser stop                       # Browser stoppen
openclaw browser reset-profile             # Profil zurücksetzen
openclaw browser tabs                       # Offene Tabs
openclaw browser open <url>                 # URL öffnen
openclaw browser close [targetId]           # Tab schließen
openclaw browser profiles                   # Profile anzeigen
openclaw browser create-profile --name <name>  # Neues Profil
openclaw browser delete-profile --name <name>  # Profil löschen

# Inspect
openclaw browser screenshot [--full-page]   # Screenshot
openclaw browser snapshot [--format aria|ai]  # Accessibility-Tree
openclaw browser console [--level error|warn|info]  # Console-Logs

# Actions
openclaw browser navigate <url>
openclaw browser resize <width> <height>
openclaw browser click <ref>
openclaw browser type <ref> <text>
openclaw browser press <key>
openclaw browser hover <ref>
openclaw browser drag <startRef> <endRef>
openclaw browser select <ref> <values...>
openclaw browser upload <paths...> [--ref <ref>]
openclaw browser fill [--fields '<json>']
openclaw browser dialog --accept|--dismiss
openclaw browser wait --time <ms>
openclaw browser evaluate --fn '<code>'
openclaw browser pdf                         # PDF generieren
```

---

## Sandbox

```bash
openclaw sandbox list                       # Sandbox-Container anzeigen
openclaw sandbox recreate --agent <id>      # Sandbox neu erstellen
openclaw sandbox explain                    # Sandbox-Konzept erklären
```

**Sandbox-Config:**
```json5
{
  agents: {
    defaults: {
      sandbox: {
        mode: "non-main",     // off | non-main | all
        scope: "agent",       // session | agent | shared
        workspaceAccess: "none",  // none | ro | rw
        docker: {
          image: "openclaw-sandbox:bookworm-slim",
          readOnlyRoot: true,
          network: "none",
          user: "1000:1000",
          capDrop: ["ALL"],
        },
      },
    },
  },
}
```

---

## Cron (Scheduled Jobs)

```bash
openclaw cron status                        # Cron-Status
openclaw cron list                          # Alle Jobs
openclaw cron add                           # Job erstellen
openclaw cron add --name <name> --every <duration> --system-event <event>
openclaw cron edit <id>                     # Job bearbeiten
openclaw cron rm <id>                       # Job löschen
openclaw cron enable <id>                   # Job aktivieren
openclaw cron disable <id>                  # Job deaktivieren
openclaw cron runs --id <id> [--limit <n>]  # Job-Runs anzeigen
openclaw cron run <id> [--force]            # Job sofort ausführen
```

**Cron-Config:**
```json5
{
  cron: {
    enabled: true,
    maxConcurrentRuns: 2,
    sessionRetention: "24h",
    runLog: {
      maxBytes: "2mb",
      keepLines: 2000,
    },
  },
}
```

---

## Config

Siehe [Config-Referenz](config-reference.md) für alle Felder.

```bash
openclaw config get <path>                  # Wert lesen
openclaw config set <path> <value>          # Wert setzen
openclaw config unset <path>                # Wert entfernen
openclaw config file                        # Config-Dateipfad
openclaw config validate                    # Config validieren
openclaw config validate --json             # JSON-Ausgabe
```

**Hot-Reload:** Die meisten Config-Änderungen werden automatisch übernommen.
Nur `gateway.*` (Port, Bind, Auth, TLS) benötigen einen Gateway-Restart.

---

## Secrets

SecretRef für Credentials (env/file/exec).

```bash
openclaw secrets reload                     # Secrets neu laden
openclaw secrets audit                      # Auf Plaintext-Residuen scannen
openclaw secrets configure                  # Interaktiver Provider-Setup
openclaw secrets apply --from <plan.json>   # Plan anwenden
```

**SecretRef-Config:**
```json5
{
  secrets: {
    providers: {
      env: { enabled: true },
      file: { enabled: true },
      vault: {
        enabled: true,
        type: "exec",
        command: "vault kv get -format=json",
      },
    },
  },
  models: {
    providers: {
      openai: {
        apiKey: { source: "env", provider: "default", id: "OPENAI_API_KEY" },
      },
    },
  },
}
```

---

## Sessions

```bash
openclaw sessions list                      # Sessions anzeigen
openclaw sessions list --active <min>       # Nur aktive Sessions
openclaw sessions list --verbose            # Details
openclaw sessions clean                     # Aufräumen
openclaw sessions cleanup --dry-run          # Zeigen was gelöscht würde
openclaw sessions cleanup --enforce         # Wirklich löschen
```

**Session-Speicherort:** `~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl`

**Session-Config:**
```json5
{
  session: {
    dmScope: "per-channel-peer",  // main | per-peer | per-channel-peer | per-account-channel-peer
    threadBindings: {
      enabled: true,
      idleHours: 24,
      maxAgeHours: 0,
    },
    reset: {
      mode: "daily",
      atHour: 4,
      idleMinutes: 120,
    },
    maintenance: {
      mode: "enforce",
      pruneAfter: "30d",
      maxEntries: 500,
    },
  },
}
```

---

## Memory

```bash
openclaw memory status                      # Index-Status
openclaw memory index                       # Neu indexieren
openclaw memory search "<query>"            # Semantische Suche
openclaw memory search --query "<query>"    # Alternative Syntax
```

**Memory-Dateien:**
- `MEMORY.md` — Kuratiertes Langzeit-Gedächtnis (nur private Sessions!)
- `memory/YYYY-MM-DD.md` — Tages-Logs

**Memory-Config:**
```json5
{
  agents: {
    defaults: {
      memorySearch: {
        enabled: true,
        provider: "openai",      // openai | gemini | voyage | mistral | ollama | local
        model: "text-embedding-3-small",
        fallback: "openai",
        query: {
          hybrid: {
            enabled: true,
            vectorWeight: 0.7,
            textWeight: 0.3,
            mmr: { enabled: true, lambda: 0.7 },
            temporalDecay: { enabled: true, halfLifeDays: 30 },
          },
        },
      },
    },
  },
}
```

---

## Security

```bash
openclaw security audit                     # Config + State auditieren
openclaw security audit --deep              // + Live-Gateway-Probe
openclaw security audit --fix               // Safe defaults + chmod
```

**Sicherheits-Grundregeln:**
1. `gateway.bind: "loopback"` — Niemals `lan` oder `0.0.0.0` ohne VPN
2. `dmPolicy: "allowlist"` oder `"pairing"` — Niemals `"open"` in Produktion
3. Token ≥ 64 Zeichen — `openclaw gateway --token $(openssl rand -hex 32)`
4. Credentials `chmod 600` — `chmod 600 ~/.openclaw/credentials/*`
5. Skills reviewen — Quellcode prüfen vor Installation
6. Kein root — OpenClaw als eigener User betreiben
7. Workspace privat — Git-Backup in **privates** Repo
8. API-Spending-Limits — Beim Provider setzen
9. Sandbox für Tools — `sandbox.mode: "non-main"` wenn möglich

---

## Pairing & Devices

```bash
openclaw pairing list                       # Ausstehende Pairing-Requests
openclaw pairing list --channel whatsapp    # Nach Channel filtern
openclaw pairing approve <channel> <code>   # Pairing genehmigen
openclaw pairing approve --channel <channel> --account <id> <code> --notify
```

---

## Hooks & Webhooks

```bash
openclaw hooks list                         # Verfügbare Hooks
openclaw hooks info <name>                  # Hook-Details
openclaw hooks check                        # Readiness-Check
openclaw hooks enable <name>                # Hook aktivieren
openclaw hooks disable <name>               # Hook deaktivieren
openclaw hooks install <path|.tgz>          # Hook installieren
openclaw hooks update <name>                # Hook updaten

# Webhooks
openclaw webhooks gmail setup --account <email>  # Gmail Pub/Sub
openclaw webhooks gmail run                 # Gmail-Webhook ausführen
```

**Hooks-Config:**
```json5
{
  hooks: {
    enabled: true,
    [REDACTED_SECRET]",
    path: "/hooks",
    mappings: [
      {
        match: { path: "gmail" },
        action: "agent",
        agentId: "main",
        deliver: true,
      },
    ],
  },
}
```

---

## Update & Versioning

```bash
openclaw --version                          # Version anzeigen (CalVer: YYYY.M.D-N)

# Update (pnpm empfohlen):
pnpm add -g openclaw@latest && pnpm approve-builds -g && openclaw doctor

# Alternative (npm):
npm install -g openclaw@latest && openclaw doctor

# Docker:
cd openclaw && git pull && bash docker-setup.sh
```

**Release-Channels:**
- `stable` = `npm dist-tag latest` → getaggte Releases
- `beta` = `npm dist-tag beta` → Prereleases

---

## Dashboard & TUI

```bash
openclaw dashboard                          # Browser-UI öffnen (http://127.0.0.1:18789)
openclaw dashboard --no-open               # URL ausgeben ohne Browser
openclaw tui                                # Terminal-UI starten
openclaw tui --session <key>               # Mit Session starten
openclaw tui --url <url> --token <token>    # Remote-Gateway
```

**Dashboard-Bereiche:**
- WebChat — Chat-Interface
- Sessions — Session-Liste + Debug
- Config — Config-Editor
- Health — Health-Monitoring
- Nodes — Verbundene Nodes

---

## System

```bash
openclaw system event --text "<text>"       # System-Event enqueue
openclaw system event --mode <now|next-heartbeat>
openclaw system heartbeat last              # Letzter Heartbeat
openclaw system heartbeat enable            # Heartbeat aktivieren
openclaw system heartbeat disable           # Heartbeat deaktivieren
openclaw system presence                    # Presence-Entries
```

---

## DNS (Discovery)

```bash
openclaw dns setup                         # CoreDNS + Tailscale Setup
openclaw dns setup --apply                  # Config installieren (macOS)
```

---

## Message (Unified Messaging)

```bash
openclaw message send --target <dest> --message "<text>"
openclaw message poll --channel <channel> --target <dest> --poll-question "<q>" --poll-option A --poll-option B
openclaw message react --channel <channel> --target <dest> --emoji "👍"
openclaw message thread create/list/reply
openclaw message emoji list/upload
openclaw message sticker send/upload
openclaw message role info/add/remove
openclaw message channel info/list
openclaw message member info
openclaw message voice status
openclaw message event list/create
```

---

## ACP (Agent Communication Protocol)

```bash
openclaw acp                               # ACP-Bridge für IDE-Integration
openclaw acp --url <url>                   # Remote-Gateway
```

---

## Agent (One-Shot)

```bash
openclaw agent --message "<text>"          # Eine Agent-Turn
openclaw agent --to <dest> --message "<text>"  # Mit Delivery
openclaw agent --channel <channel>         # Channel wählen
openclaw agent --local                      # Lokal (embedded)
openclaw agent --thinking <off|minimal|low|medium|high|xhigh>  # Extended Thinking
openclaw agent --verbose <on|full|off>     # Verbosity
openclaw agent --deliver                    // Antwort zustellen
openclaw agent --json                       // JSON-Ausgabe
```

---

## Reset & Uninstall

```bash
openclaw reset --scope <config|config+creds+sessions|full>
openclaw reset --yes --non-interactive      # Headless

openclaw uninstall --service               # Gateway-Service entfernen
openclaw uninstall --state                  # State löschen
openclaw uninstall --workspace              # Workspace löschen
openclaw uninstall --app                    # App entfernen
openclaw uninstall --all                     # Alles löschen
openclaw uninstall --yes --non-interactive  # Headless
```

---

## Weiterführende Docs

- [Config-Referenz](config-reference.md) — Alle Config-Felder
- [Installation](installation.md) — Setup & Deployment
- [Channels](channels.md) — Kanal-spezifische Config
- [Multi-Agent](multi-agent.md) — Agent-Routing
- [Workspace-Dateien](workspace-files.md) — AGENTS.md, SOUL.md, etc.
- [Memory-System](memory-system.md) — Memory & Vektorsuche
- [Docker-Setup](docker-setup.md) — Containerized Gateway
- [Security-Hardening](security-hardening.md) — Absicherung
- [Troubleshooting](troubleshooting.md) — Fehlerbehebung

path: references/config-reference.md
content: # Config-Referenz — openclaw.json vollständig

## Datei & Format

- Pfad: `~/.openclaw/openclaw.json`
- Format: **JSON5** (Kommentare `//`, trailing commas erlaubt)
- Hot-Reload: Gateway beobachtet die Datei und wendet Änderungen automatisch an
  - Ausnahme: `gateway.reload` und `gateway.remote` triggern KEINEN Restart
- Validierung: `openclaw config validate`

### $include — Config aufteilen

```json5
// ~/.openclaw/openclaw.json
{
  gateway: { port: 18789 },
  agents: { $include: "./agents.json5" },
  channels: { $include: "./channels.json5" },
  broadcast: {
    $include: ["./clients/a.json5", "./clients/b.json5"],
  },
}
```

Regeln:
- **Einzelne Datei**: ersetzt das enthaltende Objekt
- **Array von Dateien**: deep-merge in Reihenfolge (spätere gewinnen)
- **Sibling-Keys**: werden nach includes gemergt (überschreiben included values)
- **Nested includes**: bis zu 10 Ebenen tief unterstützt
- **Relative Pfade**: relativ zur einbindenden Datei aufgelöst
- **Fehlerbehandlung**: klare Fehler bei fehlenden Dateien, Parse-Fehlern und Zyklen

---

## Alle Top-Level Sections

```
meta / wizard / update / agents / models / tools / messages /
commands / session / hooks / cron / channels / canvasHost / gateway / skills / plugins / secrets / bindings / env
```

---

## meta

Automatisch verwaltet — nicht manuell editieren.

```json5
{
  meta: {
    lastTouchedVersion: "2026.3.17",
    lastTouchedAt: "2026-03-17T10:30:00.000Z",
  },
}
```

---

## wizard

Tracking des Setup-Wizards — nicht manuell editieren.

```json5
{
  wizard: {
    lastRunAt: "...",
    lastRunVersion: "2026.3.17",
    lastRunCommand: "configure",    // "setup" | "configure" | "onboard"
    lastRunMode: "local",           // "local" | "remote"
  },
}
```

---

## update

```json5
{
  update: {
    channel: "stable",    // "stable" | "beta" | "nightly"
    auto: { enabled: true },
  },
}
```

`beta` für neue Features, `stable` für Produktion.

---

## agents — Agent-Konfiguration

### agents.defaults

```json5
{
  agents: {
    defaults: {
      model: {
        primary: "anthropic/claude-sonnet-4-6",
        fallbacks: ["openai/gpt-5.2"],
      },

      // Modelle mit Aliases (für /model <alias>)
      models: {
        "anthropic/claude-sonnet-4-6": { alias: "Sonnet" },
        "anthropic/claude-opus-4-6": { alias: "Opus" },
        "openai/gpt-5.2": { alias: "GPT" },
        "google/gemini-3-pro-preview": { alias: "gemini" },
      },

      workspace: "~/.openclaw/workspace",
      skipBootstrap: false,

      // Context-Pruning: alte Tool-Ergebnisse entfernen
      contextPruning: {
        mode: "cache-ttl",
        ttl: "1h",
      },

      // Compaction
      compaction: {
        mode: "safeguard",    // "safeguard" | "aggressive" | "manual"
      },

      timeoutSeconds: 1800,
      heartbeat: { every: "1h" },
      maxConcurrent: 4,
      subagents: { maxConcurrent: 8 },

      // Group-Chat-Mention-Patterns
      groupChat: {
        mentionPatterns: ["@bot", "bot"],
      },

      // Sandbox (per-agent)
      sandbox: {
        mode: "off",         // "off" | "non-main" | "all"
        scope: "session",    // "session" | "agent" | "shared"
        workspaceAccess: "rw",  // "rw" | "ro" | "none"
        docker: {
          image: "openclaw-sandbox:latest",
          setupCommand: "apt-get update && apt-get install -y git curl",
        },
        ssh: {
          target: "user@gateway-host:22",
          identityData: { source: "env", provider: "default", id: "SSH_IDENTITY" },
          certificateData: { source: "env", provider: "default", id: "SSH_CERTIFICATE" },
          knownHostsData: { source: "env", provider: "default", id: "SSH_KNOWN_HOSTS" },
        },
      },

      // Per-Agent Tools
      tools: {
        allow: ["read", "sessions_list"],
        deny: ["exec", "write", "edit", "apply_patch", "browser"],
      },

      // Bootstrap-Limits
      bootstrapMaxChars: 20000,
      bootstrapTotalMaxChars: 150000,
    },
  },
}
```

### agents.list — Multi-Agent-Routing

```json5
{
  agents: {
    list: [
      {
        id: "home",
        default: true,
        name: "Home",
        workspace: "~/.openclaw/workspace-home",
        agentDir: "~/.openclaw/agents/home/agent",
        model: { primary: "anthropic/claude-sonnet-4-6" },
        groupChat: { mentionPatterns: ["@home", "Home"] },
        sandbox: { mode: "off" },
      },
      {
        id: "work",
        name: "Work",
        workspace: "~/.openclaw/workspace-work",
        agentDir: "~/.openclaw/agents/work/agent",
        model: { primary: "anthropic/claude-opus-4-6" },
        sandbox: { mode: "all", scope: "agent" },
        tools: {
          allow: ["read", "exec"],
          deny: ["write", "edit"],
        },
      },
    ],
  },
}
```

### Compaction-Modi

| Modus | Verhalten | Kosten |
|---|---|---|
| `safeguard` | Auto bei ~80% Context-Limit | Moderat |
| `aggressive` | Häufiger compacten | Spart Tokens |
| `manual` | Nur mit `/compact` | Volle Kontrolle |

### Sandbox-Modi

| Modus | Verhalten |
|---|---|
| `off` | Kein Sandbox (Standard) |
| `non-main` | Nur Nicht-Main-Sessions |
| `all` | Alle Sessions |

### Sandbox-Scopes

| Scope | Container-Isolation |
|---|---|
| `session` | Ein Container pro Session |
| `agent` | Ein Container pro Agent |
| `shared` | Gemeinsamer Container |

---

## models — LLM-Provider & Modelle

```json5
{
  models: {
    mode: "merge",    // "merge" = mit Defaults zusammenführen | "replace" = nur eigene
    providers: {
      "anthropic": {
        baseUrl: "https://api.anthropic.com",
        api: "anthropic-messages",
        models: [
          {
            id: "claude-sonnet-4-6",
            name: "Claude Sonnet 4.6",
            reasoning: false,
            input: ["text", "image"],
            cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
            contextWindow: 200000,
            maxTokens: 8192,
          },
        ],
      },
      "openai": {
        baseUrl: "https://api.openai.com/v1",
        api: "openai-completions",
        models: [
          { id: "gpt-5.2", name: "GPT-5.2", reasoning: true },
          { id: "gpt-5.2-codex", name: "GPT-5.2 Codex", reasoning: false },
        ],
      },
      "ollama": {
        baseUrl: "http://localhost:11434/v1",
        api: "openai-completions",
        models: [
          { id: "kimi-k2.5:cloud", name: "Kimi K2.5 (Cloud)", reasoning: true },
          { id: "deepseek-v3.2:cloud", name: "DeepSeek V3.2 (Cloud)", reasoning: true },
        ],
      },
    },
  },
}
```

### API-Typen

| api | Für |
|---|---|
| `anthropic-messages` | Anthropic (Claude) |
| `openai-completions` | OpenAI-kompatibel (DeepSeek, Mistral, NVIDIA, Ollama, Moonshot) |
| `google-generative-ai` | Google (Gemini, Antigravity) |
| `deepgram` | Audio: Nova-3 |

### Trick: Gleiche baseUrl, verschiedene API-Keys

```json5
"nvidia":          { baseUrl: "https://integrate.api.nvidia.com/v1", models: [...] },
"nvidia-deepseek": { baseUrl: "https://integrate.api.nvidia.com/v1", models: [...] },
"nvidia-qwen":     { baseUrl: "https://integrate.api.nvidia.com/v1", models: [...] },
```

### Trick: Ollama Cloud-Modelle

```json5
"ollama": {
  baseUrl: "http://localhost:11434/v1",
  models: [
    { id: "kimi-k2.5:cloud", name: "Kimi K2.5 (Cloud)", reasoning: true, contextWindow: 262144 },
    { id: "deepseek-v3.2:cloud", name: "DeepSeek V3.2 (Cloud)", reasoning: true },
    { id: "qwen3-vl:235b-instruct-cloud", input: ["text", "image"] },
  ],
}
```

---

## channels — Messaging-Kanäle

```json5
{
  channels: {
    whatsapp: {
      enabled: true,
      dmPolicy: "allowlist",       // "pairing" | "allowlist" | "open" | "disabled"
      selfChatMode: true,
      allowFrom: ["+4915568920209"],
      groupPolicy: "allowlist",
      groups: {
        "*": { requireMention: true },
        "[REDACTED_SECRET]": { allow: true, requireMention: false },
      },
      debounceMs: 0,
      mediaMaxMb: 50,
      accounts: {
        personal: { authDir: "~/.openclaw/credentials/whatsapp/personal" },
        biz: { authDir: "~/.openclaw/credentials/whatsapp/biz" },
      },
      defaultAccount: "personal",
      healthMonitor: { enabled: true },
    },

    telegram: {
      enabled: true,
      dmPolicy: "pairing",
      accounts: {
        default: {
          botToken: "123456:ABC...",
          dmPolicy: "allowlist",
          allowFrom: ["tg:7403482253"],
          groupPolicy: "allowlist",
          streaming: "partial",
          mediaMaxMb: 50,
        },
        alerts: {
          botToken: "987654:XYZ...",
          dmPolicy: "allowlist",
          allowFrom: ["tg:123456789"],
        },
      },
    },

    discord: {
      enabled: true,
      accounts: {
        default: {
          [REDACTED_SECRET]",
          guilds: {
            "123456789012345678": {
              channels: {
                "222222222222222222": { allow: true, requireMention: false },
              },
            },
          },
        },
      },
    },

    slack: {
      enabled: true,
      appToken: "xapp-...",
      botToken: "xoxb-...",
      dmPolicy: "allowlist",
      allowFrom: ["slack:U12345"],
    },

    signal: {
      enabled: true,
      account: "+15551234567",
    },
  },
}
```

### dmPolicy

| Wert | Bedeutung | Produktion? |
|---|---|---|
| `pairing` | One-Time-Pairing-Code | ✅ Empfohlen |
| `allowlist` | Nur `allowFrom` | ✅ Sicher |
| `open` | Jeder | ⚠️ Nur Tests |
| `disabled` | Keine DMs | Gruppen-only |

**ACHTUNG**: WhatsApp dmPolicy gilt **GLOBAL** für den Account!

### Multi-Account-Routing

```json5
{
  bindings: [
    { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
    { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },
  ],
}
```

### Routing-Priorität (Bindings)

Bindings sind **deterministisch** und **spezifischste gewinnt**:

1. `peer` match (exakte DM/Group/Channel-ID)
2. `parentPeer` match (Thread-Vererbung)
3. `guildId + roles` (Discord Role Routing)
4. `guildId` (Discord)
5. `teamId` (Slack)
6. `accountId` match für einen Channel
7. Channel-Level match (`accountId: "*"`)
8. Fallback auf Default-Agent (`agents.list[].default`, sonst erster Eintrag, sonst `main`)

---

## gateway

```json5
{
  gateway: {
    port: 18789,
    mode: "local",           // "local" | "remote"
    bind: "loopback",        // "loopback" | "lan" | "tailnet" | "custom"
    reload: {
      mode: "hybrid",        // "hybrid" | "hot" | "restart" | "off"
      debounceMs: 300,
    },
    controlUi: {
      enabled: true,
      allowedOrigins: ["https://hostname.taildcb944.ts.net"],
    },
    auth: {
      mode: "token",
      token: { source: "env", provider: "default", id: "OPENCLAW_GATEWAY_TOKEN" },
      allowTailscale: true,
    },
    trustedProxies: ["100.64.0.0/10"],  // Tailscale CGNAT
    tailscale: {
      mode: "serve",         // "off" | "serve" | "funnel"
      resetOnExit: false,
    },
    channelHealthCheckMinutes: 5,
    channelStaleEventThresholdMinutes: 30,
    channelMaxRestartsPerHour: 10,
    push: {
      apns: {
        relay: {
          baseUrl: "https://relay.example.com",
          timeoutMs: 10000,
        },
      },
    },
  },
}
```

### Reload-Modi

| Modus | Verhalten |
|---|---|
| `hybrid` | Hot-Applie für sichere Änderungen, Auto-Restart für kritische |
| `hot` | Nur Hot-Applie, loggt Warnung wenn Restart nötig |
| `restart` | Immer Restart bei Config-Änderung |
| `off` | Kein File-Watching, manuell Restart |

### Hot-Applie vs Restart

| Kategorie | Hot-Applie? |
|---|---|
| Channels (`channels.*`) | ✅ Ja |
| Agents & Models (`agent`, `agents`, `models`) | ✅ Ja |
| Automation (`hooks`, `cron`, `heartbeat`) | ✅ Ja |
| Sessions & Messages (`session`, `messages`) | ✅ Ja |
| Tools & Media (`tools`, `browser`, `skills`, `audio`) | ✅ Ja |
| UI & Misc (`ui`, `logging`, `identity`, `bindings`) | ✅ Ja |
| Gateway Server (`gateway.*`) | ❌ Restart |
| Infrastructure (`discovery`, `canvasHost`, `plugins`) | ❌ Restart |

---

## session — Session-Management

```json5
{
  session: {
    dmScope: "per-channel-peer",  // "main" | "per-peer" | "per-channel-peer" | "per-account-channel-peer"
    mainKey: "main",

    identityLinks: {
      alice: ["telegram:123456789", "discord:987654321012345678"],
    },

    threadBindings: {
      enabled: true,
      idleHours: 24,
      maxAgeHours: 0,
    },

    reset: {
      mode: "daily",
      atHour: 4,
      idleMinutes: 120,
    },

    resetByType: {
      thread: { mode: "daily", atHour: 4 },
      direct: { mode: "idle", idleMinutes: 240 },
      group: { mode: "idle", idleMinutes: 120 },
    },

    resetByChannel: {
      discord: { mode: "idle", idleMinutes: 10080 },
    },

    resetTriggers: ["/new", "/reset"],

    sendPolicy: {
      rules: [
        { action: "deny", match: { channel: "discord", chatType: "group" } },
        { action: "deny", match: { keyPrefix: "cron:" } },
      ],
      default: "allow",
    },

    maintenance: {
      mode: "enforce",
      pruneAfter: "30d",
      maxEntries: 500,
      rotateBytes: "10mb",
      maxDiskBytes: "1gb",
      highWaterBytes: "800mb",
      resetArchiveRetention: "14d",
    },

    store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
  },
}
```

### dmScope-Optionen

| Wert | Session-Key | Empfohlen für |
|---|---|---|
| `main` | `agent:<id>:<mainKey>` | Single-User |
| `per-peer` | `agent:<id>:direct:<peerId>` | Multi-Device |
| `per-channel-peer` | `agent:<id>:<channel>:direct:<peerId>` | Multi-User Inboxes |
| `per-account-channel-peer` | `agent:<id>:<channel>:<account>:direct:<peerId>` | Multi-Account |

### Maintenance-Modi

| Modus | Verhalten |
|---|---|
| `warn` | Reportet nur, mutiert nicht |
| `enforce` | Wendet Cleanup an |

---

## tools

```json5
{
  tools: {
    web: {
      search: {
        enabled: false,
        provider: "brave",   // "brave" | "tavily"
        apiKey: { source: "env", provider: "default", id: "BRAVE_API_KEY" },
      },
      fetch: { enabled: true },
    },
    media: {
      audio: {
        enabled: true,
        maxBytes: 20971520,
        providerOptions: {
          deepgram: { detect_language: true, punctuate: true, smart_format: true },
        },
        models: [{ provider: "deepgram", model: "nova-3" }],
      },
    },
    sessions: { visibility: "all" },
    agentToAgent: {
      enabled: false,
      allow: ["home", "work"],
    },
  },
}
```

---

## messages — TTS & Reaktionen

```json5
{
  messages: {
    tts: {
      provider: "edge",
      edge: { enabled: true, voice: "de-DE-ConradNeural", lang: "de-DE" },
    },
    ackReactionScope: "group-mentions",  // "all" | "group-mentions" | "none"
  },
}
```

Deutsche Edge-TTS-Stimmen: `de-DE-ConradNeural` (m), `de-DE-KatjaNeural` (w).

---

## commands / hooks / cron

```json5
{
  commands: {
    native: "auto",
    nativeSkills: "auto",
    restart: true,
    ownerDisplay: "raw",
  },

  hooks: {
    enabled: true,
    token: { source: "env", provider: "default", id: "HOOKS_TOKEN" },
    path: "/hooks",
    defaultSessionKey: "hook:ingress",
    allowRequestSessionKey: false,
    allowedSessionKeyPrefixes: ["hook:"],
    mappings: [
      {
        match: { path: "gmail" },
        action: "agent",
        agentId: "main",
        deliver: true,
      },
    ],
  },

  cron: {
    enabled: true,
    maxConcurrentRuns: 2,
    sessionRetention: "24h",
    runLog: {
      maxBytes: "2mb",
      keepLines: 2000,
    },
    retry: {
      maxAttempts: 3,
      backoffMs: [60000, 120000, 300000],
      retryOn: ["rate_limit", "overloaded", "network", "server_error"],
    },
  },
}
```

---

## secrets — Secrets Management

```json5
{
  secrets: {
    providers: {
      default: { source: "env" },
      filemain: {
        source: "file",
        path: "~/.openclaw/secrets.json",
        mode: "json",
      },
      vault: {
        source: "exec",
        command: "/usr/local/bin/openclaw-vault-resolver",
        args: ["--profile", "prod"],
        passEnv: ["PATH", "VAULT_ADDR"],
        jsonOnly: true,
      },
    },
    defaults: {
      env: "default",
      file: "filemain",
      exec: "vault",
    },
  },
}
```

### SecretRef-Contract

```json5
// Env-Variable
{ source: "env", provider: "default", id: "OPENAI_API_KEY" }

// File (JSON-Pointer)
{ source: "file", provider: "filemain", id: "/providers/openai/apiKey" }

// Exec (externer Resolver)
{ source: "exec", provider: "vault", id: "providers/openai/apiKey" }
```

### Verwendungsbeispiele

```json5
{
  models: {
    providers: {
      openai: {
        apiKey: { source: "env", provider: "default", id: "OPENAI_API_KEY" },
      },
    },
  },
  channels: {
    googlechat: {
      serviceAccountRef: {
        source: "exec",
        provider: "vault",
        id: "channels/googlechat/serviceAccount",
      },
    },
  },
}
```

---

## bindings — Multi-Agent-Routing

```json5
{
  bindings: [
    // WhatsApp Personal → Home Agent
    { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },

    // WhatsApp Business → Work Agent
    { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },

    // Spezifischer DM zu Opus
    {
      agentId: "opus",
      match: {
        channel: "whatsapp",
        peer: { kind: "direct", id: "+15551234567" },
      },
    },

    // Spezifische Gruppe zu Family Agent
    {
      agentId: "family",
      match: {
        channel: "whatsapp",
        peer: { kind: "group", id: "[REDACTED_SECRET]" },
      },
    },

    // Discord Guild + Role Routing
    {
      agentId: "mod",
      match: {
        channel: "discord",
        guildId: "123456789",
        roles: ["admin", "moderator"],
      },
    },
  ],
}
```

---

## env — Environment Variables

```json5
{
  env: {
    OPENROUTER_API_KEY: "sk-or-...",
    vars: { GROQ_API_KEY: "gsk-..." },
    shellEnv: { enabled: true, timeoutMs: 15000 },
  },
}
```

### Env-Var-Substitution

```json5
{
  gateway: { auth: { [REDACTED_SECRET]" } },
  models: {
    providers: {
      custom: { [REDACTED_SECRET]" },
    },
  },
}
```

Regeln:
- Nur Großbuchstaben: `[A-Z_][A-Z0-9_]*`
- Fehlende/leere Variablen → Fehler
- Escape mit `$${VAR}` für literale Ausgabe
- Funktioniert in `$include`-Dateien

---

## Häufige Config-Fehler

| Fehler | Symptom | Fix |
|---|---|---|
| `allowFrom` als String statt Array | Channel startet nicht | `["+49..."]` (Array!) |
| Telegram allowFrom als String | Keine Nachrichten | `[7403482253]` (Zahl!) |
| WhatsApp ohne Ländercode | Keine Nachrichten | `"+4915568920209"` (E.164) |
| `bind: "lan"` ohne Auth | Gateway-Start verweigert | Auth setzen |
| Doppelte Modell-IDs | Unvorhersehbar | Jede ID nur 1x |
| `trustedProxies` fehlt | allowTailscale ignoriert | `["100.64.0.0/10"]` |
| `allowedOrigins` fehlt | CORS im Dashboard | Tailscale-Domain eintragen |
| Provider ≠ auth.profiles Key | Auth fehlschlag | Namen abgleichen |
| `dmScope: "main"` mit Multi-User | Session-Lecks | `"per-channel-peer"` |

---

## Validierung

```bash
openclaw config validate       # Syntax + Struktur prüfen
openclaw config get <pfad>     # Einzelnen Wert lesen
openclaw config set <pfad> <wert>  # Wert setzen
openclaw config edit           # Im Editor öffnen
openclaw doctor                # Gesundheitscheck nach Änderung
```

---

## Config Hot-Reload

Gateway beobachtet `~/.openclaw/openclaw.json`:

- **Hot-Applie**: Channels, Models, Agents, Tools, Hooks, Cron, Session
- **Restart-Bedingung**: Gateway-Server, Infrastructure

Änderungen triggern automatisch (je nach `gateway.reload.mode`).

---

## Workspace-Dateien

| Datei | Zweck | Geladen |
|---|---|---|
| `AGENTS.md` | Betriebsanweisungen | Jede Session |
| `SOUL.md` | Persönlichkeit, Ton | Jede Session |
| `USER.md` | Nutzerprofil | Jede Session |
| `TOOLS.md` | Tool-Hinweise | Jede Session |
| `IDENTITY.md` | Name, Emoji, Vibe | Bootstrap |
| `HEARTBEAT.md` | Scheduled-Tasks / Cron-Checkliste | Heartbeat |
| `MEMORY.md` | Langzeit-Gedächtnis | Nur private Sessions |
| `BOOT.md` | Startup-Checkliste | Gateway-Restart |
| `BOOTSTRAP.md` | Einmal-Setup | Nur einmal |
| `memory/YYYY-MM-DD.md` | Tages-Logs | Session-Start |

---

## Per-Agent Sandbox & Tools

```json5
{
  agents: {
    list: [
      {
        id: "personal",
        workspace: "~/.openclaw/workspace-personal",
        sandbox: { mode: "off" },
        // Keine Tool-Beschränkungen
      },
      {
        id: "family",
        workspace: "~/.openclaw/workspace-family",
        sandbox: { mode: "all", scope: "agent" },
        tools: {
          allow: ["read"],
          deny: ["exec", "write", "edit", "apply_patch"],
        },
      },
    ],
  },
}
```

**Hinweis**: `tools.elevated` ist **global** und sender-basiert, nicht per-Agent konfigurierbar.

path: references/dashboard.md
content: # Dashboard / Control UI — Vollständige Referenz

## Zugriff

```
http://127.0.0.1:18789/         # Lokal
https://<host>.ts.net/           # Via Tailscale Serve
```

Config: `gateway.controlUi.enabled: true` (Default)

---

## Sidebar-Navigation

### 💬 Chat
WebChat direkt im Browser. Gleiche Funktionen wie Telegram/WhatsApp.
Nützlich für Tests, Debug und wenn kein Kanal eingerichtet ist.
Unterstützt Media-Upload, Slash-Commands, Streaming.

### Control-Bereich

**📊 Overview** — Gateway-Status, aktive Sessions, Channels, Primary Model, Uptime, Version, Token-Übersicht.

**🔗 Channels** — Liste aller Channels mit Status (connected/error/disabled). Aktionen: Restart, Disconnect. WhatsApp-QR für Pairing. Telegram-Webhook-Status.

**((o)) Instances** — Laufende Gateway-Instanzen mit PID, Startzeit. Meist nur 1 Instanz.

**📄 Sessions** — Aktive + archivierte Sessions. Filter nach Channel/Agent/Zeitraum. Pro Session: Model, Tokens, Kosten. Aktionen: Inspect, Compact, Clean.

**📊 Usage** — Token-Verbrauch pro Modell/Provider. Kosten-Aufschlüsselung. Heartbeat-Kosten separat.

**✨ Cron Jobs** — Heartbeat-Status, Verlauf, nächster geplanter Run. Webhook-Wakeups.

### Agent-Bereich

**📁 Agents** — Agent-Liste (Multi-Agent). Bindings (Channel → Agent). Workspace-Dateien anzeigen/editieren.

**⚡ Skills** — Installierte Skills (Bundled/Managed/Workspace). Status, ClawHub-Suche, Reload.

**🖥️ Nodes** — Verbundene Nodes mit Capabilities. Pairing genehmigen/ablehnen. Details: Typ, IP, Last Seen.

### Settings-Bereich

**⚙️ Config** — openclaw.json im Browser editieren. JSON5-Highlighting, Validierung, Hot-Reload.

**🔧 Debug** — Echtzeit-Event-Stream. Tool-Aufrufe mit I/O. Session-State. Agent-Reasoning.

**📋 Logs** — Gateway-Logs mit Level-Filter (error/warn/info/debug). Echtzeit-Streaming.

### Resources

**📖 Docs** — Link zur offiziellen Dokumentation.

---

## Dashboard-Konfiguration

### CORS für Tailscale (PFLICHT bei Serve!)
```json5
{
  gateway: {
    controlUi: {
      allowedOrigins: ["https://hostname.taildcb944.ts.net"],
    },
  },
}
```

### Custom Base Path
```json5
{ gateway: { controlUi: { basePath: "/dashboard/" } } }
```

### Assets bauen (Git-Installation)
```bash
pnpm install && pnpm build:control-ui
ls dist/control-ui/    # Prüfen: index.html vorhanden?
```

npm/pnpm-Installation: Assets bereits enthalten.

---

## Troubleshooting

| Problem | Lösung |
|---|---|
| Leere Seite | `pnpm build:control-ui` |
| CORS-Fehler | `allowedOrigins` setzen |
| Auth-Fehler | Token prüfen, `allowTailscale` + `trustedProxies` |
| "device identity required" | HTTPS nötig → Tailscale Serve |
| Port nicht erreichbar | `ss -tlnp \| grep 18789` |
| WebSocket-Fehler | `trustedProxies: ["100.64.0.0/10"]` |


path: references/docker-setup.md
content: # Docker-Deployment — Containerized Gateway

## Wann Docker?

| Szenario | Docker? | Begründung |
|---|---|---|
| VPS/Server (24/7) | ✅ Ja | Isolation, Reproduzierbarkeit |
| macOS lokal | ❌ Nein | VM-Overhead, npm direkt schneller |
| Sandbox für Tools | ✅ Ja | Gateway lokal, Tools in Container |
| Erstmalig testen | ✅ Ja | Sicher, leicht entfernbar |

**Wichtig:** Docker ist optional. Für lokale Entwicklung ist `pnpm add -g openclaw@latest` schneller.

---

## Quick Start (Empfohlen)

```bash
# Im Repo-Root:
./docker-setup.sh
```

### Was das Script macht:

1. **Image bauen** (oder pull wenn `OPENCLAW_IMAGE` gesetzt)
2. **Onboarding** starten (interaktiv)
3. **Config schreiben** mit `gateway.bind: lan`
4. **Gateway starten** via Docker Compose
5. **Token generieren** und in `.env` schreiben

### Nach Abschluss:

- Dashboard öffnen: `http://127.0.0.1:18789/`
- Token in Settings einfügen
- URL erneut holen: `docker compose run --rm openclaw-cli dashboard --no-open`

---

## Environment-Variablen

| Variable | Beschreibung |
|---|---|
| `OPENCLAW_IMAGE` | Remote-Image statt lokalem Build (z.B. `ghcr.io/openclaw/openclaw:latest`) |
| `OPENCLAW_DOCKER_APT_PACKAGES` | Extra apt-Pakete während Build |
| `OPENCLAW_EXTENSIONS` | Extensions vorinstallieren (`diagnostics-otel matrix`) |
| `OPENCLAW_EXTRA_MOUNTS` | Zusätzliche Bind-Mounts |
| `OPENCLAW_HOME_VOLUME` | Named Volume für `/home/node` |
| `OPENCLAW_SANDBOX` | Sandbox-Bootstrap aktivieren (`1`, `true`, `yes`, `on`) |
| `OPENCLAW_INSTALL_DOCKER_CLI` | Docker CLI im Image installieren |
| `OPENCLAW_DOCKER_SOCKET` | Docker-Socket-Pfad override |
| `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS` | Private `ws://` für CLI erlauben |
| `OPENCLAW_BROWSER_DISABLE_GRAPHICS_FLAGS` | Chromium-Flags deaktivieren |
| `OPENCLAW_BROWSER_DISABLE_EXTENSIONS` | Extensions aktiviert lassen |
| `OPENCLAW_BROWSER_RENDERER_PROCESS_LIMIT` | Chromium Renderer-Limit |

---

## Containerized Gateway (Docker Compose)

### compose.yml (Default)

```yaml
services:
  openclaw-gateway:
    image: openclaw:local
    restart: unless-stopped
    ports:
      - "18789:18789"
    volumes:
      - ~/.openclaw:/home/node/.openclaw
      - ~/openclaw/workspace:/home/node/.openclaw/workspace
    # Optional: User-Mapping
    # user: "1000:1000"

  openclaw-cli:
    image: openclaw:local
    volumes:
      - ~/.openclaw:/home/node/.openclaw
      - ~/openclaw/workspace:/home/node/.openclaw/workspace
    profiles: ["cli"]
    entrypoint: ["openclaw"]
```

### CLI via Docker Compose

```bash
docker compose run --rm openclaw-cli doctor
docker compose run --rm openclaw-cli channels add --channel telegram --token <TOKEN>
docker compose run --rm openclaw-cli dashboard --no-open
```

---

## Remote Image (ohne lokalen Build)

Offizielle Images: **GitHub Container Registry**

```bash
# Tags:
# - ghcr.io/openclaw/openclaw:main       (latest main branch)
# - ghcr.io/openclaw/openclaw:2026.2.26   (Release-Tag)
# - ghcr.io/openclaw/openclaw:latest      (latest stable)

export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
./docker-setup.sh
```

Das Script pullt statt zu bauen wenn `OPENCLAW_IMAGE` gesetzt ist.

---

## Base Image Metadata

Default-Image: `node:24-bookworm`

OCI Annotations:
- `org.opencontainers.image.base.name=docker.io/library/node:24-bookworm`
- `org.opencontainers.image.source=https://github.com/openclaw/openclaw`
- `org.opencontainers.image.url=https://openclaw.ai`
- `org.opencontainers.image.documentation=https://docs.openclaw.ai/install/docker`

---

## Agent Sandbox (Docker Gateway + Containerized Tools)

### Enable Sandbox

```bash
export OPENCLAW_SANDBOX=1
./docker-setup.sh
```

Custom Socket (rootless Docker):
```bash
export OPENCLAW_SANDBOX=1
export OPENCLAW_DOCKER_SOCKET=/run/user/1000/docker.sock
./docker-setup.sh
```

**Hinweise:**
- `docker.sock` wird erst nach Sandbox-Prerequisites gemountet
- Bei Fehlern wird `agents.defaults.sandbox.mode` auf `off` zurückgesetzt
- `Dockerfile.sandbox` muss existieren (oder `scripts/sandbox-setup.sh` laufen)

### Sandbox-Config

```json5
agents: {
  defaults: {
    sandbox: {
      mode: "non-main",       // "off" | "non-main" | "all"
      scope: "agent",         // "session" | "agent" | "shared"
      workspaceAccess: "none", // "none" | "ro" | "rw"
      docker: {
        image: "openclaw-sandbox:bookworm-slim",
        network: "none",      // Kein Netzwerk (sicherste)
        readOnlyRoot: true,
        tmpfs: ["/tmp", "/var/tmp", "/run"],
        user: "1000:1000",
        capDrop: ["ALL"],
        setupCommand: "apt-get update && apt-get install -y git curl jq",
      },
      prune: {
        idleHours: 24,
        maxAgeDays: 7,
      },
    },
  },
}
```

**Setup-Command-Hinweise:**
- Default: `network: "none"` → apt-get schlägt fehl
- Für Pakete: `network: "bridge"` + `readOnlyRoot: false` + `user: "0:0"`
- Container wird bei `setupCommand`-Änderung neu erstellt (~5min Cooldown)

### Sandbox-Images bauen

```bash
# Standard-Sandbox
scripts/sandbox-setup.sh          # openclaw-sandbox:bookworm-slim

# Mit Tooling (node, go, python, curl, jq)
scripts/sandbox-common-setup.sh    # openclaw-sandbox-common:bookworm-slim

# Browser-Sandbox (Chromium + noVNC)
scripts/sandbox-browser-setup.sh   # openclaw-sandbox-browser:bookworm-slim
```

### Sandbox-Backend-Optionen

| Backend | Beschreibung |
|---|---|
| `docker` | Lokale Docker-Container (Default) |
| `ssh` | SSH-Remote-Server |
| `openshell` | OpenShell-Remote-Workspace |

### Tool-Policy in Sandbox

```json5
tools: {
  sandbox: {
    tools: {
      allow: ["exec", "process", "read", "write", "edit", "sessions_list"],
      deny: ["browser", "canvas", "nodes", "cron", "discord", "gateway"],
    },
  },
}
```

- `deny` gewinnt über `allow`
- Leeres `allow` = alle Tools (minus deny)

---

## Power-User Container

Default-Image ist **security-first** (non-root `node`, kein Chromium, kein sudo).

### Vollständiger Container

```bash
# 1. /home/node persistieren
export OPENCLAW_HOME_VOLUME="openclaw_home"
./docker-setup.sh

# 2. System-Packages backen
export OPENCLAW_DOCKER_APT_PACKAGES="git curl jq"
./docker-setup.sh

# 3. Playwright ohne npx
docker compose run --rm openclaw-cli \
  node /app/node_modules/playwright-core/cli.js install chromium
```

---

## Extra Mounts

```bash
export OPENCLAW_EXTRA_MOUNTS="$HOME/.codex:/home/node/.codex:ro,$HOME/github:/home/node/github:rw"
./docker-setup.sh
```

**Hinweise:**
- Pfade müssen in Docker Desktop (macOS/Windows) geteilt sein
- Format: `source:target[:options]`
- Bei Änderungen: `docker-setup.sh` neu laufen lassen

---

## Permissions-Probleme

Image läuft als `node` (UID 1000).

```bash
# Option 1 (empfohlen): Ownership auf UID 1000
sudo chown -R 1000:$(id -g) ~/.openclaw
sudo chmod -R u+rwX,g+rwX,o-rwx ~/.openclaw

# Option 2: Gruppe beschreibbar
chmod -R 775 ~/.openclaw

# Option 3 (LETZTER AUSWEG): World-writable
chmod -R 777 ~/.openclaw
```

---

## Channel Setup

```bash
# WhatsApp (QR)
docker compose run --rm openclaw-cli channels login

# Telegram (Bot Token)
docker compose run --rm openclaw-cli channels add --channel telegram --token "<TOKEN>"

# Discord (Bot Token)
docker compose run --rm openclaw-cli channels add --channel discord --token "<TOKEN>"
```

---

## Health Checks

```bash
# Container-Probes (kein Auth nötig)
curl -fsS http://127.0.0.1:18789/healthz
curl -fsS http://127.0.0.1:18789/readyz

# Deep Health (Gateway + Channels)
docker compose exec openclaw-gateway node dist/index.js health --token "$OPENCLAW_GATEWAY_TOKEN"
```

---

## LAN vs Loopback

`docker-setup.sh` defaultet `OPENCLAW_GATEWAY_BIND=lan` für Docker.

| Bind | Zugriff |
|---|---|
| `lan` | Host-Browser + Host-CLI erreichen Gateway |
| `loopback` | Nur Prozesse im Container-Namespace |

Bei Pairing-Problemen:
```bash
docker compose run --rm openclaw-cli config set gateway.mode local
docker compose run --rm openclaw-cli config set gateway.bind lan
docker compose run --rm openclaw-cli devices list --url ws://127.0.0.1:18789
```

---

## Automation/CI

Non-Interactive mit `-T`:

```bash
docker compose run -T --rm openclaw-cli gateway probe
docker compose run -T --rm openclaw-cli devices list --json
```

---

## Docker + Ollama

```json5
models: {
  providers: {
    ollama: {
      // macOS Docker Desktop:
      baseUrl: "http://host.docker.internal:11434",
      // Linux (Docker-Bridge-IP):
      // baseUrl: "http://172.17.0.1:11434",
      [REDACTED_SECRET]",
      api: "openai-completions",
    },
  },
}
```

---

## Shell Helpers (Optional)

```bash
mkdir -p ~/.clawdock && curl -sL https://raw.githubusercontent.com/openclaw/openclaw/main/scripts/shell-helpers/clawdock-helpers.sh -o ~/.clawdock/clawdock-helpers.sh

# In ~/.zshrc:
echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc && source ~/.zshrc

# Commands:
clawdock-start
clawdock-stop
clawdock-dashboard
clawdock-help
```

---

## Storage Model

| Pfad | Persistenz |
|---|---|
| `~/.openclaw/` | Host-Bind-Mount (überlebt Container) |
| `~/.openclaw/workspace/` | Host-Bind-Mount |
| Sandbox `/tmp`, `/var/tmp`, `/run` | `tmpfs` (ephemeral) |
| `/home/node` (optional) | Named Volume wenn `OPENCLAW_HOME_VOLUME` |

---

## Troubleshooting

| Problem | Lösung |
|---|---|
| Build OOM (exit 137) | Mindestens 2 GB RAM |
| Workspace nicht sichtbar | Volume-Mount in `docker-compose.yml` prüfen |
| "Cannot connect to Docker daemon" | `sudo systemctl start docker` |
| Slow auf macOS | VM-Overhead → npm direkt nutzen |
| Permission denied | Ownership/Permissions oben prüfen |
| Container startet nicht nach Config-Änderung | `docker compose run --rm openclaw-cli doctor` |
| QR nicht angezeigt | Dashboard → Channels nutzen |
| "Connection closed" nach Scan | Gateway restart → erneut scannen |
| Sandbox Image fehlt | `scripts/sandbox-setup.sh` |

---

## Security Notes

- Gateway läuft als `node` User (non-root)
- Kein Chromium/Playwright im Default-Image
- Kein sudo
- Sandbox-Default: `network: "none"` (kein Internet für Tools)
- `network: "host"` ist blockiert
- `network: "container:<id>"` ist blockiert (break-glass: `dangerouslyAllowContainerNamespaceJoin`)

---

## Verwandte Docs

- **Quick-Ref**: `references/quick-reference.md` — Docker Quick-Start
- **Security**: `references/security-hardening.md` — Sandbox-Konfiguration Details
- **Installation**: `references/installation.md` — npm/pnpm Setup
- **Config**: `references/config-reference.md` — Sandbox-Config Schema

path: references/examples.md
content: # Praxis-Beispiele — Typische OpenClaw-Setups

## Beispiel 1: Minimal-Setup für Einsteiger (VPS + Telegram)

**Szenario**: Contabo VPS, Telegram als einziger Kanal, Claude als Modell.

### Config
```json5
// ~/.openclaw/openclaw.json
{
  gateway: {
    bind: "loopback",
    auth: {
      mode: "token",
      [REDACTED_SECRET] rand -hex 32)",
    },
  },
  channels: {
    telegram: {
      enabled: true,
      adapter: "telegram",
      // Token via: @BotFather → /newbot
    },
  },
  models: {
    default: "anthropic/claude-sonnet-4-20250514",
  },
  agent: {
    heartbeat: {
      enabled: false,           // Anfangs deaktiviert (spart Tokens)
    },
  },
}
```

### AGENTS.md (minimal)
```markdown
# Betriebsanweisungen

Du bist mein persönlicher Assistent. Antworte auf Deutsch.
Sei hilfreich, präzise und freundlich.
Bestätige destruktive Aktionen vor der Ausführung.
```

### SOUL.md (minimal)
```markdown
# Persönlichkeit
- Professionell, freundlich, direkt
- Deutsch als Standard
- Verwende gelegentlich das Lobster-Emoji 🦞
```

### Erste Schritte
```bash
# 1. Installieren
curl -fsSL https://get.openclaw.ai | bash

# 2. Wizard durchlaufen (Token, Model, Telegram-Bot)
openclaw setup

# 3. Gateway starten
openclaw gateway install   # systemd service
openclaw gateway start

# 4. Health Check
openclaw doctor
openclaw channels status --probe

# 5. In Telegram Bot anschreiben → Fertig!
```

---

## Beispiel 2: VPS + Tailscale + MacBook-Node

**Szenario**: Gateway auf Hetzner VPS, MacBook als Node für Browser-Automation.

### VPS-Setup
```bash
# Tailscale installieren
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
tailscale ip -4   # z.B. 100.64.x.x
```

### Config auf VPS
```json5
{
  gateway: {
    bind: "loopback",
    tailscale: {
      mode: "serve",
      resetOnExit: false,
    },
    auth: {
      mode: "token",
      [REDACTED_SECRET]",
      allowTailscale: true,
    },
    controlUi: {
      enabled: true,
    },
  },
  channels: {
    telegram: { enabled: true, adapter: "telegram" },
    whatsapp: { enabled: true, adapter: "whatsapp" },
  },
  models: {
    default: "anthropic/claude-sonnet-4-20250514",
    heartbeat: [REDACTED_SECRET],  // Günstig für Heartbeat
  },
}
```

### MacBook einrichten
```bash
# 1. Tailscale installieren + einloggen
brew install tailscale
tailscale up

# 2. OpenClaw macOS App installieren
brew install --cask openclaw

# 3. App öffnen → Settings → Gateway
#    URL: https://<vps>.your-tailnet.ts.net
#    → Connect → Pairing-Request wird erstellt

# 4. Auf VPS genehmigen:
openclaw devices list
openclaw devices approve <requestId>

# 5. Prüfen:
openclaw nodes status
# → MacBook sollte "connected" sein mit canvas.*, system.* Capabilities
```

### Browser-Automation testen
```
# In Telegram dem Bot schreiben:
"Öffne google.de und suche nach 'OpenClaw Tailscale Setup'"
# → Gateway sendet browser.* Befehle an MacBook-Node
```

---

## Beispiel 3: VPS + iPhone + Raspberry Pi

**Szenario**: Zentraler Gateway, iPhone für unterwegs, Pi für Smart-Home-Kontrolle.

### Architektur
```
Internet / Tailscale
        │
  ┌─────┴──────────────┐
  │  Hetzner VPS       │  Gateway + Telegram + WhatsApp
  │  100.64.0.1        │  Tailscale Serve
  └─────┬──────────────┘
        │
   ┌────┴──────────────────────┐
   │                           │
┌──┴───────────┐  ┌────────────┴──────┐
│  iPhone      │  │  Raspberry Pi 5   │
│  iOS App     │  │  Headless Node    │
│  100.64.0.2  │  │  100.64.0.3       │
│  Kamera,     │  │  system.run,      │
│  Canvas,     │  │  GPIO, Sensoren   │
│  Voice       │  │  Smart-Home       │
└──────────────┘  └───────────────────┘
```

### Pi als Headless Node einrichten
```bash
# 1. Raspberry Pi OS Lite (64-bit) installieren
# 2. SSH aktivieren, Updates
sudo apt update && sudo apt upgrade -y

# 3. Node.js 22+ installieren
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash -
sudo apt install -y nodejs

# 4. Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

# 5. OpenClaw (nur Node-Host, kein Gateway!)
npm install -g openclaw@latest

# 6. Node-Host starten
openclaw node host \
  --gateway wss://<vps>.your-tailnet.ts.net \
  --token <gateway-token>

# 7. Auf VPS genehmigen:
openclaw devices approve <requestId>
```

### Pi Node als systemd-Service
```ini
# ~/.config/systemd/user/openclaw-node.service
[Unit]
Description=OpenClaw Node Host
After=network-online.target

[Service]
ExecStart=%h/.npm-global/bin/openclaw node host \
  --gateway wss://<vps>.your-tailnet.ts.net \
  --token <gateway-token>
Restart=always
RestartSec=10
Environment=NODE_ENV=production

[Install]
WantedBy=default.target
```

```bash
# loginctl enable-linger nötig für --user services!
loginctl enable-linger $USER
systemctl --user daemon-reload
systemctl --user enable --now openclaw-node
```

### iPhone verbinden
1. OpenClaw iOS App installieren
2. Tailscale iOS App installieren + einloggen
3. In Telegram dem Bot schreiben: `/pair`
4. Setup-Code kopieren → iOS App → Settings → Gateway → Code einfügen
5. Auf VPS: `openclaw devices approve <requestId>`

---

## Beispiel 4: Multi-Agent mit getrennten Workspaces

**Szenario**: Ein persönlicher Agent + ein Arbeits-Agent auf demselben Gateway.

### Config
```json5
{
  agents: {
    list: [
      {
        agentId: "alex-privat",
        name: "Lobster 🦞",
        agentDir: "~/.openclaw/agents/alex-privat",
        workspaceDir: "~/.openclaw/workspaces/privat",
      },
      {
        agentId: "alex-arbeit",
        name: "WorkBot 🏢",
        agentDir: "~/.openclaw/agents/alex-arbeit",
        workspaceDir: "~/.openclaw/workspaces/arbeit",
      },
    ],
  },
  bindings: {
    // Telegram → Privat-Agent
    "telegram:*": { agentId: "alex-privat" },
    // Slack → Arbeits-Agent
    "slack:*": { agentId: "alex-arbeit" },
    // WhatsApp → Privat (default)
    "whatsapp:*": { agentId: "alex-privat" },
    // WhatsApp Arbeitsgruppe → Arbeits-Agent
    "whatsapp:group:ArbeitsGruppe": { agentId: "alex-arbeit" },
  },
}
```

**Regel**: Nie `workspaceDir` zwischen Agents teilen!

---

## Beispiel 5: Kosten-optimiertes Setup

**Szenario**: Monatliche API-Kosten unter 20€ halten.

### Strategie
```json5
{
  models: {
    // Hauptmodell: Gutes Preis-Leistung
    default: "anthropic/claude-sonnet-4-20250514",
    // Heartbeat: Billigstes Modell
    heartbeat: "anthropic/claude-haiku-3-20250307",
  },
  agent: {
    heartbeat: {
      enabled: true,
      interval: "4h",          // Nur alle 4 Stunden (statt default 1h)
    },
    session: {
      compaction: {
        maxTokens: 80000,       // Früher compacten
      },
    },
  },
}
```

### HEARTBEAT.md (Minimal!)
```markdown
## Heartbeat-Aufgaben
- [ ] Prüfe ob neue Nachrichten in meinen Channels warten
```
Mehr Tasks = mehr Token-Verbrauch pro Heartbeat!

### Kosten-Monitoring
```bash
# Token-Verbrauch aktueller Session
# In Telegram:
/status

# Historische Kosten (wenn vom Provider unterstützt)
openclaw sessions list --costs
```

### Spar-Tricks
1. **Heartbeat deaktivieren** wenn nicht nötig: `heartbeat.enabled: false`
2. **SSH statt Heartbeat** für Maintenance: Gateway direkt ansprechen
3. **Compaction-Limit senken**: Weniger Context = weniger Tokens
4. **Günstige Modelle für Routing**: `models.heartbeat` separat setzen
5. **Skills minimal halten**: Weniger geladene Skills = weniger System-Prompt-Tokens

---

## Beispiel 6: Sicheres Setup mit Docker-Sandbox

**Szenario**: Maximale Isolation — Agent kann Host nicht beschädigen.

### docker-compose.yml
```yaml
services:
  openclaw:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw
    restart: unless-stopped
    user: "1000:1000"
    volumes:
      - ./data:/home/openclaw/.openclaw
    environment:
      - OPENCLAW_GATEWAY_TOKEN=${GATEWAY_TOKEN}
      - OPENCLAW_GATEWAY_PASSWORD=${GATEWAY_PASSWORD}
    ports:
      - "127.0.0.1:18789:18789"
    security_opt:
      - no-new-privileges:true
    read_only: true
    tmpfs:
      - /tmp
    networks:
      - openclaw-net

networks:
  openclaw-net:
    driver: bridge
```

### Sandbox-Config
```json5
{
  gateway: {
    bind: "loopback",
    auth: { mode: "token" },
  },
  agent: {
    sandbox: {
      enabled: true,
      // Agent-Prozesse laufen im Docker-Container
      // Host-Zugriff ist vollständig blockiert
    },
  },
}
```

---

## Beispiel 7: iMessage via BlueBubbles + Linux Gateway

**Szenario**: Gateway auf Linux VPS, iMessage über einen Mac zuhause.

### Architektur
```
VPS (Linux)                    Mac mini (zuhause)
┌─────────────────┐           ┌─────────────────┐
│  OpenClaw       │◄──────────│  BlueBubbles     │
│  Gateway        │ Tailscale │  Server          │
│  (kein macOS    │           │  (signed into    │
│   nötig!)       │           │   Messages)      │
└─────────────────┘           └─────────────────┘
```

### Schritte
1. BlueBubbles auf Mac installieren (https://bluebubbles.app)
2. BlueBubbles-Server starten (Mac muss eingeloggt + online bleiben)
3. Beide Geräte im selben Tailnet
4. In openclaw.json:
```json5
{
  channels: {
    imessage: {
      enabled: true,
      adapter: "bluebubbles",
      // BlueBubbles-Server-URL über Tailscale
      host: "http://<mac-tailscale-ip>:1234",
      [REDACTED_SECRET]",
    },
  },
}
```

---

## Cheat-Sheet: Welches Setup für welchen Zweck?

| Zweck | Gateway | Nodes | Channels | Tailscale |
|---|---|---|---|---|
| Einsteiger / Test | Lokal oder VPS | Keine | Telegram | Optional |
| Always-On Assistant | VPS | MacBook + iPhone | Telegram + WhatsApp | ✅ Serve |
| Smart Home | Raspberry Pi | Weitere Pi's | Telegram | ✅ Serve |
| Max Security | Docker auf VPS | Keine | WebChat only | ✅ Serve |
| Multi-Device | VPS | Mac + iPhone + Pi | Alle | ✅ Serve |
| Kosten-Mini | VPS (1€/Monat) | Keine | Telegram | SSH-Tunnel |
| iMessage | VPS (Linux) | Mac (BlueBubbles) | iMessage + Telegram | ✅ Serve |


path: references/installation.md
content: # Installation & Erste Schritte

## Voraussetzungen

- **Node.js 22+** (required) — **Node.js 24 empfohlen** für beste Performance
- macOS, Linux, oder Windows (via WSL2, **dringend empfohlen**)
- 2 GB RAM minimum (4 GB empfohlen)
- 10 GB+ Disk

---

## Methode 1: npm/pnpm (empfohlen für lokale Nutzung)

### Mit pnpm (empfohlen)

```bash
# pnpm aktivieren
corepack enable

# OpenClaw installieren
pnpm add -g openclaw@latest
pnpm approve-builds -g

# Onboarding-Wizard starten
openclaw onboard
```

### Mit npm

```bash
npm install -g openclaw@latest

# Onboarding-Wizard starten
openclaw onboard
```

### Onboarding-Wizard

Der Wizard fragt ab:

1. **Gateway bind-Modus** → `loopback` wählen! (nur lokal)
2. **Auth-Modus** → `token` wählen! (empfohlen)
3. **Gateway-Token** → automatisch generiert oder eigenes
4. **Tailscale?** → Off, es sei denn Tailscale wird verwendet
5. **AI-Provider** → Anthropic/OpenAI/Ollama/etc.
6. **API-Key** → Interaktiv oder via Environment-Variable
7. **Channel-Setup** → WhatsApp/Telegram/Discord etc.
8. **Daemon installieren?** → `--install-daemon` für systemd user service

### Alternative: Direktes Setup ohne Wizard

```bash
# Daemon installieren und starten
openclaw gateway install --install-daemon

# Alternativ: Ohne Daemon
openclaw gateway start
```

### Nach der Installation

```bash
openclaw doctor              # Gesundheitscheck (IMMER!)
openclaw status              # Kurzer Status
openclaw dashboard           # Browser-UI (Port 18789)
```

---

## Methode 2: Docker (empfohlen für VPS/Server)

### Standard-Setup

```bash
git clone https://github.com/openclaw/openclaw.git
cd openclaw
bash docker-setup.sh
```

Das Script:

1. Baut das Docker-Image
2. Startet den Onboarding-Wizard (interaktiv)
3. Konfiguriert Docker Compose
4. Startet den Gateway-Container

### Docker-Compose-Befehle

```bash
# Gateway starten
docker compose up -d openclaw-gateway

# CLI-Befehle ausführen
docker compose run --rm openclaw-cli doctor
docker compose run --rm openclaw-cli channels add --channel telegram --token <TOKEN>
docker compose run --rm openclaw-cli dashboard --no-open

# Logs
docker compose logs -f openclaw-gateway

# Shell im Container
docker compose exec openclaw-gateway bash

# Als root (für Paketinstallation):
docker compose exec -u root openclaw-gateway bash
```

### Alternative Docker-Images

```bash
# Alpine-basiertes Community-Image:
docker pull alpine/openclaw:latest

# Phioranex Community-Image mit install-Script:
curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh | sudo bash
```

### Docker-Volumes

```
~/.openclaw           → /home/node/.openclaw     (Config, Sessions, Credentials)
~/openclaw/workspace   → /home/node/.openclaw/workspace (Agent-Workspace)
```

### Docker + Ollama (lokale Modelle)

```json5
// In openclaw.json:
models: {
  providers: {
    ollama: {
      // Auf macOS mit Docker Desktop:
      baseUrl: "http://host.docker.internal:11434",
      // Auf Linux:
      baseUrl: "http://172.17.0.1:11434",
    },
  },
}
```

---

## Methode 3: DigitalOcean 1-Click

DigitalOcean bietet ein vorkonfiguriertes Droplet-Image mit:

- OpenClaw vorinstalliert
- Docker-Container-Isolation
- Non-Root-User-Execution
- Hardened Firewall

---

## Methode 4: Docker Sandbox (maximale Isolation)

```bash
docker sandbox create --name my-openclaw shell .
docker sandbox network proxy my-openclaw --allow-host localhost
docker sandbox run my-openclaw
# Im Sandbox:
npm install -g n && n 22
hash -r
npm install -g openclaw@latest
openclaw setup
```

Vorteile: Micro-VM-Isolation, API-Key-Injection über Network-Proxy (Keys nie im Container).

---

## Nach der Installation

### 1. API-Key einrichten

Provider wählen (Anthropic empfohlen für Claude):

```bash
# Environment-Variable
export ANTHROPIC_API_KEY="sk-ant-..."

# Oder in Config
openclaw config set models.providers.anthropic.apiKey "sk-ant-..."
```

### 2. Channel verbinden

Mindestens einen Messaging-Kanal einrichten:

```bash
# Telegram
openclaw channels add --channel telegram --token "123456:ABC..."

# WhatsApp (QR-Code scannen)
openclaw channels login --channel whatsapp

# Discord
openclaw channels add --channel discord --token "YOUR_BOT_TOKEN"
```

### 3. Pairing durchführen

```bash
openclaw pairing list
openclaw pairing approve <channel> <code>
```

### 4. Workspace personalisieren

```bash
cd ~/.openclaw/workspace

# Dateien bearbeiten:
# AGENTS.md  - Betriebsanweisungen
# SOUL.md    - Persönlichkeit
# USER.md    - Nutzerprofil
# MEMORY.md  - Langzeit-Gedächtnis
```

### 5. Security-Check

```bash
openclaw doctor
openclaw security audit --deep
```

### 6. Test-Nachricht senden

Im gewählten Kanal den Bot anschreiben.

---

## Update

### Mit pnpm (empfohlen)

```bash
pnpm add -g openclaw@latest && pnpm approve-builds -g && openclaw doctor
```

### Mit npm

```bash
npm install -g openclaw@latest && openclaw doctor
```

### Mit Docker

```bash
cd openclaw && git pull && bash docker-setup.sh
```

**Nach jedem Update**: `openclaw doctor` ausführen!

---

## systemd Daemon

### Installation

```bash
openclaw gateway install --install-daemon
```

### Verwaltung

```bash
# Status
systemctl --user status openclaw-gateway

# Logs
journalctl --user -u openclaw-gateway -f

# Neustart
systemctl --user restart openclaw-gateway

# Stop
systemctl --user stop openclaw-gateway
```

---

## Gateway-Modi

### local (Standard)

Nur localhost kann zugreifen:

```json5
{
  gateway: {
    mode: "local",
    bind: "loopback",
    port: 18789,
  },
}
```

### remote (Tailscale/VPN)

Extern erreichbar via Tailscale:

```json5
{
  gateway: {
    mode: "remote",
    bind: "tailnet",
    auth: {
      mode: "token",
      token: { source: "env", provider: "default", id: "OPENCLAW_GATEWAY_TOKEN" },
      allowTailscale: true,
    },
    trustedProxies: ["100.64.0.0/10"],
    tailscale: {
      mode: "serve",
      resetOnExit: false,
    },
  },
}
```

---

## Häufige Installationsprobleme

### Node.js Version zu alt

```bash
# Prüfen
node --version  # Muss >= 22 sein

# Mit nvm upgraden
nvm install 24
nvm use 24
```

### pnpm approve-builds vergessen

```bash
pnpm approve-builds -g
```

### Gateway startet nicht

```bash
# Logs prüfen
openclaw gateway log

# Doctor laufen lassen
openclaw doctor --fix
```

### Port bereits belegt

```bash
# Anderen Port verwenden
openclaw config set gateway.port 18889
systemctl --user restart openclaw-gateway
```

### Config-Fehler

```bash
# Config validieren
openclaw config validate

# Config reparieren
openclaw doctor --fix
```

---

## Nächste Schritte

1. **Channel-Dokumentation lesen**: `references/channels.md`
2. **Config verstehen**: `references/config-reference.md`
3. **Workspace einrichten**: `references/workspace-files.md`
4. **Security härten**: `references/security-hardening.md`
5. **Skills nutzen**: `references/skills-guide.md`

path: references/memory-system.md
content: # Memory-System — Deep Dive

## Architektur-Überblick

OpenClaw nutzt ein dateibasiertes Markdown-Memory-System mit optionaler semantischer Suche.
**Kernprinzip: Dateien sind die Quelle der Wahrheit** — der Agent behält nur, was auf Disk geschrieben wird.

```
Workspace/
├── MEMORY.md              # Langzeit (kuratiert, nur private Sessions)
└── memory/
    ├── 2026-03-17.md      # Tages-Log (append-only)
    ├── 2026-03-18.md
    └── ...
```

### Memory-Ebenen

| Datei | Zweck | Wann geladen |
|-------|-------|--------------|
| `MEMORY.md` | Kuratierte Fakten, Entscheidungen, Präferenzen | Jede private Session |
| `memory/YYYY-MM-DD.md` | Tagesnotizen, Running-Log | Heute + Gestern am Session-Start |

> **Hinweis**: Wenn sowohl `MEMORY.md` als auch `memory.md` existieren, wird nur `MEMORY.md` geladen (Großbuchstaben priorisiert).

---

## Memory-Tools

OpenClaw stellt zwei Agent-Tools bereit:

### `memory_search`
Semantische Suche über indizierte Snippets:
- Gibt Snippet-Text (~700 Zeichen), Dateipfad, Zeilenbereich, Score zurück
- Unterstützt Hybrid-Suche (BM25 + Vektor)
- MMR für Diversität, Temporal Decay für Aktualität

### `memory_get`
Gezieltes Lesen einer Memory-Datei:
- Liest workspace-relative Pfade
- Optional mit Startzeile und Zeilenanzahl
- Graceful Degradation: Bei nicht existierender Datei wird `{text: "", path}` zurückgegeben

```json5
// Tool-Beispiel
memory_get({ path: "memory/2026-03-17.md", startLine: 50, lines: 20 })
```

---

## Memory Flush (automatisch vor Compaction)

Wenn eine Session sich der Context-Window-Grenze nähert, triggert OpenClaw einen stillen Turn:
- Agent wird aufgefordert, wichtige Infos in `memory/YYYY-MM-DD.md` zu schreiben
- Standard-Antwort: `NO_REPLY` (User sieht nichts)

### Konfiguration

```json5
agents: {
  defaults: {
    compaction: {
      reserveTokensFloor: 20000,
      memoryFlush: {
        enabled: true,
        softThresholdTokens: 4000,
        systemPrompt: "Session nearing compaction. Store durable memories now.",
        prompt: "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store.",
      },
    },
  },
}
```

### Flush-Details

- **Trigger**: `tokenEstimate > contextWindow - reserveTokensFloor - softThresholdTokens`
- **Ein Flush pro Compaction-Zyklus** (in sessions.json getrackt)
- **Workspace muss schreibbar sein** (`workspaceAccess: "ro"` oder `"none"` → Flush übersprungen)

---

## Semantic Memory Search

### Provider-Auswahl (Auto-Detect)

Wenn `memorySearch.provider` nicht gesetzt ist, wählt OpenClaw automatisch:

1. `local` — wenn `memorySearch.local.modelPath` existiert
2. `openai` — wenn OpenAI-Key gefunden
3. `gemini` — wenn Gemini-Key gefunden
4. `voyage` — wenn Voyage-Key gefunden
5. `mistral` — wenn Mistral-Key gefunden
6. **disabled** — wenn kein Key

### Konfiguration

```json5
agents: {
  defaults: {
    memorySearch: {
      enabled: true,
      provider: "openai",           // "openai" | "gemini" | "voyage" | "mistral" | "local" | "ollama"
      model: "text-embedding-3-small",

      // Remote-Provider-Optionen
      remote: {
        apiKey: { source: "env", provider: "default", id: "OPENAI_API_KEY" },
        baseUrl: "https://api.openai.com/v1",  // Optional: Custom Endpoint
        headers: { "X-Custom": "value" },      // Optional: Custom Headers
        batch: { enabled: true, concurrency: 2 }, // Batch-API für große Korpora
      },

      // Lokale Embeddings
      local: {
        modelPath: null,  // Oder "hf:ggml-org/embeddinggemma-300m-qat-q8_0-GGUF/..."
      },

      // Zusätzliche Pfade
      extraPaths: ["../team-docs", "/srv/shared-notes"],

      // Embedding-Cache
      cache: {
        enabled: true,
        maxEntries: 50000,
      },
    },
  },
}
```

---

## Hybrid Search (BM25 + Vektor)

Kombiniert semantische Ähnlichkeit mit exakten Keyword-Matches:

```json5
agents: {
  defaults: {
    memorySearch: {
      query: {
        hybrid: {
          enabled: true,
          vectorWeight: 0.7,       // 0-1, Gewicht für Vektor-Score
          textWeight: 0.3,         // 0-1, Gewicht für BM25-Score
          candidateMultiplier: 4,  // Kandidaten-Pool = maxResults * multiplier
        },
      },
    },
  },
}
```

### Warum Hybrid?

- **Vektor-Suche** gut für: "Mac Studio gateway host" ≈ "the machine running the gateway"
- **BM25** gut für: exakte IDs (`a828e60`), Code-Symbole, Fehlerstrings

---

## MMR Re-Ranking (Diversität)

Vermeidet redundante Ergebnisse mit Maximal Marginal Relevance:

```json5
memorySearch: {
  query: {
    hybrid: {
      mmr: {
        enabled: true,
        lambda: 0.7,  // 0 = max Diversität, 1 = max Relevanz
      },
    },
  },
}
```

**Beispiel**: Suche nach "home network setup"
- Ohne MMR: 5 fast identische Ergebnisse
- Mit MMR: Diverse Ergebnisse (Router-Config, AdGuard, VLAN-Setup)

---

## Temporal Decay (Aktualität)

Bevorzugt aktuelle Memory-Einträge:

```json5
memorySearch: {
  query: {
    hybrid: {
      temporalDecay: {
        enabled: true,
        halfLifeDays: 30,  // Score halbiert sich alle 30 Tage
      },
    },
  },
}
```

**Decay-Berechnung**: `decayedScore = score × e^(-λ × ageInDays)`

**Evergreen-Dateien** werden nicht decayed:
- `MEMORY.md`
- Nicht-datierte Dateien in `memory/` (z.B. `memory/projects.md`)

---

## QMD Backend (Experimental)

Alternatives Such-Backend mit BM25 + Vektor + Reranking:

```json5
memory: {
  backend: "qmd",
  citations: "auto",  // "auto" | "on" | "off"
  qmd: {
    command: "qmd",  // Oder Pfad zum Binary
    searchMode: "search",  // "search" | "vsearch" | "query"
    includeDefaultMemory: true,

    paths: [
      { name: "docs", path: "~/notes", pattern: "**/*.md" },
    ],

    sessions: {
      enabled: true,
      retentionDays: 30,
      exportDir: "~/.openclaw/agents/<id>/qmd/sessions",
    },

    update: {
      interval: "5m",
      debounceMs: 15000,
      onBoot: true,
    },

    limits: {
      maxResults: 6,
      maxSnippetChars: 700,
      timeoutMs: 4000,
    },

    scope: {
      default: "deny",
      rules: [
        { action: "allow", match: { chatType: "direct" } },
        { action: "deny", match: { keyPrefix: "discord:channel:" } },
      ],
    },
  },
}
```

### QMD-Details

- **Installation**: `bun install -g https://github.com/tobi/qmd`
- **SQLite**: Muss Extension-Unterstützung haben (`brew install sqlite` auf macOS)
- **Modelle**: Auto-Download von HuggingFace bei erstem `qmd query`
- **Fallback**: Bei QMD-Fehler wird automatisch auf SQLite-Backend zurückgefallen

---

## Multimodal Memory (Gemini Embedding 2)

Indexiert Bilder und Audio (nur mit Gemini Embedding 2):

```json5
agents: {
  defaults: {
    memorySearch: {
      provider: "gemini",
      model: "gemini-embedding-2-preview",
      multimodal: {
        enabled: true,
        modalities: ["image", "audio"],  // Oder ["all"]
        maxFileBytes: 10000000,          // 10 MB Limit
      },
      extraPaths: ["assets/reference", "voice-notes"],
      fallback: "none",  // Multimodal erfordert "none"
    },
  },
}
```

**Unterstützte Formate**:
- Bilder: `.jpg`, `.jpeg`, `.png`, `.webp`, `.gif`, `.heic`, `.heif`
- Audio: `.mp3`, `.wav`, `.ogg`, `.opus`, `.m4a`, `.aac`, `.flac`

---

## Session Memory Search (Experimental)

Indexiert Session-Transkripte für Recall:

```json5
agents: {
  defaults: {
    memorySearch: {
      experimental: { sessionMemory: true },
      sources: ["memory", "sessions"],
      sync: {
        sessions: {
          deltaBytes: 100000,    // ~100 KB
          deltaMessages: 50,     // JSONL-Zeilen
        },
      },
    },
  },
}
```

**Hinweis**: Session-Indexierung ist opt-in und läuft asynchron.

---

## Embedding Cache

Vermeidet erneutes Embedding unveränderter Texte:

```json5
agents: {
  defaults: {
    memorySearch: {
      cache: {
        enabled: true,
        maxEntries: 50000,  // ~50K Chunks
      },
    },
  },
}
```

---

## SQLite Vector Acceleration (sqlite-vec)

Beschleunigt Vektor-Suche in SQLite:

```json5
agents: {
  defaults: {
    memorySearch: {
      store: {
        vector: {
          enabled: true,  // Default: true
          extensionPath: "/path/to/sqlite-vec",  // Optional
        },
      },
    },
  },
}
```

---

## Was indexiert wird

| Dateityp | Indexiert |
|----------|-----------|
| `MEMORY.md` | ✅ |
| `memory/**/*.md` | ✅ |
| `extraPaths` (Markdown) | ✅ |
| `extraPaths` (Bilder/Audio) | ✅ (nur Gemini Embedding 2) |
| Session-Transkripte | ✅ (experimental, opt-in) |

**Index-Speicherort**: `~/.openclaw/memory/<agentId>.sqlite`

---

## Troubleshooting

### Memory-Tools nicht verfügbar

```bash
# Prüfen ob memorySearch aktiviert ist
openclaw config get agents.defaults.memorySearch.enabled

# Provider prüfen
openclaw config get agents.defaults.memorySearch.provider
```

### Embedding-Fehler

```bash
# OpenAI-Key setzen
export OPENAI_API_KEY="sk-..."

# Oder in Config
openclaw config set agents.defaults.memorySearch.provider openai
```

### QMD-Binary nicht gefunden

```bash
# Installieren
bun install -g https://github.com/tobi/qmd

# Oder fallback auf SQLite
openclaw config set memory.backend sqlite
```

### Re-Index erzwingen

```bash
# Index zurücksetzen (bei Provider/Modell-Wechsel)
rm ~/.openclaw/memory/<agentId>.sqlite

# Gateway neu starten
systemctl --user restart openclaw-gateway
```

---

## CLI-Befehle

```bash
# Memory flush (manuell)
openclaw memory flush

# Sessions auflisten
openclaw sessions list

# Sessions bereinigen
openclaw sessions clean
```

---

## Best Practices

1. **Memory schreiben**: Bei Entscheidungen, Präferenzen, wichtigen Fakten → in `MEMORY.md`
2. **Tagesnotizen**: In `memory/YYYY-MM-DD.md` (append-only)
3. **Bei "Merke dir das"**: Agent bitten, in Memory zu schreiben
4. **MEMORY.md privat halten**: Niemals in Group-Sessions laden
5. **Hybrid + MMR + Decay aktivieren**: Beste Recall-Qualität

---

## Referenz

- Docs: https://docs.openclaw.ai/concepts/memory
- Companion Skill: `cognee-openclaw-memory` für Knowledge-Graph-Memory

path: references/multi-agent.md
content: # Multi-Agent-Routing

## Konzept

OpenClaw kann mehrere isolierte Agenten in einem Gateway hosten. Jeder Agent hat:
- **Eigenen Workspace** (Dateien, AGENTS.md, SOUL.md, USER.md, Memory)
- **Eigenes agentDir** (Auth-Profile, Model-Registry)
- **Eigene Sessions** (`~/.openclaw/agents/<agentId>/sessions/`)

Auth-Profile sind **per-Agent**. Credentials werden nicht automatisch geteilt.

---

## Single-Agent-Modus (Default)

Wenn keine Multi-Agent-Konfiguration vorhanden ist:

```json5
{
  agents: {
    defaults: {
      workspace: "~/.openclaw/workspace",
    },
  },
}
```

- `agentId` defaultet zu **`main`**
- Sessions keyed als `agent:main:<mainKey>`
- State: `~/.openclaw/agents/main/agent`

---

## Multi-Agent-Setup

### Mit Wizard

```bash
openclaw agents add work
openclaw agents add personal
```

Der Wizard erstellt:
- Workspace-Verzeichnis (`~/.openclaw/workspace-<id>`)
- `agentDir` (`~/.openclaw/agents/<id>/agent`)
- Session-Store (`~/.openclaw/agents/<id>/sessions`)

### Manuell in openclaw.json

```json5
{
  agents: {
    list: [
      {
        id: "home",
        default: true,
        name: "Home",
        workspace: "~/.openclaw/workspace-home",
        agentDir: "~/.openclaw/agents/home/agent",
        model: "anthropic/claude-sonnet-4-5",
        sandbox: {
          mode: "off",
        },
        tools: {
          allow: ["exec", "read", "write"],
          deny: [],
        },
      },
      {
        id: "work",
        name: "Work",
        workspace: "~/.openclaw/workspace-work",
        agentDir: "~/.openclaw/agents/work/agent",
        model: "anthropic/claude-opus-4-6",
        sandbox: {
          mode: "all",
          scope: "agent",
        },
        tools: {
          allow: ["read"],
          deny: ["exec", "write", "edit", "browser"],
        },
        groupChat: {
          mentionPatterns: ["@work", "@workbot"],
        },
      },
    ],
  },
}
```

---

## Bindings (Routing-Regeln)

Bindings bestimmen, welcher Agent welche Nachrichten empfängt. **Most-specific-wins**:

1. `peer` Match (exakte DM/Group/Channel-ID)
2. `parentPeer` Match (Thread-Inheritance)
3. `guildId + roles` (Discord Role-Routing)
4. `guildId` (Discord Server)
5. `teamId` (Slack Team)
6. `accountId` Match für Channel
7. Channel-level (`accountId: "*"`)
8. Default Agent (`agents.list[].default`, oder erster Eintrag, oder `main`)

### Binding-Beispiele

```json5
bindings: [
  // Specifischer DM zu Opus-Agent
  {
    agentId: "opus",
    match: {
      channel: "whatsapp",
      peer: { kind: "direct", id: "+15551234567" },
    },
  },

  // Kanal-weiter Fallback für WhatsApp
  {
    agentId: "home",
    match: { channel: "whatsapp" },
  },

  // Account-spezifisch
  {
    agentId: "work",
    match: { channel: "whatsapp", accountId: "biz" },
  },

  // Channel-weit (accountId: "*")
  {
    agentId: "chat",
    match: { channel: "telegram", accountId: "*" },
  },

  // Discord-Group mit Mention-Pattern
  {
    agentId: "family",
    match: {
      channel: "discord",
      peer: { kind: "group", id: "120363999999999999" },
    },
  },
],
```

### Account-Scoping

- Binding ohne `accountId` → matcht nur Default-Account
- `accountId: "*"` → matcht alle Accounts auf dem Channel
- Duplicate Bindings werden automatisch auf Account-Scoping umgestellt

---

## Per-Agent Sandbox & Tools

Jeder Agent kann eigene Sandbox- und Tool-Einstellungen haben:

```json5
{
  agents: {
    list: [
      {
        id: "personal",
        workspace: "~/.openclaw/workspace-personal",
        sandbox: { mode: "off" },
        // Keine Tool-Einschränkungen
      },
      {
        id: "family",
        workspace: "~/.openclaw/workspace-family",
        sandbox: {
          mode: "all",
          scope: "agent",
          docker: {
            setupCommand: "apt-get update && apt-get install -y git curl",
          },
        },
        tools: {
          allow: ["read"],
          deny: ["exec", "write", "edit", "apply_patch", "browser", "nodes", "cron"],
        },
        groupChat: {
          mentionPatterns: ["@family", "@familybot"],
        },
      },
    ],
  },
}
```

**Hinweis**: `setupCommand` läuft unter `sandbox.docker.*`. Per-Agent Docker-Overrides werden ignoriert, wenn der Scope `"shared"` ist.

---

## Session-DmScope

Isolations-Level für Direct Messages:

| dmScope | Beschreibung | Use-Case |
|---------|--------------|----------|
| `main` | Alle DMs teilen eine Session | Single-User |
| `per-channel-peer` | DMs pro Channel+Sender isoliert | Multi-User |
| `per-account-channel-peer` | DMs pro Account+Channel+Sender | Multi-Account |

```json5
session: {
  dmScope: "per-channel-peer",
  threadBindings: "auto",  // "auto" | "manual"
}
```

---

## CLI-Befehle

```bash
# Agent-Liste
openclaw agents list
openclaw agents list --bindings

# Neuen Agent erstellen
openclaw agents add <id>

# Binding hinzufügen
openclaw agents bind <agentId> "channel:telegram:accountId:alerts"

# Binding entfernen
openclaw agents unbind <agentId> "channel:telegram:accountId:alerts"
```

---

## Pfade

| Pfad | Beschreibung |
|------|--------------|
| `~/.openclaw/openclaw.json` | Haupt-Config |
| `~/.openclaw/workspace-<id>/` | Agent-Workspace |
| `~/.openclaw/agents/<id>/agent/` | Auth-Profile, Model-Registry |
| `~/.openclaw/agents/<id>/sessions/` | Session-Logs (*.jsonl) |

---

## Platform-Beispiele

### Discord-Bots per Agent

```json5
{
  agents: {
    list: [
      { id: "main", workspace: "~/.openclaw/workspace-main" },
      { id: "coding", workspace: "~/.openclaw/workspace-coding" },
    ],
  },
  bindings: [
    { agentId: "main", match: { channel: "discord", accountId: "default" } },
    { agentId: "coding", match: { channel: "discord", accountId: "coding" } },
  ],
  channels: {
    discord: {
      groupPolicy: "allowlist",
      accounts: {
        default: {
          [REDACTED_SECRET]",
          guilds: {
            "123456789012345678": {
              channels: {
                "222222222222222222": { allow: true, requireMention: false },
              },
            },
          },
        },
        coding: {
          [REDACTED_SECRET]",
          guilds: {
            "123456789012345678": {
              channels: {
                "333333333333333333": { allow: true, requireMention: false },
              },
            },
          },
        },
      },
    },
  },
}
```

### WhatsApp-Nummern per Agent

```bash
# Accounts verlinken
openclaw channels login --channel whatsapp --account personal
openclaw channels login --channel whatsapp --account biz
```

```json5
{
  agents: {
    list: [
      { id: "home", default: true, workspace: "~/.openclaw/workspace-home" },
      { id: "work", workspace: "~/.openclaw/workspace-work" },
    ],
  },
  bindings: [
    { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
    { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },
  ],
}
```

---

## Best Practices

1. **Isolierte Workspaces**: Jeder Agent bekommt eigenen Workspace-Ordner
2. **dmScope: `per-channel-peer`**: Für Multi-User-Setups
3. **Sandbox pro Agent**: Verschiedene Trust-Level mit `sandbox.mode`
4. **Binding-Reihenfolge**: Spezifischere Regeln zuerst
5. **Account-Trennung**: Ein WhatsApp-Account kann mehrere Agenten via `bindings` routen
6. **Niemals agentDir teilen**: Verursacht Auth/Session-Kollisionen
7. **Credentials kopieren**: Bei Bedarf `auth-profiles.json` manuell kopieren

---

## Agent-to-Agent Messaging

Agenten können sich gegenseitig Nachrichten senden (opt-in):

```json5
tools: {
  agentToAgent: {
    enabled: true,
    allow: ["home", "work"],  // Whitelist der Agenten
  },
}
```

**Standardmäßig deaktiviert.** Wenn aktiviert, können Agenten via `agentToAgent` Tool kommunizieren.

---

## Identity & Name

Jeder Agent kann eigene Identitäts-Informationen haben:

```json5
{
  agents: {
    list: [
      {
        id: "family",
        name: "Family",
        identity: { name: "Family Bot" },
        groupChat: {
          mentionPatterns: ["@family", "@familybot", "Family Bot"],
        },
      },
    ],
  },
}
```

---

## Workspace-Isolation

**Wichtig:** Der Workspace ist das Default-Arbeitsverzeichnis, aber KEINE harte Sandbox.

- Relative Pfade → innerhalb Workspace
- Absolute Pfade → können andere Host-Verzeichnisse erreichen
- Für echte Isolation: `sandbox.mode` aktivieren

---

## Referenz

- Docs: https://docs.openclaw.ai/concepts/multi-agent
- **Config-Referenz**: `references/config-reference.md` — agents.list Schema
- **Security**: `references/security-hardening.md` — Per-Agent Sandbox & Tools
- **Docker**: `references/docker-setup.md` — Sandbox-Container Setup
- **CLI**: `references/cli-reference.md` — `openclaw agents` Befehle
- **Quick-Ref**: `references/quick-reference.md` — Multi-Agent Quick-Setup

path: references/nodes-and-remote.md
content: # Nodes & Remote Access — Geräte als Nodes anschließen

## Was ist ein Node?

Ein Node ist ein **Companion-Gerät** (macOS, iOS, Android, Headless-Linux), das sich per WebSocket
mit dem Gateway verbindet und lokale Aktionen ausführt (Kamera, Screen, Canvas, Shell-Befehle).

**Nodes sind KEINE Gateways.** Messaging-Kanäle (Telegram, WhatsApp etc.) laufen auf dem Gateway,
nicht auf Nodes. Nodes sind Peripheriegeräte.

```
┌─────────────────────────────────┐
│  Gateway (VPS/Server)           │  ← Messaging, Sessions, Brain
│  ws://127.0.0.1:18789          │
└──────────┬──────────────────────┘
           │ WebSocket (Tailscale/LAN)
    ┌──────┴──────────────────────┐
    │  Node: MacBook (macOS App)  │  ← Browser-Control, Canvas, Voice Wake
    │  Node: iPhone (iOS App)     │  ← Kamera, Screen Recording, Canvas
    │  Node: Android Phone        │  ← Kamera, Screen Recording, SMS
    │  Node: Raspberry Pi         │  ← system.run, Hardware-Control
    │  Node: Headless Linux       │  ← system.run, system.which
    └─────────────────────────────┘
```

---

## Node-Typen & Fähigkeiten

| Node-Typ | Fähigkeiten | Pairing |
|---|---|---|
| macOS Menübar-App | Voice Wake, PTT, WebChat, Canvas, Browser-Control, Debug | Bonjour/mDNS |
| iOS App | Canvas, Voice Wake, Talk Mode, Kamera, Screen Recording | QR-Code / Deep Link |
| Android App | Canvas, Talk Mode, Kamera, Screen Recording, SMS | QR-Code |
| macOS Node-Mode | system.run, system.notify, Canvas, Kamera | Bonjour/mDNS |
| Headless Node | system.run, system.which (kein UI) | CLI-Pairing |

---

## Szenario: Gateway auf VPS + MacBook als Node

### Voraussetzungen
- Gateway läuft auf VPS (Contabo, Hetzner, etc.)
- Tailscale auf beiden Geräten installiert und eingeloggt
- Beide im selben Tailnet

### Schritt 1: Tailscale auf VPS installieren
```bash
# Auf dem VPS:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
# Tailscale-IP notieren: tailscale ip -4
```

### Schritt 2: Gateway für Tailscale konfigurieren
```json5
// ~/.openclaw/openclaw.json auf dem VPS:
{
  gateway: {
    bind: "loopback",           // Bleibt loopback!
    tailscale: {
      mode: "serve",            // Tailnet-only (empfohlen)
      // mode: "funnel",        // NUR wenn öffentlich nötig (GEFÄHRLICH!)
      resetOnExit: false,
    },
    auth: {
      mode: "token",
      [REDACTED_SECRET]",
      allowTailscale: true,     // Tailscale-Identity-Auth erlauben
    },
  },
}
```

```bash
# Gateway neu starten
systemctl --user restart openclaw-gateway
```

### Schritt 3: macOS Menübar-App als Node verbinden
1. OpenClaw macOS App installieren
2. App öffnen → Settings → Gateway
3. Gateway-URL eingeben: `https://<vps-hostname>.your-tailnet.ts.net`
4. Token eingeben (oder Tailscale-Auth wenn `allowTailscale: true`)
5. Pairing-Request wird auf Gateway erstellt

### Schritt 4: Pairing auf Gateway genehmigen
```bash
# Auf dem VPS:
openclaw devices list              # Offene Pairing-Requests anzeigen
openclaw devices approve <requestId>
```

### Schritt 5: Verifizieren
```bash
openclaw nodes status              # Node sollte "connected" zeigen
openclaw nodes describe --all      # Fähigkeiten aller Nodes anzeigen
```

---

## Szenario: Gateway auf VPS + iPhone als Node

### Schritt 1: Gateway mit Tailscale Serve (wie oben)

### Schritt 2: iOS App installieren und verbinden
1. OpenClaw iOS App aus App Store installieren
2. App öffnen → Settings → Gateway
3. Zwei Optionen:
   - **QR-Code**: Im Gateway-Dashboard (WebChat) QR-Code generieren → Scannen
   - **Deep Link**: `openclaw://setup?code=<SETUP_CODE>` → In App öffnen
   - **Manuell**: Gateway-URL + Token eingeben

### Schritt 3: Pairing via Telegram (bequemster Weg)
```
# Im Telegram-Chat mit dem Bot:
/pair
# → Bot antwortet mit Setup-Code
# → Code in iOS App → Settings → Gateway einfügen
```

### Schritt 4: Genehmigen
```bash
openclaw devices approve <requestId>
```

---

## Szenario: Headless Node (Linux/Pi)

Für Maschinen ohne GUI — nur `system.run` und `system.which`:

```bash
# Auf dem Node-Rechner:
npm install -g openclaw@latest

# Headless Node starten:
openclaw node host --gateway wss://<vps-hostname>.your-tailnet.ts.net \
  --token <gateway-token>

# Oder mit TLS:
openclaw node host --gateway wss://<hostname>:18789 \
  --tls --tls-fingerprint <fingerprint>
```

Node-Config wird gespeichert in: `~/.openclaw/node.json`
Exec-Approvals: `~/.openclaw/exec-approvals.json`

---

## Szenario: Raspberry Pi als immer-on Node

```bash
# Auf dem Pi:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

npm install -g openclaw@latest

# Als systemd-Service:
cat > ~/.config/systemd/user/openclaw-node.service << 'EOF'
[Unit]
Description=OpenClaw Node Host
After=network-online.target

[Service]
ExecStart=%h/.npm-global/bin/openclaw node host \
  --gateway wss://<vps-hostname>.your-tailnet.ts.net \
  --token <gateway-token>
Restart=always
RestartSec=10

[Install]
WantedBy=default.target
EOF

systemctl --user daemon-reload
systemctl --user enable --now openclaw-node
```

---

## Node-Discovery (Bonjour/mDNS)

### Lokales Netzwerk (LAN)
- Gateway advertised sich via `_openclaw-gw._tcp` (Bonjour/mDNS)
- macOS/iOS Nodes entdecken Gateway automatisch im LAN
- Kein manuelles URL-Eingeben nötig

### Tailscale-Netzwerk
- mDNS-Broadcasts propagieren nicht über Tailscale
- **Lösung**: DNS-SD über Unicast-DNS (Tailscale DNS-Server)
- Android nutzt `dnsjava` Library für Unicast-DNS-SD
- iOS nutzt QR-First-Pairing wenn kein lokaler Gateway gefunden

---

## Node-Befehle ausführen

```bash
# Befehl auf einem spezifischen Node ausführen
openclaw nodes run --node <idOrNameOrIp> -- echo "Hello from node"

# Benachrichtigung auf Node senden
openclaw nodes notify --node <idOrNameOrIp> \
  --title "Ping" --body "Gateway ready" \
  --priority active   # passive | active | timeSensitive

# Node-Details anzeigen
openclaw nodes describe --node <id>

# Alle Nodes anzeigen
openclaw nodes status
```

---

## Browser-Control über Node

Für Gateway auf Server + Browser auf MacBook:

1. Gateway auf VPS (Tailscale Serve)
2. macOS Node auf MacBook (Menübar-App, selbes Tailnet)
3. Gateway proxied Browser-Aktionen zum Node
4. **Kein separater Serve-URL** nötig
5. **Kein Funnel** für Browser-Control nutzen!

---

## Exec-Approvals (Sicherheit)

Nodes können Shell-Befehle ausführen — das muss kontrolliert werden:

```json5
// ~/.openclaw/exec-approvals.json (auf dem Node)
{
  "mode": "ask",          // "ask" | "allowlist" | "full"
  // ask = Jeder Befehl muss bestätigt werden
  // allowlist = Nur bestimmte Befehle erlaubt
  // full = Alles erlaubt (GEFÄHRLICH!)
}
```

macOS App: Settings → Exec Approvals (gleiche Modi)

---

## Wichtige Regeln

1. **Nodes sind Peripherie** — Messaging geht über Gateway, nicht über Nodes
2. **Pairing = Vertrauens-Akt** — Setup-Code wie Passwort behandeln!
3. **Kein Funnel für Nodes** — Nur Tailscale Serve oder LAN
4. **exec-approvals** — Auf jedem Node konfigurieren
5. **Node-ID persistent** — Gespeichert in `~/.openclaw/node.json`
6. **PATH-Overrides ignoriert** — Tools in Standard-Locations installieren


path: references/quick-reference.md
content: # Quick Reference — Schnellnachschlage

> Einseitige Referenz für häufige Konfigurationen und Befehle.

---

## Verzeichnisstruktur

```
~/.openclaw/
├── openclaw.json          # Haupt-Config (JSON5)
├── credentials/           # API-Keys (chmod 600!)
├── agents/<id>/sessions/  # Session-Logs
├── skills/                # Managed-Skills
└── workspace/             # Agent-Workspace
    ├── AGENTS.md          # Betriebsanweisungen
    ├── SOUL.md            # Persönlichkeit
    ├── USER.md            # Nutzerprofil
    ├── MEMORY.md          # Langzeit-Gedächtnis
    └── memory/            # Tagesnotizen
```

---

## Minimal-Config

```json5
{
  gateway: { bind: "loopback", auth: { mode: "token", token: "<64+ chars>" } },
  channels: { telegram: { enabled: true, botToken: "..." } },
  models: { default: "anthropic/claude-sonnet-4-20250514" },
}
```

---

## Security-Checkliste

| Setting | Wert | Befehl |
|---------|------|--------|
| Gateway-Bind | `loopback` | `openclaw config set gateway.bind loopback` |
| DM-Policy | `allowlist` | `openclaw config set channels.defaults.dmPolicy allowlist` |
| Token | 64+ chars | `openclaw [REDACTED_SECRET] --force --length 64` |
| Secrets | SecretRef | `openclaw secrets configure` |
| Credentials | chmod 600 | `chmod 600 ~/.openclaw/credentials/*` |

---

## DM-Policy Modi

| Modus | Verhalten | Use-Case |
|-------|-----------|----------|
| `pairing` | Code anfordern + genehmigen | Ersteinrichtung |
| `allowlist` | Nur allowFrom-IDs | ✅ Produktion |
| `open` | Jeder darf (gefährlich!) | ❌ Vermeiden |
| `disabled` | Keine DMs | Spezifisch |

---

## Channel-Quick-Setup

### Telegram
```bash
@BotFather → /newbot → Token kopieren
openclaw channels add --channel telegram --token "<TOKEN>"
# User-ID finden: @userinfobot anschreiben
```

### WhatsApp
```bash
openclaw channels login --channel whatsapp
# QR im Dashboard scannen
# Pairing: openclaw pairing approve whatsapp <CODE>
```

### Discord
```bash
# Discord Dev Portal → Bot → Token + Message Content Intent!
openclaw channels add --channel discord --token "<TOKEN>"
```

---

## Models hinzufügen

```json5
models: {
  default: "anthropic/claude-sonnet-4-20250514",
  heartbeat: [REDACTED_SECRET],  // Günstig für Heartbeat
  providers: {
    openai: { apiKey: { source: "env", id: "OPENAI_API_KEY" } },
    ollama: { baseUrl: "http://localhost:11434", api: "openai-completions" },
  },
}
```

---

## Sandbox-Quick-Config

```json5
agents: {
  defaults: {
    sandbox: {
      mode: "non-main",      // "off" | "non-main" | "all"
      scope: "agent",         // "session" | "agent" | "shared"
      workspaceAccess: "ro",  // "none" | "ro" | "rw"
      docker: {
        image: "openclaw-sandbox:bookworm-slim",
        network: "none",      // Sicherste Option
      },
    },
  },
}
```

---

## Multi-Agent Quick-Setup

```json5
agents: {
  list: [
    { id: "home", default: true, workspace: "~/.openclaw/workspace-home" },
    { id: "work", workspace: "~/.openclaw/workspace-work" },
  ],
},
bindings: [
  { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
  { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },
],
```

```bash
openclaw agents add work
openclaw agents bind work "whatsapp:biz"
```

---

## Memory mit Semantic Search

```json5
agents: {
  defaults: {
    memorySearch: {
      enabled: true,
      provider: "openai",
      model: "text-embedding-3-small",
      query: {
        hybrid: { enabled: true },
        mmr: { enabled: true, lambda: 0.7 },
        temporalDecay: { enabled: true, halfLifeDays: 30 },
      },
    },
    compaction: {
      memoryFlush: { enabled: true },
    },
  },
}
```

---

## Docker Quick-Start

```bash
# Mit Sandbox
export OPENCLAW_SANDBOX=1
./docker-setup.sh

# Ohne Sandbox
./docker-setup.sh

# Remote Image
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
./docker-setup.sh
```

---

## Tailscale Modi

| Modus | Zugriff | Auth |
|-------|---------|------|
| `serve` | Tailnet-only | Token oder Tailscale-Identity |
| `funnel` | Öffentlich (VORSICHT!) | Password PFLICHT |
| `tailnet` bind | Tailnet-IP, kein HTTPS | Token |

```json5
gateway: {
  bind: "loopback",
  tailscale: { mode: "serve" },
  auth: { mode: "token", token: "...", allowTailscale: true },
}
```

---

## SecretRef Formate

```json5
// Environment Variable
{ source: "env", provider: "default", id: "OPENAI_API_KEY" }

// JSON-File
{ source: "file", provider: "filemain", id: "/providers/openai/apiKey" }

// External (1Password, Vault, sops)
{ source: "exec", provider: "onepassword", id: "value" }
```

---

## CLI-Einzeiler

```bash
# Status
openclaw doctor && openclaw status

# Gateway
openclaw gateway restart

# Config validieren
openclaw config validate

# Channels testen
openclaw channels status --probe

# Skills neu laden
openclaw skills reload

# Pairing
openclaw pairing list whatsapp
openclaw pairing approve whatsapp <CODE>

# Token rotieren
openclaw [REDACTED_SECRET] --force --length 64

# Logs
openclaw logs --follow --channel telegram

# Session-Status
openclaw sessions list
```

---

## Troubleshooting-Patterns

| Problem | Erster Schritt |
|---------|----------------|
| Gateway startet nicht | `openclaw doctor` |
| Config-Fehler | JSON5-Syntax prüfen (trailing commas OK) |
| Channel verbindet nicht | `openclaw channels status --probe` |
| Token nicht erkannt | Environment-Variable gesetzt? |
| Sandbox-Container fehlt | `scripts/sandbox-setup.sh` |
| Permissions in Docker | `sudo chown -R 1000:$(id -g) ~/.openclaw` |
| QR-Code abgelaufen | `openclaw channels login` erneut |
| Node verbindet nicht | `tailscale status` auf beiden Seiten |

---

## Kosten sparen

```json5
agent: {
  heartbeat: { every: "6h" },  // Statt 30m → 90% weniger
},
models: {
  default: "anthropic/claude-sonnet-4-20250514",
  heartbeat: "anthropic/claude-haiku-3-20250307",
},
```

---

## Referenz-Links

| Thema | Datei |
|-------|-------|
| Installation | `references/installation.md` |
| Config-Details | `references/config-reference.md` |
| Channels | `references/channels.md` |
| Security | `references/security-hardening.md` |
| Docker | `references/docker-setup.md` |
| Multi-Agent | `references/multi-agent.md` |
| Skills | `references/skills-guide.md` |
| Memory | `references/memory-system.md` |
| CLI-Befehle | `references/cli-reference.md` |

path: references/security-hardening.md
content: # Security-Hardening — OpenClaw absichern

## Threat Model

OpenClaw hat **volle Kontrolle über den Rechner** — kann Dateien erstellen/löschen,
Software installieren, Skripte ausführen, Internet-Dienste kontaktieren.
Deshalb: Isolation und Least-Privilege sind Pflicht.

---

## Checkliste (Minimum-Sicherheit)

```bash
# 1. Gateway nur lokal binden
openclaw config set gateway.bind loopback

# 2. DM-Policy auf Allowlist
openclaw config set channels.defaults.dmPolicy allowlist
# Eigene User-IDs eintragen!

# 3. Token rotieren (64+ Zeichen)
openclaw [REDACTED_SECRET] --force --length 64

# 4. Secrets mit SecretRef (nicht Plaintext!)
openclaw secrets configure
openclaw secrets audit --check

# 5. Credentials schützen
chmod 600 ~/.openclaw/credentials/*

# 6. Doctor prüft Security-Config
openclaw doctor
openclaw doctor --run doctor    # DM-Policy-Check
openclaw security audit --deep  # Tiefes Audit
```

---

## Personal Assistant Security Model

OpenClaw ist für **Personal Assistant** Workloads konzipiert, nicht für Multi-Tenant-SaaS.

**Implikation:**
- Gateway läuft als regulärer User (nicht root)
- Operator-Trust-Boundary: Du vertraust dir selbst
- Keine Tenant-Isolation zwischen verschiedenen WhatsApp/Telegram-Absendern
- Bei Shared-Slack-Workspace: Reale Risk, allen im Channel zu vertrauen

**Best Practice:**
- `dmPolicy: "allowlist"` — Nur deine eigenen Nummern/User-IDs
- `groupPolicy: "allowlist"` — Gruppen mit bekannten Mitgliedern
- Sandbox für Tools aktivieren — Isoliert Tool-Ausführung

---

## DM-Policy (Access Control)

```json5
// Channel-Level Default
channels: {
  defaults: {
    dmPolicy: "allowlist",    // Globaler Default für alle Channels
  },
  whatsapp: {
    dmPolicy: "pairing",      // Override für WhatsApp
    allowFrom: ["+49123456789"],
    groupPolicy: "allowlist",
    groupAllowFrom: ["+49123456789"],
    reject_action: "silent_drop",
    log_rejections: true,
  },
}
```

**DM-Policy-Modi:**

| Modus | Verhalten | Empfehlung |
|---|---|---|
| `pairing` | User muss Code anfordern und genehmigt werden | Ersteinrichtung |
| `allowlist` | Nur `allowFrom`-IDs dürfen schreiben | ✅ Produktion |
| `open` | Jeder darf schreiben (erfordert `allowFrom: ["*"]`) | ❌ Vermeiden |
| `disabled` | Keine DMs erlaubt | Spezifische Use-Cases |

**Active-Surface-Filtering:**
- Deaktivierte Channels/Accounts: SecretRefs blockieren Startup NICHT
- `SECRETS_REF_IGNORED_INACTIVE_SURFACE` — Non-fatal Warning

**Wichtig:** `allowFrom`-IDs sind plattformspezifisch:
- WhatsApp: E.164-String mit `+` (z.B. `"+4915568920209"`)
- Telegram: Numerische User-ID als Zahl (z.B. `7403482253`)

---

## SecretRef — Sichere Credential-Verwaltung

API-Keys **niemals** im Plaintext in Config speichern!

### SecretRef-Contract

```json5
// Basis-Objekt (überall gleich):
{ source: "env" | "file" | "exec", provider: "...", id: "..." }
```

### source: "env" — Environment Variable

```json5
models: {
  providers: {
    openai: {
      apiKey: { source: "env", provider: "default", id: "OPENAI_API_KEY" },
    },
  },
}
```

**Validierung:**
- `provider` muss `^[a-z][a-z0-9_-]{0,63}$` matchen
- `id` muss `^[A-Z][A-Z0-9_]{0,127}$` matchen

### source: "file" — JSON-File mit Pointer

```json5
secrets: {
  providers: {
    filemain: {
      source: "file",
      path: "~/.openclaw/secrets.json",
      mode: "json",  // oder "singleValue"
    },
  },
}

models: {
  providers: {
    openai: {
      apiKey: { source: "file", provider: "filemain", id: "/providers/openai/apiKey" },
    },
  },
}
```

**Validierung:**
- `id` muss JSON-Pointer sein (`/...`)
- RFC6901 Escaping: `~` → `~0`, `/` → `~1`

### source: "exec" — External Secret Manager (1Password, Vault, sops)

```json5
secrets: {
  providers: {
    onepassword_openai: {
      source: "exec",
      command: "/opt/homebrew/bin/op",
      allowSymlinkCommand: true,  // Für Homebrew-Shims
      trustedDirs: ["/opt/homebrew"],
      args: ["read", "op://Personal/OpenClaw QA API Key/password"],
      passEnv: ["HOME"],
      jsonOnly: false,
    },
  },
}

models: {
  providers: {
    openai: {
      apiKey: { source: "exec", provider: "onepassword_openai", id: "value" },
    },
  },
}
```

**Exec-Integrationen:**
- **1Password CLI**: `op read op://...`
- **HashiCorp Vault**: `vault kv get -field=KEY secret/openclaw`
- **sops**: `sops -d --extract '["providers"]["openai"]["apiKey"]' secrets.enc.json`

**Request/Response-Protokoll (stdin/stdout JSON):**
```json
// Request:
{ "protocolVersion": 1, "provider": "vault", "ids": ["providers/openai/apiKey"] }

// Response:
{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "sk-..." } }

// Mit Fehlern:
{ "protocolVersion": 1, "values": {}, "errors": { "providers/openai/apiKey": { "message": "not found" } } }
```

### Secrets-CLI

```bash
# Audit (Plaintext-Scan)
openclaw secrets audit --check

# Interaktiver Wizard
openclaw secrets configure

# Nur Provider setup
openclaw secrets configure --providers-only

# Plan anwenden
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json

# Runtime-Refresh
openclaw secrets reload
```

**Sicherheits-Modell:**
- SecretRefs werden beim Gateway-Start eager aufgelöst
- Startup fail-fast wenn Active-Surface SecretRef nicht auflösbar
- Reload nutzt atomic swap: Full success oder last-known-good snapshot
- Keine Rollback-Backups mit Plaintext-Values (one-way safety)

---

## Gateway-Sicherheit

| Setting | Sicher | Gefährlich |
|---|---|---|
| `gateway.bind` | `loopback` | `lan`, `0.0.0.0` |
| `gateway.auth.mode` | `token` | `none` |
| `dmPolicy` | `allowlist` | `open` |
| `tools.exec.host` | `sandbox` | `gateway` |
| `tools.exec.security` | `full` | `relaxed` |

### Remote-Zugriff (wenn nötig)
- **Tailscale** (empfohlen): `gateway.mode: "tailscale"`, `gateway.bind: "tailscale"`
- **SSH-Tunnel**: `ssh -L 18789:127.0.0.1:18789 user@server`
- **NIEMALS** Port 18789 direkt ins Internet exponieren!

### Gateway Auth Surface Diagnostics

Bei SecretRef auf `gateway.auth.token`, `gateway.auth.password`, `gateway.remote.token`, oder `gateway.remote.password` loggt Gateway den Surface-State:

- `active`: SecretRef ist Teil des effektiven Auth-Surface (muss auflösen)
- `inactive`: SecretRef wird ignoriert (anderer Auth-Surface gewinnt)

Code: `SECRETS_GATEWAY_AUTH_SURFACE`

---

## Skill-Sicherheit

Skills sind die größte Angriffsfläche. OpenClaw lädt Skills aus drei Orten:

| Ort | Präzedenz | Sichtbarkeit |
|---|---|---|
| `<workspace>/skills` | Höchste | Nur dieser Agent |
| `~/.openclaw/skills` | Mitte | Alle Agents auf dieser Maschine |
| Bundled Skills | Niedrigste | Mitgeliefert |

**ClawHub-Sicherheit:**
- 5700+ Skills verfügbar — nicht alle sicher
- "Hide Suspicious" auf ClawHub aktivieren
- VirusTotal-Report auf ClawHub-Seite prüfen
- Quellcode reviewen vor Installation

### Skill-Gating (Load-Time Filter)

Skills können Requirements definieren:

```json5
---
name: gemini
description: Use Gemini CLI for coding assistance
metadata:
  {
    "openclaw":
      {
        "emoji": "♊️",
        "requires": { "bins": ["gemini"], "env": ["GEMINI_API_KEY"] },
        "primaryEnv": "GEMINI_API_KEY",
        "install":
          [
            {
              "id": "brew",
              "kind": "brew",
              "formula": "gemini-cli",
              "bins": ["gemini"],
              "label": "Install Gemini CLI (brew)",
            },
          ],
      },
  }
---
```

**Gating-Fields:**
- `requires.bins` — Binary muss auf PATH existieren
- `requires.env` — Env-Var muss existieren ODER in Config gesetzt sein
- `requires.config` — `openclaw.json`-Pfad muss truthy sein
- `primaryEnv` — Env-Var für `skills.entries.<name>.apiKey`

**Wichtig bei Sandbox:**
- `requires.bins` wird auf dem HOST geprüft (Load-Time)
- In Sandbox muss Binary zusätzlich IM CONTAINER existieren
- Installiere via `agents.defaults.sandbox.docker.setupCommand`

### Config-Overrides

```json5
skills: {
  entries: {
    "my-skill": {
      enabled: true,
      apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" },
      env: { MY_VAR: "value" },
      config: { endpoint: "https://example.com" },
    },
  },
}
```

**Regeln:**
- `enabled: false` deaktiviert Skill (auch bundled)
- `env` wird nur injiziert wenn Var nicht bereits gesetzt
- `apiKey` kann Plaintext-String ODER SecretRef sein
- `allowBundled`: Allowlist für bundled Skills (managed/workspace Skills nicht betroffen)

---

## Sandbox-Konfiguration

Sandboxing isoliert Tool-Ausführung in Docker-Container.

### Was wird sandboxed?
- Tool-Execution (`exec`, `read`, `write`, `edit`, `apply_patch`, `process`)
- Optional: Sandbox-Browser (`agents.defaults.sandbox.browser.enabled`)

**Nicht sandboxed:**
- Gateway-Prozess selbst
- `tools.elevated` (läuft auf dem Host, bypasses Sandbox)

### Sandbox-Modes

| Mode | Verhalten |
|---|---|
| `off` | Kein Sandboxing |
| `non-main` | Nur nicht-main Sessions (Default für Normal-Chat auf Host) |
| `all` | Alle Sessions in Sandbox |

**Wichtig:** `non-main` basiert auf `session.mainKey` (default `"main"`), nicht Agent-ID. Gruppen/Channel-Sessions haben eigene Keys → werden sandboxed.

### Sandbox-Scope

| Scope | Container-Anzahl |
|---|---|
| `session` | Ein Container pro Session (Default) |
| `agent` | Ein Container pro Agent |
| `shared` | Ein Container für alle (keine Isolation!) |

### Sandbox-Backend

| Backend | Beschreibung |
|---|---|
| `docker` | Lokale Docker-Container (Default) |
| `ssh` | SSH-Remote-Server |
| `openshell` | OpenShell-Remote-Workspace |

### Workspace-Access

| Mode | Zugriff |
|---|---|
| `none` | Sandbox-Workspace unter `~/.openclaw/sandboxes` (Default) |
| `ro` | Agent-Workspace read-only unter `/agent` |
| `rw` | Agent-Workspace read/write unter `/workspace` |

### Sandbox-Config-Beispiel

```json5
agents: {
  defaults: {
    sandbox: {
      mode: "non-main",
      scope: "agent",
      workspaceAccess: "none",
      docker: {
        image: "openclaw-sandbox:bookworm-slim",
        network: "none",            // Kein Netzwerk (sicherste Option)
        readOnlyRoot: true,
        tmpfs: ["/tmp", "/var/tmp", "/run"],
        user: "1000:1000",
        capDrop: ["ALL"],
        pidsLimit: 256,
        memory: "1g",
        memorySwap: "2g",
        cpus: 1,
        setupCommand: "apt-get update && apt-get install -y git curl jq",
        // setupCommand braucht network != "none" + user: "0:0" für apt-get
      },
      prune: {
        idleHours: 24,     // Container >24h idle löschen
        maxAgeDays: 7,      // Container >7 Tage löschen
      },
    },
  },
}
```

### Sandbox-Images bauen

```bash
# Standard-Image
scripts/sandbox-setup.sh  # baut openclaw-sandbox:bookworm-slim

# Mit mehr Tooling (curl, jq, node, python, git)
scripts/sandbox-common-setup.sh  # baut openclaw-sandbox-common:bookworm-slim

# Browser-Image
scripts/sandbox-browser-setup.sh  # baut openclaw-sandbox-browser:bookworm-slim
```

### Tool-Policy (Allow/Deny)

```json5
tools: {
  sandbox: {
    tools: {
      allow: ["exec", "process", "read", "write", "edit", "sessions_list", "sessions_history"],
      deny: ["browser", "canvas", "nodes", "cron", "discord", "gateway"],
    },
  },
}
```

- `deny` gewinnt über `allow`
- Leeres `allow` = alle Tools (minus deny)
- Nicht-leeres `allow` = nur gelistete Tools (minus deny)

### SSH-Backend

```json5
agents: {
  defaults: {
    sandbox: {
      mode: "all",
      backend: "ssh",
      workspaceAccess: "rw",
      ssh: {
        target: "user@gateway-host:22",
        workspaceRoot: "/tmp/openclaw-sandboxes",
        identityFile: "~/.ssh/id_ed25519",
        // ODER SecretRefs:
        identityData: { source: "env", provider: "default", id: "SSH_IDENTITY" },
        certificateData: { source: "env", provider: "default", id: "SSH_CERTIFICATE" },
        knownHostsData: { source: "env", provider: "default", id: "SSH_KNOWN_HOSTS" },
      },
    },
  },
}
```

### Sandbox-Troubleshooting

| Problem | Ursache | Lösung |
|---|---|---|
| Image nicht gefunden | Nicht gebaut | `scripts/sandbox-setup.sh` |
| Container läuft nicht | Wird on-demand erstellt | Warten oder `openclaw sandbox list` |
| Permission denied in Sandbox | UID/GID mismatch | `docker.user` setzen oder Workspace chown |
| Tools nicht gefunden | PATH nicht in Sandbox | `docker.env.PATH` setzen |
| apt-get failed | Kein Netzwerk | `docker.network: "bridge"` + `readOnlyRoot: false` |

---

## API-Key-Management

```bash
# Keys NIE in Workspace-Dateien speichern!
# Keys NIE in öffentliche Repos pushen!

# Secrets-Check:
grep -r "sk-" ~/.openclaw/
grep -r "ANTHROPIC_API_KEY" ~/.openclaw/workspace/
# → Sollte nichts finden

# API-Spending-Limits beim Provider setzen!
# Heartbeat alle 30min kann $0.50-2.00/Tag kosten
```

---

## Betriebssystem-Härtung

```bash
# Eigenen User für OpenClaw anlegen
sudo adduser --system --home /home/openclaw openclaw

# Firewall (ufw)
sudo ufw default deny incoming
sudo ufw allow ssh
# Port 18789 NICHT freigeben (nur loopback!)

# Nicht als root betreiben!
# ssh openclaw@server, dann openclaw-Befehle
```

---

## Empfohlene Architektur für VPS

```
VPS (Contabo/Hetzner/DO)
├── Docker-Container: openclaw-gateway
│   ├── Non-root user (node)
│   ├── Gateway bind: loopback
│   └── Sandbox für Tools
├── ufw: nur SSH erlaubt
├── Tailscale: für Remote-Dashboard-Zugriff
└── Separater User: kein Zugriff auf Prod-Daten
```

---

## Verwandte Docs

- **Quick-Ref**: `references/quick-reference.md` — Security-Checkliste
- **Config**: `references/config-reference.md` — secrets.*, agents.* Schema
- **Docker**: `references/docker-setup.md` — Sandbox-Container Setup
- **Multi-Agent**: `references/multi-agent.md` — Per-Agent Sandbox & Tools
- **CLI**: `references/cli-reference.md` — `openclaw secrets`, `openclaw [REDACTED_SECRET]`


path: references/skills-guide.md
content: # Skills — Entwicklung, Installation & Sicherheit

## Skill-Typen

| Typ | Pfad | Beschreibung |
|---|---|---|
| Bundled | Im npm-Paket | Mitgelieferte Skills |
| Managed | `~/.openclaw/skills/` | Via ClawHub installiert |
| Workspace | `<workspace>/skills/` | Manuell erstellt, pro Agent |

**Präzedenz bei Namenskonflikten:**
`<workspace>/skills` (höchste) → `~/.openclaw/skills` → bundled skills (niedrigste)

Zusätzliche Skill-Ordner (niedrigste Präzedenz) via `skills.load.extraDirs` in `openclaw.json`.

---

## Multi-Agent & Shared Skills

- **Per-Agent-Skills** liegen in `<workspace>/skills` — nur für diesen Agent sichtbar
- **Shared-Skills** liegen in `~/.openclaw/skills` — für alle Agents auf dieser Maschine
- **Shared-Folders** via `skills.load.extraDirs` — gemeinsamer Skill-Pack für mehrere Agents

---

## ClawHub — Registry & Sync

ClawHub ist die öffentliche Skills-Registry: **https://clawhub.com**

### Installieren

```bash
# Skill suchen
clawhub search "memory"
clawhub search "calendar"

# Installieren (default: ./skills oder fallback workspace)
clawhub install <skill-slug>

# Update
clawhub update <skill-slug>
clawhub update --all

# Nach Installation: Skills neu laden
openclaw skills reload
# ODER Gateway neu starten (Skills sind erst in neuer Session aktiv!)
openclaw gateway restart

# Installierte Skills anzeigen
openclaw skills list
```

### Sync (Publish)

```bash
# Alle Skills scannen + Updates publishen
clawhub sync --all
```

---

## SKILL.md-Format (AgentSkills-kompatibel)

### Minimales Frontmatter

```markdown
---
name: mein-skill
description: Beschreibung was der Skill tut und wann er getriggert werden soll.
---
```

**Pflichtfelder:**
- `name` — Nur Buchstaben, Zahlen, Bindestriche
- `description` — Wann der Skill aktiviert werden soll (Trigger-Phrasen)

**Wichtig:** Der Parser unterstützt **nur Single-Line** Frontmatter-Keys.

### Volles Frontmatter mit Metadata

```markdown
---
name: image-lab
description: Generate or edit images via a provider-backed image workflow
metadata:
  {
    "openclaw":
      {
        "emoji": "🖼️",
        "requires": { "bins": ["uv"], "env": ["GEMINI_API_KEY"], "config": ["browser.enabled"] },
        "primaryEnv": "GEMINI_API_KEY",
        "os": ["darwin", "linux"],
        "homepage": "https://example.com/skill",
        "always": false,
        "install":
          [
            {
              "id": "brew",
              "kind": "brew",
              "formula": "ripgrep",
              "bins": ["rg"],
              "label": "Install ripgrep (brew)",
            },
          ],
      },
  }
---
```

### Metadata-Felder (`metadata.openclaw`)

| Feld | Typ | Beschreibung |
|---|---|---|
| `always` | boolean | Skill immer laden (skip andere Gates) |
| `emoji` | string | Emoji für macOS Skills UI |
| `homepage` | string | URL für "Website" in macOS Skills UI |
| `os` | string[] | Plattform-Filter: `darwin`, `linux`, `win32` |
| `requires.bins` | string[] | Binaries, die auf PATH existieren müssen |
| `requires.anyBins` | string[] | Mindestens eines muss existieren |
| `requires.env` | string[] | Env-Vars, die existieren ODER in Config gesetzt sein müssen |
| `requires.config` | string[] | `openclaw.json`-Pfade, die truthy sein müssen |
| `primaryEnv` | string | Env-Var für `skills.entries.<name>.apiKey` |
| `install` | array | Installer-Specs für macOS Skills UI |

### Optional User-Invocable Flags

| Flag | Default | Beschreibung |
|---|---|---|
| `user-invocable` | `true` | Skill als `/slash-command` verfügbar |
| `disable-model-invocation` | `false` | Skill nicht im Model-Prompt laden |
| `command-dispatch` | — | `tool` für direkten Tool-Dispatch |
| `command-tool` | — | Tool-Name für `command-dispatch: tool` |
| `command-arg-mode` | `raw` | Args-Handling für Tool-Dispatch |

### Verzeichnis-Struktur

```
mein-skill/
├── SKILL.md           # Pflicht: Anweisungen
├── scripts/           # Optional: Ausführbare Skripte
├── references/        # Optional: Referenz-Dokumente
└── assets/            # Optional: Templates, Icons
```

### Workspace-Skills erstellen

```bash
mkdir -p ~/.openclaw/workspace/skills/mein-skill
# SKILL.md dort anlegen
openclaw skills reload
```

---

## Skill-Gating (Load-Time Filter)

OpenClaw filtert Skills beim Laden basierend auf `metadata.openclaw.requires`:

### Requirements-Check

```json5
{
  "requires": {
    "bins": ["uv", "python3"],        // Alle müssen auf PATH sein
    "anyBins": ["node", "bun"],      // Mindestens eines muss existieren
    "env": ["GEMINI_API_KEY"],       // Env-Var muss existieren oder in Config
    "config": ["browser.enabled"],   // openclaw.json-Pfad muss truthy sein
  },
}
```

**Wichtig bei Sandbox:**
- `requires.bins` wird auf dem HOST geprüft (Load-Time)
- In Sandbox muss Binary zusätzlich IM CONTAINER existieren
- Installiere via `agents.defaults.sandbox.docker.setupCommand`
- `setupCommand` braucht: `network != "none"`, `readOnlyRoot: false`, `user: "0:0"`

### Installer-Specs

```json5
{
  "install":
    [
      {
        "id": "brew",
        "kind": "brew",
        "formula": "ripgrep",
        "bins": ["rg"],
        "label": "Install ripgrep (brew)",
      },
      {
        "id": "npm",
        "kind": "node",
        "package": "typescript",
        "bins": ["tsc"],
        "label": "Install TypeScript (npm)",
      },
      {
        "id": "download",
        "kind": "download",
        "url": "https://example.com/binary",
        "archive": "tar.gz",
        "targetDir": "~/.openclaw/tools/my-skill",
      },
    ],
}
```

**Installer-Logik:**
- Gateway wählt EINEN bevorzugten Installer (brew > node > go > download)
- Mehrere `download`-Specs werden alle gelistet
- `os: ["darwin"]` filtert Optionen nach Plattform
- `skills.install.nodeManager` in Config: `npm` (default), `pnpm`, `yarn`, `bun`

---

## Config-Overrides

```json5
{
  skills: {
    install: {
      nodeManager: "pnpm",  // npm | pnpm | yarn | bun
    },
    load: {
      extraDirs: ["/path/to/shared/skills"],
      watch: true,
      watchDebounceMs: 250,
    },
    entries: {
      "my-skill": {
        enabled: true,
        apiKey: { source: "env", provider: "default", id: "MY_API_KEY" },
        env: { MY_VAR: "value" },
        config: { endpoint: "https://example.com" },
      },
      "peekaboo": { enabled: true },
      "sag": { enabled: false },
    },
    allowBundled: ["skill-one", "skill-two"],  // Optional: bundled-Skills-Allowlist
  },
}
```

**Regeln:**
- `enabled: false` deaktiviert Skill (auch bundled)
- `env` wird nur injiziert wenn Var nicht bereits gesetzt
- `apiKey` kann Plaintext-String ODER SecretRef sein
- `config`: Custom-Fields für Per-Skill-Konfig
- `allowBundled`: Allowlist für bundled Skills (managed/workspace Skills nicht betroffen)

---

## Environment-Injection (Per-Agent-Run)

Beim Start eines Agent-Runs:
1. Skill-Metadaten lesen
2. `skills.entries.<key>.env` und `apiKey` auf `process.env` anwenden
3. System-Prompt mit **eligible** Skills bauen
4. Originale Environment nach Run-Ende wiederherstellen

**Scoped to Agent-Run**, nicht global!

---

## Session-Snapshot (Performance)

OpenClaw snapshottet **eligible Skills beim Session-Start** und re-used die Liste für folgende Turns in der gleichen Session.

Änderungen an Skills oder Config greifen in der nächsten neuen Session.

Skills können auch mid-Session refreshen (Skills Watcher oder neuer Remote-Node).

---

## Remote macOS Nodes (Linux Gateway)

Wenn Gateway auf Linux läuft, aber ein macOS Node verbunden ist mit `system.run` erlaubt:
- macOS-only Skills werden als eligible behandelt, wenn Binary auf Node existiert
- Agent führt Skills via `nodes` tool aus (`nodes.run`)
- Skills bleiben sichtbar wenn Node offline geht; Invocations schlagen fehl bis Reconnect

---

## Security-Hinweise

### Risiko-Bewertung

- **26% der Community-Skills** enthalten mind. eine Schwachstelle (Cisco)
- Risiken: Prompt-Injections, Tool-Poisoning, versteckte Malware in `scripts/`
- Unsichere Datenverarbeitung

### Schutzmaßnahmen

1. **Quellcode reviewen** vor Installation
2. **ClawHub "Hide Suspicious"** aktivieren
3. **VirusTotal-Report** auf ClawHub-Seite prüfen
4. **Code in Claude einfügen** und nach Risiken fragen
5. **Sandbox nutzen**: `agents.defaults.sandbox.mode: "non-main"`
6. **Nur verifizierte Skills** von bekannten Autoren installieren

### Secret-Handling

```json5
// Env-Injection läuft im HOST-Prozess (nicht Sandbox!)
skills: {
  entries: {
    "my-skill": {
      apiKey: { source: "env", provider: "default", id: "MY_API_KEY" },
      // NICHT in prompts/logs verwenden!
    },
  },
}
```

---

## Token-Impact (Skills List)

Eligible Skills werden als kompakte XML-Liste in den System-Prompt injiziert.

**Kosten-Formel (Zeichen):**
```
total = 195 + Σ (97 + len(name_escaped) + len(description_escaped) + len(location_escaped))
```

**Beispiel:**
- Base overhead: 195 Zeichen
- Per Skill: 97 Zeichen + XML-escaped Feldlängen
- ~97 Zeichen ≈ 24 Tokens (OpenAI-style Tokenizer)

---

## Skills Watcher (Auto-Refresh)

```json5
skills: {
  load: {
    watch: true,
    watchDebounceMs: 250,
  },
}
```

Watcht Skill-Folder und updated Snapshot bei `SKILL.md`-Änderungen.

---

## CLI-Referenz

```bash
# Skills auflisten
openclaw skills list

# Skills neu laden (nach Installation)
openclaw skills reload

# ClawHub
clawhub search <query>
clawhub install <slug>
clawhub update <slug>
clawhub update --all
clawhub sync --all
```

---

## Troubleshooting

| Problem | Lösung |
|---|---|
| Skill nicht sichtbar | `openclaw skills list` → SKILL.md-Format prüfen (name + description im YAML) |
| Skill nicht aktiv nach Installation | `openclaw gateway restart` (Skills erst in neuer Session!) |
| Nur 1 von 6 Skills registriert | YAML-Syntax-Fehler (Doppelpunkt in description escapen) |
| Binary nicht gefunden in Sandbox | `setupCommand` mit `network: "bridge"`, `readOnlyRoot: false`, `user: "0:0"` |
| `requires.bins` Check schlägt fehl | Binary auf HOST vorhanden? In Sandbox separat installieren |
| Skill disabled trotz Config | `enabled: true` explizit setzen |
| Env nicht injiziert | Var bereits in `process.env`? Check: `skills.entries.<name>.env` |

---

## Verwandte Docs

- **Quick-Ref**: `references/quick-reference.md` — Skills-CLI Einzeiler
- **Config**: `references/config-reference.md` — skills.* Schema
- **Security**: `references/security-hardening.md` — Skill Security & Gating
- **CLI**: `references/cli-reference.md` — `openclaw skills` und `clawhub` Befehle

path: references/tailscale-integration.md
content: # Tailscale-Integration — Remote-Zugriff richtig konfigurieren

## Überblick: Drei Zugriffsmodi

| Modus | Wer kann zugreifen | HTTPS | Config |
|---|---|---|---|
| `serve` (empfohlen) | Nur Tailnet-Geräte | ✅ automatisch | `tailscale.mode: "serve"` |
| `funnel` (vorsicht!) | Öffentliches Internet | ✅ automatisch | `tailscale.mode: "funnel"` + Password |
| `tailnet` bind | Tailnet-Geräte | ❌ manuell | `gateway.bind: "tailnet"` |
| SSH-Tunnel | Wer SSH-Zugang hat | ❌ | Kein Config nötig |

**Empfehlung für 99% der Fälle: `serve`**

---

## Tailscale Serve (Tailnet-only, empfohlen)

Gateway bleibt auf `127.0.0.1`, Tailscale proxied HTTPS-Traffic.
Nur Geräte im selben Tailnet können zugreifen.

### Config
```json5
{
  gateway: {
    bind: "loopback",
    tailscale: {
      mode: "serve",
      resetOnExit: false,     // true = tailscale serve reset bei Shutdown
    },
    auth: {
      mode: "token",
      [REDACTED_SECRET]",
      allowTailscale: true,   // Tailscale-Identity-Auth erlauben
    },
  },
}
```

### CLI-Alternative
```bash
openclaw gateway --tailscale serve
```

### Zugriff
```
https://<hostname>.your-tailnet.ts.net
```

### Auth-Optionen bei Serve
- **allowTailscale: true** → Tailscale-User werden automatisch erkannt (kein Token nötig)
- **allowTailscale: false** → Token/Password trotzdem erforderlich
- OpenClaw verifiziert Tailscale-Identity über `tailscale whois` + Header-Prüfung

---

## Tailscale Funnel (öffentlich, VORSICHT!)

Macht den Gateway über das öffentliche Internet erreichbar.
**Nur nutzen wenn wirklich nötig!**

### Config
```json5
{
  gateway: {
    bind: "loopback",
    tailscale: {
      mode: "funnel",
    },
    auth: {
      mode: "password",       // PFLICHT bei Funnel!
      [REDACTED_SECRET]",
    },
  },
}
```

**Besser**: Password über Environment-Variable:
```bash
export OPENCLAW_GATEWAY_PASSWORD="starkes-passwort-hier"
```

### CLI-Alternative
```bash
openclaw gateway --tailscale funnel --auth password
```

### Funnel-Voraussetzungen
- Tailscale v1.38.3+
- MagicDNS aktiviert
- HTTPS aktiviert für das Tailnet
- `funnel` Node-Attribut gesetzt
- Nur Ports 443, 8443, 10000 (TLS)
- macOS: Open-Source Tailscale App-Variante nötig

### Sicherheits-Hinweis
- **Funnel injiziert KEINE Identity-Headers** (anders als Serve)
- Deshalb: Password-Auth PFLICHT
- Funnel weigert sich zu starten ohne `auth.mode: "password"`

---

## Direct Tailnet Bind (ohne Serve/Funnel)

Gateway hört direkt auf der Tailscale-IP — kein HTTPS, kein Proxy.

```json5
{
  gateway: {
    bind: "tailnet",          // Bindet auf Tailscale-IP
    auth: {
      mode: "token",
      [REDACTED_SECRET]",
    },
  },
}
```

### Zugriff
```
http://<tailscale-ip>:18789
ws://<tailscale-ip>:18789
```

**Achtung**: `http://127.0.0.1:18789` funktioniert in diesem Modus NICHT!

---

## SSH-Tunnel (ohne Tailscale-Config)

Kein Config-Change nötig — Gateway bleibt auf loopback:

```bash
# Von deinem Laptop:
ssh -L 18789:127.0.0.1:18789 user@vps-ip

# Dann lokal zugreifen:
# http://127.0.0.1:18789
```

### Permanenter SSH-Tunnel (systemd)
```bash
# ~/.config/systemd/user/openclaw-ssh-tunnel.service
[Unit]
Description=OpenClaw SSH Tunnel
After=network-online.target

[Service]
ExecStart=/usr/bin/ssh -N -L 18789:127.0.0.1:18789 user@vps-ip
Restart=always
RestartSec=10

[Install]
WantedBy=default.target
```

```bash
systemctl --user enable --now openclaw-ssh-tunnel
```

**Wichtig**: Auch über SSH-Tunnel muss `gateway.auth.token` gesetzt sein!

---

## Praxis-Szenario: VPS + Tailscale + Nodes

### Setup-Reihenfolge

#### 1. Tailscale auf VPS installieren
```bash
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --ssh    # Optional: SSH über Tailscale
tailscale ip -4            # IP notieren
tailscale status           # Prüfen
```

#### 2. Tailscale auf allen Nodes installieren
```bash
# MacBook:
brew install tailscale
# iPhone/Android: App Store / Play Store
# Raspberry Pi:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
```

#### 3. Gateway konfigurieren
```json5
// Auf dem VPS: ~/.openclaw/openclaw.json
{
  gateway: {
    bind: "loopback",
    tailscale: { mode: "serve" },
    auth: {
      mode: "token",
      [REDACTED_SECRET]",
      allowTailscale: true,
    },
  },
}
```

```bash
systemctl --user restart openclaw-gateway
```

#### 4. Dashboard testen
```
https://<vps-hostname>.your-tailnet.ts.net
```
→ Token eingeben → Dashboard sollte laden

#### 5. macOS Node verbinden
- OpenClaw macOS App → Settings → Gateway
- URL: `https://<vps-hostname>.your-tailnet.ts.net`
- Verbinden → Pairing-Request

#### 6. Pairing genehmigen
```bash
# Auf VPS:
openclaw devices list
openclaw devices approve <requestId>
```

#### 7. Verifizieren
```bash
openclaw nodes status        # Node connected?
openclaw channels status --probe  # Channels OK?
```

---

## Troubleshooting Tailscale

| Problem | Lösung |
|---|---|
| "Serve requires HTTPS" | HTTPS im Tailscale Admin Panel aktivieren |
| Funnel startet nicht | Password-Auth fehlt, oder Tailscale < v1.38.3 |
| Node findet Gateway nicht | `tailscale status` auf beiden Seiten prüfen |
| "device identity required" | HTTPS nötig — SSH-Tunnel oder Tailscale Serve nutzen |
| Dashboard nicht erreichbar | `tailscale serve status` prüfen, Firewall checken |
| allowTailscale funktioniert nicht | Nur bei `serve` Mode, nicht bei `funnel` |

### Diagnose-Befehle
```bash
tailscale status                  # Tailscale-Verbindung prüfen
tailscale serve status            # Serve-Config anzeigen
tailscale ping <hostname>         # Erreichbarkeit testen
tailscale whois <ip>              # Identity prüfen
```


path: references/tricks-and-hacks.md
content: # Tricks & Hacks — Power-User-Tipps

## Kosten-Optimierung

### Token-Verbrauch senken
```json5
agent: {
  heartbeat: {
    every: "6h",     // Statt "30m" → spart 90%+ der Heartbeat-Kosten
  },
},
agents: {
  defaults: {
    compaction: {
      mode: "safeguard",       // Kompaktiert intelligent
      reserveTokensFloor: 20000,
    },
  },
}
```

### Hybrid-Modell-Strategie
- **Heartbeat + Simple Tasks**: Günstiges lokales Model (Ollama/llama3.2)
- **Komplexe Aufgaben**: Claude Sonnet/Opus via API
- **ACHTUNG**: heartbeat.model Bug kann in main-Session bluten (Issue #22133)

### Zero-Token-Wartung
Direkt per SSH/VS Code Dateien bearbeiten statt Bot-Befehle:
```bash
# SSH-Zugriff für Cursor/VS Code:
# File → New Window → Connect with SSH → user@server
# Dann SOUL.md, Skills, Configs direkt editieren = 0 Token-Kosten
```

---

## Produktivitäts-Hacks

### Web-Prototyping on the go
```
Prompt an Bot: "Recherchiere X, mach mir eine HTML-Seite und hoste sie auf Surge"
```
→ Bot erstellt und deployed eine Webseite, teilbar per Link

### Obsidian-Integration
- Obsidian Vault ($5/mo) auf OpenClaw-Maschine einrichten
- Agent kann in Vault lesen und schreiben
- Persönlicher Knowledge-Graph + Task-Management per Chat
→ WhatsApp/Voicenote → Agent durchsucht Vault → Antwort

### Session-Management
```
/status    — Was läuft gerade? (Model, Tokens, Kosten)
/new       — Frische Session (bei verwirrendem Kontext)
/compact   — Manuell kompaktieren (bei langer Session)
```

### Memory-Tricks
```
# Explizit Memory schreiben lassen:
"Merke dir in USER.md, dass ich kurze Antworten mit Code-Beispielen will"
"Schreibe in MEMORY.md: Projekt X nutzt Docker Compose auf Contabo"
"Aktualisiere memory/ mit der heutigen Entscheidung zu Y"

# Memory-Review forcieren:
"Lies MEMORY.md und entferne alles was veraltet ist"
"Konsolidiere die letzten 7 Tage aus memory/ in MEMORY.md"
```

---

## Fortgeschrittene Config-Tricks

### Mehrere Workspaces testen
```bash
# Workspace-A für Produktion, Workspace-B zum Testen
cp -r ~/.openclaw/workspace ~/.openclaw/workspace-test
# In openclaw.json temporär umschalten:
# agents.defaults.workspace: "~/.openclaw/workspace-test"
# ACHTUNG: Nur EIN aktiver Workspace — sonst State-Drift!
```

### Custom System-Prompt über AGENTS.md
```markdown
# In AGENTS.md hinzufügen:
## Antwort-Format
- Immer zuerst eine Zusammenfassung in einem Satz
- Dann technische Details
- Code-Beispiele mit Kommentaren
- Sprache: Deutsch, Tech-Begriffe auf Englisch OK
```

### Crash-Recovery-Watchdog
```bash
# systemd-Watchdog (automatischer Neustart bei Crash):
# ~/.config/systemd/user/openclaw-gateway.service
[Service]
Restart=always
RestartSec=10
WatchdogSec=300
```

### Logging nach Supabase
- Supabase Free-Tier als Logging-Backend
- Dashboard zeigt jede Interaktion
- Kosten-Monitoring bei API-Key-Kompromittierung
- Bot kann Supabase-Setup selbst konfigurieren

---

## Workspace Git-Workflow

```bash
# Automatisches Backup nach jeder Änderung
cd ~/.openclaw/workspace

# .gitignore für sensible Daten
cat > .gitignore << 'EOF'
# Keine Credentials committen!
*.key
*.token
*.secret
EOF

# Pre-Commit-Hook für automatische Backups
cat > .git/hooks/post-commit << 'EOF'
#!/bin/bash
git push origin main 2>/dev/null || true
EOF
chmod +x .git/hooks/post-commit
```

---

## Nützliche Einzeiler

```bash
# Alle aktiven Sessions mit Kosten anzeigen
openclaw sessions list

# Config-Diff nach Änderung
diff ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak

# Memory-Größe prüfen
wc -l ~/.openclaw/workspace/MEMORY.md
du -sh ~/.openclaw/workspace/memory/

# Alte Memory-Dateien aufräumen (älter als 30 Tage)
find ~/.openclaw/workspace/memory/ -name "*.md" -mtime +30 -ls

# Gateway-Health-Check (API)
curl -s http://127.0.0.1:18789/health

# Alle Channels auf einmal testen
openclaw channels status --probe

# Exposed Secrets finden
grep -rn "sk-\|api_key\|token\|secret" ~/.openclaw/workspace/ --include="*.md"
```

---

## Integration mit anderen Tools

### n8n-Webhooks
- OpenClaw kann Webhooks empfangen/senden
- n8n-Workflow → Webhook → OpenClaw verarbeitet → Antwort an Channel
- Nützlich für: E-Mail-Zusammenfassungen, RSS-Alerts, Monitoring

### Tailscale für Remote-Zugriff
```json5
gateway: {
  mode: "tailscale",
  bind: "tailscale",    // Nur über Tailscale-Netzwerk erreichbar
}
```
→ Dashboard + WebChat von überall erreichbar, aber sicher

### Docker Model Runner (komplett lokale LLMs)
```bash
# Docker Model Runner + OpenClaw in Docker Sandbox
# = 0 API-Kosten, volle Privatsphäre
docker model pull llama3.2:latest
# OpenClaw zeigt alle Docker Model Runner Modelle automatisch
```

---

## "Erste Woche"-Leitfaden

1. **Tag 1-2**: Nur chatten. Wetter fragen, Artikel zusammenfassen, Smalltalk.
2. **Tag 3**: SOUL.md und USER.md anpassen. Ton und Präferenzen definieren.
3. **Tag 4**: Erste echte Aufgabe: E-Mail-Draft, Code-Review, Recherche.
4. **Tag 5**: HEARTBEAT.md einrichten. Regelmäßige Check-ins definieren.
5. **Tag 6**: Memory-System testen. "Merke dir X", am nächsten Tag prüfen.
6. **Tag 7**: Ersten Custom-Skill erstellen oder ClawHub-Skill installieren.

→ Nach einer Woche Korrekturen klingt dein Agent komplett anders als am Anfang.
   **Das ist der Punkt.**

---

## Bekannte Gotchas (Stand 02/2026)

1. **heartbeat.model Bug** → Kann main-Session-Model überschreiben (#22133)
2. **Skills nur in neuer Session** → Nach install/reload: Gateway restart ODER /new
3. **Mehrere Workspaces** → `openclaw doctor` warnt, nur einen aktiv halten
4. **WhatsApp DM-Policy** → Global pro Account, nicht pro Agent
5. **MEMORY.md in Groups** → Sollte nie passieren, falls doch: Update + Doctor
6. **Docker macOS** → Langsamer als npm direkt, nur nutzen wenn Isolation nötig
7. **Context-Window** → Heartbeat kann mit 16k Model Context-Compaction-Loop auslösen
8. **Supabase-Leak (historisch)** → Moltbook-Incident Januar 2026, inzwischen gefixt


path: references/troubleshooting.md
content: # Troubleshooting — Häufige Probleme & Lösungen

## Diagnose-Grundlagen

```bash
# IMMER zuerst:
openclaw --version
openclaw doctor
openclaw doctor --run doctor    # DM-Policy-Check
openclaw doctor --run security  # Security-Audit
openclaw status

# Logs lesen:
journalctl --user -u openclaw-gateway -n 50 --no-pager
# oder:
tail -n 120 /tmp/openclaw-gateway.log
# Docker:
docker compose logs -f openclaw-gateway

# Deep Health (Gateway + Channels):
openclaw health --token "$OPENCLAW_GATEWAY_TOKEN"
```

---

## Gateway startet nicht nach Config-Änderung

```bash
# 1. Config validieren
openclaw doctor

# 2. JSON5-Syntax prüfen
node -e "require('fs').readFileSync(process.env.HOME+'/.openclaw/openclaw.json','utf8')" && echo "OK"

# 3. Logs analysieren
journalctl --user -u openclaw-gateway -n 50 --no-pager
tail -n 120 /tmp/openclaw-gateway.log

# 4. Port belegt?
ss -ltnp | grep 18789

# 5. Backup wiederherstellen
cp ~/.openclaw/openclaw.json.bak ~/.openclaw/openclaw.json
systemctl --user restart openclaw-gateway
```

**Häufigste Ursache**: Unbekannter Key oder falscher Typ in openclaw.json.
JSON5 erlaubt Kommentare, aber keine unbekannten Felder!

---

## "systemctl --user unavailable"

```bash
# Falsch: Als root eingeloggt
# Richtig: Als openclaw-User einloggen
ssh openclaw@<server-ip>

# Dann:
openclaw gateway install
systemctl --user start openclaw-gateway
systemctl --user enable openclaw-gateway

# Wenn lingering fehlt:
loginctl enable-linger openclaw
```

---

## Modell hinzufügen schlägt fehl

```bash
# Fallstricke:
# 1. "id" muss "provider/model-name" Format haben
# 2. Bei OpenRouter-Style IDs: Provider-Prefix dazu!
#    z.B. "openrouter/moonshotai/kimi-k2"
# 3. "api": "openai-completions" vs "openai-responses" (versionsabhängig!)
# 4. "contextWindow" und "maxTokens" müssen Zahlen sein, keine Strings!
# 5. Ollama in Docker: baseUrl = "http://host.docker.internal:11434"
```

---

## Node verbindet nicht

```bash
openclaw nodes status
openclaw channels status --probe

# Gateway muss von Node erreichbar sein:
# - Tailscale: gateway.bind auf "tailscale" setzen
# - Lokales Netz: gateway.bind auf "lan" (nur mit VPN!)
# - Port 18789 muss erreichbar sein
```

---

## Skills werden nicht geladen

```bash
# Skills erst in neuer Session aktiv!
openclaw gateway restart

# Dann prüfen:
openclaw skills list

# Skill-Verzeichnisse prüfen:
ls ~/.openclaw/workspace/skills/    # Workspace-Skills
ls ~/.openclaw/skills/              # Managed-Skills

# Nur 1 von N Skills sichtbar?
# → SKILL.md prüfen:
#   - YAML-Frontmatter mit name + description?
#   - Kein Syntax-Fehler im YAML?
#   - Doppelpunkte in description mit Quotes escapen!
```

---

## Heartbeat-Probleme

### Heartbeat-Model-Bug (Issue #22133)
```
Symptom: Main-Session plötzlich mit 16k Context statt 200k
Ursache: heartbeat.model überschreibt main-Session-Model
Fix: heartbeat.model entfernen oder auf gleiches Model setzen
Workaround: /new in Telegram → Modell wird zurückgesetzt
```

### Heartbeat verbraucht zu viele Tokens
```json5
agent: {
  heartbeat: {
    every: "6h",       // Von "30m" auf "6h" reduzieren
    // oder:
    every: "off",      // Heartbeat komplett deaktivieren
  },
}
```

---

## Memory-Probleme

### Memory wird nicht gefunden
```bash
# memorySearch aktiv?
openclaw config get agents.defaults.memorySearch.enabled

# Embedding-Provider konfiguriert?
# Auto-Detect: local → openai → gemini
# Manuell prüfen: API-Key für Embeddings vorhanden?

# Erster Aufruf langsam → QMD lädt GGUF-Modelle herunter
```

### Memory geht bei Compaction verloren
```json5
// memoryFlush aktivieren:
agents: {
  defaults: {
    compaction: {
      memoryFlush: { enabled: true },
    },
  },
}
```

### MEMORY.md wird in Gruppen geladen (Datenschutz!)
→ Das sollte NICHT passieren. MEMORY.md wird nur in privaten Sessions geladen.
Falls doch: `openclaw doctor` + Version updaten.

---

## WhatsApp-Probleme

| Problem | Lösung |
|---|---|
| QR-Code abgelaufen | `openclaw channels login` erneut |
| Bot antwortet nicht | `openclaw channels status --probe` |
| Fremde können schreiben | `dmPolicy: "allowlist"` + `allowFrom` prüfen |
| Bot in Gruppen zu geschwätzig | Gruppen-Verhalten in AGENTS.md regeln |

---

## Performance-Probleme

| Problem | Lösung |
|---|---|
| Langsame Antworten | Model-Latenz prüfen, ggf. kleineres Model |
| Hohe Kosten | Heartbeat-Intervall erhöhen, günstigeres Model |
| Docker langsam auf macOS | npm-Installation statt Docker nutzen |
| Context-Compaction zu häufig | Größeres Model-Context-Window nutzen |
| Memory-Search langsam | Erster Aufruf = Model-Download, danach schneller |

---

## Notfall: Komplett zurücksetzen

```bash
# 1. Gateway stoppen
systemctl --user stop openclaw-gateway

# 2. Backup (!)
tar czf ~/openclaw-emergency-backup-$(date +%Y%m%d).tar.gz ~/.openclaw/

# 3. Config zurücksetzen
openclaw onboard    # Wizard erneut durchlaufen

# 4. Oder: Backup-Config wiederherstellen
cp ~/.openclaw/openclaw.json.bak ~/.openclaw/openclaw.json

# 5. Neu starten
systemctl --user start openclaw-gateway
openclaw doctor
```

---

## SecretRef-Probleme

### "Secret provider not found"

```bash
# Provider-Config prüfen:
openclaw secrets configure --providers-only

# Testen:
openclaw secrets reload

# Audit:
openclaw secrets audit --check
```

**Häufige Ursachen:**
- Fehlender `secrets.providers` Block in Config
- `provider`-Name nicht registriert
- `exec`-Kommando nicht ausführbar

### "Environment variable not found"

```json5
// Falsch:
{ source: "env", provider: "default", id: "openai_api_key" }  // Kleinbuchstaben

// Richtig:
{ source: "env", provider: "default", id: "OPENAI_API_KEY" }  // GROSSBUCHSTABEN
```

### Exec-SecretRef mit 1Password

```json5
secrets: {
  providers: {
    onepassword: {
      source: "exec",
      command: "/opt/homebrew/bin/op",
      args: ["read", "op://Vault/Item/field"],
      allowSymlinkCommand: true,  // Für Homebrew-Shims
    },
  },
}
```

---

## Sandbox-Probleme

### Container startet nicht

```bash
# Image prüfen:
docker images | grep openclaw-sandbox

# Fehlt? Nachbauen:
scripts/sandbox-setup.sh  # Standard
scripts/sandbox-common-setup.sh  # Mit Tooling
```

### Permission denied in Sandbox

```bash
# UID/GID mismatch
# Option 1: Container-User auf Host-User setzen
docker.user: "1000:1000"

# Option 2: Workspace beschreibbar
sudo chown -R 1000:$(id -g) ~/.openclaw/workspace
```

### Tools nicht gefunden in Sandbox

```json5
// setupCommand braucht Netzwerk + Root:
sandbox: {
  docker: {
    network: "bridge",      // Nicht "none"!
    readOnlyRoot: false,    // Für apt-get
    user: "0:0",            // Root für setup
    setupCommand: "apt-get update && apt-get install -y git curl jq",
  },
}
```

### Sandbox-Pod läuft nicht

```bash
# Status prüfen:
openclaw sandbox list
openclaw sandbox status

# Logs:
journalctl --user -u openclaw-gateway -n 100 | grep -i sandbox
```

---

## Skill-Gating-Probleme

### Skill wird nicht geladen

```bash
# Skill-Status prüfen:
openclaw skills list

# Wenn fehlt, SKILL.md prüfen:
# - YAML-Frontmatter mit name + description?
# - Kein Syntax-Fehler im YAML?
# - description darf KEINE Doppelpunkte ohne Quotes haben!
```

**YAML-Fehler-Beispiel:**
```markdown
# FALSCH:
---
name: my-skill
description: Use when X, Y: Z  ← Doppelpunkt ohne Quotes!
---

# RICHTIG:
---
name: my-skill
description: "Use when X, Y: Z"
---
```

### "requires.bins" nicht erfüllt

```json5
// Skill braucht Binary auf HOST und in Sandbox:
// 1. Host-Check: Binary auf PATH?
which uv

// 2. Sandbox: In setupCommand installieren
sandbox: {
  docker: {
    network: "bridge",
    readOnlyRoot: false,
    user: "0:0",
    setupCommand: "apt-get update && apt-get install -y curl && curl -LsSf https://astral.sh/uv/install.sh | sh",
  },
}
```

---

## Multi-Agent-Probleme

### Bindings greifen nicht

```bash
# Bindings auflisten:
openclaw agents list --bindings

# Häufige Fehler:
# - accountId vergessen (Default-Account wird angenommen)
# - peer-Format falsch (Channel-spezifisch)
# - Reihenfolge: Spezifische Bindings zuerst!
```

### Agent wird nicht gefunden

```json5
// Falsch: Kein default-Agent
agents: { list: [{ id: "work", ... }] }

// Richtig: Default-Agent markieren
agents: { list: [{ id: "main", default: true, ... }, { id: "work", ... }] }
```

### Credentials teilen

**Auth-Profile sind per-Agent!**

```bash
# Credential kopieren (manuell):
cp ~/.openclaw/credentials/anthropic/default \
   ~/.openclaw/agents/work/agent/credentials/anthropic/default
```

---

## Model-Provider-Probleme

### "Model not found"

```json5
// Falsches Format:
models: { default: "claude-sonnet-4" }  // Fehlt Provider!

// Richtig:
models: { default: "anthropic/claude-sonnet-4-20250514" }

// OpenRouter mit Provider-Prefix:
models: {
  providers: {
    openrouter: { baseUrl: "https://openrouter.ai/api", api: "openai-completions" },
  },
  default: [REDACTED_SECRET],  // Provider-Prefix!
}
```

### Ollama in Docker

```json5
models: {
  providers: {
    ollama: {
      // macOS Docker Desktop:
      baseUrl: "http://host.docker.internal:11434",
      // Linux:
      // baseUrl: "http://172.17.0.1:11434",
      api: "openai-completions",
    },
  },
}
```

---

## Docker-Specific

### Build OOM (Exit 137)

```bash
# Mindestens 2GB RAM für Build
# Option 1: Swap erhöhen
# Option 2: Mit mehr RAM bauen
```

### Container nicht erreichbar

```bash
# Bind-Adresse prüfen:
docker compose exec openclaw-gateway env | grep BIND

# LAN-Access:
# gateway.bind: "lan" in docker-compose.yml oder OPENCLAW_GATEWAY_BIND=lan
```

### QR nicht angezeigt

```bash
# Dashboard → Channels → WhatsApp QR
# ODER:
openclaw channels login --channel whatsapp --qr terminal
```

---

## Performance-Optimierung

| Problem | Lösung |
|---------|--------|
| Langsame Antworten | Kleineres Model für heartbeat |
| Hohe API-Kosten | `heartbeat.every: "6h"` statt `"30m"` |
| Docker langsam auf macOS | npm-Installation statt Docker |
| Context-Compaction-Loop | Größeres contextWindow oder `compaction.maxTokens` erhöhen |
| Memory-Search langsam | Erster Aufruf = Model-Download (~5min) |
| Skills-Token-Overhead | Unnötige Skills deaktivieren (`enabled: false`) |


path: references/workspace-files.md
content: # Workspace-Dateien — Templates & Best Practices

> Alle Dateien unter `~/.openclaw/workspace/` werden bei jedem Session-Start geladen.
> `MEMORY.md` nur in privaten Sessions, nie in Gruppen.

## Datei-Übersicht

| Datei | Geladen | Zweck |
|---|---|---|
| AGENTS.md | Jede Session | Betriebsanweisungen, Regeln, Prioritäten |
| SOUL.md | Jede Session | Persönlichkeit, Ton, Grenzen |
| USER.md | Jede Session | Nutzerprofil, Anrede, Präferenzen |
| TOOLS.md | Jede Session | Tool-spezifische Hinweise |
| IDENTITY.md | Jede Session | Name, Emoji, Vibe |
| HEARTBEAT.md | Jeder Heartbeat | Scheduled-Tasks-Checkliste |
| MEMORY.md | Nur privat | Langzeit-Gedächtnis (kuratiert, ~100 Zeilen) |
| BOOTSTRAP.md | Einmalig | Erstes Setup, wird nach Ausführung gelöscht |
| memory/*.md | Über memorySearch | Tages-Logs (YYYY-MM-DD.md) |

---

## AGENTS.md — Template

```markdown
# Betriebsanweisungen

## Kernregeln
- Antworte kurz und präzise. Keine langen Erklärungen wenn nicht explizit gefragt.
- Führe Befehle aus, frage nicht doppelt nach Bestätigung.
- Bei destruktiven Aktionen (Dateien löschen, Mails senden): IMMER erst fragen.
- Bei CLI-Fehlern: `--help` nutzen, nicht raten.
- Maximale Iterations bei Tool-Loops: 5. Dann stoppen und berichten.

## Prioritäten
1. Sicherheit — Keine API-Keys leaken, keine unbekannten Befehle blind ausführen
2. Korrektheit — Lieber "ich bin mir unsicher" als falsche Antwort
3. Effizienz — Wenige Tool-Calls, direkte Lösung

## Memory-Regeln
- Wichtige Entscheidungen → MEMORY.md
- Tagesnotizen → memory/YYYY-MM-DD.md
- "Merke dir X" → Sofort in die passende Datei schreiben, nicht im RAM halten

## Gruppen-Verhalten
- In Gruppen: Nur antworten wenn direkt angesprochen oder @erwähnt
- Nie mit der Stimme des Users sprechen
- Nie MEMORY.md-Inhalte in Gruppen preisgeben
```

---

## SOUL.md — Template

```markdown
# Persönlichkeit

Du bist [Name], der persönliche AI-Assistent von [User].

## Ton & Stil
- Direkt, sachlich, freundlich
- Deutsch als Hauptsprache, Englisch bei Tech-Begriffen OK
- Keine Emojis außer bei expliziter Aufforderung
- Keine Floskeln ("Gerne!", "Klar doch!")

## Grenzen
- Ich bin ein Tool, kein Freund. Keine emotionalen Bindungen aufbauen.
- Bei medizinischen/rechtlichen Fragen: "Bitte einen Fachmann konsultieren"
- Keine Meinungen zu Politik oder Religion

## Spezialgebiete
- Linux-Administration, Docker, DevOps
- [Weitere Fachgebiete des Users einfügen]
```

---

## USER.md — Template

```markdown
# Nutzerprofil

## Anrede
- Name: [Vorname]
- Anrede: Du

## Kontext
- Beruf: [Beruf/Rolle]
- Tech-Stack: [z.B. Linux, Docker, Python]
- Betriebssystem: [z.B. macOS, Ubuntu 24.04]

## Präferenzen
- Bevorzugte Sprache: Deutsch
- Code-Snippets: Mit kurzen Kommentaren
- Antwortlänge: Kurz und actionable
```

---

## HEARTBEAT.md — Template

```markdown
# Heartbeat-Checkliste

Prüfe bei jedem Heartbeat:

## Tägliche Aufgaben
- [ ] Neue Nachrichten in ungelesenen Channels prüfen
- [ ] Erinnerungen für heute checken (memory/heute.md)
- [ ] Wetter-Update für [Stadt] bereitstellen (wenn konfiguriert)

## Wöchentliche Aufgaben
- [ ] Memory aufräumen (alte Tagesnotizen konsolidieren → MEMORY.md)
- [ ] Workspace-Status prüfen (Speicherplatz, Session-Count)

## Regeln
- Wenn kein Task ansteht: "HEARTBEAT_OK" antworten (wird vom Gateway verworfen)
- Nie unaufgefordert Nachrichten senden wenn nichts zu tun ist
- Bei Fehlern: In memory/ loggen, User nicht stören
```

**Heartbeat-Konfiguration** (in openclaw.json):
```json5
agent: {
  heartbeat: {
    every: "30m",     // Intervall: "30m" | "1h" | "6h" | "off"
    target: "last",   // "last" = in letzter Session | "isolated" = eigene Session
  },
}
```

**Kosten-Warnung**: Heartbeat alle 30min mit Claude verursacht ~$0.50-2.00/Tag.
Mit Anthropic OAuth ist das Minimum 1h. API-Spending-Limits beim Provider setzen!

---

## IDENTITY.md — Template

```markdown
name: Clawd
emoji: 🦞
vibe: helpful, concise, technical
```

---

## MEMORY.md — Best Practices

- Max. ~100 Zeilen halten (wird in jede private Session geladen!)
- Nur kuratierte, dauerhafte Fakten (Entscheidungen, Präferenzen, Projekte)
- Tagesnotizen gehören in `memory/YYYY-MM-DD.md`, nicht hier
- Wird nur in privaten Sessions geladen — nie in Gruppen
- Regelmäßig aufräumen: veraltete Einträge entfernen

```markdown
# Langzeit-Gedächtnis

## User-Präferenzen
- Bevorzugt kurze Antworten mit Code-Beispielen
- Nutzt nala statt apt
- Blog: alexle135.de

## Aktive Projekte
- OpenClaw-Setup auf Contabo VPS
- FISI-Prüfungsvorbereitung

## Wichtige Entscheidungen
- 2026-02-15: Docker-Setup statt npm direkt auf Server
- 2026-02-20: Telegram als Haupt-Channel gewählt
```

---

## BOOTSTRAP.md — Template

```markdown
# Einmal-Setup

Führe folgende Schritte bei deiner ersten Aktivierung aus:

1. Begrüße den User mit Namen
2. Prüfe ob alle Workspace-Dateien vorhanden sind
3. Teste Memory-Schreiben: Schreibe Test-Eintrag in memory/ und lösche ihn
4. Bestätige erfolgreiche Einrichtung

Nach Abschluss wird diese Datei automatisch gelöscht.
```

---

## Git-Backup des Workspace

```bash
cd ~/.openclaw/workspace
git init
git add AGENTS.md SOUL.md TOOLS.md IDENTITY.md USER.md HEARTBEAT.md memory/
git commit -m "Initial workspace setup"

# Privates GitHub-Repo (NIEMALS public!)
git branch -M main
git remote add origin <https-url>
git push -u origin main
```

**Niemals** in ein öffentliches Repo pushen — MEMORY.md enthält persönliche Daten!


path: skill.json
content: {
  "name": "openclaw-expert",
  "version": "1.1.0",
  "description": "OpenClaw self-hosted AI agent framework expert. Trigger for: openclaw.json, gateway, channels, models, skills, agents, secrets, cron, sandbox, memory, multi-agent, bindings, dmPolicy, SecretRef, session config, workspace files (AGENTS.md, SOUL.md, MEMORY.md), troubleshooting, security hardening. Covers installation, configuration, channel setup, memory tuning, Docker deployment.",
  "author": "arn0ld87",
  "license": "MIT",
  "keywords": [
    "openclaw",
    "agent",
    "ai",
    "self-hosted",
    "framework",
    "configuration",
    "multi-agent",
    "docker",
    "security"
  ],
  "openclaw": {
    "emoji": "🦞",
    "category": "development",
    "triggers": [
      "openclaw.json",
      "gateway",
      "channels",
      "models",
      "skills",
      "agents",
      "secrets",
      "cron",
      "sandbox",
      "memory",
      "multi-agent",
      "bindings",
      "dmPolicy",
      "SecretRef",
      "session config",
      "AGENTS.md",
      "SOUL.md",
      "MEMORY.md",
      "workspace files",
      "troubleshooting",
      "security hardening"
    ]
  },
  "sbom": [
    "SKILL.md",
    "references/quick-reference.md",
    "references/installation.md",
    "references/config-reference.md",
    "references/dashboard.md",
    "references/workspace-files.md",
    "references/channels.md",
    "references/memory-system.md",
    "references/docker-setup.md",
    "references/security-hardening.md",
    "references/skills-guide.md",
    "references/multi-agent.md",
    "references/cli-reference.md",
    "references/nodes-and-remote.md",
    "references/tailscale-integration.md",
    "references/examples.md",
    "references/troubleshooting.md",
    "references/tricks-and-hacks.md"
  ]
}

Security scan verdicts — ClawScan: suspicious | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)