opencode-plugin-preload-skills 1.1.4 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +251 -117
- package/dist/index.cjs +378 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +380 -51
- package/dist/index.js.map +1 -1
- package/package.json +11 -4
package/README.md
CHANGED
|
@@ -1,208 +1,342 @@
|
|
|
1
1
|
# opencode-plugin-preload-skills
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Smart skill loading for OpenCode — automatic, contextual, and budget-aware
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/opencode-plugin-preload-skills)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://github.com/juhas96/opencode-plugin-preload-skills)
|
|
8
8
|
|
|
9
|
-
A plugin for [OpenCode](https://opencode.ai) that
|
|
9
|
+
A powerful plugin for [OpenCode](https://opencode.ai) that intelligently loads skills based on context — file types, directory patterns, agent type, conversation content, and more.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
## Features
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
| Feature | Description |
|
|
16
|
+
|---------|-------------|
|
|
17
|
+
| **Always-On Skills** | Load skills at session start |
|
|
18
|
+
| **File-Type Triggers** | Load skills when touching `.py`, `.ts`, etc. |
|
|
19
|
+
| **Agent-Specific** | Different skills for different agents |
|
|
20
|
+
| **Path Patterns** | Glob patterns like `src/api/**` |
|
|
21
|
+
| **Content Triggers** | Keywords in conversation trigger skills |
|
|
22
|
+
| **Skill Groups** | Bundle skills together with `@group-name` |
|
|
23
|
+
| **Conditional Loading** | Load only if dependency exists |
|
|
24
|
+
| **Token Budget** | Cap total skill tokens to protect context |
|
|
25
|
+
| **Summaries Mode** | Load compact summaries instead of full content |
|
|
26
|
+
| **Usage Analytics** | Track which skills are actually used |
|
|
27
|
+
|
|
28
|
+
> **⚠️ Warning:** Preloaded skills consume context window tokens. Use `maxTokens` to set a budget and `useSummaries` for large skills.
|
|
22
29
|
|
|
23
30
|
---
|
|
24
31
|
|
|
25
32
|
## Quick Start
|
|
26
33
|
|
|
27
|
-
**1. Add
|
|
34
|
+
**1. Add to `opencode.json`:**
|
|
28
35
|
|
|
29
36
|
```json
|
|
30
37
|
{
|
|
31
|
-
"$schema": "https://opencode.ai/config.json",
|
|
32
38
|
"plugin": ["opencode-plugin-preload-skills"]
|
|
33
39
|
}
|
|
34
40
|
```
|
|
35
41
|
|
|
36
|
-
**2. Create
|
|
42
|
+
**2. Create `.opencode/preload-skills.json`:**
|
|
37
43
|
|
|
38
44
|
```json
|
|
39
45
|
{
|
|
40
|
-
"skills": ["
|
|
46
|
+
"skills": ["coding-standards"],
|
|
47
|
+
"fileTypeSkills": {
|
|
48
|
+
".py": ["flask", "python-patterns"],
|
|
49
|
+
".ts,.tsx": ["typescript-patterns"]
|
|
50
|
+
}
|
|
41
51
|
}
|
|
42
52
|
```
|
|
43
53
|
|
|
44
|
-
**3. Create
|
|
54
|
+
**3. Create skill files in `.opencode/skills/<name>/SKILL.md`**
|
|
45
55
|
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Configuration Reference
|
|
59
|
+
|
|
60
|
+
### All Options
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"skills": ["always-loaded-skill"],
|
|
65
|
+
"fileTypeSkills": {
|
|
66
|
+
".py": ["flask"],
|
|
67
|
+
".ts,.tsx": ["typescript"]
|
|
68
|
+
},
|
|
69
|
+
"agentSkills": {
|
|
70
|
+
"plan": ["planning-skill"],
|
|
71
|
+
"code": ["coding-skill"]
|
|
72
|
+
},
|
|
73
|
+
"pathPatterns": {
|
|
74
|
+
"src/api/**": ["api-design"],
|
|
75
|
+
"src/components/**": ["react-patterns"]
|
|
76
|
+
},
|
|
77
|
+
"contentTriggers": {
|
|
78
|
+
"database": ["sql-patterns"],
|
|
79
|
+
"authentication": ["auth-security"]
|
|
80
|
+
},
|
|
81
|
+
"groups": {
|
|
82
|
+
"frontend": ["react", "css", "testing"],
|
|
83
|
+
"backend": ["api-design", "database"]
|
|
84
|
+
},
|
|
85
|
+
"conditionalSkills": [
|
|
86
|
+
{ "skill": "react", "if": { "packageHasDependency": "react" } },
|
|
87
|
+
{ "skill": "prisma", "if": { "fileExists": "prisma/schema.prisma" } }
|
|
88
|
+
],
|
|
89
|
+
"maxTokens": 10000,
|
|
90
|
+
"useSummaries": false,
|
|
91
|
+
"analytics": false,
|
|
92
|
+
"persistAfterCompaction": true,
|
|
93
|
+
"debug": false
|
|
94
|
+
}
|
|
48
95
|
```
|
|
49
96
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
97
|
+
### Options Table
|
|
98
|
+
|
|
99
|
+
| Option | Type | Default | Description |
|
|
100
|
+
|--------|------|---------|-------------|
|
|
101
|
+
| `skills` | `string[]` | `[]` | Always load these skills |
|
|
102
|
+
| `fileTypeSkills` | `Record<string, string[]>` | `{}` | Map file extensions to skills |
|
|
103
|
+
| `agentSkills` | `Record<string, string[]>` | `{}` | Map agent names to skills |
|
|
104
|
+
| `pathPatterns` | `Record<string, string[]>` | `{}` | Map glob patterns to skills |
|
|
105
|
+
| `contentTriggers` | `Record<string, string[]>` | `{}` | Map keywords to skills |
|
|
106
|
+
| `groups` | `Record<string, string[]>` | `{}` | Define skill bundles |
|
|
107
|
+
| `conditionalSkills` | `ConditionalSkill[]` | `[]` | Load if condition met |
|
|
108
|
+
| `maxTokens` | `number` | `undefined` | Max tokens for all skills |
|
|
109
|
+
| `useSummaries` | `boolean` | `false` | Use skill summaries |
|
|
110
|
+
| `analytics` | `boolean` | `false` | Track skill usage |
|
|
111
|
+
| `persistAfterCompaction` | `boolean` | `true` | Keep skills after compaction |
|
|
112
|
+
| `debug` | `boolean` | `false` | Enable debug logs |
|
|
113
|
+
|
|
54
114
|
---
|
|
55
115
|
|
|
56
|
-
##
|
|
116
|
+
## Feature Details
|
|
117
|
+
|
|
118
|
+
### File-Type Skills
|
|
119
|
+
|
|
120
|
+
Load skills when agent touches files with specific extensions:
|
|
57
121
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"fileTypeSkills": {
|
|
125
|
+
".py": ["flask", "python-best-practices"],
|
|
126
|
+
".ts,.tsx": ["typescript-advanced-types"],
|
|
127
|
+
".go": ["golang-patterns"]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
62
130
|
```
|
|
63
131
|
|
|
64
|
-
|
|
132
|
+
Triggers on: `read`, `edit`, `write`, `glob`, `grep` tools.
|
|
65
133
|
|
|
66
|
-
|
|
134
|
+
### Agent-Specific Skills
|
|
67
135
|
|
|
68
|
-
|
|
136
|
+
Load different skills for different OpenCode agents:
|
|
69
137
|
|
|
70
|
-
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"agentSkills": {
|
|
141
|
+
"plan": ["architecture-planning", "task-breakdown"],
|
|
142
|
+
"code": ["coding-standards", "testing-patterns"],
|
|
143
|
+
"review": ["code-review-checklist"]
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
71
147
|
|
|
72
|
-
|
|
73
|
-
|----------|------|-------|
|
|
74
|
-
| 1 | `.opencode/preload-skills.json` | Project |
|
|
75
|
-
| 2 | `./preload-skills.json` | Project root |
|
|
76
|
-
| 3 | `~/.config/opencode/preload-skills.json` | Global |
|
|
148
|
+
### Path Patterns
|
|
77
149
|
|
|
78
|
-
|
|
150
|
+
Use glob patterns to match file paths:
|
|
79
151
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"pathPatterns": {
|
|
155
|
+
"src/api/**": ["api-design", "rest-patterns"],
|
|
156
|
+
"src/components/**/*.tsx": ["react-component-patterns"],
|
|
157
|
+
"tests/**": ["testing-best-practices"]
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Content Triggers
|
|
85
163
|
|
|
86
|
-
|
|
164
|
+
Load skills when keywords appear in conversation:
|
|
87
165
|
|
|
88
166
|
```json
|
|
89
167
|
{
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
168
|
+
"contentTriggers": {
|
|
169
|
+
"database": ["sql-patterns", "orm-usage"],
|
|
170
|
+
"authentication": ["auth-security", "jwt-patterns"],
|
|
171
|
+
"performance": ["optimization-tips"]
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Skill Groups
|
|
177
|
+
|
|
178
|
+
Bundle related skills and reference with `@`:
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"groups": {
|
|
183
|
+
"frontend": ["react", "css", "accessibility"],
|
|
184
|
+
"backend": ["api-design", "database", "caching"]
|
|
185
|
+
},
|
|
186
|
+
"skills": ["@frontend"]
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Use `@frontend` anywhere you'd use a skill name.
|
|
191
|
+
|
|
192
|
+
### Conditional Skills
|
|
193
|
+
|
|
194
|
+
Load skills only when conditions are met:
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"conditionalSkills": [
|
|
199
|
+
{
|
|
200
|
+
"skill": "react-patterns",
|
|
201
|
+
"if": { "packageHasDependency": "react" }
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"skill": "prisma-guide",
|
|
205
|
+
"if": { "fileExists": "prisma/schema.prisma" }
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"skill": "ci-patterns",
|
|
209
|
+
"if": { "envVar": "CI" }
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Condition types:**
|
|
216
|
+
- `packageHasDependency` — Check package.json dependencies
|
|
217
|
+
- `fileExists` — Check if file exists in project
|
|
218
|
+
- `envVar` — Check if environment variable is set
|
|
219
|
+
|
|
220
|
+
### Token Budget
|
|
221
|
+
|
|
222
|
+
Limit total tokens to protect your context window:
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"maxTokens": 8000,
|
|
227
|
+
"skills": ["skill-a", "skill-b", "skill-c"]
|
|
97
228
|
}
|
|
98
229
|
```
|
|
99
230
|
|
|
231
|
+
Skills load in order until budget is exhausted. Remaining skills are skipped.
|
|
232
|
+
|
|
233
|
+
### Skill Summaries
|
|
234
|
+
|
|
235
|
+
Add a `summary` field to your skill frontmatter for compact loading:
|
|
236
|
+
|
|
237
|
+
```markdown
|
|
100
238
|
---
|
|
239
|
+
name: my-skill
|
|
240
|
+
description: Full description
|
|
241
|
+
summary: Brief one-liner for summary mode
|
|
242
|
+
---
|
|
243
|
+
```
|
|
101
244
|
|
|
102
|
-
|
|
245
|
+
Enable with:
|
|
103
246
|
|
|
104
|
-
|
|
247
|
+
```json
|
|
248
|
+
{
|
|
249
|
+
"useSummaries": true
|
|
250
|
+
}
|
|
251
|
+
```
|
|
105
252
|
|
|
106
|
-
|
|
107
|
-
|----------|------|-------|
|
|
108
|
-
| 1 | `.opencode/skills/<name>/SKILL.md` | Project |
|
|
109
|
-
| 2 | `.claude/skills/<name>/SKILL.md` | Project (Claude-compatible) |
|
|
110
|
-
| 3 | `~/.config/opencode/skills/<name>/SKILL.md` | Global |
|
|
111
|
-
| 4 | `~/.claude/skills/<name>/SKILL.md` | Global (Claude-compatible) |
|
|
253
|
+
If no `summary` field, auto-generates from first paragraph.
|
|
112
254
|
|
|
113
|
-
|
|
255
|
+
### Usage Analytics
|
|
256
|
+
|
|
257
|
+
Track which skills are loaded and how often:
|
|
258
|
+
|
|
259
|
+
```json
|
|
260
|
+
{
|
|
261
|
+
"analytics": true
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Saves to `.opencode/preload-skills-analytics.json`.
|
|
114
266
|
|
|
115
267
|
---
|
|
116
268
|
|
|
117
269
|
## Skill File Format
|
|
118
270
|
|
|
119
|
-
Skills use markdown with YAML frontmatter:
|
|
120
|
-
|
|
121
271
|
```markdown
|
|
122
272
|
---
|
|
123
273
|
name: skill-name
|
|
124
|
-
description: Brief description
|
|
274
|
+
description: Brief description for logs
|
|
275
|
+
summary: Optional one-liner for summary mode
|
|
125
276
|
---
|
|
126
277
|
|
|
127
278
|
# Skill Content
|
|
128
279
|
|
|
129
|
-
|
|
130
|
-
is injected into the agent's context.
|
|
131
|
-
|
|
132
|
-
## Sections
|
|
133
|
-
|
|
134
|
-
Organize with headers, code blocks, lists, etc.
|
|
280
|
+
Full instructions here...
|
|
135
281
|
```
|
|
136
282
|
|
|
137
|
-
###
|
|
283
|
+
### Locations (in priority order)
|
|
138
284
|
|
|
139
|
-
|
|
140
|
-
|
|
285
|
+
1. `.opencode/skills/<name>/SKILL.md` (project)
|
|
286
|
+
2. `.claude/skills/<name>/SKILL.md` (project)
|
|
287
|
+
3. `~/.config/opencode/skills/<name>/SKILL.md` (global)
|
|
288
|
+
4. `~/.claude/skills/<name>/SKILL.md` (global)
|
|
141
289
|
|
|
142
290
|
---
|
|
143
291
|
|
|
144
292
|
## How It Works
|
|
145
293
|
|
|
146
294
|
```
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
│
|
|
152
|
-
│
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
│
|
|
159
|
-
│
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
│
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
│ Session │──▶ Cleanup session tracking
|
|
171
|
-
│ deleted │
|
|
172
|
-
└─────────────────────┘
|
|
295
|
+
┌─────────────────────────────────────────────────────────┐
|
|
296
|
+
│ SESSION START │
|
|
297
|
+
├─────────────────────────────────────────────────────────┤
|
|
298
|
+
│ 1. Load `skills` + `conditionalSkills` (if met) │
|
|
299
|
+
│ 2. Apply token budget if set │
|
|
300
|
+
│ 3. Inject on first message │
|
|
301
|
+
├─────────────────────────────────────────────────────────┤
|
|
302
|
+
│ DURING SESSION │
|
|
303
|
+
├─────────────────────────────────────────────────────────┤
|
|
304
|
+
│ On file access: │
|
|
305
|
+
│ → Check fileTypeSkills (by extension) │
|
|
306
|
+
│ → Check pathPatterns (by glob match) │
|
|
307
|
+
│ │
|
|
308
|
+
│ On message: │
|
|
309
|
+
│ → Check agentSkills (by agent name) │
|
|
310
|
+
│ → Check contentTriggers (by keyword) │
|
|
311
|
+
│ → Inject any pending skills │
|
|
312
|
+
├─────────────────────────────────────────────────────────┤
|
|
313
|
+
│ COMPACTION │
|
|
314
|
+
├─────────────────────────────────────────────────────────┤
|
|
315
|
+
│ All loaded skills added to compaction context │
|
|
316
|
+
│ (if persistAfterCompaction: true) │
|
|
317
|
+
└─────────────────────────────────────────────────────────┘
|
|
173
318
|
```
|
|
174
319
|
|
|
175
320
|
---
|
|
176
321
|
|
|
177
322
|
## Best Practices
|
|
178
323
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
324
|
+
1. **Use `fileTypeSkills` over `skills`** — Only load what's needed
|
|
325
|
+
2. **Set `maxTokens`** — Protect your context window
|
|
326
|
+
3. **Use `groups`** — Organize related skills
|
|
327
|
+
4. **Enable `analytics`** — Find unused skills
|
|
328
|
+
5. **Write `summary` fields** — For large skills, enable `useSummaries`
|
|
183
329
|
|
|
184
330
|
---
|
|
185
331
|
|
|
186
332
|
## Troubleshooting
|
|
187
333
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
5. **Check logs** — Look for `preload-skills` service messages
|
|
195
|
-
|
|
196
|
-
### Skills lost after compaction?
|
|
197
|
-
|
|
198
|
-
Ensure `persistAfterCompaction` is `true` (this is the default).
|
|
199
|
-
|
|
200
|
-
### Context window running out quickly?
|
|
201
|
-
|
|
202
|
-
You may have too many or too large skills preloaded. Consider:
|
|
203
|
-
- Reducing the number of preloaded skills
|
|
204
|
-
- Trimming skill content to essentials
|
|
205
|
-
- Moving less critical skills to on-demand loading
|
|
334
|
+
| Problem | Solution |
|
|
335
|
+
|---------|----------|
|
|
336
|
+
| Skills not loading | Check config path, skill file exists, frontmatter valid |
|
|
337
|
+
| Wrong skills loading | Check trigger conditions, enable `debug: true` |
|
|
338
|
+
| Context too small | Reduce skills, set `maxTokens`, enable `useSummaries` |
|
|
339
|
+
| Skills lost after compaction | Ensure `persistAfterCompaction: true` |
|
|
206
340
|
|
|
207
341
|
---
|
|
208
342
|
|