Skip to content

Repository files navigation

Claude Code platform License npm version npm downloads node version plugin

claude-lifecycle-core

Middleware hub for Claude Code plugins. Register once, dispatch to many.

claude-lifecycle-core is a Claude Code plugin that hooks into all lifecycle events and dispatches them to lightweight subscriber plugins. Subscribers are npm packages that export plain JavaScript callbacks — no hooks.json boilerplate, no stdin parsing, no response formatting.

Install

npm install -g claude-lifecycle-core

The hub registers itself as a Claude Code plugin automatically via postinstall. It starts dispatching events in your next Claude Code session.

Writing a Subscriber Plugin

const { definePlugin } = require('claude-lifecycle-core');

module.exports = definePlugin({
  name: 'my-plugin',
  version: '1.0.0',
  subscriptions: {
    onPostToolBatch: async (context) => {
      return { additionalContext: 'Hello from my plugin!' };
    },
  },
});

Publish as an npm package with claude-lifecycle-core as a peerDependency.

Available Hooks

Hook Callback Can Block?
SessionStart onSessionStart(ctx) No
UserPromptSubmit onUserPromptSubmit(ctx) Yes
PreToolUse onPreToolUse(ctx) Yes
PostToolBatch onPostToolBatch(ctx) No
SubagentStart onSubagentStart(ctx) No
SessionEnd onSessionEnd(ctx) No

HookContext

{
  hookEventName: 'PostToolBatch',
  toolCalls: [...],
  prompt: '...',
  raw: { ... },
  store: {
    get(key) { ... },
    set(key, value) { ... },
  },
}

Return Types

Non-blocking hooks: Return { additionalContext: 'string' } to inject a system reminder, or null for no-op.

Blocking hooks: Return { status: 'approved' } or { status: 'blocked', message: 'reason' }. Null/undefined = approved.

Shared Store

The context.store persists key-value data across hook events within a session. Store is reset on each SessionStart. Namespace your keys: 'my-plugin:counter'.

CLI

lifecycle install <path>       # Install a subscriber plugin
lifecycle uninstall <name>     # Remove a plugin from registry
lifecycle enable <name>        # Enable a plugin
lifecycle disable <name>       # Disable a plugin
lifecycle list                 # Show all registered plugins
lifecycle config               # Show hub configuration

How It Works

  • The hub is the only Claude Code plugin — subscribers are NOT separate plugins
  • On each hook event, the hub reads stdin, loads enabled subscribers, and calls matching callbacks
  • Each plugin gets a 2s timeout (configurable) with a 4s total timeout across all plugins
  • Results are aggregated: additionalContext strings concatenated with --- separators
  • For blocking hooks (UserPromptSubmit, PreToolUse), any plugin returning blocked halts the action
  • Errors are caught per-plugin — one plugin crashing never affects others
  • Store is cleared on SessionStart to keep data session-scoped

Config

Hub config at ~/.config/claude-lifecycle/config.json:

{
  "defaultTimeout": 2000,
  "totalTimeout": 4000,
  "logLevel": "error"
}

Uninstall

npm uninstall -g claude-lifecycle-core

The preuninstall script automatically deregisters the plugin from Claude Code.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages