From 595ed835406c1df32145dd9e0ef7b3f18ec84176 Mon Sep 17 00:00:00 2001 From: neriousy Date: Tue, 3 Feb 2026 12:59:18 +0100 Subject: [PATCH 1/3] fix:dax --- .agents/skills/test-skill/SKILL.md | 8 ++++ .claude/skills/test-skill/SKILL.md | 8 ++++ .opencode/skills/test-skill/SKILL.md | 8 ++++ .skills/test-skill/SKILL.md | 25 +++++++++++++ packages/opencode/src/skill/skill.ts | 56 ++++++++++++++++++---------- 5 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 .agents/skills/test-skill/SKILL.md create mode 100644 .claude/skills/test-skill/SKILL.md create mode 100644 .opencode/skills/test-skill/SKILL.md create mode 100644 .skills/test-skill/SKILL.md diff --git a/.agents/skills/test-skill/SKILL.md b/.agents/skills/test-skill/SKILL.md new file mode 100644 index 000000000000..f24a619d8cab --- /dev/null +++ b/.agents/skills/test-skill/SKILL.md @@ -0,0 +1,8 @@ +--- +name: agent-test-skill +description: Skill loaded from .agents/skills for local debugging +--- + +# Agent Test Skill + +If you can load this skill, external skills from `.agents/skills/` are being discovered. diff --git a/.claude/skills/test-skill/SKILL.md b/.claude/skills/test-skill/SKILL.md new file mode 100644 index 000000000000..f6f44a217536 --- /dev/null +++ b/.claude/skills/test-skill/SKILL.md @@ -0,0 +1,8 @@ +--- +name: claude-test-skill +description: Skill loaded from .claude/skills for local debugging +--- + +# Claude Test Skill + +If you can load this skill, external skills from `.claude/skills/` are being discovered. diff --git a/.opencode/skills/test-skill/SKILL.md b/.opencode/skills/test-skill/SKILL.md new file mode 100644 index 000000000000..955663787ea8 --- /dev/null +++ b/.opencode/skills/test-skill/SKILL.md @@ -0,0 +1,8 @@ +--- +name: opencode-test-skill +description: Skill loaded from .opencode/skills for local debugging +--- + +# OpenCode Test Skill + +If you can load this skill, skills from `.opencode/skills/` are being discovered. diff --git a/.skills/test-skill/SKILL.md b/.skills/test-skill/SKILL.md new file mode 100644 index 000000000000..2e941307d333 --- /dev/null +++ b/.skills/test-skill/SKILL.md @@ -0,0 +1,25 @@ +--- +name: test-skill +description: A simple test skill to verify local skill loading works correctly +--- + +# Test Skill + +This is a test skill that can be used to verify that the local skill loading mechanism is working properly. + +## When to Use + +Use this skill when you need to test if skills are being loaded from the `.skills/` folder correctly. + +## Instructions + +1. Check if this skill appears in the skill list +2. Verify the skill metadata is correct +3. Test loading skill content + +## Example + +If this skill loads correctly, you should see: + +- Name: test-skill +- Description: A simple test skill to verify local skill loading works correctly diff --git a/packages/opencode/src/skill/skill.ts b/packages/opencode/src/skill/skill.ts index 26b9b1065955..fd5c6cec6485 100644 --- a/packages/opencode/src/skill/skill.ts +++ b/packages/opencode/src/skill/skill.ts @@ -40,8 +40,10 @@ export namespace Skill { }), ) - // External skill patterns to search for (project-level and global) - const EXTERNAL_PATTERNS = [".claude/skills/**/SKILL.md", ".agents/skills/**/SKILL.md"] + // External skill directories to search for (project-level and global) + // These follow the directory layout used by Claude Code and other agents. + const EXTERNAL_DIRS = [".claude", ".agents"] + const EXTERNAL_SKILL_GLOB = new Bun.Glob("skills/**/SKILL.md") const OPENCODE_SKILL_GLOB = new Bun.Glob("{skill,skills}/**/SKILL.md") const SKILL_GLOB = new Bun.Glob("**/SKILL.md") @@ -84,25 +86,41 @@ export namespace Skill { // Scan external skill directories (.claude/skills/, .agents/skills/, etc.) // Load global (home) first, then project-level (so project-level overwrites) if (!Flag.OPENCODE_DISABLE_EXTERNAL_SKILLS) { - for (const pattern of EXTERNAL_PATTERNS) { - // Scan global home directory for external skills first - const glob = new Bun.Glob(pattern) - for await (const match of glob.scan({ - cwd: Global.Path.home, - absolute: true, - onlyFiles: true, - followSymlinks: true, - dot: true, - })) { - await addSkill(match) + for (const dir of EXTERNAL_DIRS) { + const root = path.join(Global.Path.home, dir) + if (!(await Filesystem.isDir(root))) continue + try { + for await (const match of EXTERNAL_SKILL_GLOB.scan({ + cwd: root, + absolute: true, + onlyFiles: true, + followSymlinks: true, + dot: true, + })) { + await addSkill(match) + } + } catch (error) { + log.error("failed to scan global skills", { dir: root, error }) } + } - // Then walk up from current directory to find project-level skills (overwrites globals) - for (const match of await Filesystem.globUp(pattern, Instance.directory, Instance.worktree).catch((error) => { - log.error("failed to scan project directories for skills", { pattern, error }) - return [] - })) { - await addSkill(match) + for await (const root of Filesystem.up({ + targets: EXTERNAL_DIRS, + start: Instance.directory, + stop: Instance.worktree, + })) { + try { + for await (const match of EXTERNAL_SKILL_GLOB.scan({ + cwd: root, + absolute: true, + onlyFiles: true, + followSymlinks: true, + dot: true, + })) { + await addSkill(match) + } + } catch (error) { + log.error("failed to scan project skills", { dir: root, error }) } } } From 31d3ce2bac426a38b796c16f7644ac4d81656d3a Mon Sep 17 00:00:00 2001 From: neriousy Date: Tue, 3 Feb 2026 13:08:03 +0100 Subject: [PATCH 2/3] chore: cleanup files --- .agents/skills/test-skill/SKILL.md | 8 -------- .claude/skills/test-skill/SKILL.md | 8 -------- .opencode/skills/test-skill/SKILL.md | 8 -------- .skills/test-skill/SKILL.md | 25 ------------------------- 4 files changed, 49 deletions(-) delete mode 100644 .agents/skills/test-skill/SKILL.md delete mode 100644 .claude/skills/test-skill/SKILL.md delete mode 100644 .opencode/skills/test-skill/SKILL.md delete mode 100644 .skills/test-skill/SKILL.md diff --git a/.agents/skills/test-skill/SKILL.md b/.agents/skills/test-skill/SKILL.md deleted file mode 100644 index f24a619d8cab..000000000000 --- a/.agents/skills/test-skill/SKILL.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: agent-test-skill -description: Skill loaded from .agents/skills for local debugging ---- - -# Agent Test Skill - -If you can load this skill, external skills from `.agents/skills/` are being discovered. diff --git a/.claude/skills/test-skill/SKILL.md b/.claude/skills/test-skill/SKILL.md deleted file mode 100644 index f6f44a217536..000000000000 --- a/.claude/skills/test-skill/SKILL.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: claude-test-skill -description: Skill loaded from .claude/skills for local debugging ---- - -# Claude Test Skill - -If you can load this skill, external skills from `.claude/skills/` are being discovered. diff --git a/.opencode/skills/test-skill/SKILL.md b/.opencode/skills/test-skill/SKILL.md deleted file mode 100644 index 955663787ea8..000000000000 --- a/.opencode/skills/test-skill/SKILL.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: opencode-test-skill -description: Skill loaded from .opencode/skills for local debugging ---- - -# OpenCode Test Skill - -If you can load this skill, skills from `.opencode/skills/` are being discovered. diff --git a/.skills/test-skill/SKILL.md b/.skills/test-skill/SKILL.md deleted file mode 100644 index 2e941307d333..000000000000 --- a/.skills/test-skill/SKILL.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: test-skill -description: A simple test skill to verify local skill loading works correctly ---- - -# Test Skill - -This is a test skill that can be used to verify that the local skill loading mechanism is working properly. - -## When to Use - -Use this skill when you need to test if skills are being loaded from the `.skills/` folder correctly. - -## Instructions - -1. Check if this skill appears in the skill list -2. Verify the skill metadata is correct -3. Test loading skill content - -## Example - -If this skill loads correctly, you should see: - -- Name: test-skill -- Description: A simple test skill to verify local skill loading works correctly From fe22b9f9f3d87d45a43719f2a35a6f41da10e963 Mon Sep 17 00:00:00 2001 From: neriousy Date: Tue, 3 Feb 2026 13:14:20 +0100 Subject: [PATCH 3/3] refactor: remove try catch --- packages/opencode/src/skill/skill.ts | 44 ++++++++++++---------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/packages/opencode/src/skill/skill.ts b/packages/opencode/src/skill/skill.ts index fd5c6cec6485..17e8ff707058 100644 --- a/packages/opencode/src/skill/skill.ts +++ b/packages/opencode/src/skill/skill.ts @@ -83,25 +83,29 @@ export namespace Skill { } } + const scanExternal = async (root: string, scope: "global" | "project") => { + return Array.fromAsync( + EXTERNAL_SKILL_GLOB.scan({ + cwd: root, + absolute: true, + onlyFiles: true, + followSymlinks: true, + dot: true, + }), + ) + .then((matches) => Promise.all(matches.map(addSkill))) + .catch((error) => { + log.error(`failed to scan ${scope} skills`, { dir: root, error }) + }) + } + // Scan external skill directories (.claude/skills/, .agents/skills/, etc.) // Load global (home) first, then project-level (so project-level overwrites) if (!Flag.OPENCODE_DISABLE_EXTERNAL_SKILLS) { for (const dir of EXTERNAL_DIRS) { const root = path.join(Global.Path.home, dir) if (!(await Filesystem.isDir(root))) continue - try { - for await (const match of EXTERNAL_SKILL_GLOB.scan({ - cwd: root, - absolute: true, - onlyFiles: true, - followSymlinks: true, - dot: true, - })) { - await addSkill(match) - } - } catch (error) { - log.error("failed to scan global skills", { dir: root, error }) - } + await scanExternal(root, "global") } for await (const root of Filesystem.up({ @@ -109,19 +113,7 @@ export namespace Skill { start: Instance.directory, stop: Instance.worktree, })) { - try { - for await (const match of EXTERNAL_SKILL_GLOB.scan({ - cwd: root, - absolute: true, - onlyFiles: true, - followSymlinks: true, - dot: true, - })) { - await addSkill(match) - } - } catch (error) { - log.error("failed to scan project skills", { dir: root, error }) - } + await scanExternal(root, "project") } }