Where Custom Skill Definitions Are Stored in Craft Agents

Custom skill definitions in Craft Agents are stored as SKILL.md files inside workspace-specific subdirectories located at <workspace-root>/skills/<skill-slug>/, with metadata and content parsed from front-matter and markdown body.

In the craft-ai-agents/craft-agents-oss repository, custom skills are persisted locally on the filesystem rather than in a centralized database. Each workspace maintains its own isolated skills directory containing sub-folders named after their respective skill slugs. Understanding this storage architecture is essential for debugging skill loading issues or implementing custom tooling around the Craft Agents platform.

Workspace Skill Storage Location

Every workspace in Craft Agents has a dedicated root directory. Within that directory, custom skills reside in a predefined skills folder.

The absolute path convention follows this structure:

<workspace-root>/skills/<skill-slug>/SKILL.md

According to the source code in packages/shared/src/workspaces/storage.ts, the function getWorkspaceSkillsPath() returns the absolute path to this skills directory by appending /skills to the workspace root【#84-L89】. This design ensures that skills are scoped per workspace, preventing namespace collisions between different projects.

How Skills Are Structured on Disk

The SKILL.md File Format

Each custom skill is a subdirectory containing a mandatory SKILL.md file. This file serves as the single source of truth for the skill's definition, combining YAML front-matter for metadata and markdown for the implementation body.

The loadWorkspaceSkills() function and related utilities in packages/shared/src/skills/storage.ts read these files to populate the skill registry at runtime【#87-L90】. The metadata structure conforms to the SkillMetadata interface defined in packages/shared/src/skills/types.ts, which standardizes fields like name, description, and configuration parameters.

Supporting Assets

Skills may include additional assets such as icons. The getSkillIconPath() utility looks for icon.* files located alongside SKILL.md within the skill directory【#78-L86】. This colocation pattern keeps all skill-related assets bundled together for easy portability and version control.

Programmatic Access to Skill Storage

The @craft-agents/shared package exports several utilities for interacting with custom skill storage without hardcoding file paths.

Listing Available Skills

To retrieve all skill slugs within a workspace:

import { listSkillSlugs } from '@craft-agents/shared/src/skills/storage';
import { getWorkspacePath } from '@craft-agents/shared/src/workspaces/storage';

const wsId = 'my-workspace';
const wsRoot = getWorkspacePath(wsId);

const slugs = listSkillSlugs(wsRoot);
console.log('Workspace skills:', slugs);

The listSkillSlugs() function scans the <workspace-root>/skills directory and returns an array of directory names representing each skill slug【#35-L40】.

Loading Skill Metadata and Content

To load a specific skill's complete definition:

import { loadSkill } from '@craft-agents/shared/src/skills/storage';
import { getWorkspacePath } from '@craft-agents/shared/src/workspaces/storage';

const wsRoot = getWorkspacePath('my-workspace');
const skill = loadSkill(wsRoot, 'my-custom-skill');

if (skill) {
  console.log('Skill name:', skill.metadata.name);
  console.log('Description:', skill.metadata.description);
  console.log('Body:', skill.content);
}

loadSkill() reads the SKILL.md file for the given slug and parses both the front-matter metadata and the markdown body【#78-L81】.

Resolving Skill Asset Paths

To locate a skill's icon file:

import { getSkillIconPath } from '@craft-agents/shared/src/skills/storage';
import { getWorkspacePath } from '@craft-agents/shared/src/workspaces/storage';

const iconPath = getSkillIconPath(getWorkspacePath('my-workspace'), 'my-custom-skill');
console.log('Icon location:', iconPath);

This utility checks for image files matching icon.* patterns within the skill's directory【#78-L86】.

Key Source Files and Functions

The storage mechanism is implemented across several files in the packages/shared directory:

Summary

  • Custom skills are stored per workspace in <workspace-root>/skills/<skill-slug>/SKILL.md.
  • The getWorkspaceSkillsPath() utility provides the canonical path resolution for skill directories.
  • Each skill directory contains a SKILL.md file with front-matter metadata and optional assets like icons.
  • Use listSkillSlugs() to enumerate skills and loadSkill() to read specific definitions.
  • The storage layer is implemented in packages/shared/src/skills/storage.ts with type definitions in types.ts.

Frequently Asked Questions

What happens if a SKILL.md file is missing from a skill directory?

If the SKILL.md file is missing or malformed, the loadSkill() function will return null or throw a parsing error depending on the validation context. The listSkillSlugs() function only returns directory names, so it may list a slug that subsequently fails to load if the file is absent.

Can I store other files in the skill directory besides SKILL.md?

Yes. The directory structure supports additional assets such as icon.* files, which are resolved via getSkillIconPath(). While the system primarily looks for SKILL.md, you can include supplementary files like configuration JSON or documentation, though these require custom loading logic outside the standard skill storage utilities.

How does Craft Agents handle skill name collisions between workspaces?

Since skills are stored within workspace-specific skills directories, collisions are naturally prevented at the storage level. Each workspace operates in isolation, and the getWorkspacePath() function ensures that skill lookups are scoped to the correct workspace root. Skills from different workspaces cannot interfere with each other unless explicitly shared through external synchronization mechanisms.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →