summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSpoon <[email protected]>2026-01-29 18:47:06 +0100
committerGitHub <[email protected]>2026-01-29 11:47:06 -0600
commit45ec3105b18c7c0700f05cdb82ea733e584c17fc (patch)
tree4edd50a58b911d21f1cfd53384ed3af842526d08
parent5a56e8172f68270bbf115906779423dfd0d0187d (diff)
downloadopencode-45ec3105b18c7c0700f05cdb82ea733e584c17fc.tar.gz
opencode-45ec3105b18c7c0700f05cdb82ea733e584c17fc.zip
feat: support config skill registration (#9640)
Co-authored-by: Aiden Cline <[email protected]>
-rw-r--r--packages/opencode/src/config/config.ts6
-rw-r--r--packages/opencode/src/skill/skill.ts21
-rw-r--r--packages/opencode/src/tool/skill.ts5
-rw-r--r--packages/sdk/js/src/v2/gen/types.gen.ts9
4 files changed, 38 insertions, 3 deletions
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index 04a3b1e9c..adf733e32 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -560,6 +560,11 @@ export namespace Config {
})
export type Command = z.infer<typeof Command>
+ export const Skills = z.object({
+ paths: z.array(z.string()).optional().describe("Additional paths to skill folders"),
+ })
+ export type Skills = z.infer<typeof Skills>
+
export const Agent = z
.object({
model: z.string().optional(),
@@ -895,6 +900,7 @@ export namespace Config {
.record(z.string(), Command)
.optional()
.describe("Command configuration, see https://opencode.ai/docs/commands"),
+ skills: Skills.optional().describe("Additional skill folder paths"),
watcher: z
.object({
ignore: z.array(z.string()).optional(),
diff --git a/packages/opencode/src/skill/skill.ts b/packages/opencode/src/skill/skill.ts
index 12fc9ee90..5b300a928 100644
--- a/packages/opencode/src/skill/skill.ts
+++ b/packages/opencode/src/skill/skill.ts
@@ -1,5 +1,6 @@
import z from "zod"
import path from "path"
+import os from "os"
import { Config } from "../config/config"
import { Instance } from "../project/instance"
import { NamedError } from "@opencode-ai/util/error"
@@ -40,6 +41,7 @@ export namespace Skill {
const OPENCODE_SKILL_GLOB = new Bun.Glob("{skill,skills}/**/SKILL.md")
const CLAUDE_SKILL_GLOB = new Bun.Glob("skills/**/SKILL.md")
+ const SKILL_GLOB = new Bun.Glob("**/SKILL.md")
export const state = Instance.state(async () => {
const skills: Record<string, Info> = {}
@@ -122,6 +124,25 @@ export namespace Skill {
}
}
+ // Scan additional skill paths from config
+ const config = await Config.get()
+ for (const skillPath of config.skills?.paths ?? []) {
+ const expanded = skillPath.startsWith("~/") ? path.join(os.homedir(), skillPath.slice(2)) : skillPath
+ const resolved = path.isAbsolute(expanded) ? expanded : path.join(Instance.directory, expanded)
+ if (!(await Filesystem.isDir(resolved))) {
+ log.warn("skill path not found", { path: resolved })
+ continue
+ }
+ for await (const match of SKILL_GLOB.scan({
+ cwd: resolved,
+ absolute: true,
+ onlyFiles: true,
+ followSymlinks: true,
+ })) {
+ await addSkill(match)
+ }
+ }
+
return skills
})
diff --git a/packages/opencode/src/tool/skill.ts b/packages/opencode/src/tool/skill.ts
index 9536685ef..76d9fd535 100644
--- a/packages/opencode/src/tool/skill.ts
+++ b/packages/opencode/src/tool/skill.ts
@@ -62,12 +62,11 @@ export const SkillTool = Tool.define("skill", async (ctx) => {
always: [params.name],
metadata: {},
})
- // Load and parse skill content
- const parsed = await ConfigMarkdown.parse(skill.location)
+ const content = (await ConfigMarkdown.parse(skill.location)).content
const dir = path.dirname(skill.location)
// Format output similar to plugin pattern
- const output = [`## Skill: ${skill.name}`, "", `**Base directory**: ${dir}`, "", parsed.content.trim()].join("\n")
+ const output = [`## Skill: ${skill.name}`, "", `**Base directory**: ${dir}`, "", content.trim()].join("\n")
return {
title: `Loaded skill: ${skill.name}`,
diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts
index 12c7bf7df..ceab04c19 100644
--- a/packages/sdk/js/src/v2/gen/types.gen.ts
+++ b/packages/sdk/js/src/v2/gen/types.gen.ts
@@ -1633,6 +1633,15 @@ export type Config = {
subtask?: boolean
}
}
+ /**
+ * Additional skill folder paths to scan
+ */
+ skills?: {
+ /**
+ * Additional paths to skill folders to scan
+ */
+ paths?: Array<string>
+ }
watcher?: {
ignore?: Array<string>
}