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