Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 69 additions & 8 deletions docs/config-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@ and `project` are required. Everything else is optional and has sensible default
"toolsProfile": "full",
"sandbox": false
},
"telegram": {
"botToken": "123456:ABC-...",
"allowFrom": ["123456789"],
"groups": {
"-100123456789": { "requireMention": true }
"channels": {
"telegram": {
"botToken": "123456:ABC-...",
"allowFrom": ["123456789"],
"groups": {
"-100123456789": { "requireMention": true }
}
}
}
}
Expand Down Expand Up @@ -190,17 +192,76 @@ Agent behavior configuration. Applied during bootstrap (when `provider` is prese
| `toolsProfile` | string | `"full"` | Agent tools profile (`"full"`, `"coding"`, `"messaging"`, etc.). |
| `sandbox` | boolean | — | Set to `false` to disable sandbox mode (`agents.defaults.sandbox.mode off`). |

## `telegram`
## `channels`

Telegram channel configuration (optional). Applied during bootstrap after onboarding.
Communication channels. Each key is a channel name; the value is
channel-specific config. Applied during bootstrap via `openclaw config set`.

Known channels with wizard support: **telegram**, **discord**, **slack**, **whatsapp**.
Unknown channel names are accepted — they pass through to OpenClaw directly.

### `enabled` field

Every channel supports an `enabled` boolean:

| `enabled` value | Behavior |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `true` | Channel is configured during bootstrap. |
| omitted | Treated as `true` — presence of the channel key means "enable it." |
| `false` | Channel is skipped during bootstrap. Config is preserved (useful for temporarily disabling a channel without deleting its credentials). |

### `channels.telegram`

| Field | Type | Description |
| ---------------------------- | -------- | ------------------------------------------------ |
| `enabled` | boolean | Enable this channel (default: `true`). |
| `botToken` | string | Bot token from BotFather (required). |
| `allowFrom` | string[] | Telegram user IDs allowed to DM the bot. |
| `groups` | object | Group IDs and their settings. |
| `groups.<id>.requireMention` | boolean | Whether the bot requires @mention in this group. |

### `channels.discord`

| Field | Type | Description |
| --------- | ------- | -------------------------------------- |
| `enabled` | boolean | Enable this channel (default: `true`). |
| `token` | string | Discord bot token (required). |

### `channels.slack`

| Field | Type | Description |
| ---------- | ------- | ------------------------------------------------------ |
| `enabled` | boolean | Enable this channel (default: `true`). |
| `botToken` | string | Slack Bot Token `xoxb-...` (required). |
| `appToken` | string | Slack App Token `xapp-...` for Socket Mode (required). |

### `channels.whatsapp`

| Field | Type | Description |
| --------- | ------- | -------------------------------------- |
| `enabled` | boolean | Enable this channel (default: `true`). |

No credentials needed — uses QR code pairing after provisioning:
`clawctl oc -i <name> channels login --channel whatsapp`

Additional channel-specific fields beyond the essentials listed above are
accepted and passed through to OpenClaw. See
[OpenClaw channel docs](https://docs.openclaw.ai/channels) for all options.

## `openclaw`

Arbitrary OpenClaw config passthrough. Each key is a dotpath, applied via
`openclaw config set` during bootstrap. No host-side validation — OpenClaw
validates at daemon restart.

```json
"openclaw": {
"channels.discord.streaming": "partial",
"channels.discord.voice.enabled": true,
"session.dmScope": "per-channel-peer"
}
```

## Secret references

String values in the config can use URI references instead of plaintext secrets:
Expand All @@ -216,5 +277,5 @@ secrets and can be safely committed to git. See

- [`config.json`](../examples/config.json) — minimal (name + project only)
- [`config.bootstrap.json`](../examples/config.bootstrap.json) — minimal working gateway (name + project + API key)
- [`config.full.json`](../examples/config.full.json) — all options including provider + telegram
- [`config.full.json`](../examples/config.full.json) — all options including provider + channels
- [`config.op.json`](../examples/config.op.json) — zero-plaintext secrets using `op://` and `env://` references
13 changes: 8 additions & 5 deletions examples/config.full.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,14 @@
}
},

"telegram": {
"botToken": "123456:ABC-...",
"allowFrom": ["123456789"],
"groups": {
"-100123456789": { "requireMention": true }
"channels": {
"telegram": {
"enabled": true,
"botToken": "123456:ABC-...",
"allowFrom": ["123456789"],
"groups": {
"-100123456789": { "requireMention": true }
}
}
}
}
7 changes: 5 additions & 2 deletions examples/config.op.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
"type": "zai",
"apiKey": "op://Sam/z.AI API Key/credential"
},
"telegram": {
"botToken": "op://Sam/Telegram Token/credential"
"channels": {
"telegram": {
"enabled": true,
"botToken": "op://Sam/Telegram Token/credential"
}
}
}
12 changes: 12 additions & 0 deletions packages/cli/src/components/capability-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@ export function CapabilitySection({
);
}

if (field.type === "toggle") {
const checked = values[path] === "true";
return (
<Box key={path}>
<Text bold={isFocused} color={isFocused ? "cyan" : undefined}>
{isFocused ? "\u25b8 " : " "}
{checked ? "[x]" : "[ ]"} {field.label}
</Text>
</Box>
);
}

if ((field.type === "text" || field.type === "password") && isEditing) {
return (
<Box key={path}>
Expand Down
36 changes: 27 additions & 9 deletions packages/cli/src/components/config-review.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { Text, Box } from "ink";
import type { InstanceConfig } from "@clawctl/types";
import { CHANNEL_REGISTRY, CHANNEL_ORDER } from "@clawctl/types";
import { ALL_CAPABILITIES } from "@clawctl/capabilities";

interface ConfigReviewProps {
Expand Down Expand Up @@ -123,15 +124,32 @@ export function ConfigReview({ config, validationErrors, validationWarnings }: C
</Text>
)}
</Row>
<Row label="Telegram">
{config.telegram ? (
<Text color="green">{"\u2713"} configured</Text>
) : (
<Text dimColor>
{"\u2500\u2500"} not configured {"\u2500\u2500"}
</Text>
)}
</Row>
{/* Channel rows */}
{CHANNEL_ORDER.map((name) => {
const def = CHANNEL_REGISTRY[name];
if (!def) return null;
const chConfig = config.channels?.[name];
const isConfigured = chConfig !== undefined;
const summary =
isConfigured && def.configDef.summary
? def.configDef.summary(
typeof chConfig === "object" ? (chConfig as Record<string, string>) : {},
)
: null;
return (
<Row key={name} label={def.label}>
{isConfigured ? (
<Text color="green">
{"\u2713"} {summary || "configured"}
</Text>
) : (
<Text dimColor>
{"\u2500\u2500"} not configured {"\u2500\u2500"}
</Text>
)}
</Row>
);
})}
</Box>

<Box
Expand Down
13 changes: 0 additions & 13 deletions packages/cli/src/components/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,19 +141,6 @@ export const SIDEBAR_HELP: Record<string, SidebarContent> = {
"personalize interactions.",
],
},
telegram: {
title: "Telegram",
lines: [
"Connect a Telegram bot for",
"chat-based agent control.",
"",
"Requires a bot token from",
"@BotFather on Telegram.",
"",
"allowFrom: Telegram user IDs",
"groups: Group IDs + settings",
],
},
review: {
title: "Review",
lines: [
Expand Down
Loading
Loading