Refactor OpenClaw Extensions: Reduce LOC by 700+
You probably know the feeling of seeing the same code patterns every time you open a new file. When you’re building plugins, it often feels like you’re writing the same configuration logic and security checks over and over. We’ve identified a few areas where we can clean this up and save a lot of lines of code.
Here is the plan for refactoring our cluster backlog.
1. Channel plugin config and security scaffolding
Section titled “1. Channel plugin config and security scaffolding”This is our highest-value cluster. You’ll see repeated shapes across many channel plugins that handle account management and security policies.
Repeated shapes across many channel plugins:
config.listAccountIdsconfig.resolveAccountconfig.defaultAccountIdconfig.setAccountEnabledconfig.deleteAccountconfig.describeAccountsecurity.resolveDmPolicy
Strong examples:
extensions/telegram/src/channel.tsextensions/googlechat/src/channel.tsextensions/slack/src/channel.tsextensions/discord/src/channel.tsextensions/matrix/src/channel.tsextensions/irc/src/channel.tsextensions/signal/src/channel.tsextensions/mattermost/src/channel.ts
Likely extraction shape:
buildChannelConfigAdapter(...)buildMultiAccountConfigAdapter(...)buildDmSecurityAdapter(...)
Expected savings:
- ~250-450 LOC
Risk:
- Medium. Each channel has slightly different
isConfigured, warnings, and normalization.
2. Extension runtime singleton boilerplate
Section titled “2. Extension runtime singleton boilerplate”This is a very safe area to clean up. Nearly every extension you look at uses the same runtime holder pattern.
let runtime: PluginRuntime | null = nullsetXRuntimegetXRuntime
Strong examples:
extensions/telegram/src/runtime.tsextensions/matrix/src/runtime.tsextensions/slack/src/runtime.tsextensions/discord/src/runtime.tsextensions/whatsapp/src/runtime.tsextensions/imessage/src/runtime.tsextensions/twitch/src/runtime.ts
Special-case variants:
extensions/bluebubbles/src/runtime.tsextensions/line/src/runtime.tsextensions/synology-chat/src/runtime.ts
Likely extraction shape:
createPluginRuntimeStore<T>(errorMessage)
Expected savings:
- ~180-260 LOC
Risk:
- Low
3. Onboarding prompt and config-patch steps
Section titled “3. Onboarding prompt and config-patch steps”This area covers a large surface. Many onboarding files repeat the same steps for resolving IDs and prompting for secrets.
Strong examples:
extensions/bluebubbles/src/onboarding.tsextensions/googlechat/src/onboarding.tsextensions/msteams/src/onboarding.tsextensions/zalo/src/onboarding.tsextensions/zalouser/src/onboarding.tsextensions/nextcloud-talk/src/onboarding.tsextensions/matrix/src/onboarding.tsextensions/irc/src/onboarding.ts
Existing helper seam:
src/channels/plugins/onboarding/helpers.ts
Likely extraction shape:
promptAllowFromList(...)buildDmPolicyAdapter(...)applyScopedAccountPatch(...)promptSecretFields(...)
Expected savings:
- ~300-600 LOC
Risk:
- Medium. Easy to over-generalize; keep helpers narrow and composable.
4. Multi-account config-schema fragments
Section titled “4. Multi-account config-schema fragments”You’ll find repeated schema fragments across various extensions. These common patterns handle things like allowlists and account-scoped configurations.
Common patterns:
const allowFromEntry = z.union([z.string(), z.number()])- account schema plus:
accounts: z.object({}).catchall(accountSchema).optional()defaultAccount: z.string().optional()
- repeated DM/group fields
- repeated markdown/tool policy fields
Strong examples:
extensions/bluebubbles/src/config-schema.tsextensions/zalo/src/config-schema.tsextensions/zalouser/src/config-schema.tsextensions/matrix/src/config-schema.tsextensions/nostr/src/config-schema.ts
Likely extraction shape:
AllowFromEntrySchemabuildMultiAccountChannelSchema(accountSchema)buildCommonDmGroupFields(...)
Expected savings:
- ~120-220 LOC
Risk:
- Low to medium. Some schemas are simple, some are special.
5. Webhook and monitor lifecycle startup
Section titled “5. Webhook and monitor lifecycle startup”This is a good medium-value cluster. We see the same startAccount and monitor setup patterns across several extensions.
Strong examples:
extensions/googlechat/src/channel.tsextensions/bluebubbles/src/channel.tsextensions/zalo/src/channel.tsextensions/telegram/src/channel.tsextensions/nextcloud-talk/src/channel.ts
Existing helper seam:
src/plugin-sdk/channel-lifecycle.ts
Likely extraction shape:
- helper for account monitor lifecycle
- helper for webhook-backed account startup
Expected savings:
- ~150-300 LOC
Risk:
- Medium to high. Transport details diverge quickly.
6. Small exact-clone cleanup
Section titled “6. Small exact-clone cleanup”This is a low-risk cleanup bucket for exact duplicates found in the codebase.
Examples:
- duplicated gateway argv detection:
src/infra/gateway-lock.tssrc/cli/daemon-cli/lifecycle.ts
- duplicated port diagnostics rendering:
src/cli/daemon-cli/restart-health.ts
- duplicated session-key construction:
src/web/auto-reply/monitor/broadcast.ts
Expected savings:
- ~30-60 LOC
Risk:
- Low
Test clusters
Section titled “Test clusters”We can also clean up our test suites by extracting shared helpers for common event fixtures and setup harnesses.
LINE webhook event fixtures
Section titled “LINE webhook event fixtures”Strong examples:
src/line/bot-handlers.test.ts
Likely extraction:
makeLineEvent(...)runLineEvent(...)makeLineAccount(...)
Expected savings:
- ~120-180 LOC
Telegram native command auth matrix
Section titled “Telegram native command auth matrix”Strong examples:
src/telegram/bot-native-commands.group-auth.test.tssrc/telegram/bot-native-commands.plugin-auth.test.ts
Likely extraction:
- forum context builder
- denied-message assertion helper
- table-driven auth cases
Expected savings:
- ~80-140 LOC
Zalo lifecycle setup
Section titled “Zalo lifecycle setup”Strong examples:
extensions/zalo/src/monitor.lifecycle.test.ts
Likely extraction:
- shared monitor setup harness
Expected savings:
- ~50-90 LOC
Brave llm-context unsupported-option tests
Section titled “Brave llm-context unsupported-option tests”Strong examples:
src/agents/tools/web-tools.enabled-defaults.test.ts
Likely extraction:
it.each(...)matrix
Expected savings:
- ~30-50 LOC
Suggested order
Section titled “Suggested order”If you’re looking for a place to start, we recommend following this order:
- Runtime singleton boilerplate
- Small exact-clone cleanup
- Config and security builder extraction
- Test-helper extraction
- Onboarding step extraction
- Monitor lifecycle helper extraction
Next steps
Section titled “Next steps”- Check out the plugin-sdk/channel-lifecycle.ts for existing helpers.
- Review channels/plugins/onboarding/helpers.ts before adding new onboarding logic.
OpenClaw Expert
Still stuck?
If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.