Merge branch 'fix/bundled-plugin-deps' into tlon-dev

This commit is contained in:
Hunter Miller 2026-01-26 17:06:45 -06:00
commit d503f0ad86
14 changed files with 308 additions and 137 deletions

View File

@ -16,20 +16,27 @@ Status: supported via plugin. Direct messages, group chats, media, locations, Fl
messages, template messages, and quick replies are supported. Reactions and threads messages, template messages, and quick replies are supported. Reactions and threads
are not supported. are not supported.
## Plugin required ## Plugin setup
Install the LINE plugin: LINE is bundled with Clawdbot. Its dependencies are automatically installed on first load
when you enable the plugin.
To enable, add `line` to your plugins allow list:
```json5
{
plugins: {
allow: ["line"]
}
}
```
Alternatively, install explicitly from npm:
```bash ```bash
clawdbot plugins install @clawdbot/line clawdbot plugins install @clawdbot/line
``` ```
Local checkout (when running from a git repo):
```bash
clawdbot plugins install ./extensions/line
```
## Setup ## Setup
1) Create a LINE Developers account and open the Console: 1) Create a LINE Developers account and open the Console:

View File

@ -13,32 +13,32 @@ but it requires E2EE to be enabled.
Status: supported via plugin (matrix-bot-sdk). Direct messages, rooms, threads, media, reactions, Status: supported via plugin (matrix-bot-sdk). Direct messages, rooms, threads, media, reactions,
polls (send + poll-start as text), location, and E2EE (with crypto support). polls (send + poll-start as text), location, and E2EE (with crypto support).
## Plugin required ## Plugin setup
Matrix ships as a plugin and is not bundled with the core install. Matrix is bundled with Clawdbot. Its dependencies are automatically installed on first load
when you enable the plugin.
Install via CLI (npm registry): To enable, add `matrix` to your plugins allow list:
```json5
{
plugins: {
allow: ["matrix"]
}
}
```
Alternatively, install explicitly from npm:
```bash ```bash
clawdbot plugins install @clawdbot/matrix clawdbot plugins install @clawdbot/matrix
``` ```
Local checkout (when running from a git repo):
```bash
clawdbot plugins install ./extensions/matrix
```
If you choose Matrix during configure/onboarding and a git checkout is detected,
Clawdbot will offer the local install path automatically.
Details: [Plugins](/plugin) Details: [Plugins](/plugin)
## Setup ## Setup
1) Install the Matrix plugin: 1) Add `matrix` to your plugins allow list (or install via CLI).
- From npm: `clawdbot plugins install @clawdbot/matrix`
- From a local checkout: `clawdbot plugins install ./extensions/matrix`
2) Create a Matrix account on a homeserver: 2) Create a Matrix account on a homeserver:
- Browse hosting options at [https://matrix.org/ecosystem/hosting/](https://matrix.org/ecosystem/hosting/) - Browse hosting options at [https://matrix.org/ecosystem/hosting/](https://matrix.org/ecosystem/hosting/)
- Or host it yourself. - Or host it yourself.

View File

@ -11,22 +11,29 @@ Status: supported via plugin (bot token + WebSocket events). Channels, groups, a
Mattermost is a self-hostable team messaging platform; see the official site at Mattermost is a self-hostable team messaging platform; see the official site at
[mattermost.com](https://mattermost.com) for product details and downloads. [mattermost.com](https://mattermost.com) for product details and downloads.
## Plugin required ## Plugin setup
Mattermost ships as a plugin and is not bundled with the core install.
Mattermost is bundled with Clawdbot. Its dependencies are automatically installed on first
load when you enable the plugin.
To enable, add `mattermost` to your plugins allow list:
```json5
{
plugins: {
allow: ["mattermost"]
}
}
```
The onboarding wizard and `clawdbot channels add` also offer to enable Mattermost.
Alternatively, install explicitly from npm:
Install via CLI (npm registry):
```bash ```bash
clawdbot plugins install @clawdbot/mattermost clawdbot plugins install @clawdbot/mattermost
``` ```
Local checkout (when running from a git repo):
```bash
clawdbot plugins install ./extensions/mattermost
```
If you choose Mattermost during configure/onboarding and a git checkout is detected,
Clawdbot will offer the local install path automatically.
Details: [Plugins](/plugin) Details: [Plugins](/plugin)
## Quick setup ## Quick setup

View File

@ -12,30 +12,34 @@ Updated: 2026-01-21
Status: text + DM attachments are supported; channel/group file sending requires `sharePointSiteId` + Graph permissions (see [Sending files in group chats](#sending-files-in-group-chats)). Polls are sent via Adaptive Cards. Status: text + DM attachments are supported; channel/group file sending requires `sharePointSiteId` + Graph permissions (see [Sending files in group chats](#sending-files-in-group-chats)). Polls are sent via Adaptive Cards.
## Plugin required ## Plugin setup
Microsoft Teams ships as a plugin and is not bundled with the core install.
**Breaking change (2026.1.15):** MS Teams moved out of core. If you use it, you must install the plugin. Microsoft Teams is bundled with Clawdbot. Its dependencies are automatically installed on
first load when you enable the plugin.
Explainable: keeps core installs lighter and lets MS Teams dependencies update independently. **Note (2026.1.15):** MS Teams is a plugin to keep core installs lighter and let its
dependencies update independently.
To enable, add `msteams` to your plugins allow list:
```json5
{
plugins: {
allow: ["msteams"]
}
}
```
Alternatively, install explicitly from npm:
Install via CLI (npm registry):
```bash ```bash
clawdbot plugins install @clawdbot/msteams clawdbot plugins install @clawdbot/msteams
``` ```
Local checkout (when running from a git repo):
```bash
clawdbot plugins install ./extensions/msteams
```
If you choose Teams during configure/onboarding and a git checkout is detected,
Clawdbot will offer the local install path automatically.
Details: [Plugins](/plugin) Details: [Plugins](/plugin)
## Quick setup (beginner) ## Quick setup (beginner)
1) Install the Microsoft Teams plugin. 1) Add `msteams` to your plugins allow list (or install via CLI).
2) Create an **Azure Bot** (App ID + client secret + tenant ID). 2) Create an **Azure Bot** (App ID + client secret + tenant ID).
3) Configure Clawdbot with those credentials. 3) Configure Clawdbot with those credentials.
4) Expose `/api/messages` (port 3978 by default) via a public URL or tunnel. 4) Expose `/api/messages` (port 3978 by default) via a public URL or tunnel.

View File

@ -7,22 +7,29 @@ read_when:
Status: supported via plugin (webhook bot). Direct messages, rooms, reactions, and markdown messages are supported. Status: supported via plugin (webhook bot). Direct messages, rooms, reactions, and markdown messages are supported.
## Plugin required ## Plugin setup
Nextcloud Talk ships as a plugin and is not bundled with the core install.
Nextcloud Talk is bundled with Clawdbot. Its dependencies are automatically installed on first
load when you enable the plugin.
To enable, add `nextcloud-talk` to your plugins allow list:
```json5
{
plugins: {
allow: ["nextcloud-talk"]
}
}
```
The onboarding wizard and `clawdbot channels add` also offer to enable Nextcloud Talk.
Alternatively, install explicitly from npm:
Install via CLI (npm registry):
```bash ```bash
clawdbot plugins install @clawdbot/nextcloud-talk clawdbot plugins install @clawdbot/nextcloud-talk
``` ```
Local checkout (when running from a git repo):
```bash
clawdbot plugins install ./extensions/nextcloud-talk
```
If you choose Nextcloud Talk during configure/onboarding and a git checkout is detected,
Clawdbot will offer the local install path automatically.
Details: [Plugins](/plugin) Details: [Plugins](/plugin)
## Quick setup (beginner) ## Quick setup (beginner)

View File

@ -10,33 +10,31 @@ read_when:
Nostr is a decentralized protocol for social networking. This channel enables Clawdbot to receive and respond to encrypted direct messages (DMs) via NIP-04. Nostr is a decentralized protocol for social networking. This channel enables Clawdbot to receive and respond to encrypted direct messages (DMs) via NIP-04.
## Install (on demand) ## Plugin setup
### Onboarding (recommended) Nostr is bundled with Clawdbot. Its dependencies are automatically installed on first load
when you enable the plugin.
- The onboarding wizard (`clawdbot onboard`) and `clawdbot channels add` list optional channel plugins. To enable, add `nostr` to your plugins allow list:
- Selecting Nostr prompts you to install the plugin on demand.
Install defaults: ```json5
{
plugins: {
allow: ["nostr"]
}
}
```
- **Dev channel + git checkout available:** uses the local plugin path. The onboarding wizard (`clawdbot onboard`) and `clawdbot channels add` also offer to enable
- **Stable/Beta:** downloads from npm. Nostr when you select it.
You can always override the choice in the prompt. Alternatively, install explicitly from npm:
### Manual install
```bash ```bash
clawdbot plugins install @clawdbot/nostr clawdbot plugins install @clawdbot/nostr
``` ```
Use a local checkout (dev workflows): Restart the Gateway after enabling plugins.
```bash
clawdbot plugins install --link <path-to-clawdbot>/extensions/nostr
```
Restart the Gateway after installing or enabling plugins.
## Quick setup ## Quick setup

View File

@ -12,30 +12,35 @@ be further restricted via allowlists.
Status: supported via plugin. DMs, group mentions, thread replies, and text-only media fallback Status: supported via plugin. DMs, group mentions, thread replies, and text-only media fallback
(URL appended to caption). Reactions, polls, and native media uploads are not supported. (URL appended to caption). Reactions, polls, and native media uploads are not supported.
## Plugin required ## Plugin setup
Tlon ships as a plugin and is not bundled with the core install. Tlon is bundled with Clawdbot. Its dependencies (`@urbit/http-api`, `@urbit/aura`) are
automatically installed on first load when you enable the plugin.
Install via CLI (npm registry): To enable, add `tlon` to your plugins allow list and configure the channel:
```bash ```json5
clawdbot plugins install @clawdbot/tlon {
``` plugins: {
allow: ["tlon"]
Local checkout (when running from a git repo): },
channels: {
```bash tlon: {
clawdbot plugins install ./extensions/tlon enabled: true,
// ... config below
}
}
}
``` ```
Details: [Plugins](/plugin) Details: [Plugins](/plugin)
## Setup ## Setup
1) Install the Tlon plugin. 1) Gather your ship URL and login code.
2) Gather your ship URL and login code. 2) Add `tlon` to your plugins allow list.
3) Configure `channels.tlon`. 3) Configure `channels.tlon`.
4) Restart the gateway. 4) Restart the gateway (dependencies install automatically on first load).
5) DM the bot or mention it in a group channel. 5) DM the bot or mention it in a group channel.
Minimal config (single account): Minimal config (single account):

View File

@ -7,17 +7,31 @@ read_when:
Status: experimental. Direct messages only; groups coming soon per Zalo docs. Status: experimental. Direct messages only; groups coming soon per Zalo docs.
## Plugin required ## Plugin setup
Zalo ships as a plugin and is not bundled with the core install.
- Install via CLI: `clawdbot plugins install @clawdbot/zalo` Zalo is bundled with Clawdbot. Its dependencies are automatically installed on first load
- Or select **Zalo** during onboarding and confirm the install prompt when you enable the plugin.
- Details: [Plugins](/plugin)
To enable, add `zalo` to your plugins allow list:
```json5
{
plugins: {
allow: ["zalo"]
}
}
```
Or select **Zalo** during onboarding. Alternatively, install explicitly from npm:
```bash
clawdbot plugins install @clawdbot/zalo
```
Details: [Plugins](/plugin)
## Quick setup (beginner) ## Quick setup (beginner)
1) Install the Zalo plugin: 1) Add `zalo` to your plugins allow list (or install via CLI/onboarding).
- From a source checkout: `clawdbot plugins install ./extensions/zalo`
- From npm (if published): `clawdbot plugins install @clawdbot/zalo`
- Or pick **Zalo** in onboarding and confirm the install prompt
2) Set the token: 2) Set the token:
- Env: `ZALO_BOT_TOKEN=...` - Env: `ZALO_BOT_TOKEN=...`
- Or config: `channels.zalo.botToken: "..."`. - Or config: `channels.zalo.botToken: "..."`.

View File

@ -10,11 +10,24 @@ Status: experimental. This integration automates a **personal Zalo account** via
> **Warning:** This is an unofficial integration and may result in account suspension/ban. Use at your own risk. > **Warning:** This is an unofficial integration and may result in account suspension/ban. Use at your own risk.
## Plugin required ## Plugin setup
Zalo Personal ships as a plugin and is not bundled with the core install.
- Install via CLI: `clawdbot plugins install @clawdbot/zalouser` Zalo Personal is bundled with Clawdbot. Its dependencies are automatically installed on first
- Or from a source checkout: `clawdbot plugins install ./extensions/zalouser` load when you enable the plugin.
- Details: [Plugins](/plugin)
To enable, add `zalouser` to your plugins allow list:
```json5
{
plugins: {
allow: ["zalouser"]
}
}
```
Alternatively, install explicitly from npm: `clawdbot plugins install @clawdbot/zalouser`
Details: [Plugins](/plugin)
## Prerequisite: zca-cli ## Prerequisite: zca-cli
The Gateway machine must have the `zca` binary available in `PATH`. The Gateway machine must have the `zca` binary available in `PATH`.

View File

@ -44,6 +44,7 @@ See [Voice Call](/plugins/voice-call) for a concrete example plugin.
- [Nostr](/channels/nostr) — `@clawdbot/nostr` - [Nostr](/channels/nostr) — `@clawdbot/nostr`
- [Zalo](/channels/zalo) — `@clawdbot/zalo` - [Zalo](/channels/zalo) — `@clawdbot/zalo`
- [Microsoft Teams](/channels/msteams) — `@clawdbot/msteams` - [Microsoft Teams](/channels/msteams) — `@clawdbot/msteams`
- [Tlon/Urbit](/channels/tlon) — bundled as `tlon` (disabled by default; auto-installs deps)
- Google Antigravity OAuth (provider auth) — bundled as `google-antigravity-auth` (disabled by default) - Google Antigravity OAuth (provider auth) — bundled as `google-antigravity-auth` (disabled by default)
- Gemini CLI OAuth (provider auth) — bundled as `google-gemini-cli-auth` (disabled by default) - Gemini CLI OAuth (provider auth) — bundled as `google-gemini-cli-auth` (disabled by default)
- Qwen OAuth (provider auth) — bundled as `qwen-portal-auth` (disabled by default) - Qwen OAuth (provider auth) — bundled as `qwen-portal-auth` (disabled by default)
@ -128,8 +129,9 @@ A plugin directory may include a `package.json` with `clawdbot.extensions`:
Each entry becomes a plugin. If the pack lists multiple extensions, the plugin id Each entry becomes a plugin. If the pack lists multiple extensions, the plugin id
becomes `name/<fileBase>`. becomes `name/<fileBase>`.
If your plugin imports npm deps, install them in that directory so If your plugin imports npm deps, bundled plugins will **auto-install** them on
`node_modules` is available (`npm install` / `pnpm install`). first load. For workspace/linked plugins during development, run `npm install`
or `pnpm install` in the plugin directory manually.
### Channel catalog metadata ### Channel catalog metadata

View File

@ -28,9 +28,22 @@ The Voice Call plugin runs **inside the Gateway process**.
If you use a remote Gateway, install/configure the plugin on the **machine running the Gateway**, then restart the Gateway to load it. If you use a remote Gateway, install/configure the plugin on the **machine running the Gateway**, then restart the Gateway to load it.
## Install ## Plugin setup
### Option A: install from npm (recommended) Voice Call is bundled with Clawdbot. Its dependencies are automatically installed on first
load when you enable the plugin.
To enable, add `voice-call` to your plugins allow list:
```json5
{
plugins: {
allow: ["voice-call"]
}
}
```
Alternatively, install explicitly from npm:
```bash ```bash
clawdbot plugins install @clawdbot/voice-call clawdbot plugins install @clawdbot/voice-call
@ -38,15 +51,6 @@ clawdbot plugins install @clawdbot/voice-call
Restart the Gateway afterwards. Restart the Gateway afterwards.
### Option B: install from a local folder (dev, no copying)
```bash
clawdbot plugins install ./extensions/voice-call
cd ./extensions/voice-call && pnpm install
```
Restart the Gateway afterwards.
## Config ## Config
Set config under `plugins.entries.voice-call.config`: Set config under `plugins.entries.voice-call.config`:

View File

@ -19,9 +19,22 @@ This plugin runs **inside the Gateway process**.
If you use a remote Gateway, install/configure it on the **machine running the Gateway**, then restart the Gateway. If you use a remote Gateway, install/configure it on the **machine running the Gateway**, then restart the Gateway.
## Install ## Plugin setup
### Option A: install from npm Zalo Personal is bundled with Clawdbot. Its dependencies are automatically installed on first
load when you enable the plugin.
To enable, add `zalouser` to your plugins allow list:
```json5
{
plugins: {
allow: ["zalouser"]
}
}
```
Alternatively, install explicitly from npm:
```bash ```bash
clawdbot plugins install @clawdbot/zalouser clawdbot plugins install @clawdbot/zalouser
@ -29,15 +42,6 @@ clawdbot plugins install @clawdbot/zalouser
Restart the Gateway afterwards. Restart the Gateway afterwards.
### Option B: install from a local folder (dev)
```bash
clawdbot plugins install ./extensions/zalouser
cd ./extensions/zalouser && pnpm install
```
Restart the Gateway afterwards.
## Prerequisite: zca-cli ## Prerequisite: zca-cli
The Gateway machine must have `zca` on `PATH`: The Gateway machine must have `zca` on `PATH`:

View File

@ -81,14 +81,24 @@ When the operator says “release”, immediately do this preflight (no extra qu
## Plugin publish scope (npm) ## Plugin publish scope (npm)
We only publish **existing npm plugins** under the `@clawdbot/*` scope. Bundled We publish some plugins to npm under the `@clawdbot/*` scope for users who prefer
plugins that are not on npm stay **disk-tree only** (still shipped in explicit installation. However, **all plugins are bundled** in `extensions/**` and
`extensions/**`). their dependencies are **auto-installed on first load** when enabled.
Process to derive the list: ### Bundled plugins with auto-install
1) `npm search @clawdbot --json` and capture the package names.
2) Compare with `extensions/*/package.json` names. Bundled plugins ship with source code but not `node_modules`. When a bundled plugin
3) Publish only the **intersection** (already on npm). is enabled and has external dependencies (not `clawdbot` workspace refs), the loader
automatically runs `npm install` in the plugin directory on first load.
This means users don't need to manually install plugins or their dependencies—they
just enable the plugin in config and restart.
### npm-published plugins (optional)
Some plugins are also published to npm for users who prefer explicit installation
via `clawdbot plugins install @clawdbot/xxx`. This copies the plugin to
`~/.clawdbot/extensions/` and runs `npm install` there.
Current npm plugin list (update as needed): Current npm plugin list (update as needed):
- @clawdbot/bluebubbles - @clawdbot/bluebubbles
@ -103,5 +113,14 @@ Current npm plugin list (update as needed):
- @clawdbot/zalo - @clawdbot/zalo
- @clawdbot/zalouser - @clawdbot/zalouser
Release notes must also call out **new optional bundled plugins** that are **not To add a new plugin to npm:
on by default** (example: `tlon`). 1) First-publish manually: `cd extensions/<plugin> && npm publish --access public`
2) Add to the list above
3) Future releases will include it automatically
### Bundled-only plugins
Some plugins are bundled but not published to npm (e.g., `tlon`). These work via
the auto-install mechanism—users just enable them in config.
Release notes should call out **new bundled plugins** so users know they're available.

View File

@ -1,3 +1,4 @@
import { spawnSync } from "node:child_process";
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
@ -43,6 +44,69 @@ const registryCache = new Map<string, PluginRegistry>();
const defaultLogger = () => createSubsystemLogger("plugins"); const defaultLogger = () => createSubsystemLogger("plugins");
/**
* Ensures plugin dependencies are installed for bundled plugins.
* Bundled plugins ship with source but not node_modules; this installs
* deps on first load if the plugin has dependencies in package.json.
*/
function ensureBundledPluginDeps(params: {
rootDir: string;
pluginId: string;
logger: PluginLogger;
}): { ok: boolean; error?: string } {
const { rootDir, pluginId, logger } = params;
const packageJsonPath = path.join(rootDir, "package.json");
if (!fs.existsSync(packageJsonPath)) {
return { ok: true }; // No package.json, nothing to install
}
let manifest: { dependencies?: Record<string, string> };
try {
manifest = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
} catch {
return { ok: true }; // Can't parse, skip
}
const deps = manifest.dependencies ?? {};
const depNames = Object.keys(deps).filter(
(name) => !name.startsWith("clawdbot") && name !== "clawdbot",
);
if (depNames.length === 0) {
return { ok: true }; // No external dependencies
}
// Check if first dependency exists in node_modules
const firstDep = depNames[0];
const depPath = path.join(rootDir, "node_modules", ...firstDep.split("/"));
if (fs.existsSync(depPath)) {
return { ok: true }; // Dependencies already installed
}
logger.info?.(`[plugins] ${pluginId}: installing dependencies…`);
try {
const result = spawnSync("npm", ["install", "--omit=dev", "--silent"], {
cwd: rootDir,
encoding: "utf-8",
timeout: 300_000,
stdio: ["ignore", "pipe", "pipe"],
});
if (result.status !== 0) {
const errorMsg = result.stderr?.trim() || result.stdout?.trim() || "unknown error";
return { ok: false, error: `npm install failed: ${errorMsg}` };
}
logger.info?.(`[plugins] ${pluginId}: dependencies installed`);
return { ok: true };
} catch (err) {
return { ok: false, error: `failed to install dependencies: ${String(err)}` };
}
}
const resolvePluginSdkAlias = (): string | null => { const resolvePluginSdkAlias = (): string | null => {
try { try {
const modulePath = fileURLToPath(import.meta.url); const modulePath = fileURLToPath(import.meta.url);
@ -282,6 +346,29 @@ export function loadClawdbotPlugins(options: PluginLoadOptions = {}): PluginRegi
continue; continue;
} }
// Ensure bundled plugin dependencies are installed before loading
if (candidate.origin === "bundled") {
const depsResult = ensureBundledPluginDeps({
rootDir: candidate.rootDir,
pluginId,
logger,
});
if (!depsResult.ok) {
logger.error(`[plugins] ${record.id} failed to install deps: ${depsResult.error}`);
record.status = "error";
record.error = depsResult.error ?? "failed to install dependencies";
registry.plugins.push(record);
seenIds.set(pluginId, candidate.origin);
registry.diagnostics.push({
level: "error",
pluginId: record.id,
source: record.source,
message: record.error,
});
continue;
}
}
let mod: ClawdbotPluginModule | null = null; let mod: ClawdbotPluginModule | null = null;
try { try {
mod = jiti(candidate.source) as ClawdbotPluginModule; mod = jiti(candidate.source) as ClawdbotPluginModule;