Merge pull request #966 from jonasherr/fix/skills-directory-path-810

fix: use correct 'skills' directory path and respect OPENCODE_CONFIG_DIR
This commit is contained in:
Kenny 2026-01-21 12:00:02 -05:00 committed by GitHub
commit bc7b413bc2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 13 additions and 11 deletions

View File

@ -147,8 +147,8 @@ Three specializations in one:
### Custom Skills ### Custom Skills
Load custom skills from: Load custom skills from:
- `.opencode/skill/*/SKILL.md` (project) - `.opencode/skills/*/SKILL.md` (project)
- `~/.config/opencode/skill/*/SKILL.md` (user) - `~/.config/opencode/skills/*/SKILL.md` (user)
- `.claude/skills/*/SKILL.md` (Claude Code compat) - `.claude/skills/*/SKILL.md` (Claude Code compat)
- `~/.claude/skills/*/SKILL.md` (Claude Code user) - `~/.claude/skills/*/SKILL.md` (Claude Code user)

View File

@ -36,7 +36,7 @@ features/
| Type | Priority (highest first) | | Type | Priority (highest first) |
|------|--------------------------| |------|--------------------------|
| Commands | `.opencode/command/` > `~/.config/opencode/command/` > `.claude/commands/` > `~/.claude/commands/` | | Commands | `.opencode/command/` > `~/.config/opencode/command/` > `.claude/commands/` > `~/.claude/commands/` |
| Skills | `.opencode/skill/` > `~/.config/opencode/skill/` > `.claude/skills/` > `~/.claude/skills/` | | Skills | `.opencode/skills/` > `~/.config/opencode/skills/` > `.claude/skills/` > `~/.claude/skills/` |
| Agents | `.claude/agents/` > `~/.claude/agents/` | | Agents | `.claude/agents/` > `~/.claude/agents/` |
| MCPs | `.claude/.mcp.json` > `.mcp.json` > `~/.claude/.mcp.json` | | MCPs | `.claude/.mcp.json` > `.mcp.json` > `~/.claude/.mcp.json` |

View File

@ -5,7 +5,7 @@ import { tmpdir } from "os"
import type { LoadedSkill } from "./types" import type { LoadedSkill } from "./types"
const TEST_DIR = join(tmpdir(), "async-loader-test-" + Date.now()) const TEST_DIR = join(tmpdir(), "async-loader-test-" + Date.now())
const SKILLS_DIR = join(TEST_DIR, ".opencode", "skill") const SKILLS_DIR = join(TEST_DIR, ".opencode", "skills")
function createTestSkill(name: string, content: string, mcpJson?: object): string { function createTestSkill(name: string, content: string, mcpJson?: object): string {
const skillDir = join(SKILLS_DIR, name) const skillDir = join(SKILLS_DIR, name)

View File

@ -4,7 +4,7 @@ import { join } from "path"
import { tmpdir } from "os" import { tmpdir } from "os"
const TEST_DIR = join(tmpdir(), "skill-loader-test-" + Date.now()) const TEST_DIR = join(tmpdir(), "skill-loader-test-" + Date.now())
const SKILLS_DIR = join(TEST_DIR, ".opencode", "skill") const SKILLS_DIR = join(TEST_DIR, ".opencode", "skills")
function createTestSkill(name: string, content: string, mcpJson?: object): string { function createTestSkill(name: string, content: string, mcpJson?: object): string {
const skillDir = join(SKILLS_DIR, name) const skillDir = join(SKILLS_DIR, name)

View File

@ -1,11 +1,11 @@
import { promises as fs } from "fs" import { promises as fs } from "fs"
import { join, basename } from "path" import { join, basename } from "path"
import { homedir } from "os"
import yaml from "js-yaml" import yaml from "js-yaml"
import { parseFrontmatter } from "../../shared/frontmatter" import { parseFrontmatter } from "../../shared/frontmatter"
import { sanitizeModelField } from "../../shared/model-sanitizer" import { sanitizeModelField } from "../../shared/model-sanitizer"
import { resolveSymlinkAsync, isMarkdownFile } from "../../shared/file-utils" import { resolveSymlinkAsync, isMarkdownFile } from "../../shared/file-utils"
import { getClaudeConfigDir } from "../../shared" import { getClaudeConfigDir } from "../../shared"
import { getOpenCodeConfigDir } from "../../shared/opencode-config-dir"
import type { CommandDefinition } from "../claude-code-command-loader/types" import type { CommandDefinition } from "../claude-code-command-loader/types"
import type { SkillScope, SkillMetadata, LoadedSkill, LazyContentLoader } from "./types" import type { SkillScope, SkillMetadata, LoadedSkill, LazyContentLoader } from "./types"
import type { SkillMcpConfig } from "../skill-mcp-manager/types" import type { SkillMcpConfig } from "../skill-mcp-manager/types"
@ -187,13 +187,14 @@ export async function loadProjectSkills(): Promise<Record<string, CommandDefinit
} }
export async function loadOpencodeGlobalSkills(): Promise<Record<string, CommandDefinition>> { export async function loadOpencodeGlobalSkills(): Promise<Record<string, CommandDefinition>> {
const opencodeSkillsDir = join(homedir(), ".config", "opencode", "skill") const configDir = getOpenCodeConfigDir({ binary: "opencode" })
const opencodeSkillsDir = join(configDir, "skills")
const skills = await loadSkillsFromDir(opencodeSkillsDir, "opencode") const skills = await loadSkillsFromDir(opencodeSkillsDir, "opencode")
return skillsToRecord(skills) return skillsToRecord(skills)
} }
export async function loadOpencodeProjectSkills(): Promise<Record<string, CommandDefinition>> { export async function loadOpencodeProjectSkills(): Promise<Record<string, CommandDefinition>> {
const opencodeProjectDir = join(process.cwd(), ".opencode", "skill") const opencodeProjectDir = join(process.cwd(), ".opencode", "skills")
const skills = await loadSkillsFromDir(opencodeProjectDir, "opencode-project") const skills = await loadSkillsFromDir(opencodeProjectDir, "opencode-project")
return skillsToRecord(skills) return skillsToRecord(skills)
} }
@ -249,11 +250,12 @@ export async function discoverProjectClaudeSkills(): Promise<LoadedSkill[]> {
} }
export async function discoverOpencodeGlobalSkills(): Promise<LoadedSkill[]> { export async function discoverOpencodeGlobalSkills(): Promise<LoadedSkill[]> {
const opencodeSkillsDir = join(homedir(), ".config", "opencode", "skill") const configDir = getOpenCodeConfigDir({ binary: "opencode" })
const opencodeSkillsDir = join(configDir, "skills")
return loadSkillsFromDir(opencodeSkillsDir, "opencode") return loadSkillsFromDir(opencodeSkillsDir, "opencode")
} }
export async function discoverOpencodeProjectSkills(): Promise<LoadedSkill[]> { export async function discoverOpencodeProjectSkills(): Promise<LoadedSkill[]> {
const opencodeProjectDir = join(process.cwd(), ".opencode", "skill") const opencodeProjectDir = join(process.cwd(), ".opencode", "skills")
return loadSkillsFromDir(opencodeProjectDir, "opencode-project") return loadSkillsFromDir(opencodeProjectDir, "opencode-project")
} }

View File

@ -18,7 +18,7 @@ export interface SkillInfo {
} }
export interface SkillLoadOptions { export interface SkillLoadOptions {
/** When true, only load from OpenCode paths (.opencode/skill/, ~/.config/opencode/skill/) */ /** When true, only load from OpenCode paths (.opencode/skills/, ~/.config/opencode/skills/) */
opencodeOnly?: boolean opencodeOnly?: boolean
/** Pre-merged skills to use instead of discovering */ /** Pre-merged skills to use instead of discovering */
skills?: LoadedSkill[] skills?: LoadedSkill[]