[PR #11060] feat(plugin): add dynamic skill discovery via plugin hooks #13647

Open
opened 2026-02-16 18:18:29 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/11060

State: open
Merged: No


Add Dynamic Skill Discovery via Plugin Hooks

Fixes #8304 #10148

What does this PR do?

This PR adds support for plugins to dynamically provide skills through two new hooks: skill.list and skill.load. Plugins can now register skills at runtime that will be discovered and made available to the LLM alongside static skills from .opencode/skill/ directories.

Problem Solved

Previously, skills were only loaded from static filesystem locations. Plugins had no way to dynamically provide skills based on runtime conditions. This limitation prevented use cases like:

  • Loading skills specific to the current workspace/project context
  • Providing skills that depend on external configuration or APIs
  • Dynamic skill discovery based on environment or runtime state
  • Context-aware skills that change based on user preferences or project type

Implementation

The implementation adds a skill provider registry system:

  1. Provider Registration (packages/opencode/src/plugin/index.ts):

    • During plugin initialization, plugins implementing skill.list or skill.load hooks are registered as skill providers
    • Each provider is stored in a module-level registry
  2. Dynamic Skill Discovery (packages/opencode/src/skill/skill.ts):

    • Skill.all() now queries all registered providers in addition to static skills
    • Skill.get() checks providers when looking up skills by name
    • Skill.loadContent() uses provider's skill.load hook to retrieve skill content
    • Provider errors are caught and logged without crashing the system
  3. Hook Definitions (packages/plugin/src/index.ts):

    • skill.list: Returns array of skill metadata (name, description, location)
    • skill.load: Returns skill content for a given location string

How did you verify your code works?

  1. Type Safety: bun typecheck passes without errors

  2. Test Suite: bun turbo test executes successfully

  3. Manual Testing:

    • Created a plugin implementing skill.list and skill.load hooks
    • Verified dynamic skills from plugin appear in the Skill tool description
    • Executed plugin-provided skills successfully
    • Confirmed static skills continue to work alongside dynamic skills
    • Tested error handling by triggering provider failures
    • Verified skills are re-discovered on each session turn
  4. Code Review:

    • Follows OpenCode style guide (no any types, uses const, error handling with .catch())
    • Maintains backward compatibility with existing static skill loading
    • Properly handles multiple providers and merges results

Edge Cases Handled

  • Multiple plugins can each provide skills independently
  • Provider failures are logged but don't crash the system
  • Static and dynamic skills are properly merged (dynamic skills can override static ones)
  • Skill loading falls back to filesystem if no provider handles the location
**Original Pull Request:** https://github.com/anomalyco/opencode/pull/11060 **State:** open **Merged:** No --- # Add Dynamic Skill Discovery via Plugin Hooks Fixes #8304 #10148 ## What does this PR do? This PR adds support for plugins to dynamically provide skills through two new hooks: `skill.list` and `skill.load`. Plugins can now register skills at runtime that will be discovered and made available to the LLM alongside static skills from `.opencode/skill/` directories. ## Problem Solved Previously, skills were only loaded from static filesystem locations. Plugins had no way to dynamically provide skills based on runtime conditions. This limitation prevented use cases like: - Loading skills specific to the current workspace/project context - Providing skills that depend on external configuration or APIs - Dynamic skill discovery based on environment or runtime state - Context-aware skills that change based on user preferences or project type ## Implementation The implementation adds a skill provider registry system: 1. **Provider Registration** (`packages/opencode/src/plugin/index.ts`): - During plugin initialization, plugins implementing `skill.list` or `skill.load` hooks are registered as skill providers - Each provider is stored in a module-level registry 2. **Dynamic Skill Discovery** (`packages/opencode/src/skill/skill.ts`): - `Skill.all()` now queries all registered providers in addition to static skills - `Skill.get()` checks providers when looking up skills by name - `Skill.loadContent()` uses provider's `skill.load` hook to retrieve skill content - Provider errors are caught and logged without crashing the system 3. **Hook Definitions** (`packages/plugin/src/index.ts`): - `skill.list`: Returns array of skill metadata (name, description, location) - `skill.load`: Returns skill content for a given location string ## How did you verify your code works? 1. **Type Safety**: `bun typecheck` passes without errors 2. **Test Suite**: `bun turbo test` executes successfully 3. **Manual Testing**: - Created a plugin implementing `skill.list` and `skill.load` hooks - Verified dynamic skills from plugin appear in the Skill tool description - Executed plugin-provided skills successfully - Confirmed static skills continue to work alongside dynamic skills - Tested error handling by triggering provider failures - Verified skills are re-discovered on each session turn 4. **Code Review**: - Follows OpenCode style guide (no `any` types, uses `const`, error handling with `.catch()`) - Maintains backward compatibility with existing static skill loading - Properly handles multiple providers and merges results ## Edge Cases Handled - Multiple plugins can each provide skills independently - Provider failures are logged but don't crash the system - Static and dynamic skills are properly merged (dynamic skills can override static ones) - Skill loading falls back to filesystem if no provider handles the location
yindo added the pull-request label 2026-02-16 18:18:29 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#13647