openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
99 lines (82 loc) • 5.55 kB
Markdown
---
summary: "The lightweight setup entry helper and the narrow setup helper families"
title: "Plugin SDK defineSetupPluginEntry helper"
sidebarTitle: "defineSetupPluginEntry"
read_when:
- You are writing a setup-entry.ts file
- You need the narrow setup, archive, or secret-file helper imports
---
The entry helper for the lightweight `setup-entry.ts` file, and the narrow
setup helper families that pair with it. Part of the
[Plugin entry points](/plugins/sdk-entrypoints) reference.
## `defineSetupPluginEntry`
**Import:** `openclaw/plugin-sdk/channel-core`
For the lightweight `setup-entry.ts` file. Returns just `{ plugin }` with no
runtime or CLI wiring.
```typescript
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
export default defineSetupPluginEntry(myChannelPlugin);
```
OpenClaw loads this instead of the full entry when a channel is disabled or
unconfigured. See
[Setup and Config](/plugins/sdk-setup#setup-entry) for when this matters.
Doctor also inspects this public setup entry when finishing a deferred plugin
upgrade. It uses `plugin.lifecycle.detectLegacyStateMigrations` when provided.
Keep the detector on this lightweight entry while a released version may still
need a legacy migration; omitting it does not prove that the full entry has no
migration, so Doctor keeps the upgrade obligation pending. Missing or broken
setup entries also keep the obligation pending.
Pair `defineSetupPluginEntry(...)` with the narrow setup helper families:
| Import | Use for |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `openclaw/plugin-sdk/setup-runtime` | Runtime-safe setup helpers: `createSetupTranslator`, import-safe setup patch adapters, lookup-note output, `promptResolvedAllowFrom`, `splitSetupEntries`, delegated setup proxies |
| `openclaw/plugin-sdk/channel-setup` | Optional-install setup surfaces |
| `openclaw/plugin-sdk/channel-dm-policy` | Account-aware DM policy descriptors for setup flows |
| `openclaw/plugin-sdk/setup-tools` | Setup/install CLI, archive, and docs helpers |
| `openclaw/plugin-sdk/archive` | Bounded TAR/gzip member inspection, archive extraction, and single-entry reads |
| `openclaw/plugin-sdk/root-walk` | Budgeted, root-bounded directory walking |
| `openclaw/plugin-sdk/secret-file` | Pinned secret reads and first-writer-wins creation |
`inspectTarArchive({ archivePath, timeoutMs, limits, entryFilter, onFiltered })`
returns a bounded, frozen list of accepted `{ path, kind, size }` TAR/gzip members
without creating an extracted tree. It uses fs-safe's complete admission and
zero-strip extraction policy, not tar display output. Paths use the existing
canonical archive identity; LF and Unicode spelling are preserved. Use matching
filter/limit settings and retain or verify the same archive bytes for subsequent
extraction: inspection results are not reusable write authority. Only the resolved
result is complete-admission evidence; a filter callback can precede a later
policy failure. The member manifest does not synthesize implicit parent directories,
so whole-tree consumers must authorize those parent paths separately.
Keep heavy SDKs, CLI registration, and long-lived runtime services in the
full entry.
Bundled workspace channels that split setup and runtime surfaces can use
`defineBundledChannelSetupEntry(...)` from
`openclaw/plugin-sdk/channel-entry-contract` instead. It lets the setup
entry keep setup-safe plugin/secrets exports while still exposing a runtime
setter:
```typescript
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
export default defineBundledChannelSetupEntry({
importMetaUrl: import.meta.url,
plugin: {
specifier: "./channel-plugin-api.js",
exportName: "myChannelPlugin",
},
runtime: {
specifier: "./runtime-api.js",
exportName: "setMyChannelRuntime",
},
registerSetupRuntime(api) {
api.registerHttpRoute({
path: "/my-channel/events",
auth: "plugin",
handler: async (req, res) => {
/* setup-safe route */
},
});
},
});
```
Use this only when a setup flow truly needs a lightweight runtime setter or
setup-safe gateway surface for an unconfigured channel.
`registerSetupRuntime` runs only for `"setup-runtime"` loads; keep it
limited to config-only routes or methods required by that setup flow.