MCPcopy Create free account
hub / github.com/Zoo-Code-Org/Zoo-Code / createSkill

Method createSkill

src/services/skills/SkillsManager.ts:348–424  ·  view source on GitHub ↗

* Create a new skill * @param name - Skill name (must be valid per agentskills.io spec) * @param source - "global" or "project" * @param description - Skill description * @param modeSlugs - Optional mode restrictions (undefined/empty = any mode) * @returns Path to created SKILL.md file

(
		name: string,
		source: "global" | "project",
		description: string,
		modeSlugs?: string[],
	)

Source from the content-addressed store, hash-verified

346 * @returns Path to created SKILL.md file
347 */
348 async createSkill(
349 name: string,
350 source: "global" | "project",
351 description: string,
352 modeSlugs?: string[],
353 ): Promise<string> {
354 // Validate skill name
355 const validation = this.validateSkillName(name)
356 if (!validation.valid) {
357 throw new Error(validation.error)
358 }
359
360 // Validate description
361 const trimmedDescription = description.trim()
362 if (trimmedDescription.length < 1 || trimmedDescription.length > 1024) {
363 throw new Error(t("skills:errors.description_length", { length: trimmedDescription.length }))
364 }
365
366 // Determine base directory
367 let baseDir: string
368 if (source === "global") {
369 baseDir = getGlobalRooDirectory()
370 } else {
371 const provider = this.providerRef.deref()
372 if (!provider?.cwd) {
373 throw new Error(t("skills:errors.no_workspace"))
374 }
375 baseDir = path.join(provider.cwd, ".roo")
376 }
377
378 // Always use the generic skills directory (mode info stored in frontmatter now)
379 const skillsDir = path.join(baseDir, "skills")
380 const skillDir = path.join(skillsDir, name)
381 const skillMdPath = path.join(skillDir, "SKILL.md")
382
383 // Check if skill already exists
384 if (await fileExists(skillMdPath)) {
385 throw new Error(t("skills:errors.already_exists", { name, path: skillMdPath }))
386 }
387
388 // Create the skill directory
389 await fs.mkdir(skillDir, { recursive: true })
390
391 // Generate SKILL.md content with frontmatter
392 const titleName = name
393 .split("-")
394 .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
395 .join(" ")
396
397 // Build frontmatter with optional modeSlugs
398 const frontmatterLines = [`name: ${name}`, `description: ${trimmedDescription}`]
399 if (modeSlugs && modeSlugs.length > 0) {
400 frontmatterLines.push(`modeSlugs:`)
401 for (const slug of modeSlugs) {
402 frontmatterLines.push(` - ${slug}`)
403 }
404 }
405

Callers 2

handleCreateSkillFunction · 0.80

Calls 6

validateSkillNameMethod · 0.95
discoverSkillsMethod · 0.95
tFunction · 0.90
getGlobalRooDirectoryFunction · 0.90
fileExistsFunction · 0.90
writeFileMethod · 0.80

Tested by

no test coverage detected