Feature Request: Plugin shutdown hook for graceful cleanup #7529

Open
opened 2026-02-16 18:07:27 -05:00 by yindo · 1 comment
Owner

Originally created by @ErcinDedeoglu on GitHub (Jan 25, 2026).

Originally assigned to: @thdxr on GitHub.

Summary

Add a shutdown/exit hook to the plugin system so plugins can perform cleanup operations before OpenCode exits.

Use Case

I'm developing opencode-sync, a plugin that syncs OpenCode data (sessions, messages, config, etc.) to a private GitHub repository.

The plugin needs to sync local changes to remote before exit to prevent data loss. Currently, there's no way for plugins to:

  1. Know when OpenCode is about to exit
  2. Perform async cleanup operations before process termination

Current Behavior

Looking at the source:

  • packages/plugin/src/index.ts - The Hooks interface only has event hook for Bus events
  • packages/opencode/src/cli/cmd/tui/thread.ts - Has onExit callback but it's internal, not exposed to plugins
  • Session events are Created, Updated, Deleted, Diff, Error - no shutdown event

When OpenCode exits (Ctrl+C, :q, etc.), plugins have no opportunity to run cleanup code.

Proposed Solution

Add a shutdown hook to the plugin Hooks interface:

export interface Hooks {
  event?(input: { event: Bus.Event }): void;
  shutdown?(): Promise<void>;  // New hook
}

The shutdown hook should:

  1. Be called before OpenCode terminates
  2. Support async operations (return Promise)
  3. Have a reasonable timeout (e.g., 5 seconds) to prevent hanging

Alternatives Considered

  1. Node.js process events (beforeExit, SIGINT, SIGTERM) - OpenCode intercepts signals before plugin handlers run
  2. Frequent background syncing - Works but can't guarantee final changes are synced
  3. File watching with debounce - Same limitation, final changes may be lost

Additional Context

This would enable plugins to:

  • Sync data to remote storage
  • Close database connections
  • Flush logs
  • Clean up temporary files
  • Save state

Thank you for considering this feature!

Originally created by @ErcinDedeoglu on GitHub (Jan 25, 2026). Originally assigned to: @thdxr on GitHub. ## Summary Add a shutdown/exit hook to the plugin system so plugins can perform cleanup operations before OpenCode exits. ## Use Case I'm developing [opencode-sync](https://github.com/ErcinDedeoglu/opencode-sync), a plugin that syncs OpenCode data (sessions, messages, config, etc.) to a private GitHub repository. The plugin needs to sync local changes to remote before exit to prevent data loss. Currently, there's no way for plugins to: 1. Know when OpenCode is about to exit 2. Perform async cleanup operations before process termination ## Current Behavior Looking at the source: - `packages/plugin/src/index.ts` - The `Hooks` interface only has `event` hook for Bus events - `packages/opencode/src/cli/cmd/tui/thread.ts` - Has `onExit` callback but it's internal, not exposed to plugins - Session events are `Created`, `Updated`, `Deleted`, `Diff`, `Error` - no shutdown event When OpenCode exits (Ctrl+C, `:q`, etc.), plugins have no opportunity to run cleanup code. ## Proposed Solution Add a `shutdown` hook to the plugin `Hooks` interface: ```typescript export interface Hooks { event?(input: { event: Bus.Event }): void; shutdown?(): Promise<void>; // New hook } ``` The shutdown hook should: 1. Be called before OpenCode terminates 2. Support async operations (return Promise) 3. Have a reasonable timeout (e.g., 5 seconds) to prevent hanging ## Alternatives Considered 1. **Node.js process events** (`beforeExit`, `SIGINT`, `SIGTERM`) - OpenCode intercepts signals before plugin handlers run 2. **Frequent background syncing** - Works but can't guarantee final changes are synced 3. **File watching with debounce** - Same limitation, final changes may be lost ## Additional Context This would enable plugins to: - Sync data to remote storage - Close database connections - Flush logs - Clean up temporary files - Save state Thank you for considering this feature!
Author
Owner

@github-actions[bot] commented on GitHub (Jan 25, 2026):

This issue might be a duplicate of existing issues. Please check:

  • #10003: Add shutdown/exit event allowing a plugin to run before closing (direct duplicate)
  • #9157: Memory leak: Instance disposal doesn't clean up plugins or cached resources (requests dispose() hook for cleanup)
  • #9859: Windows: Ghost port bindings when server killed via SIGTERM (related signal handling for graceful shutdown)
  • #9156: Memory leak: Uncleaned timeouts, intervals, and subscriptions (related resource cleanup needs)
  • #5409: SessionStart hook for session lifecycle events (related plugin lifecycle hook requests)
  • #5305: Plugin Hook for Instant TUI Commands (related plugin system extensibility)
  • #5515: Finish hook, when LLM is ready to get new instructions (related lifecycle hook requests)

Feel free to ignore if none of these address your specific case.

@github-actions[bot] commented on GitHub (Jan 25, 2026): This issue might be a duplicate of existing issues. Please check: - #10003: Add shutdown/exit event allowing a plugin to run before closing (direct duplicate) - #9157: Memory leak: Instance disposal doesn't clean up plugins or cached resources (requests dispose() hook for cleanup) - #9859: Windows: Ghost port bindings when server killed via SIGTERM (related signal handling for graceful shutdown) - #9156: Memory leak: Uncleaned timeouts, intervals, and subscriptions (related resource cleanup needs) - #5409: SessionStart hook for session lifecycle events (related plugin lifecycle hook requests) - #5305: Plugin Hook for Instant TUI Commands (related plugin system extensibility) - #5515: Finish hook, when LLM is ready to get new instructions (related lifecycle hook requests) Feel free to ignore if none of these address your specific case.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#7529