opencode-skill-activation
v0.4.13
Published
Dynamic skill activation plugin for OpenCode
Readme
opencode-skill-activation
Dynamic skill activation plugin for OpenCode that monitors session context and proactively suggests relevant skills to AI agents.
Version: v0.4.13 - Notifications use synthetic: true and ignored: true flags per MessageV2 spec to prevent agent switching (testing).
Features
- Context Monitoring: Tracks files edited, keywords, and skill usage
- Smart Recommendations: Suggests skills based on patterns and rules
- Safe Notifications: Safeguards prevent context flooding
- Dual Output: Supports both agent context and delegate formats
- Comprehensive Testing: 319+ unit tests with >80% coverage
- Starter Rules: Built-in rules for git, testing, typescript, docker, and database skills
Installation
# Add to your OpenCode plugin configuration
npm install opencode-skill-activation@latestNote: Version 0.4.8 fixes AI context pollution by separating internal logging from user notifications. Configure your preferred agent for notifications in the plugin config.
Quick Start
Add to OpenCode plugins:
{ "plugins": ["opencode-skill-activation"] }Configure (optional) - create
~/.config/opencode/skill-activation/config.json:{ "enabled": true, "verbosity": "minimal", "notifications": { "enabled": true, "agent": "generalist" } }Use skill_check tool:
skill_check({ task: "I'm working on a TypeScript React component", format: 'agent', });
Configuration
Create ~/.config/opencode/skill-activation/config.json:
{
"enabled": true,
"verbosity": "minimal",
"notifications": {
"enabled": true,
"agent": "generalist"
},
"safeguards": {
"cooldownMs": 60000,
"minFilesForProactive": 2,
"sessionStartGraceMs": 5000,
"minPriorityForInjection": "high"
},
"skillPaths": {
"strategy": "project-first",
"projectDir": ".opencode/skill",
"globalDir": "~/.config/opencode/skill",
"rulesStrategy": "global-only",
"projectRulesDir": ".opencode/skill-activation"
},
"metricsEnabled": true,
"triggerOnFileEdit": true,
"triggerOnWriteTools": true,
"autoCheckOnSessionStart": false,
"autoCheckOnSubagentStart": false
}Configuration Options
| Option | Type | Default | Description |
| ------------------------------------ | ------- | ---------------------------- | ------------------------------------------------------------ |
| enabled | boolean | true | Enable/disable the plugin |
| verbosity | string | "minimal" | Output level: "silent", "minimal", "detailed" |
| safeguards.cooldownMs | number | 60000 | Milliseconds between suggestions |
| safeguards.minFilesForProactive | number | 2 | Files needed before proactive suggestions |
| safeguards.sessionStartGraceMs | number | 5000 | Grace period after session start |
| safeguards.minPriorityForInjection | string | "high" | Minimum priority: "critical", "high", "medium", "low" |
| metricsEnabled | boolean | true | Enable metrics collection |
| triggerOnFileEdit | boolean | true | Trigger on file edits |
| triggerOnWriteTools | boolean | true | Trigger on write operations |
| autoCheckOnSessionStart | boolean | false | Auto-check skills at session start |
| autoCheckOnSubagentStart | boolean | false | Auto-check on subagent start |
| notifications.enabled | boolean | true | Enable/disable TUI notifications |
| notifications.agent | string | "generalist" | Agent to use for notifications (set to "" to disable) |
| skillPaths.strategy | string | "project-first" | Skill lookup: "project-first", "project-only", "global-only" |
| skillPaths.projectDir | string | ".opencode/skill" | Custom project skill directory (relative to project root) |
| skillPaths.globalDir | string | "~/.config/opencode/skill" | Custom global skill directory |
| skillPaths.rulesStrategy | string | "global-only" | Rules lookup: "global-only", "project-first", "project-only" |
| skillPaths.projectRulesDir | string | ".opencode/skill-activation" | Custom project rules directory |
Creating Rules
Create ~/.config/opencode/skill-activation/rules.json:
{
"version": "1.0",
"description": "My custom skill activation rules",
"skills": {
"typescript-expert": {
"priority": "high",
"description": "Suggest for TypeScript work",
"enabled": true,
"promptTriggers": {
"keywords": ["typescript", "ts", "type safety"],
"intentPatterns": [".*type.*system.*", ".*interface.*"],
"filePatterns": ["**/*.ts", "**/*.tsx"],
"excludeKeywords": ["not typescript", "javascript only"],
"excludeFilePatterns": ["**/test/**"]
},
"suggestsWith": ["react-ts", "node-ts"]
},
"rust-expert": {
"priority": "high",
"description": "Suggest for Rust work",
"enabled": true,
"promptTriggers": {
"keywords": ["rust", "cargo", "rustc"],
"filePatterns": ["**/*.rs"]
}
}
}
}Rule Properties
| Property | Type | Description |
| ------------------------------------ | -------- | -------------------------------------- |
| priority | string | "critical", "high", "medium", or "low" |
| description | string | Human-readable description |
| enabled | boolean | Enable/disable this rule |
| promptTriggers.keywords | string[] | Keywords to match (case-insensitive) |
| promptTriggers.intentPatterns | string[] | Regex patterns for intent matching |
| promptTriggers.filePatterns | string[] | Glob patterns for file matching |
| promptTriggers.excludeKeywords | string[] | Keywords that prevent matching |
| promptTriggers.excludeFilePatterns | string[] | File patterns that prevent matching |
| suggestsWith | string[] | Additional skills to suggest |
Usage
Using skill_check Tool
// Basic skill check
skill_check();
// With task context
({
task: "I'm debugging a memory leak in my Rust application",
});
// Agent-friendly output
skill_check({ format: 'agent' });
// Detailed output for display
skill_check({ format: 'delegate' });Example Output
Agent format:
Skill Suggestion: rust-debug
Based on your current context, the rust-debug skill may be helpful.
Reason: Matched keyword: rust
Priority: high
Usage: skill("rust-debug")Delegate format:
Skill Check Results
===================
Session: abc123
Context: 5 keywords, 3 files
Matched Skills (2):
--------------------
1. rust-debug
Priority: high
Match Type: keyword
Pattern: rust
Confidence: 70%
Reason: Matched keyword pattern
2. memory-analysis
Priority: medium
Match Type: intent
Pattern: .*memory.*leak.*
Confidence: 90%
Reason: Matched intent pattern
Loaded Skills: rust-expert
Files Tracked: src/main.rs, Cargo.toml, Cargo.lockAPI Reference
Plugin Functions
import { SkillActivationPlugin } from 'opencode-skill-activation';
// Create plugin instance
const plugin = new SkillActivationPlugin();
// Initialize and get hooks
const hooks = await plugin.createHooks();
// Runtime configuration updates
plugin.updateConfig({
verbosity: 'detailed',
safeguards: { cooldownMs: 30000 },
});
// Shutdown plugin
await plugin.shutdown();Types
import type {
PluginConfig,
SkillRule,
SkillRulesFile,
SessionState,
MatchedSkill,
} from 'opencode-skill-activation';How It Works
- Session Monitoring: Tracks files you read/edit and keywords in context
- Pattern Matching: Matches your context against defined rules
- Skill Suggestions: Recommends skills when rules match
- Learning: Improves recommendations based on your skill usage
Safeguards
The plugin includes safeguards to prevent notification flooding:
- Cooldown: 60 seconds between suggestions
- Grace Period: 5 seconds after session start
- Min Files: 2 files before proactive suggestions
- Min Priority: Only high+ priority suggestions auto-injected
Critical priority skills bypass all safeguards.
Troubleshooting
No skills being suggested
Check that plugin is enabled:
cat ~/.config/opencode/skill-activation/config.jsonVerify rules are properly formatted:
cat ~/.config/opencode/skill-activation/rules.json | jq .Check TUI output for errors:
{ "verbosity": "detailed" }Ensure you're editing/tracking enough files
Notifications cause agent switching (Known OpenCode Bug)
This is a known OpenCode bug (GitHub #4475, #4901). Calling session.prompt() with noReply: true causes the agent to switch back to the default agent.
Current Status: Notifications are disabled by default in v0.4.11+ due to this bug.
If you want notifications (and accept the agent switching behavior):
{
"notifications": {
"enabled": true,
"agent": ""
}
}Upstream Fix: GitHub issue #3378 proposes a skipInference parameter for silent message insertion. Once OpenCode implements this, notifications can be re-enabled without side effects.
Notifications polluting AI context (Legacy)
If using an older version where notifications were enabled by default:
{
"notifications": {
"enabled": true,
"agent": "generalist"
}
}The agent parameter is required for OpenCode's ignored: true flag to work correctly. Set it to whichever agent you use most (e.g., "generalist", "architect").
Repeated messages in loop
If you see repeated notification messages during subagent initiation, update to v0.4.8 or later which includes re-entrancy guards and separates internal logging from user notifications.
npm install opencode-skill-activation@latestToo many suggestions
- Increase cooldownMs in safeguards
- Raise minPriorityForInjection threshold
- Add more specific patterns to rules
- Reduce verbosity to "silent"
Configuration not loading
- Check config file exists at
~/.config/opencode/skill-activation/config.json - Verify JSON is valid
- Check file permissions
- Review TUI output for loading errors
Development
Installation
git clone https://github.com/yourusername/opencode-skill-activation.git
cd opencode-skill-activation
npm installBuilding
npm run buildTesting
# Run tests
npm run test
# Run with coverage
npm run test:coverage
# Run once
npm run test:runProject Structure
opencode-skill-activation/
├── src/
│ ├── config/ # Configuration loading and schemas
│ ├── rules/ # Pattern matching and rules engine
│ ├── context/ # Session state and tracking
│ ├── notify/ # Notification system (TUI, agent, safeguards)
│ ├── tools/ # Custom tools (skill_check, tool hooks)
│ └── utils/ # Utility functions
├── skill/ # Bundled skills
├── tests/ # Unit tests
└── package.jsonContributing
- Fork the repository
- Create a feature branch
- Add tests for your changes
- Ensure all tests pass
- Submit a pull request
License
MIT License - see LICENSE file for details.
Changelog
See CHANGELOG.md for version history and changes.
