feat: support .agents/skills/ directory for cross-agent skill discovery (#9966)

Adds loading from two .agents/skills/ locations:
- ~/.agents/skills/ (personal/user-level, source "agents-skills-personal")
- {workspace}/.agents/skills/ (project-level, source "agents-skills-project")

Precedence: extra < bundled < managed < personal .agents/skills < project .agents/skills < workspace.

Closes #8822
This commit is contained in:
Taras Lukavyi
2026-02-12 14:56:19 +01:00
committed by GitHub
parent dcb921944a
commit d85150357f
2 changed files with 172 additions and 2 deletions

View File

@@ -4,6 +4,7 @@ import {
type Skill,
} from "@mariozechner/pi-coding-agent";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import type { OpenClawConfig } from "../../config/config.js";
import type {
@@ -121,7 +122,7 @@ function loadSkillEntries(
};
const managedSkillsDir = opts?.managedSkillsDir ?? path.join(CONFIG_DIR, "skills");
const workspaceSkillsDir = path.join(workspaceDir, "skills");
const workspaceSkillsDir = path.resolve(workspaceDir, "skills");
const bundledSkillsDir = opts?.bundledSkillsDir ?? resolveBundledSkillsDir();
const extraDirsRaw = opts?.config?.skills?.load?.extraDirs ?? [];
const extraDirs = extraDirsRaw
@@ -150,13 +151,23 @@ function loadSkillEntries(
dir: managedSkillsDir,
source: "openclaw-managed",
});
const personalAgentsSkillsDir = path.resolve(os.homedir(), ".agents", "skills");
const personalAgentsSkills = loadSkills({
dir: personalAgentsSkillsDir,
source: "agents-skills-personal",
});
const projectAgentsSkillsDir = path.resolve(workspaceDir, ".agents", "skills");
const projectAgentsSkills = loadSkills({
dir: projectAgentsSkillsDir,
source: "agents-skills-project",
});
const workspaceSkills = loadSkills({
dir: workspaceSkillsDir,
source: "openclaw-workspace",
});
const merged = new Map<string, Skill>();
// Precedence: extra < bundled < managed < workspace
// Precedence: extra < bundled < managed < agents-skills-personal < agents-skills-project < workspace
for (const skill of extraSkills) {
merged.set(skill.name, skill);
}
@@ -166,6 +177,12 @@ function loadSkillEntries(
for (const skill of managedSkills) {
merged.set(skill.name, skill);
}
for (const skill of personalAgentsSkills) {
merged.set(skill.name, skill);
}
for (const skill of projectAgentsSkills) {
merged.set(skill.name, skill);
}
for (const skill of workspaceSkills) {
merged.set(skill.name, skill);
}