Skip to content

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.listAccountIds
  • config.resolveAccount
  • config.defaultAccountId
  • config.setAccountEnabled
  • config.deleteAccount
  • config.describeAccount
  • security.resolveDmPolicy

Strong examples:

  • extensions/telegram/src/channel.ts
  • extensions/googlechat/src/channel.ts
  • extensions/slack/src/channel.ts
  • extensions/discord/src/channel.ts
  • extensions/matrix/src/channel.ts
  • extensions/irc/src/channel.ts
  • extensions/signal/src/channel.ts
  • extensions/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 = null
  • setXRuntime
  • getXRuntime

Strong examples:

  • extensions/telegram/src/runtime.ts
  • extensions/matrix/src/runtime.ts
  • extensions/slack/src/runtime.ts
  • extensions/discord/src/runtime.ts
  • extensions/whatsapp/src/runtime.ts
  • extensions/imessage/src/runtime.ts
  • extensions/twitch/src/runtime.ts

Special-case variants:

  • extensions/bluebubbles/src/runtime.ts
  • extensions/line/src/runtime.ts
  • extensions/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.ts
  • extensions/googlechat/src/onboarding.ts
  • extensions/msteams/src/onboarding.ts
  • extensions/zalo/src/onboarding.ts
  • extensions/zalouser/src/onboarding.ts
  • extensions/nextcloud-talk/src/onboarding.ts
  • extensions/matrix/src/onboarding.ts
  • extensions/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.

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.ts
  • extensions/zalo/src/config-schema.ts
  • extensions/zalouser/src/config-schema.ts
  • extensions/matrix/src/config-schema.ts
  • extensions/nostr/src/config-schema.ts

Likely extraction shape:

  • AllowFromEntrySchema
  • buildMultiAccountChannelSchema(accountSchema)
  • buildCommonDmGroupFields(...)

Expected savings:

  • ~120-220 LOC

Risk:

  • Low to medium. Some schemas are simple, some are special.

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.ts
  • extensions/bluebubbles/src/channel.ts
  • extensions/zalo/src/channel.ts
  • extensions/telegram/src/channel.ts
  • extensions/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.

This is a low-risk cleanup bucket for exact duplicates found in the codebase.

Examples:

  • duplicated gateway argv detection:
    • src/infra/gateway-lock.ts
    • src/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

We can also clean up our test suites by extracting shared helpers for common event fixtures and setup harnesses.

Strong examples:

  • src/line/bot-handlers.test.ts

Likely extraction:

  • makeLineEvent(...)
  • runLineEvent(...)
  • makeLineAccount(...)

Expected savings:

  • ~120-180 LOC

Strong examples:

  • src/telegram/bot-native-commands.group-auth.test.ts
  • src/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

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

If you’re looking for a place to start, we recommend following this order:

  1. Runtime singleton boilerplate
  2. Small exact-clone cleanup
  3. Config and security builder extraction
  4. Test-helper extraction
  5. Onboarding step extraction
  6. Monitor lifecycle helper extraction

AI Setup Assistant

OpenClaw

OpenClaw Expert

Still stuck?

If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.