opencode-knowledge 0.4.2 → 0.5.0-next.1

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.
Files changed (3) hide show
  1. package/README.md +68 -253
  2. package/dist/index.js +65 -27
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,24 +1,20 @@
1
- # opencode-knowledge
1
+ # opencode-knowledge <img src="./assets/opencode-knowledge-logo.png" align="right" height="100"/>
2
2
 
3
- A comprehensive knowledge management system for OpenCode that provides:
4
- - **Role-based AI personalities** - Customize OpenCode's communication style
5
- - **Knowledge vault** - Organize coding standards, patterns, and best practices
6
- - **Tag-based search** - Quickly find relevant knowledge packages
7
- - **Session management** - Track loaded packages and optimize token usage
3
+ An OpenCode plugin that dynamically loads knowledge from your vault on-demand. Add any content you want, the AI figures out what to load using tags and descriptions.
8
4
 
9
5
  ## Features
10
6
 
11
- ### 🎭 Personality System
12
- Choose from different AI personas (staff engineer, frontend specialist, cthulhu, etc.) that influence how OpenCode communicates and approaches problems.
13
-
14
7
  ### 📚 Knowledge Vault
15
- Create a structured library of markdown-based knowledge packages with frontmatter metadata for easy discovery and loading.
8
+
9
+ Organize coding standards, patterns, and best practices in markdown files with frontmatter metadata.
16
10
 
17
11
  ### 🔍 Smart Search
18
- Tag-based search system finds relevant knowledge packages based on your current task.
12
+
13
+ Tag-based search finds relevant packages. The AI uses tags and descriptions to discover the right context.
19
14
 
20
15
  ### 💾 Session Persistence
21
- Tracks loaded packages across sessions and provides token-optimized context injection.
16
+
17
+ Automatically indexes your vault on session start and tracks loaded packages.
22
18
 
23
19
  ---
24
20
 
@@ -46,25 +42,15 @@ Add the plugin to your OpenCode config:
46
42
 
47
43
  ## Quick Start
48
44
 
49
- ### 1. Create Settings File
45
+ ### 1. Create Knowledge Vault
50
46
 
51
- Create `.opencode/knowledge/settings.json` in your project:
52
-
53
- ```json
54
- {
55
- "role": "staff_engineer"
56
- }
57
- ```
58
-
59
- ### 2. Create Knowledge Vault (Optional)
60
-
61
- If you want to use the knowledge management features, create a vault structure:
47
+ Create the vault directory structure:
62
48
 
63
49
  ```bash
64
50
  mkdir -p .opencode/knowledge/vault/standards
65
51
  ```
66
52
 
67
- ### 3. Create Your First Knowledge Package
53
+ ### 2. Create Your First Knowledge Package
68
54
 
69
55
  Create `.opencode/knowledge/vault/standards/code-conventions.md`:
70
56
 
@@ -81,39 +67,42 @@ category: standards
81
67
  # Code Conventions
82
68
 
83
69
  ## Naming
70
+
84
71
  - Use camelCase for variables and functions
85
72
  - Use PascalCase for classes and types
86
73
 
87
74
  ## Formatting
75
+
88
76
  - Use single quotes for strings
89
77
  - Line width: 100 characters
90
78
  - Always use semicolons
91
79
  ```
92
80
 
93
- ### 4. Start OpenCode Session
81
+ ### 3. Start OpenCode Session
94
82
 
95
83
  The knowledge catalog is **automatically built on session start**. Just start a new session and the plugin will:
84
+
96
85
  - Scan your vault for packages
97
86
  - Build the searchable catalog
98
87
  - Inject knowledge map on first message
99
88
 
100
- ### 5. Search and Load Knowledge
89
+ ### 4. Configure Personality (Optional)
101
90
 
102
- Search for packages by tags:
91
+ Optionally configure OpenCode's communication style by creating `.opencode/knowledge/settings.json`:
103
92
 
104
- ```
105
- knowledge_search [tags=typescript,conventions]
93
+ ```json
94
+ {
95
+ "role": "staff_engineer"
96
+ }
106
97
  ```
107
98
 
108
- Load packages into your session:
109
-
110
- ```
111
- knowledge_load [paths=standards/code-conventions.md]
112
- ```
99
+ See the [Personalities](#personalities-optional) section for available options.
113
100
 
114
101
  ---
115
102
 
116
- ## Available Personalities
103
+ ## Personalities (Optional)
104
+
105
+ The plugin works perfectly fine without any personality configuration. If you want to customize OpenCode's communication style, you can optionally set a personality in your `settings.json`.
117
106
 
118
107
  ### staff_engineer
119
108
 
@@ -129,73 +118,6 @@ Ancient cosmic entity providing technical guidance with existential dread and co
129
118
 
130
119
  ---
131
120
 
132
- ## Tools
133
-
134
- ### knowledge_search
135
-
136
- Search for knowledge packages by tags.
137
-
138
- ```
139
- knowledge_search [tags=typescript,react,testing]
140
- ```
141
-
142
- **Parameters**: Comma-separated list of tags
143
-
144
- **Output**: Ranked list of matching packages with relevance scores
145
-
146
- **Example**:
147
- ```
148
- Found 5 packages matching [typescript, react]:
149
-
150
- - **frontend/react-patterns.md** (75%)
151
- Tags: typescript, react, patterns
152
- Common React patterns and best practices
153
-
154
- - **standards/typescript-conventions.md** (50%)
155
- Tags: typescript, conventions
156
- TypeScript coding standards
157
- ```
158
-
159
- ---
160
-
161
- ### knowledge_load
162
-
163
- Load knowledge packages into the current session.
164
-
165
- ```
166
- knowledge_load [paths=standards/code-conventions.md,frontend/react-patterns.md]
167
- ```
168
-
169
- **Parameters**: Comma-separated list of package paths (relative to vault/)
170
-
171
- **Output**: Package content injected into context
172
-
173
- **Features**:
174
- - Deduplication (won't load same package twice)
175
- - Session tracking (remembers what's loaded)
176
- - Error handling (warns about missing packages)
177
-
178
- ---
179
-
180
- ### knowledge_index
181
-
182
- Manually rebuild the knowledge catalog from your vault.
183
-
184
- ```
185
- knowledge_index
186
- ```
187
-
188
- **Output**: Summary of categories and packages indexed.
189
-
190
- **Note**: The catalog is **automatically built on session start**, so you rarely need this tool.
191
-
192
- **When to use**:
193
- - After adding packages mid-session
194
- - If auto-build failed during session start
195
- - To verify catalog contents
196
-
197
- ---
198
-
199
121
  ## Knowledge Package Format
200
122
 
201
123
  Knowledge packages are markdown files with YAML frontmatter:
@@ -212,8 +134,8 @@ required_knowledge:
212
134
  - other-package-1
213
135
  - other-package-2
214
136
  file_patterns:
215
- - "*.tsx"
216
- - "*.test.ts"
137
+ - '*.tsx'
138
+ - '*.test.ts'
217
139
  ---
218
140
 
219
141
  # Package Title
@@ -223,13 +145,37 @@ Your knowledge content here...
223
145
 
224
146
  ### Frontmatter Fields
225
147
 
226
- | Field | Required | Description |
227
- |-------|----------|-------------|
228
- | `tags` | Yes | Array of searchable tags |
229
- | `description` | Yes | Brief summary (used in search results) |
230
- | `category` | Yes | Category for organization (e.g., `frontend`, `backend`, `standards`) |
231
- | `required_knowledge` | No | Other packages that should be loaded first |
232
- | `file_patterns` | No | File patterns where this knowledge applies |
148
+ | Field | Required | Description |
149
+ | -------------------- | -------- | -------------------------------------------------------------------- |
150
+ | `tags` | Yes | Array of searchable tags |
151
+ | `description` | Yes | Brief summary (used in search results) |
152
+ | `category` | Yes | Category for organization (e.g., `frontend`, `backend`, `standards`) |
153
+ | `required_knowledge` | No | Other packages that should be loaded automatically before this one (supports recursive dependencies) |
154
+ | `file_patterns` | No | File patterns where this knowledge applies (not yet implemented) |
155
+
156
+ ### Dependency Loading
157
+
158
+ The `required_knowledge` field enables automatic dependency loading. When you load a package, the plugin automatically loads all its dependencies first, recursively.
159
+
160
+ **Example:**
161
+
162
+ ```markdown
163
+ <!-- vault/personal/blog-writing.md -->
164
+ ---
165
+ tags: [blog, writing]
166
+ description: Blog writing guidelines
167
+ category: personal
168
+ required_knowledge:
169
+ - personal/author-context
170
+ ---
171
+ ```
172
+
173
+ When AI loads `personal/blog-writing.md`, the plugin:
174
+ 1. Detects the `required_knowledge` dependency
175
+ 2. Automatically loads `personal/author-context.md` first
176
+ 3. Then loads `personal/blog-writing.md`
177
+
178
+ This ensures the AI always has complete context without manual tracking. Dependencies can be nested (Package A requires B, B requires C), and the plugin handles circular dependencies gracefully.
233
179
 
234
180
  ---
235
181
 
@@ -239,9 +185,9 @@ Your knowledge content here...
239
185
  your-project/
240
186
  └── .opencode/
241
187
  └── knowledge/
242
- ├── settings.json # Plugin configuration
243
- ├── knowledge.json # Auto-generated catalog (gitignored)
244
- ├── vault/ # Your knowledge packages
188
+ ├── settings.json
189
+ ├── knowledge.json
190
+ ├── vault/
245
191
  │ ├── frontend/
246
192
  │ │ ├── react-patterns.md
247
193
  │ │ └── state-management.md
@@ -250,139 +196,13 @@ your-project/
250
196
  │ └── standards/
251
197
  │ ├── code-conventions.md
252
198
  │ └── testing-guide.md
253
- └── tracker/ # Session state (gitignored)
199
+ └── tracker/
254
200
  ├── session-state.jsonl
255
201
  └── knowledge-reads.jsonl
256
202
  ```
257
203
 
258
204
  ---
259
205
 
260
- ## Token Optimization
261
-
262
- The plugin uses a single-phase approach for optimal token usage:
263
-
264
- ### First Message Only
265
- - Shows full category-tag map (~500-1000 tokens depending on vault size)
266
- - Injects personality
267
- - Documents available tools with examples
268
- - Creates session state
269
-
270
- ### Subsequent Messages
271
- - No knowledge context injected
272
- - LLM uses memory of first message
273
- - **100% token savings** on subsequent messages
274
-
275
- This approach provides significant token savings while ensuring the LLM has all the context it needs from the initial session setup.
276
-
277
- ---
278
-
279
- ## Example Vault Structure
280
-
281
- Here's a recommended organization pattern:
282
-
283
- ```
284
- vault/
285
- ├── frontend/
286
- │ ├── react-patterns.md # React best practices
287
- │ ├── state-management.md # Redux, Context, etc.
288
- │ ├── component-testing.md # Testing components
289
- │ └── accessibility.md # A11y guidelines
290
- ├── backend/
291
- │ ├── api-design.md # REST/GraphQL patterns
292
- │ ├── database-patterns.md # ORM, migrations
293
- │ └── error-handling.md # Error handling strategies
294
- ├── standards/
295
- │ ├── code-conventions.md # General coding standards
296
- │ ├── git-workflow.md # Branch strategy, commits
297
- │ └── code-review.md # Review guidelines
298
- └── infrastructure/
299
- ├── docker-patterns.md # Container best practices
300
- ├── ci-cd.md # Pipeline patterns
301
- └── monitoring.md # Observability
302
- ```
303
-
304
- ---
305
-
306
- ## Advanced Usage
307
-
308
- ### Creating Cross-Referenced Packages
309
-
310
- Use `required_knowledge` to create dependency chains:
311
-
312
- ```markdown
313
- ---
314
- tags:
315
- - react
316
- - advanced
317
- - performance
318
- description: Advanced React performance optimization
319
- category: frontend
320
- required_knowledge:
321
- - frontend/react-patterns
322
- - standards/code-conventions
323
- ---
324
-
325
- # Advanced React Performance
326
-
327
- This builds on basic patterns...
328
- ```
329
-
330
- ### File Pattern Targeting
331
-
332
- Specify when knowledge applies:
333
-
334
- ```markdown
335
- ---
336
- tags:
337
- - testing
338
- - jest
339
- description: Jest testing patterns
340
- category: frontend
341
- file_patterns:
342
- - "*.test.ts"
343
- - "*.test.tsx"
344
- - "*.spec.ts"
345
- ---
346
-
347
- # Jest Testing Guide
348
- ```
349
-
350
- ---
351
-
352
- ## Troubleshooting
353
-
354
- ### Settings file not found
355
-
356
- **Error**: `CONFIGURATION ERROR: Settings file not found`
357
-
358
- **Solution**: Create `.opencode/knowledge/settings.json` with:
359
- ```json
360
- {
361
- "role": "staff_engineer"
362
- }
363
- ```
364
-
365
- ### Personality not loading
366
-
367
- **Error**: `CONFIGURATION ERROR: Personality file not found`
368
-
369
- **Solution**: Verify the role name in `settings.json` matches an available personality (`staff_engineer` or `cthulhu`)
370
-
371
- ### Catalog not found
372
-
373
- **Error**: `Knowledge catalog not found. Run knowledge_index first.`
374
-
375
- **Solution**: Run `knowledge_index` to build the catalog from your vault
376
-
377
- ### Search returns no results
378
-
379
- **Possible causes**:
380
- 1. Catalog is outdated → Run `knowledge_index`
381
- 2. Tags don't match → Check tag spelling
382
- 3. No packages with those tags → Add packages or adjust search
383
-
384
- ---
385
-
386
206
  ## Development
387
207
 
388
208
  ### Building
@@ -412,17 +232,6 @@ mise run format
412
232
 
413
233
  ---
414
234
 
415
- ## Roadmap
416
-
417
- - [ ] Auto-load packages based on file patterns
418
- - [ ] Knowledge package dependencies resolution
419
- - [ ] Usage analytics and metrics
420
- - [ ] Export/import vault bundles
421
- - [ ] Knowledge package templates
422
- - [ ] VSCode extension for vault management
423
-
424
- ---
425
-
426
235
  ## Contributing
427
236
 
428
237
  Contributions welcome! Please:
@@ -434,6 +243,12 @@ Contributions welcome! Please:
434
243
 
435
244
  ---
436
245
 
246
+ ## Credits
247
+
248
+ Special thanks to [@canyavall](https://github.com/canyavall) for being the creative mind that came up with the idea and initial working solution. He continues to improve this in the shadows to this day.
249
+
250
+ ---
251
+
437
252
  ## License
438
253
 
439
254
  MIT License. See the [LICENSE](LICENSE) file for details.
package/dist/index.js CHANGED
@@ -90,22 +90,15 @@ async function createSessionState(sessionId) {
90
90
  return;
91
91
  }
92
92
  const settingsPath = ".opencode/knowledge/settings.json";
93
- if (!existsSync2(settingsPath)) {
94
- throw new Error(`CONFIGURATION ERROR: Cannot create session state - settings file not found at ${settingsPath}`);
95
- }
96
- let role;
97
- try {
98
- const settingsContent = await readFile(settingsPath, "utf-8");
99
- const settings = JSON.parse(settingsContent);
100
- if (!settings.role) {
101
- throw new Error(`CONFIGURATION ERROR: Cannot create session state - missing 'role' field in ${settingsPath}`);
102
- }
103
- role = settings.role;
104
- } catch (error) {
105
- if (error instanceof Error && error.message.includes("CONFIGURATION ERROR")) {
106
- throw error;
93
+ let role = null;
94
+ if (existsSync2(settingsPath)) {
95
+ try {
96
+ const settingsContent = await readFile(settingsPath, "utf-8");
97
+ const settings = JSON.parse(settingsContent);
98
+ role = settings.role || null;
99
+ } catch (error) {
100
+ throw new Error(`Error reading settings.json: ${error}`);
107
101
  }
108
- throw new Error(`Error reading settings.json: ${error}`);
109
102
  }
110
103
  const state = {
111
104
  role,
@@ -12720,19 +12713,53 @@ _...and ${results.length - 10} more results_`;
12720
12713
  import { readFileSync as readFileSync3, existsSync as existsSync5 } from "fs";
12721
12714
  import { join as join4 } from "path";
12722
12715
  var VAULT_DIR2 = ".opencode/knowledge/vault";
12716
+ function resolveDependencies(packagePath, vaultDir, loaded = new Set) {
12717
+ if (loaded.has(packagePath)) {
12718
+ return [];
12719
+ }
12720
+ loaded.add(packagePath);
12721
+ const result = [];
12722
+ const normalizedPath = packagePath.endsWith(".md") ? packagePath : `${packagePath}.md`;
12723
+ const fullPath = join4(vaultDir, normalizedPath);
12724
+ if (!existsSync5(fullPath)) {
12725
+ return [];
12726
+ }
12727
+ try {
12728
+ const content = readFileSync3(fullPath, "utf-8");
12729
+ const { frontmatter } = parseFrontmatter(content);
12730
+ if (frontmatter.required_knowledge && Array.isArray(frontmatter.required_knowledge)) {
12731
+ for (const dep of frontmatter.required_knowledge) {
12732
+ const depPath = dep.endsWith(".md") ? dep : `${dep}.md`;
12733
+ const depPackages = resolveDependencies(depPath, vaultDir, loaded);
12734
+ result.push(...depPackages);
12735
+ }
12736
+ }
12737
+ result.push(normalizedPath);
12738
+ } catch {
12739
+ return [];
12740
+ }
12741
+ return result;
12742
+ }
12723
12743
  var knowledgeLoadTool = tool({
12724
12744
  description: "Load one or more knowledge packages from the vault into the current session context. The package content will be available for reference in subsequent responses.",
12725
12745
  args: {
12726
12746
  paths: tool.schema.string().describe("Comma-separated package paths relative to vault (e.g., 'standards/code-conventions.md,frontend/react-patterns.md')")
12727
12747
  },
12728
12748
  async execute(args) {
12729
- const packagePaths = args.paths.split(",").map((p) => p.trim()).filter(Boolean);
12730
- if (packagePaths.length === 0) {
12749
+ const requestedPaths = args.paths.split(",").map((p) => p.trim()).filter(Boolean);
12750
+ if (requestedPaths.length === 0) {
12731
12751
  return "No package paths provided";
12732
12752
  }
12753
+ const allPackagePaths = new Set;
12754
+ const loadedTracker = new Set;
12755
+ for (const path2 of requestedPaths) {
12756
+ const resolved = resolveDependencies(path2, VAULT_DIR2, loadedTracker);
12757
+ resolved.forEach((p) => allPackagePaths.add(p));
12758
+ }
12733
12759
  const loaded = [];
12734
12760
  const failed = [];
12735
- for (const packagePath of packagePaths) {
12761
+ const packageArray = Array.from(allPackagePaths);
12762
+ for (const packagePath of packageArray) {
12736
12763
  const fullPath = join4(VAULT_DIR2, packagePath);
12737
12764
  if (!existsSync5(fullPath)) {
12738
12765
  failed.push(`\u26A0\uFE0F Package not found: ${packagePath}`);
@@ -12749,9 +12776,18 @@ ${content}`);
12749
12776
  }
12750
12777
  let output = "";
12751
12778
  if (loaded.length > 0) {
12752
- output += `\u2705 Loaded ${loaded.length}/${packagePaths.length} packages:
12779
+ const totalCount = packageArray.length;
12780
+ const requestedCount = requestedPaths.length;
12781
+ const depsCount = totalCount - requestedCount;
12782
+ if (depsCount > 0) {
12783
+ output += `\u2705 Loaded ${loaded.length}/${totalCount} packages (${requestedCount} requested + ${depsCount} dependencies):
12753
12784
 
12754
12785
  `;
12786
+ } else {
12787
+ output += `\u2705 Loaded ${loaded.length}/${totalCount} packages:
12788
+
12789
+ `;
12790
+ }
12755
12791
  output += loaded.join(`
12756
12792
 
12757
12793
  ---
@@ -12813,7 +12849,6 @@ var opencodeKnowledge = async () => {
12813
12849
  try {
12814
12850
  const state = getSessionState(input.sessionID);
12815
12851
  if (state.isFirstPrompt) {
12816
- const personality = await loadPersonality(state.role);
12817
12852
  const vaultExists = existsSync6(".opencode/knowledge/vault");
12818
12853
  if (vaultExists) {
12819
12854
  const categoryTagMap = buildCategoryTagMap();
@@ -12835,15 +12870,18 @@ var opencodeKnowledge = async () => {
12835
12870
  messageID: input.messageID || ""
12836
12871
  });
12837
12872
  }
12838
- output.parts.push({
12839
- type: "text",
12840
- text: `## Role Context
12873
+ if (state.role) {
12874
+ const personality = await loadPersonality(state.role);
12875
+ output.parts.push({
12876
+ type: "text",
12877
+ text: `## Role Context
12841
12878
 
12842
12879
  ${personality}`,
12843
- id: `personality-${Date.now()}`,
12844
- sessionID: input.sessionID,
12845
- messageID: input.messageID || ""
12846
- });
12880
+ id: `personality-${Date.now()}`,
12881
+ sessionID: input.sessionID,
12882
+ messageID: input.messageID || ""
12883
+ });
12884
+ }
12847
12885
  updateSessionState(input.sessionID, {
12848
12886
  isFirstPrompt: false,
12849
12887
  categoriesShown: vaultExists
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-knowledge",
3
- "version": "0.4.2",
3
+ "version": "0.5.0-next.1",
4
4
  "description": "An OpenCode plugin",
5
5
  "author": {
6
6
  "name": "msegoviadev",