load skills from .claude directory

also put skills inside skills/ directory
This commit is contained in:
uinstinct
2026-01-15 12:42:45 +05:30
parent 2ecccb0fa5
commit 85759451cb

View File

@@ -4,6 +4,10 @@ import {
} from "@continuedev/config-yaml"; } from "@continuedev/config-yaml";
import z from "zod"; import z from "zod";
import { IDE, Skill } from "../.."; import { IDE, Skill } from "../..";
import { walkDir } from "../../indexing/walkDir";
import { localPathToUri } from "../../util/pathToUri";
import { getGlobalFolderWithName } from "../../util/paths";
import { joinPathsToUri } from "../../util/uri";
import { getAllDotContinueDefinitionFiles } from "../loadLocalAssistants"; import { getAllDotContinueDefinitionFiles } from "../loadLocalAssistants";
const skillFrontmatterSchema = z.object({ const skillFrontmatterSchema = z.object({
@@ -11,28 +15,61 @@ const skillFrontmatterSchema = z.object({
description: z.string().min(1), description: z.string().min(1),
}); });
const SKILLS_DIR = "skills";
/**
* Get skills from .claude/skills directory
*/
async function getClaudeSkillsDir(ide: IDE) {
const fullDirs = (await ide.getWorkspaceDirs()).map((dir) =>
joinPathsToUri(dir, ".claude", SKILLS_DIR),
);
fullDirs.push(localPathToUri(getGlobalFolderWithName(SKILLS_DIR)));
return (
await Promise.all(
fullDirs.map(async (dir) => {
const exists = await ide.fileExists(dir);
if (!exists) return [];
const uris = await walkDir(dir, ide, {
source: "get claude skills files",
});
// filter markdown files only
return uris.filter((uri) => uri.endsWith(".md"));
}),
)
).flat();
}
export async function loadMarkdownSkills(ide: IDE) { export async function loadMarkdownSkills(ide: IDE) {
const errors: ConfigValidationError[] = []; const errors: ConfigValidationError[] = [];
const skills: Skill[] = []; const skills: Skill[] = [];
try { try {
const yamlAndMarkdownFiles = await getAllDotContinueDefinitionFiles( const yamlAndMarkdownFileUris = [
ide, ...(
{ await getAllDotContinueDefinitionFiles(
includeGlobal: true, ide,
includeWorkspace: true, {
fileExtType: "markdown", includeGlobal: true,
}, includeWorkspace: true,
"", // SKILL.md can exist in any .continue subdirectory fileExtType: "markdown",
); },
SKILLS_DIR,
)
).map((file) => file.path),
...(await getClaudeSkillsDir(ide)),
];
const skillFiles = yamlAndMarkdownFiles.filter((file) => const skillFiles = yamlAndMarkdownFileUris.filter((path) =>
file.path.endsWith("SKILL.md"), path.endsWith("SKILL.md"),
); );
for (const file of skillFiles) { for (const fileUri of skillFiles) {
try { try {
const content = await ide.readFile(fileUri);
const { frontmatter, markdown } = parseMarkdownRule( const { frontmatter, markdown } = parseMarkdownRule(
file.content, content,
) as unknown as { frontmatter: Skill; markdown: string }; ) as unknown as { frontmatter: Skill; markdown: string };
const validatedFrontmatter = skillFrontmatterSchema.parse(frontmatter); const validatedFrontmatter = skillFrontmatterSchema.parse(frontmatter);
@@ -40,7 +77,7 @@ export async function loadMarkdownSkills(ide: IDE) {
skills.push({ skills.push({
...validatedFrontmatter, ...validatedFrontmatter,
content: markdown, content: markdown,
path: file.path.slice(7), path: fileUri,
}); });
} catch (error) { } catch (error) {
errors.push({ errors.push({