# How to Define Custom Workflows in Dexter Using Skills: A Complete Guide

> Learn to define custom workflows in Dexter using skills. Create a SKILL.md file in your skills directory to automate tasks and streamline your development process.

- Repository: [Virat Singh/dexter](https://github.com/virattt/dexter)
- Tags: how-to-guide
- Published: 2026-02-16

---

**You can define custom workflows in Dexter using skills by creating a directory containing a [`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md) file with YAML front-matter (name and description) and markdown instructions, placing it in `~/.dexter/skills/` for personal use or `.dexter/skills/` for project-specific workflows.**

Dexter is an open-source AI research assistant that extends its capabilities through **skills**—reusable, markdown-based workflow definitions that the LLM invokes via the `skill` tool. When you define custom workflows in Dexter using skills, you create modular instructions that the agent can execute without modifying the core codebase.

## Understanding Dexter's Skill Architecture

### What Is a Skill?

A skill is a directory containing a single **[`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md)** file. The file's YAML front-matter supplies the skill's **name** and **description**, while the markdown body contains the step-by-step instructions that the agent follows when the skill is called. This structure separates metadata from execution logic, allowing Dexter to scan skills efficiently without loading full instruction sets until needed.

### The Three Skill Sources

When Dexter starts, it scans three distinct locations for skill directories:

| Source | Path | Purpose |
|--------|------|---------|
| **builtin** | `src/skills/builtin/` | Skills shipped with Dexter (e.g., the built-in DCF skill) |
| **user** | `~/.dexter/skills/` | Personal skills for the current OS user |
| **project** | `<repo-root>/.dexter/skills/` | Project-specific skills that travel with the codebase |

The scanning logic lives in **[`src/skills/registry.ts`](https://github.com/virattt/dexter/blob/main/src/skills/registry.ts)**, which walks each directory, identifies [`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md) files, and caches metadata for fast lookups.

## How Dexter Discovers and Loads Skills

The discovery process involves two distinct phases: metadata extraction and full skill loading.

**Metadata extraction** occurs during initialization in [`src/skills/registry.ts`](https://github.com/virattt/dexter/blob/main/src/skills/registry.ts). The `extractSkillMetadata` function (utilizing logic from [`src/skills/loader.ts`](https://github.com/virattt/dexter/blob/main/src/skills/loader.ts)) reads only the YAML front-matter of each [`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md) file, capturing the name, description, path, and source. This lightweight approach avoids parsing large markdown bodies during the discovery phase and stores results in a `Map<string, SkillMetadata>` called `skillMetadataCache` for O(1) subsequent lookups.

**Full skill loading** happens when the LLM actually invokes a skill. The `loadSkillFromPath` function in [`src/skills/loader.ts`](https://github.com/virattt/dexter/blob/main/src/skills/loader.ts) reads the complete [`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md), parses the front-matter, and returns a complete `Skill` object containing the markdown instructions. This on-demand loading ensures that only active skills consume memory.

Finally, `buildSkillMetadataPrompt` in [`src/skills/registry.ts`](https://github.com/virattt/dexter/blob/main/src/skills/registry.ts) concatenates discovered skill names and descriptions into a metadata block appended to the system prompt, informing the model which skills exist and when to call them.

## Step-by-Step Guide to Define Custom Workflows in Dexter Using Skills

### Step 1: Create the Skill Directory

Choose whether your skill is personal or project-specific. For a project-level workflow that travels with your codebase:

```bash
mkdir -p .dexter/skills/my-analysis

```

For personal use across all projects:

```bash
mkdir -p ~/.dexter/skills/my-analysis

```

### Step 2: Write the SKILL.md File

Create a [`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md) file in your new directory. The file must start with YAML front-matter defining `name` and `description`, followed by markdown instructions.

Example [`.dexter/skills/my-analysis/SKILL.md`](https://github.com/virattt/dexter/blob/main/.dexter/skills/my-analysis/SKILL.md):

```yaml
---
name: my-analysis
description: Run a quick fundamental analysis of a ticker.
---

# My Analysis Skill

1. **Fetch price data** for the ticker using the `financial_search` tool.
2. **Collect the last-quarter revenue and EPS** via `financial_metrics`.
3. **Calculate a simple P/E ratio** and include it in the answer.
4. **Summarize** the findings in a concise paragraph.

```

The `parseSkillFile` function in [`src/skills/loader.ts`](https://github.com/virattt/dexter/blob/main/src/skills/loader.ts) handles the front-matter parsing, while the markdown body becomes the instruction set executed by the LLM.

### Step 3: Refresh the Skill Cache

Dexter automatically discovers skills at startup. If you add a skill while the CLI is running, clear the cache by running:

```

/reload

```

Alternatively, restart the session. Internally, this clears `skillMetadataCache` in [`src/skills/registry.ts`](https://github.com/virattt/dexter/blob/main/src/skills/registry.ts) and rescans all three skill sources.

### Step 4: Invoke Your Custom Workflow

From the Dexter CLI, invoke your skill using the `/skill` command followed by the skill name and any arguments:

```

/skill my-analysis AAPL

```

The LLM receives the skill's instructions from `loadSkillFromPath`, executes the defined tool calls (`financial_search`, `financial_metrics`), and returns the final answer. The `skill` tool implementation in [`src/tools/skill.ts`](https://github.com/virattt/dexter/blob/main/src/tools/skill.ts) bridges the LLM request to the loaded skill by calling `getSkillByName` from the registry and `loadSkillFromPath` from the loader.

## Key Implementation Files in the Dexter Repository

Understanding these source files helps when debugging or extending skill functionality:

| File | Role |
|------|------|
| [`src/skills/types.ts`](https://github.com/virattt/dexter/blob/main/src/skills/types.ts) | Defines `Skill`, `SkillMetadata`, and source enum (builtin, user, project) |
| [`src/skills/loader.ts`](https://github.com/virattt/dexter/blob/main/src/skills/loader.ts) | Parses [`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md), extracts metadata, loads full skill instructions via `loadSkillFromPath` and `parseSkillFile` |
| [`src/skills/registry.ts`](https://github.com/virattt/dexter/blob/main/src/skills/registry.ts) | Scans skill directories, caches metadata in `skillMetadataCache`, builds system prompt block via `buildSkillMetadataPrompt` |
| [`src/tools/skill.ts`](https://github.com/virattt/dexter/blob/main/src/tools/skill.ts) | Implements the `skill` tool that the LLM calls to execute workflows |

## Summary

- **Skills** are markdown-based workflows stored in [`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md) files within directory structures.
- Dexter scans three sources: `src/skills/builtin/`, `~/.dexter/skills/`, and `<repo-root>/.dexter/skills/`.
- The registry in [`src/skills/registry.ts`](https://github.com/virattt/dexter/blob/main/src/skills/registry.ts) caches metadata for performance, while [`src/skills/loader.ts`](https://github.com/virattt/dexter/blob/main/src/skills/loader.ts) loads full instructions on demand.
- Create custom workflows by adding a directory and [`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md) with YAML front-matter (name, description) and markdown instructions.
- Invoke skills via `/skill <name> [args]` and refresh the cache with `/reload` if needed.

## Frequently Asked Questions

### Where should I store custom skills for a team project?

Store project-specific skills in `.dexter/skills/` at the root of your repository. This location travels with the codebase via version control, ensuring every team member has access to the same workflows when they clone the repository. Personal skills that you use across multiple projects should go in `~/.dexter/skills/` instead.

### What happens if two skills have the same name?

Dexter loads skills from three sources in a specific priority order: builtin, user, then project. If duplicate names exist, the last source scanned typically takes precedence, though the registry in [`src/skills/registry.ts`](https://github.com/virattt/dexter/blob/main/src/skills/registry.ts) stores skills in a `Map<string, SkillMetadata>` keyed by name. To avoid collisions, use descriptive, project-specific names like `myproject-financial-analysis` rather than generic terms like `analysis`.

### Can I use variables or arguments in my skill definitions?

Yes. When you invoke a skill using `/skill my-analysis AAPL`, the argument `AAPL` is passed to the skill context. Within your [`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md) instructions, you can reference these arguments as variables that the LLM will substitute when executing the workflow. The markdown body is treated as a template where the model replaces placeholders with provided arguments during the `skill` tool execution in [`src/tools/skill.ts`](https://github.com/virattt/dexter/blob/main/src/tools/skill.ts).

### How do I debug a skill that isn't appearing in Dexter?

First, verify that your [`SKILL.md`](https://github.com/virattt/dexter/blob/main/SKILL.md) file starts with valid YAML front-matter containing both `name` and `description` fields. Check that the file is located in a subdirectory under one of the three valid paths (`~/.dexter/skills/`, `.dexter/skills/`, or `src/skills/builtin/`). If Dexter is already running, execute `/reload` to clear the `skillMetadataCache` in [`src/skills/registry.ts`](https://github.com/virattt/dexter/blob/main/src/skills/registry.ts) and force a rescan. You can also check the registry logs to see if the skill directory was walked successfully during startup.