opencode-skill-autodiscovery 1.0.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 ADDED
@@ -0,0 +1,47 @@
1
+ # opencode-skill-autodiscovery
2
+
3
+ An [opencode](https://opencode.ai) plugin that auto-discovers skills installed by
4
+ VS Code agent plugins and Claude Code plugins on the current machine, and
5
+ registers them with opencode's `skills.paths` so they appear in every session.
6
+
7
+ ## Why
8
+
9
+ Skills live in different places depending on the tool that installed them:
10
+
11
+ - VS Code agent plugins: `~/.vscode/agent-plugins/installed.json`
12
+ - Claude Code plugins: `~/.claude/plugins/installed_plugins.json`
13
+
14
+ Each points at plugin directories that contain `SKILL.md` files. This plugin
15
+ walks those manifests, finds every skill directory, and adds them to the
16
+ opencode config.
17
+
18
+ ## Install
19
+
20
+ Add the package name to the `plugin` array in your `opencode.json`:
21
+
22
+ ```json
23
+ {
24
+ "plugin": ["opencode-skill-autodiscovery"]
25
+ }
26
+ ```
27
+
28
+ ## Notes
29
+
30
+ - Discovery is inherently **machine-local**: it reads manifests from the home
31
+ directory of the machine opencode is running on. Remote sessions on a
32
+ different machine will discover that machine's skills.
33
+ - The plugin is a no-op when no VS Code or Claude plugin manifests exist, or
34
+ when they contain no skills.
35
+
36
+ ## Development
37
+
38
+ ```sh
39
+ npm install
40
+ npm run build # tsc -> dist/
41
+ ```
42
+
43
+ Publish:
44
+
45
+ ```sh
46
+ npm publish --access public
47
+ ```
@@ -0,0 +1,6 @@
1
+ import type { Config } from "@opencode-ai/plugin";
2
+ declare const _default: () => Promise<{
3
+ config: (cfg: Config) => Promise<void>;
4
+ }>;
5
+ export default _default;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAU,MAAM,EAAE,MAAM,qBAAqB,CAAC;;kBAkGlC,MAAM;;AAF9B,wBAyBoB"}
package/dist/index.js ADDED
@@ -0,0 +1,116 @@
1
+ import { readFileSync, existsSync, readdirSync, statSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ const VSCODE_INSTALLED = join(homedir(), ".vscode", "agent-plugins", "installed.json");
5
+ const CLAUDE_INSTALLED = join(homedir(), ".claude", "plugins", "installed_plugins.json");
6
+ function findSkillDirs(root, out, seen) {
7
+ const resolved = join(root);
8
+ if (seen.has(resolved))
9
+ return;
10
+ seen.add(resolved);
11
+ let entries;
12
+ try {
13
+ entries = readdirSync(resolved);
14
+ }
15
+ catch {
16
+ return;
17
+ }
18
+ for (const entry of entries) {
19
+ const full = join(resolved, entry);
20
+ let isDir = false;
21
+ try {
22
+ isDir = statSync(full).isDirectory();
23
+ }
24
+ catch {
25
+ continue;
26
+ }
27
+ if (isDir) {
28
+ if (existsSync(join(full, "SKILL.md"))) {
29
+ out.add(full);
30
+ }
31
+ else {
32
+ findSkillDirs(full, out, seen);
33
+ }
34
+ }
35
+ }
36
+ }
37
+ function vscodePluginPath(pluginUri) {
38
+ const m = /^file:\/\/(.+)$/.exec(pluginUri);
39
+ if (!m)
40
+ return pluginUri;
41
+ let raw;
42
+ try {
43
+ raw = decodeURIComponent(m[1]);
44
+ }
45
+ catch {
46
+ raw = m[1];
47
+ }
48
+ if (raw.startsWith("/"))
49
+ raw = raw.slice(1);
50
+ return raw;
51
+ }
52
+ function collectVscode(out) {
53
+ if (!existsSync(VSCODE_INSTALLED))
54
+ return;
55
+ let manifest;
56
+ try {
57
+ manifest = JSON.parse(readFileSync(VSCODE_INSTALLED, "utf8"));
58
+ }
59
+ catch {
60
+ return;
61
+ }
62
+ for (const plugin of manifest.installed ?? []) {
63
+ if (!plugin.pluginUri)
64
+ continue;
65
+ const dir = vscodePluginPath(plugin.pluginUri);
66
+ if (dir)
67
+ findSkillDirs(dir, out, new Set());
68
+ }
69
+ }
70
+ function collectClaude(out) {
71
+ if (!existsSync(CLAUDE_INSTALLED))
72
+ return;
73
+ let manifest;
74
+ try {
75
+ manifest = JSON.parse(readFileSync(CLAUDE_INSTALLED, "utf8"));
76
+ }
77
+ catch {
78
+ return;
79
+ }
80
+ for (const versions of Object.values(manifest.plugins ?? {})) {
81
+ for (const plugin of versions) {
82
+ if (plugin.installPath) {
83
+ findSkillDirs(plugin.installPath, out, new Set());
84
+ }
85
+ }
86
+ }
87
+ }
88
+ export default (async () => {
89
+ return {
90
+ config: async (cfg) => {
91
+ const config = cfg;
92
+ const dirs = new Set();
93
+ collectVscode(dirs);
94
+ collectClaude(dirs);
95
+ if (dirs.size === 0)
96
+ return;
97
+ const seen = new Set();
98
+ const unique = [];
99
+ for (const dir of dirs) {
100
+ const name = dir.split(/[\\/]/).pop();
101
+ if (seen.has(name))
102
+ continue;
103
+ seen.add(name);
104
+ unique.push(dir);
105
+ }
106
+ config.skills ??= {};
107
+ config.skills.paths ??= [];
108
+ for (const dir of unique) {
109
+ if (!config.skills.paths.includes(dir)) {
110
+ config.skills.paths.push(dir);
111
+ }
112
+ }
113
+ },
114
+ };
115
+ });
116
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "opencode-skill-autodiscovery",
3
+ "version": "1.0.0",
4
+ "description": "OpenCode plugin that auto-discovers skills installed by VS Code agent plugins and Claude Code plugins, and registers them with the local opencode config.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "engines": {
19
+ "node": ">=18"
20
+ },
21
+ "scripts": {
22
+ "build": "tsc -p tsconfig.json",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "keywords": [
26
+ "opencode",
27
+ "plugin",
28
+ "skill",
29
+ "autodiscovery",
30
+ "claude",
31
+ "vscode"
32
+ ],
33
+ "devDependencies": {
34
+ "@opencode-ai/plugin": "1.18.13",
35
+ "typescript": "^5.5.0",
36
+ "@types/node": "^20.0.0"
37
+ }
38
+ }