opencode-plugin-preload-skills 1.2.0 → 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 +247 -139
- package/dist/index.cjs +283 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +285 -58
- package/dist/index.js.map +1 -1
- package/package.json +11 -4
package/README.md
CHANGED
|
@@ -1,234 +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
|
-
|
|
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
|
+
"maxTokens": 10000,
|
|
90
|
+
"useSummaries": false,
|
|
91
|
+
"analytics": false,
|
|
92
|
+
"persistAfterCompaction": true,
|
|
93
|
+
"debug": false
|
|
94
|
+
}
|
|
49
95
|
```
|
|
50
96
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
+
|
|
55
114
|
---
|
|
56
115
|
|
|
57
|
-
##
|
|
116
|
+
## Feature Details
|
|
117
|
+
|
|
118
|
+
### File-Type Skills
|
|
119
|
+
|
|
120
|
+
Load skills when agent touches files with specific extensions:
|
|
58
121
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"fileTypeSkills": {
|
|
125
|
+
".py": ["flask", "python-best-practices"],
|
|
126
|
+
".ts,.tsx": ["typescript-advanced-types"],
|
|
127
|
+
".go": ["golang-patterns"]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
63
130
|
```
|
|
64
131
|
|
|
65
|
-
|
|
132
|
+
Triggers on: `read`, `edit`, `write`, `glob`, `grep` tools.
|
|
66
133
|
|
|
67
|
-
|
|
134
|
+
### Agent-Specific Skills
|
|
135
|
+
|
|
136
|
+
Load different skills for different OpenCode agents:
|
|
68
137
|
|
|
69
|
-
|
|
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
|
+
```
|
|
70
147
|
|
|
71
|
-
|
|
148
|
+
### Path Patterns
|
|
72
149
|
|
|
73
|
-
|
|
74
|
-
|----------|------|-------|
|
|
75
|
-
| 1 | `.opencode/preload-skills.json` | Project |
|
|
76
|
-
| 2 | `./preload-skills.json` | Project root |
|
|
77
|
-
| 3 | `~/.config/opencode/preload-skills.json` | Global |
|
|
150
|
+
Use glob patterns to match file paths:
|
|
78
151
|
|
|
79
|
-
|
|
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
|
+
```
|
|
80
161
|
|
|
81
|
-
|
|
82
|
-
|--------|------|---------|-------------|
|
|
83
|
-
| `skills` | `string[]` | `[]` | Skills to always load at session start |
|
|
84
|
-
| `fileTypeSkills` | `Record<string, string[]>` | `{}` | Skills to load when specific file types are accessed |
|
|
85
|
-
| `persistAfterCompaction` | `boolean` | `true` | Re-inject skills after context compaction |
|
|
86
|
-
| `debug` | `boolean` | `false` | Enable debug logging |
|
|
162
|
+
### Content Triggers
|
|
87
163
|
|
|
88
|
-
|
|
164
|
+
Load skills when keywords appear in conversation:
|
|
89
165
|
|
|
90
166
|
```json
|
|
91
167
|
{
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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"]
|
|
100
185
|
},
|
|
101
|
-
"
|
|
102
|
-
"debug": false
|
|
186
|
+
"skills": ["@frontend"]
|
|
103
187
|
}
|
|
104
188
|
```
|
|
105
189
|
|
|
106
|
-
|
|
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"]
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Skills load in order until budget is exhausted. Remaining skills are skipped.
|
|
107
232
|
|
|
108
|
-
|
|
233
|
+
### Skill Summaries
|
|
109
234
|
|
|
110
|
-
|
|
111
|
-
- **Values**: Array of skill names to load
|
|
112
|
-
- **Trigger**: When agent uses `read`, `edit`, `write`, `glob`, or `grep` on matching files
|
|
113
|
-
- **Deduplication**: Each skill is only loaded once per session, even if multiple files match
|
|
235
|
+
Add a `summary` field to your skill frontmatter for compact loading:
|
|
114
236
|
|
|
237
|
+
```markdown
|
|
115
238
|
---
|
|
239
|
+
name: my-skill
|
|
240
|
+
description: Full description
|
|
241
|
+
summary: Brief one-liner for summary mode
|
|
242
|
+
---
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Enable with:
|
|
246
|
+
|
|
247
|
+
```json
|
|
248
|
+
{
|
|
249
|
+
"useSummaries": true
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
If no `summary` field, auto-generates from first paragraph.
|
|
116
254
|
|
|
117
|
-
|
|
255
|
+
### Usage Analytics
|
|
118
256
|
|
|
119
|
-
|
|
257
|
+
Track which skills are loaded and how often:
|
|
120
258
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
| 4 | `~/.claude/skills/<name>/SKILL.md` | Global (Claude-compatible) |
|
|
259
|
+
```json
|
|
260
|
+
{
|
|
261
|
+
"analytics": true
|
|
262
|
+
}
|
|
263
|
+
```
|
|
127
264
|
|
|
128
|
-
|
|
265
|
+
Saves to `.opencode/preload-skills-analytics.json`.
|
|
129
266
|
|
|
130
267
|
---
|
|
131
268
|
|
|
132
269
|
## Skill File Format
|
|
133
270
|
|
|
134
|
-
Skills use markdown with YAML frontmatter:
|
|
135
|
-
|
|
136
271
|
```markdown
|
|
137
272
|
---
|
|
138
273
|
name: skill-name
|
|
139
|
-
description: Brief description
|
|
274
|
+
description: Brief description for logs
|
|
275
|
+
summary: Optional one-liner for summary mode
|
|
140
276
|
---
|
|
141
277
|
|
|
142
278
|
# Skill Content
|
|
143
279
|
|
|
144
|
-
|
|
145
|
-
is injected into the agent's context.
|
|
146
|
-
|
|
147
|
-
## Sections
|
|
148
|
-
|
|
149
|
-
Organize with headers, code blocks, lists, etc.
|
|
280
|
+
Full instructions here...
|
|
150
281
|
```
|
|
151
282
|
|
|
152
|
-
###
|
|
283
|
+
### Locations (in priority order)
|
|
153
284
|
|
|
154
|
-
|
|
155
|
-
|
|
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)
|
|
156
289
|
|
|
157
290
|
---
|
|
158
291
|
|
|
159
292
|
## How It Works
|
|
160
293
|
|
|
161
294
|
```
|
|
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
|
-
└─────────────────────┘
|
|
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
|
+
└─────────────────────────────────────────────────────────┘
|
|
199
318
|
```
|
|
200
319
|
|
|
201
320
|
---
|
|
202
321
|
|
|
203
322
|
## Best Practices
|
|
204
323
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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`
|
|
209
329
|
|
|
210
330
|
---
|
|
211
331
|
|
|
212
332
|
## Troubleshooting
|
|
213
333
|
|
|
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
|
|
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` |
|
|
232
340
|
|
|
233
341
|
---
|
|
234
342
|
|