<p align="center">
  <picture>
    <source media="(prefers-color-scheme: light)" srcset="docs/assets/readme/hero-banner-light.png">
    <img src="docs/assets/readme/hero-banner.png" alt="Minion" width="100%">
  </picture>
</p>

<h1 align="center">OpenClaw</h1>
<p align="center"><strong>The AI that actually does things.</strong></p>
<p align="center"><em>EXFOLIATE! EXFOLIATE!</em></p>

<p align="center">
  <a href="https://github.com/NikolasP98/minion-ai/actions/workflows/ci.yml?branch=main"><img src="https://img.shields.io/github/actions/workflow/status/NikolasP98/minion-ai/ci.yml?branch=main&style=flat-square&color=FF5A2D&label=CI" alt="CI"></a>
  <a href="https://github.com/NikolasP98/minion-ai/releases"><img src="https://img.shields.io/github/v/release/NikolasP98/minion-ai?include_prereleases&style=flat-square&color=FF5A2D" alt="Release"></a>
  <img src="https://img.shields.io/badge/16%2B_Channels-e8547a?style=flat-square" alt="16+ Channels">
  <img src="https://img.shields.io/badge/node_%3E%3D_22-2FBF71?style=flat-square" alt="node >= 22">
  <a href="https://discord.gg/clawd"><img src="https://img.shields.io/discord/1456350064065904867?label=Discord&logo=discord&logoColor=white&color=5865F2&style=flat-square" alt="Discord"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-Proprietary-8B7F77?style=flat-square" alt="Proprietary License"></a>
</p>

---

A self-hosted personal AI assistant that runs on your devices, answers on 16+ messaging channels, speaks and listens on macOS/iOS/Android, and keeps your data private. Gateway-based. CLI-driven. Always on.

<p align="center">
  <a href="https://docs.admin-console.dev">Docs</a> &middot;
  <a href="https://discord.gg/clawd">Discord</a> &middot;
  <a href="https://clawhub.com">ClawHub</a> &middot;
  <a href="VISION.md">Vision</a>
</p>

---

## Table of Contents

**I. Developer Handbook**

- [Quick Start](#quick-start)
- [Architecture](#architecture)
- [The Agent Loop](#the-agent-loop)
- [CLI Reference](#cli-reference)
- [Configuration](#configuration)
- [Multi-Agent Routing](#multi-agent-routing)
- [Security Model](#security-model)
- [Extension & Plugin Development](#extension--plugin-development)
- [Hooks System](#hooks-system)
- [Docker Deployment](#docker-deployment)
- [Development Setup](#development-setup)
- [Caveats & WIPs](#caveats--wips)

**II. User Handbook**

- [What Is OpenClaw?](#what-is-openclaw)
- [What Can It Do?](#what-can-it-do)
- [Supported Channels](#supported-channels)
- [Talking to Your Agent](#talking-to-your-agent)
- [Chat Commands](#chat-commands)
- [Skills & Tools](#skills--tools)
- [Memory & Context](#memory--context)
- [Voice & Speech](#voice--speech)
- [Platforms & Companion Apps](#platforms--companion-apps)
- [Pairing New Devices](#pairing-new-devices)

---

# I. Developer Handbook

## Quick Start

```bash
npm install -g minion@latest
minion onboard --install-daemon
```

The onboarding wizard walks through:

1. **Risk acknowledgement** (the agent runs real commands)
2. **Provider auth** (Anthropic, OpenAI, Google, or OpenRouter API key)
3. **Channel setup** (WhatsApp, Telegram, Discord, Slack, etc.)
4. **Skill installation** (bundled + ClawHub registry)
5. **Gateway start** (background daemon or foreground)

Supports npm, pnpm, and bun. Requires Node.js 22.12.0+.

```bash
minion gateway              # Start the gateway (foreground)
minion gateway --bind lan   # Expose on LAN (for companion apps)
minion status               # Channel health + active sessions
minion doctor               # Diagnose and fix common issues
```

<p align="center">
  <a href="https://docs.admin-console.dev/start/getting-started">Full guide</a> &middot;
  <a href="https://docs.admin-console.dev/install/docker">Docker</a> &middot;
  <a href="https://docs.admin-console.dev/install/updating">Updating</a>
</p>

---

## Architecture

```
                         +-----------------------+
Channels (16+) --------->|                       |
  WhatsApp, Telegram,    |      Gateway          |
  Discord, Slack,        |   ws://0.0.0.0:18789  |
  Signal, iMessage, ...  |                       |
                         |  +-- Inference Proxy --+--> LLM Backends
Device Nodes ----------->|  |     (strips PII)   |    (Anthropic, OpenAI,
  macOS, iOS, Android    |  |                     |     Google, OpenRouter)
                         |  +-- Pi Agent ---------+
WebChat / Control UI --->|  |   (worker thread    |
                         |  |    + Landlock)       |
CLI (minion ...) ------->|  |                     |
                         |  +-- Subagents --------+
Hooks / Cron / Gmail --->|  |   (parallel lanes)  |
                         |  |                     |
                         |  +-- Skills / Tools ---+
                         |  |   (54+ bundled)     |
                         |  |                     |
                         |  +-- Memory -----------+
                         |      (KG + SQLite)     |
                         +-----------------------+
```

**Core principle:** the Gateway is a local-first WebSocket control plane. Everything connects to it -- channels push inbound messages, the CLI sends commands, companion apps stream events, and the Control UI renders state. The agent (called "Pi") runs in an isolated worker thread with optional Landlock sandboxing.

### Key directories

```
src/
  agents/          Agent runtime, session management, subagents, tool governance
  auto-reply/      Inbound dispatch, reply chunking, channel delivery
  channels/        Channel adapters (WhatsApp, Telegram, Discord, Slack, ...)
  cli/             CLI commands (50+)
  config/          Config loading, validation, types
  gateway/         WebSocket server, RPC handlers, HTTP endpoints
  hooks/           Internal + external hook system
  memory/          Knowledge graph, compaction, FTS5 search
  pairing/         Device pairing, identity graph
  plugin-sdk/      Public API for extension authors (514 exports)
  routing/         Agent routing, session keys, multi-LLM router
  security/        Command risk, skill scanning, audit, SSRF guard
  tts/             Text-to-speech (ElevenLabs, Azure, Google, OpenAI)
  voice/           Voice wake, push-to-talk, speech-to-speech
  wizard/          Onboarding prompts and flows
extensions/        45+ channel and provider plugins
skills/            54+ bundled agent skills
```

---

## The Agent Loop

This is the core execution cycle. Every inbound message follows this path:

### 1. Ingestion

```
Channel adapter (e.g. Telegram) receives message
  --> src/auto-reply/dispatch.ts :: dispatchInboundMessage()
      - Coalesce rapid messages (combine bursts into one)
      - Check channel mention/allow gates
      - Resolve group policy (tool allowlists, mention gating)
      - Normalize sender identity
      - Resolve session key: {agentId}:{channel}:{accountId}:{threadId}
      - Queue for agent run
```

### 2. Agent Resolution

```
src/routing/resolve-route.ts :: resolveAgentRoute()
  - Check bindings (per-peer, per-guild, per-role, per-account)
  - Check personal agent assignment
  - Fall back to default agent
  - Resolve workspace directory
```

### 3. Execution (the main loop)

```
src/agents/pi-embedded-runner/run.ts :: runEmbeddedPiAgent()

  INIT:
    - Resolve model + provider (hooks can override)
    - Validate context window limits
    - Select auth profile (supports rotation across multiple API keys)

  LOOP (while true):
    |
    |-- Build payload
    |     src/agents/pi-embedded-runner/run/payloads.ts
    |     - Load session transcript
    |     - Apply history limits
    |     - Build tool definitions (from policy + skills)
    |     - Embed media attachments
    |     - Sanitize for provider quirks (e.g. strip thinking blocks for Gemini)
    |
    |-- Call LLM (streaming)
    |     Provider SDK (Anthropic / OpenAI / Google / OpenRouter)
    |     - Stream response tokens
    |     - Track usage (input/output/cache tokens)
    |
    |-- Process stream
    |     src/agents/pi-embedded/pi-embedded-subscribe.ts
    |     - Accumulate assistant text
    |     - Detect tool call blocks
    |     - Extract <thinking> blocks
    |     - Emit block replies (chunked partial responses)
    |
    |-- Tool call? ──YES──> Execute tool
    |     |                   src/agents/pi-embedded/pi-embedded-subscribe.handlers.tools.ts
    |     |                   - Run before_tool_call hook
    |     |                   - Apply tool governance (allowlist/denylist)
    |     |                   - Invoke tool, collect result
    |     |                   - Truncate oversized results
    |     |                   - Run after_tool_call hook
    |     |                   - Append tool result to session
    |     |                   - Continue loop (LLM sees tool result)
    |     |
    |     NO
    |     |
    |-- Context overflow? ──YES──> Compact session
    |     |                         src/agents/pi-embedded-runner/compact.ts
    |     |                         - Extract memories to knowledge graph
    |     |                         - Compress transcript to ~30% of original
    |     |                         - Protect last 3 turns verbatim
    |     |                         - Retry (max 3 compaction attempts)
    |     |
    |     NO
    |     |
    |-- Auth/rate error? ──YES──> Rotate auth profile or failover model
    |     |                        - Try next API key in rotation
    |     |                        - Cooldown rate-limited profiles
    |     |                        - Fall back to config.model.fallbacks
    |     |
    |     NO
    |     |
    |-- DONE: break loop
```

### 4. Response Delivery

```
src/auto-reply/reply/reply-dispatcher.ts :: createReplyDispatcher()

  - Normalize text for channel (character limits, formatting)
  - Chunk on natural boundaries (paragraphs, code blocks)
  - Apply optional human-like typing delay
  - Serialize delivery (prevent out-of-order messages)

src/auto-reply/reply/provider-dispatcher.ts
  - Route to channel adapter (WhatsApp, Telegram, Slack, ...)
  - Handle media uploads, inline buttons, reactions, threads
```

### 5. Gateway Broadcasting

While the agent runs, the gateway broadcasts live events to connected clients (Control UI, companion apps):

- **Chat deltas** (streaming text, rate-limited to 150ms)
- **Agent events** (tool calls, lifecycle phases, errors)
- **Chat final** (complete response + session metadata)

---

## CLI Reference

### Setup & Onboarding

| Command            | Description                                               |
| ------------------ | --------------------------------------------------------- |
| `minion onboard`   | Interactive setup wizard (auth, channels, skills, daemon) |
| `minion configure` | Non-interactive credential and channel setup              |
| `minion setup`     | Initialize local config and workspace                     |
| `minion doctor`    | Health checks + quick fixes                               |
| `minion update`    | Check and apply updates (`--channel stable\|beta\|dev`)   |
| `minion reset`     | Reset config/state (keeps CLI installed)                  |
| `minion uninstall` | Remove gateway service + local data                       |

### Gateway

| Command                      | Description                                 |
| ---------------------------- | ------------------------------------------- |
| `minion gateway`             | Start the gateway server (foreground)       |
| `minion gateway --bind lan`  | Bind to LAN (companion apps, remote access) |
| `minion gateway --port 9000` | Custom port (default: 18789)                |
| `minion status`              | Channel health + recent sessions            |
| `minion health`              | Fetch health from running gateway           |
| `minion dashboard`           | Open Control UI in browser                  |

### Agents

| Command                 | Description                        |
| ----------------------- | ---------------------------------- |
| `minion agent`          | Run one agent turn via the gateway |
| `minion agents list`    | List configured agents             |
| `minion agents add`     | Add a new agent                    |
| `minion agents remove`  | Remove an agent                    |
| `minion agents default` | Set the default agent              |

### Sessions & Messages

| Command                     | Description                        |
| --------------------------- | ---------------------------------- |
| `minion sessions list`      | List stored sessions               |
| `minion sessions read <id>` | Read a specific session transcript |
| `minion sessions export`    | Export sessions                    |
| `minion message send`       | Send a message through a channel   |
| `minion message read`       | Read inbound messages              |
| `minion undo`               | Undo recent tool-call actions      |

### Memory & Knowledge

| Command                        | Description                    |
| ------------------------------ | ------------------------------ |
| `minion memory search <query>` | Search the knowledge graph     |
| `minion memory reindex`        | Rebuild memory indexes         |
| `minion memory status`         | Memory system health           |
| `minion import-chatgpt`        | Import ChatGPT history into KG |

### Channels & Tools

| Command                                  | Description                                      |
| ---------------------------------------- | ------------------------------------------------ |
| `minion channel add <type>`              | Add a channel (whatsapp, telegram, discord, ...) |
| `minion channel list`                    | List configured channels                         |
| `minion tools list`                      | List available agent tools                       |
| `minion tools policy`                    | View/manage tool policies                        |
| `minion browser start\|stop\|screenshot` | Manage the headless browser                      |

### Config

| Command                            | Description           |
| ---------------------------------- | --------------------- |
| `minion config get <path>`         | Read a config value   |
| `minion config set <path> <value>` | Set a config value    |
| `minion config unset <path>`       | Remove a config value |

### Advanced

| Command                                        | Description                                      |
| ---------------------------------------------- | ------------------------------------------------ |
| `minion templates list\|create\|validate`      | Manage subagent templates                        |
| `minion orchestrations list\|inspect\|cleanup` | Multi-agent orchestrations                       |
| `minion acp`                                   | Run an ACP (Agent Communication Protocol) bridge |
| `minion roi`                                   | Calculate ROI for agent automation               |

---

## Configuration

All config lives in `~/.minion/minion.json` (JSONC with `$include` support). Per-agent overrides go in `~/.minion/agents/<agentId>/agent.json`.

### Minimal config

```jsonc
{
  "agents": {
    "defaults": {
      "model": { "id": "anthropic/claude-opus-4-6" },
    },
  },
}
```

### Full config structure (key sections)

```jsonc
{
  // --- Agent defaults ---
  "agents": {
    "defaults": {
      "model": {
        "id": "anthropic/claude-opus-4-6",
        "fallbacks": ["anthropic/claude-sonnet-4-6"], // failover chain
      },
      "workspace": "default",
      "heartbeat": { "enabled": true, "intervalMs": 60000 },
      "memorySearch": { "enabled": true },
      "contextPruning": { "enabled": true },
    },
    "list": {
      "work": { "model": { "id": "anthropic/claude-sonnet-4-6" } },
      "creative": { "model": { "id": "openai/gpt-4o" } },
    },
  },

  // --- Channels ---
  "channels": {
    "telegram": { "botToken": "..." },
    "discord": { "token": "..." },
    "whatsapp": {
      /* Baileys auto-auth */
    },
    "slack": { "botToken": "...", "appToken": "..." },
  },

  // --- Tools & Security ---
  "tools": {
    "policy": { "mode": "allowlist", "allow": ["send", "browser", "web_search"] },
  },
  "security": {
    "autonomyMode": "supervised", // "readonly" | "supervised" | "full"
  },
  "guardrails": {
    "profile": "moderate", // "permissive" | "moderate" | "strict"
    "dataLeakage": { "enabled": true },
    "topicBoundaries": { "blocklist": [] },
  },

  // --- Skills ---
  "skills": {
    "allowBundled": ["github", "weather", "summarize"],
    "load": { "extraDirs": ["~/my-skills"] },
  },

  // --- Memory ---
  "memory": {
    "backend": "builtin", // "builtin" (SQLite) or "qmd" (external)
    "citations": "auto",
  },

  // --- Voice ---
  "messages": {
    "tts": { "auto": "off", "provider": "elevenlabs", "voice": "Rachel" },
  },
  "voiceProcessing": {
    "mode": "chained", // "chained" (STT->LLM->TTS) or "s2s" (OpenAI Realtime)
  },

  // --- Gateway ---
  "gateway": {
    "bind": "localhost", // "localhost" | "lan" | "0.0.0.0"
    "port": 18789,
    "token": "your-secret-token",
  },

  // --- Automation ---
  "cron": { "enabled": true },
  "hooks": { "enabled": true },
}
```

[Full configuration reference](https://docs.admin-console.dev/gateway/configuration) &middot; [Models + failover](https://docs.admin-console.dev/concepts/model-failover)

---

## Multi-Agent Routing

Multiple agents can be configured with different models, tools, and personas. Routing decides which agent handles each inbound message.

### Route resolution order

1. **Bindings** (highest priority) -- explicit per-peer, per-guild, per-role, or per-account mappings
2. **Personal agent** -- derived from the resolved user ID
3. **Default agent** -- fallback from `config.agents.defaults`

### Session key format

```
{agentId}:{channel}:{accountId}:{peerKind}:{peerId}
```

Example: `work:telegram:default:dm:123456789`

### Multi-LLM routing

A complexity scorer can route simple queries to a fast model and complex tasks to an advanced model. Configure via `config.agents.defaults.model.fallbacks`.

### Config example

```jsonc
{
  "agents": {
    "list": {
      "work": { "model": { "id": "anthropic/claude-opus-4-6" } },
      "quick": { "model": { "id": "anthropic/claude-haiku-4-5" } },
    },
  },
  "bindings": [
    { "peer": { "kind": "dm", "id": "U_BOSS" }, "agentId": "work" },
    { "guild": "DISCORD_SERVER_ID", "agentId": "quick" },
  ],
}
```

---

## Security Model

The gateway connects to real messaging surfaces. Every inbound DM is treated as untrusted input.

### Command risk classification

| Tier       | Examples                                               | Default behavior                |
| ---------- | ------------------------------------------------------ | ------------------------------- |
| **HIGH**   | `rm -rf`, `sudo`, `curl \| bash`, `dd`, `iptables`     | Blocked in readonly/supervised  |
| **MEDIUM** | `npm install`, `git push --force`, `docker run`, `ssh` | Requires approval in supervised |
| **LOW**    | `cat`, `ls`, `grep`, `whoami`, `date`                  | Always allowed                  |

### Autonomy modes

| Mode         | LOW     | MEDIUM            | HIGH    |
| ------------ | ------- | ----------------- | ------- |
| `readonly`   | allowed | blocked           | blocked |
| `supervised` | allowed | approval required | blocked |
| `full`       | allowed | allowed           | allowed |

### Security layers

| Layer                | File                               | What it does                                                    |
| -------------------- | ---------------------------------- | --------------------------------------------------------------- |
| **Landlock sandbox** | OS-level                           | Filesystem capability enforcement (Linux 5.13+)                 |
| **Worker isolation** | `agents/pi-embedded-runner/`       | Each session runs in an isolated Node.js worker                 |
| **Tool policy**      | `security/audit-tool-policy.ts`    | Per-agent allowlists/denylists for tools                        |
| **Pre-exec scanner** | `security/pre-exec-scanner.ts`     | Detects pipe-to-shell, SSRF, terminal injection, homograph URLs |
| **Credential proxy** | `agents/auth-profiles/`            | Auth profile brokering with per-tool scope                      |
| **Egress policy**    | `infra/net/network-policy.ts`      | Outbound allowlist/denylist with SSRF guard                     |
| **Exec approval**    | `gateway/exec-approval-manager.ts` | Interactive inline approval (Telegram/Discord keyboards)        |
| **Skill scanner**    | `security/skill-scanner.ts`        | Detects shell injection, hardcoded secrets, unsafe imports      |
| **Skill trust**      | `security/skill-trust.ts`          | Trust tiers: TRUSTED > VERIFIED > EXPERIMENTAL > UNTRUSTED      |
| **Prompt guard**     | `security/prompt-guard.ts`         | LLM prompt injection detection                                  |
| **Leak detector**    | `security/leak-detector.ts`        | Scans agent output for credentials                              |
| **Audit log**        | `security/audit.ts`                | Immutable JSONL log of every tool invocation                    |
| **Activity log**     | `security/activity-log.ts`         | Session-level activity tracking                                 |

### DM pairing

Enabled by default. Unknown senders receive a pairing code (8-char alphanumeric, 1-hour TTL). Approve with:

```bash
minion pairing approve <channel> <code>
```

[Security guide](https://docs.admin-console.dev/gateway/security)

---

## Extension & Plugin Development

Extensions live in `extensions/` and are loaded as npm packages. The Plugin SDK (`src/plugin-sdk/index.ts`) exposes 514 typed exports.

### Extension entry point

```typescript
// extensions/my-channel/index.ts
import type { MinionPluginService } from '@nikolasp98/minion/plugin-sdk';

export const plugin: MinionPluginService = {
  name: 'my-channel',
  version: '1.0.0',

  async onLoad(ctx) {
    // Register tools, hooks, HTTP routes
    ctx.registerTool('my_tool', { ... });
    ctx.registerHttpRoute('GET', '/my-endpoint', handler);
  },

  async onUnload() {
    // Cleanup
  }
};
```

### Extension manifest

In `package.json`:

```json
{
  "openclaw": {
    "extensions": ["./index.ts"],
    "channel": {
      "id": "my-channel",
      "label": "My Channel",
      "description": "..."
    }
  }
}
```

### SDK surface areas

- **Channel adapters** -- auth, messaging, config, media, threading
- **Tool registration** -- define custom tools with schemas and handlers
- **HTTP routes** -- register endpoints on the gateway server
- **Hooks** -- tap into lifecycle events (before/after tool calls, model resolve, etc.)
- **Config types** -- full typed access to config schemas

---

## Hooks System

Hooks execute at key lifecycle points. Three categories:

### External hooks

HTTP webhooks that trigger agent runs:

```jsonc
{
  "hooks": {
    "enabled": true,
    "mappings": [
      {
        "match": { "path": "/deploy" },
        "action": "agent",
        "agentId": "ops",
        "messageTemplate": "Deploy webhook received: {{body}}",
      },
    ],
  },
}
```

### Gmail hooks

Direct Gmail integration with optional Tailscale funnel:

```jsonc
{
  "hooks": {
    "gmail": {
      "account": "me@gmail.com",
      "label": "INBOX",
      "tailscale": { "mode": "funnel" },
    },
  },
}
```

### Internal event hooks

Custom handlers for agent lifecycle events:

```jsonc
{
  "hooks": {
    "internal": {
      "enabled": true,
      "handlers": [
        { "event": "session:start", "module": "./my-hook.ts", "export": "onSessionStart" },
        { "event": "memory:extract", "module": "./my-hook.ts", "export": "onMemoryExtract" },
      ],
    },
  },
}
```

### Plugin lifecycle hooks

Available in the agent execution pipeline:

| Hook                   | When                       | Use case                      |
| ---------------------- | -------------------------- | ----------------------------- |
| `before_model_resolve` | Before model selection     | Override model/provider       |
| `before_agent_start`   | Before agent run           | Inject context, modify params |
| `before_tool_call`     | Before each tool execution | Gate, modify, or block tools  |
| `after_tool_call`      | After each tool execution  | Log, transform results        |
| `before_message_send`  | Before outbound delivery   | Modify/filter responses       |

---

## Docker Deployment

### Quick start

```bash
docker compose up -d
```

### Services

- **minion-gateway** -- WebSocket server on port 18789 with auto-restart
- **minion-cli** -- Interactive CLI container (same volumes)

### Key volumes

```yaml
volumes:
  - ~/.minion:/home/node/.minion # Config, credentials, sessions
  - ~/.minion/workspace:/home/node/.minion/workspace
  - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
```

### Key environment variables

| Variable               | Description                     |
| ---------------------- | ------------------------------- |
| `MINION_ENV`           | `dev` / `staging` / `prod`      |
| `MINION_GATEWAY_TOKEN` | Gateway auth token              |
| `ANTHROPIC_API_KEY`    | Anthropic API key               |
| `OPENAI_API_KEY`       | OpenAI API key                  |
| `OPENROUTER_API_KEY`   | OpenRouter API key              |
| `MINION_GATEWAY_PORT`  | Custom port (default: 18789)    |
| `MINION_GATEWAY_BIND`  | `localhost` / `lan` / `0.0.0.0` |

### Production deployment

```bash
# Single server (systemd)
cp scripts/systemd/minion-gateway.service ~/.config/systemd/user/
systemctl --user enable --now minion-gateway

# Multi-server (Docker + CI/CD)
# See docs/deployment/ for GitHub Actions workflows
```

### Health check

```
GET http://localhost:18789/health
```

---

## Development Setup

```bash
git clone https://github.com/NikolasP98/minion-ai.git && cd minion-ai
pnpm install && pnpm build
```

| Command              | Description                    |
| -------------------- | ------------------------------ |
| `pnpm dev`           | Watch mode (tsx)               |
| `pnpm gateway:watch` | Gateway with auto-reload       |
| `pnpm build`         | Production build (tsdown)      |
| `pnpm test`          | Unit tests (vitest)            |
| `pnpm check`         | Lint + format (oxlint + oxfmt) |
| `pnpm tsgo`          | TypeScript type-check          |

**Release channels:** `stable` (tagged), `beta` (prereleases), `dev` (head of DEV). Switch with `minion update --channel stable|beta|dev`.

[Contributing](CONTRIBUTING.md) &middot; [Vision](VISION.md) &middot; [DeepWiki](https://deepwiki.com/NikolasP98/minion-ai)

---

## Caveats & WIPs

### Known caveats

| Issue                             | Details                                                                                                                                                                                           |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Voice config coupling**         | `voiceProcessing.mode` and `messages.tts.auto` must be aligned. `mode: "chained"` + `tts.auto: "tagged"` is broken (voice notes get text replies). Use `chained` + `inbound` or `s2s` + `tagged`. |
| **Session compaction retries**    | Context overflow triggers up to 3 compaction attempts. If all fail, the turn errors out. Very long sessions with large tool results are the most common trigger.                                  |
| **Thinking level fallback**       | Some providers don't support extended thinking. The loop auto-disables it and retries, but this burns an extra LLM call.                                                                          |
| **Multi-agent session isolation** | `sessionMode: "isolated"` vs `"shared"` is still being refined for multi-tenant scenarios.                                                                                                        |

### Experimental features

| Feature                         | Status       | Config                                                                        |
| ------------------------------- | ------------ | ----------------------------------------------------------------------------- |
| **Session transcript indexing** | Experimental | `agents.defaults.memorySearch.experimental.sessionMemory`                     |
| **Speech-to-speech (S2S)**      | Experimental | `voiceProcessing.mode: "s2s"` (OpenAI Realtime API)                           |
| **Builtin SQLite memory**       | Experimental | `memory.backend: "builtin"` (uses Node.js experimental SQLite)                |
| **apply_patch subtool**         | Experimental | `tools.experimental`                                                          |
| **Personal agents**             | Experimental | `personalAgents.enabled` -- per-user agent provisioning                       |
| **Budget tracking**             | New          | `src/agents/budget-tracker.ts` -- per-session cost tracking                   |
| **FTS5 search**                 | New          | `src/memory/search/fts5-search.ts` -- full-text memory search                 |
| **KG message sync**             | New          | `src/hooks/bundled/kg-message-sync/` -- bidirectional channel sync            |
| **Pre-exec scanner**            | New          | `src/security/pre-exec-scanner.ts` -- pipe-to-shell, SSRF, terminal injection |
| **Network policy**              | New          | `src/infra/net/network-policy.ts` -- YAML egress rules with hot-reload        |

---

# II. User Handbook

## What Is OpenClaw?

OpenClaw is your personal AI assistant that lives on your own machine and answers you on whatever messaging app you already use -- WhatsApp, Telegram, Discord, Slack, iMessage, Signal, and more. It's not a cloud service you sign up for; it runs on your hardware, talks to the AI model of your choice, and keeps everything private.

Think of it as having a capable assistant that:

- Lives in your messaging apps (not a separate app to open)
- Can browse the web, run code, manage files, and take actions
- Remembers things across conversations
- Speaks and listens (voice notes, push-to-talk)
- Works on your phone, laptop, and desktop simultaneously
- Follows your rules about what it can and can't do

---

## What Can It Do?

### Answer questions and have conversations

Send a message on any connected channel and get a thoughtful response. The agent maintains context within a session, so you can have multi-turn conversations just like texting a friend.

### Browse the web

Ask it to look something up, read a webpage, or search for information. It has a built-in browser it can control.

### Run code and commands

Need a script written? A file renamed? A git repo cloned? The agent can execute commands on the machine it runs on (with safety guardrails you control).

### Manage your schedule and email

With Gmail and Google Calendar skills, it can read your email, draft replies, check your calendar, and schedule events.

### Remember things

Tell it something important and it stores it in a knowledge graph. Ask later and it recalls. Memories persist across sessions and conversations.

### Work across channels simultaneously

Message it on WhatsApp about a task, then check in on Telegram -- it keeps the same session context. Different channels can be routed to different agents with different capabilities.

### Speak and listen

Send a voice note and it responds with voice. On companion apps (macOS, iOS, Android), use push-to-talk or voice wake for hands-free interaction.

### Automate with cron and hooks

Schedule recurring tasks (daily summaries, health checks) or trigger actions from webhooks (deploy notifications, email alerts).

---

## Supported Channels

<table>
<tr>
<td align="center" width="12.5%"><strong>WhatsApp</strong><br><sub>Baileys</sub></td>
<td align="center" width="12.5%"><strong>Telegram</strong><br><sub>grammY</sub></td>
<td align="center" width="12.5%"><strong>Discord</strong><br><sub>Carbon</sub></td>
<td align="center" width="12.5%"><strong>Slack</strong><br><sub>Bolt</sub></td>
<td align="center" width="12.5%"><strong>Signal</strong><br><sub>signal-cli</sub></td>
<td align="center" width="12.5%"><strong>iMessage</strong><br><sub>BlueBubbles</sub></td>
<td align="center" width="12.5%"><strong>Google Chat</strong><br><sub>Chat API</sub></td>
<td align="center" width="12.5%"><strong>MS Teams</strong><br><sub>Bot Framework</sub></td>
</tr>
<tr>
<td align="center"><strong>Matrix</strong><br><sub>Extension</sub></td>
<td align="center"><strong>LINE</strong><br><sub>Extension</sub></td>
<td align="center"><strong>Feishu</strong><br><sub>Extension</sub></td>
<td align="center"><strong>WebChat</strong><br><sub>Built-in</sub></td>
<td align="center"><strong>Voice Call</strong><br><sub>Extension</sub></td>
<td align="center"><strong>Nostr</strong><br><sub>Extension</sub></td>
<td align="center"><strong>IRC</strong><br><sub>Extension</sub></td>
<td align="center"><strong>Mattermost</strong><br><sub>Extension</sub></td>
</tr>
</table>

<details>
<summary><strong>More extension channels</strong></summary>
<br>

Zalo, Zalo Personal, BlueBubbles (alternative iMessage), Twitch, Nextcloud Talk, Tlon. Extensions live under `extensions/` and can be enabled in config.

See the [channels docs](https://docs.admin-console.dev/channels) for setup guides per platform.

</details>

---

## Talking to Your Agent

Just send a message on any connected channel. The agent responds like any other contact in your messaging app.

### How it works

- **DMs:** Send a direct message and the agent replies. First-time contacts go through a pairing flow (see [Pairing New Devices](#pairing-new-devices)).
- **Groups:** Add the agent to a group. By default it only responds when mentioned (`@agent`). This is configurable per group.
- **Threads:** On platforms that support threads (Slack, Discord, Telegram topics), the agent maintains separate context per thread.
- **Multi-session:** On Telegram, run parallel sessions with `/sessions` and `/switch`.

### What to expect

- The agent streams its response -- you'll see it typing, then the message appears in chunks.
- If it needs to run a tool (browse a page, search the web, execute code), it does so automatically. In supervised mode, risky commands trigger an approval button.
- Long responses are chunked to respect channel limits (WhatsApp: 4096 chars, Telegram: 4096 chars, Discord: 2000 chars, etc.).
- Attachments (images, files, voice notes) are supported on most channels.

---

## Chat Commands

Send these as messages in any connected channel:

| Command                    | What it does                                                                     |
| -------------------------- | -------------------------------------------------------------------------------- |
| `/status`                  | Session info: model, tokens used, cost                                           |
| `/new`                     | Reset the session (start fresh)                                                  |
| `/compact`                 | Compress session context (free up token space)                                   |
| `/think <level>`           | Set thinking depth: `off` \| `minimal` \| `low` \| `medium` \| `high` \| `xhigh` |
| `/verbose on\|off`         | Toggle verbose mode (show tool calls and reasoning)                              |
| `/usage off\|tokens\|full` | Per-response usage footer                                                        |
| `/sessions`                | List parallel session variants (Telegram)                                        |
| `/switch <n>`              | Switch active session (Telegram)                                                 |

---

## Skills & Tools

Skills extend what the agent can do. 54+ come bundled; more are available on [ClawHub](https://clawhub.com).

### Built-in tools

| Category       | Tools                                              | What they do                                                      |
| -------------- | -------------------------------------------------- | ----------------------------------------------------------------- |
| **Web**        | `web_fetch`, `web_search`                          | Browse pages, search the internet                                 |
| **Browser**    | `browser`                                          | Full headless browser control (click, type, screenshot, navigate) |
| **Messaging**  | `message`                                          | Send/read messages across channels                                |
| **Memory**     | `knowledge_graph`                                  | Search and manage the knowledge graph                             |
| **Sessions**   | `sessions_list`, `sessions_send`, `sessions_spawn` | Manage parallel sessions and subagents                            |
| **Media**      | `image`, `canvas`, `tts`                           | Generate images, draw on canvas, text-to-speech                   |
| **Automation** | `cron`                                             | Schedule and manage recurring tasks                               |
| **Auth**       | `gog_auth_*`                                       | Google OAuth for Gmail, Calendar, Drive                           |

### Example bundled skills

| Skill          | What it adds                               |
| -------------- | ------------------------------------------ |
| `github`       | PR creation, issue management, code review |
| `weather`      | Current conditions and forecasts           |
| `summarize`    | Summarize long documents or web pages      |
| `obsidian`     | Read/write notes in an Obsidian vault      |
| `1password`    | Look up credentials securely               |
| `video-frames` | Extract and analyze video frames           |
| `coding-agent` | Enhanced code generation and refactoring   |
| `voice-call`   | Voice calling capabilities                 |

### Installing skills from ClawHub

```bash
minion skills install <skill-name>
```

Or add custom skill directories:

```jsonc
{
  "skills": {
    "load": { "extraDirs": ["~/my-custom-skills"] },
  },
}
```

---

## Memory & Context

The agent has two layers of memory:

### Session memory (short-term)

Each conversation has a session transcript. When it gets too long, the agent automatically compacts it -- summarizing older turns while keeping recent ones intact. You can trigger this manually with `/compact`.

### Knowledge graph (long-term)

Important facts, preferences, and information are extracted from conversations and stored in a persistent knowledge graph. The agent searches this automatically when relevant.

- Memories survive across sessions and channel switches
- Backend: SQLite with vector embeddings (builtin) or external search (QMD)
- Search manually with `minion memory search "query"`

### What gets remembered

The agent extracts facts naturally from conversation: names, preferences, project details, decisions, important dates. You can also explicitly say "remember that..." to store something.

---

## Voice & Speech

### Voice notes

Send a voice note on any channel that supports them (WhatsApp, Telegram, Discord). The agent transcribes it, processes it, and can reply with a voice note back.

### Text-to-speech

Enable TTS and the agent speaks its responses:

```jsonc
{
  "messages": {
    "tts": { "auto": "inbound", "provider": "elevenlabs", "voice": "Rachel" },
  },
}
```

Providers: ElevenLabs, Microsoft Azure, Google Cloud, OpenAI.

### Push-to-talk

On companion apps (macOS, iOS, Android), use push-to-talk or voice wake for hands-free conversations.

---

## Platforms & Companion Apps

| Platform    | What you get                                                                    |
| ----------- | ------------------------------------------------------------------------------- |
| **Linux**   | Gateway host (recommended). Full CLI, Landlock sandbox, systemd daemon.         |
| **macOS**   | Menu bar app with Voice Wake, Talk Mode, Canvas, health dashboard, PTT.         |
| **iOS**     | Canvas, Voice Wake, Talk Mode, camera input, screen recording, Bonjour pairing. |
| **Android** | Canvas, Talk Mode, camera input, screen recording, optional SMS channel.        |
| **Windows** | WSL2 recommended. Full CLI + gateway support.                                   |

Companion apps connect to the gateway over your local network (or Tailscale for remote). They add device-native capabilities: camera, screen capture, location, notifications, and voice I/O.

---

## Pairing New Devices

When you (or someone else) messages the agent for the first time on a channel, DM pairing kicks in:

1. The agent sends a **pairing code** (8-character, expires in 1 hour)
2. You approve it on the machine running the gateway:
   ```bash
   minion pairing approve <channel> <code>
   ```
3. The sender is added to the allowlist and can chat freely

This prevents strangers from using your agent. You can pre-approve contacts:

```jsonc
{
  "channels": {
    "whatsapp": {
      "allowFrom": ["+1234567890", "+0987654321"],
    },
  },
}
```

---

## Documentation

<table>
<tr><td><a href="https://docs.admin-console.dev/start/getting-started">Getting Started</a></td><td><a href="https://docs.admin-console.dev/concepts/architecture">Architecture</a></td></tr>
<tr><td><a href="https://docs.admin-console.dev/gateway/configuration">Configuration</a></td><td><a href="https://docs.admin-console.dev/channels">Channels</a></td></tr>
<tr><td><a href="https://docs.admin-console.dev/gateway/security">Security</a></td><td><a href="https://docs.admin-console.dev/tools">Tools</a></td></tr>
<tr><td><a href="https://docs.admin-console.dev/tools/skills">Skills</a></td><td><a href="https://docs.admin-console.dev/start/wizard">Wizard</a></td></tr>
<tr><td><a href="https://docs.admin-console.dev/gateway/remote">Remote Access</a></td><td><a href="https://docs.admin-console.dev/install/docker">Docker</a></td></tr>
<tr><td><a href="https://docs.admin-console.dev/platforms/macos">macOS</a> &middot; <a href="https://docs.admin-console.dev/platforms/ios">iOS</a> &middot; <a href="https://docs.admin-console.dev/platforms/android">Android</a></td><td><a href="https://docs.admin-console.dev/platforms/linux">Linux</a> &middot; <a href="https://docs.admin-console.dev/platforms/windows">Windows</a></td></tr>
</table>
