Files
ClawSkills/development/docs/entry-point.md
zhi 238574ffd2 feat: add development and hf-hangman-lab skills
development: absorbed openclaw-plugin-dev as a workflow, with
reference docs for plugin structure, hooks, tools, state, config.

hf-hangman-lab: hf-wakeup workflow — full agent wakeup lifecycle:
set busy → check due slots → select & defer → identify task →
plan work → create work channel → execute. All branches end with
status reset to idle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-19 13:31:27 +00:00

1.3 KiB

Plugin Entry Point

Format

import type { OpenClawPluginApi } from "openclaw/plugin-sdk";

const _G = globalThis as Record<string, unknown>;
const LIFECYCLE_KEY = "_myPluginGatewayLifecycleRegistered";

export default {
  id: "my-plugin",
  name: "My Plugin",
  register(api: OpenClawPluginApi) {
    const config = normalizeConfig(api);

    // Gateway lifecycle: only once
    if (!_G[LIFECYCLE_KEY]) {
      _G[LIFECYCLE_KEY] = true;
      // Start sidecars, init global resources
      api.on("gateway_stop", () => { _G[LIFECYCLE_KEY] = false; });
    }

    // Agent session hooks: every register() call (dedup inside handler)
    registerMyHook(api, config);

    // Tools
    registerMyTools(api, config);

    api.logger.info("my-plugin: registered");
  },
};

Why globalThis?

OpenClaw may hot-reload plugins. Module-level variables reset on reload, but globalThis persists. All mutable state must be on globalThis:

  • Startup flags → prevent double initialization
  • Dedup sets → prevent double hook execution
  • Runtime references → keep connections alive across reloads
  • Shared registries → preserve cross-plugin state

Naming Convention

_<pluginId>PluginXxx     # Internal state (e.g., _prismFacetRouters)
__<pluginId>             # Cross-plugin public API (e.g., __yonexusClient)