# Understanding the Structure of a Skill in OpenWork

> Discover the structure of an OpenWork Skill. Learn how SkillItem interfaces with Markdown source files and the skill-markdownts utility for executable logic.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: internals
- Published: 2026-08-21

---

**An OpenWork Skill is a lightweight metadata object defined by the `SkillItem` interface that points to a Markdown source file containing executable logic, parsed by the [`skill-markdown.ts`](https://github.com/different-ai/openwork/blob/main/skill-markdown.ts) utility.**

The `different-ai/openwork` repository implements a modular skill system where reusable functionality—ranging from simple commands to complex browser automation—is encapsulated as discrete units. Understanding the structure of a Skill in OpenWork requires examining both the TypeScript metadata definitions in the server types and the Markdown source convention that stores the actual implementation.

## The Core Metadata: SkillItem Interface

According to the source code in [`dev/apps/server/src/types.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/types.ts), every Skill is represented by a `SkillItem` interface that serves as the server's indexing and routing contract. This lightweight object contains six key properties:

- **name**: Human-readable identifier used in the UI and for routing
- **path**: Filesystem location relative to the workspace (e.g., `"src/skills/my-skill.md"`)
- **description**: Short summary displayed in the Skills picker
- **scope**: Visibility level—either `"project"` (workspace-private) or `"global"` (shared across all workspaces)
- **trigger**: Optional slash-command string (e.g., `"/my-skill"`) for chat invocation
- **error**: Optional error message populated when the skill file fails to parse or compile

The **scope** property determines whether a Skill is registered per-project or globally, while the **trigger** enables direct invocation from the chat interface without navigating the Skills picker.

## The Markdown Source Convention

Beyond the metadata object, the actual Skill content resides in Markdown files following a strict front-matter convention. The parser located in [`dev/ee/packages/utils/src/skill-markdown.ts`](https://github.com/different-ai/openwork/blob/main/dev/ee/packages/utils/src/skill-markdown.ts) extracts three components via the `parseSkillMarkdown()` function:

1. **Front-matter** (delimited by `---`): Contains `name` and optional `description`
2. **Body**: Executable markdown including code blocks, prompts, and instructional text
3. **hasFrontmatter**: Boolean indicating successful front-matter extraction

Thus, a complete Skill consists of the metadata object (`SkillItem`) used for indexing, and the Markdown source file that provides the implementation and UI rendering instructions.

## Server-Side Skill Management

The [`dev/apps/server/src/skills.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/skills.ts) module implements the server-side discovery and rendering pipeline. Two critical functions manage the Skill lifecycle:

**Skill Discovery**: The `listSkills()` function aggregates all available Skills for a given workspace, scanning the filesystem and returning an array of `SkillItem` objects populated with metadata extracted from each Markdown file.

**Content Rendering**: The `renderSkillContentForResponse()` function prepares the Markdown body for client consumption, wrapping content in renderable blocks optimized for the chat interface.

## Practical Implementation Examples

### Defining a Skill in Markdown

Create a file at [`skills/example-skill.md`](https://github.com/different-ai/openwork/blob/main/skills/example-skill.md):

```markdown
---
name: Example Skill
description: Demonstrates the skill structure
---

## What this skill does

It replies with a friendly greeting.

```typescript
export async function run() {
  return "Hello from Example Skill!";
}

```

```

When parsed by `parseSkillMarkdown()`, this generates a `SkillItem` object with `scope: "project"` (default for filesystem-discovered skills) and the extracted metadata.

### Loading Skills Programmatically

```typescript
import { listSkills } from "./skills.js";
import { WorkspaceInfo } from "./types.js";

async function getWorkspaceSkills(workspace: WorkspaceInfo) {
  // Returns SkillItem[] indexed from the filesystem
  const skills = await listSkills(workspace.path, true);
  return skills;
}

```

This function, defined in [`dev/apps/server/src/skills.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/skills.ts), reads the workspace directory structure and builds the complete list of available Skills.

### Rendering for the Chat UI

```typescript
import { renderSkillContentForResponse } from "./skills.js";

function formatSkillResponse(item: SkillItem, markdownBody: string) {
  // Wraps body for client-side rendering in the chat interface
  return renderSkillContentForResponse(item, markdownBody);
}

```

This utility ensures that Skill content is properly formatted before transmission to the client, handling any necessary markdown transformations or metadata injection.

## Key Files in the Skill Architecture

- **[`dev/apps/server/src/types.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/types.ts)**: Defines the `SkillItem` interface and related type contracts
- **[`dev/apps/server/src/skills.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/skills.ts)**: Implements `listSkills()` for discovery and `renderSkillContentForResponse()` for rendering
- **[`dev/ee/packages/utils/src/skill-markdown.ts`](https://github.com/different-ai/openwork/blob/main/dev/ee/packages/utils/src/skill-markdown.ts)**: Contains `parseSkillMarkdown()` for front-matter extraction and markdown composition
- **[`dev/apps/server/src/skills.test.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/skills.test.ts)**: Unit tests validating the parsing logic and API surface

These files collectively define how OpenWork models a Skill: a structured metadata object that points to a Markdown source file, parsed by specialized utilities, and managed by server-side aggregation functions.

## Summary

- **Skills are metadata objects**: The `SkillItem` interface in [`dev/apps/server/src/types.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/types.ts) defines the canonical structure with properties for identification, scope, and routing.
- **Content lives in Markdown**: Skill implementations use front-matter for metadata and the body for executable logic, parsed by `parseSkillMarkdown()` in [`skill-markdown.ts`](https://github.com/different-ai/openwork/blob/main/skill-markdown.ts).
- **Scope controls visibility**: The `scope` property distinguishes between project-specific (`"project"`) and global (`"global"`) Skills.
- **Triggers enable chat integration**: Optional `trigger` properties allow slash-command invocation from the chat interface without UI navigation.
- **Server-side aggregation**: The [`skills.ts`](https://github.com/different-ai/openwork/blob/main/skills.ts) module handles filesystem discovery via `listSkills()` and content preparation via `renderSkillContentForResponse()`.

## Frequently Asked Questions

### What properties are required in a SkillItem object?

The `SkillItem` interface requires four properties: `name`, `path`, `description`, and `scope`. The `trigger` and `error` properties are optional, with `error` typically populated dynamically by the server when parsing fails or compilation errors occur.

### How does OpenWork distinguish between project and global Skills?

The `scope` property accepts either `"project"` or `"global"` as defined in [`dev/apps/server/src/types.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/types.ts). Project-scoped Skills are private to their workspace and loaded from the local project directory, while global Skills are shared across all workspaces and typically loaded from a global configuration path.

### Where is Skill content actually stored?

Skill content resides in Markdown files referenced by the `path` property of the `SkillItem` object. These files contain YAML front-matter for metadata and a Markdown body for executable logic, parsed by the `parseSkillMarkdown()` function in [`dev/ee/packages/utils/src/skill-markdown.ts`](https://github.com/different-ai/openwork/blob/main/dev/ee/packages/utils/src/skill-markdown.ts).

### How are Skills invoked from the chat interface?

When a user types a trigger string (e.g., `"/my-skill"`) defined in the optional `trigger` property, the server routes the request to the corresponding Skill, reads the Markdown file from the `path` location, parses the front-matter, and renders the content using `renderSkillContentForResponse()` for display in the client UI.