# How to Write a Custom Skill for oh-my-codex with the SKILL.md Format

> Learn to write a custom skill for oh-my-codex using the SKILL.md format. Discover how to structure your skill files with YAML front-matter and XML-style markdown sections for seamless integration.

- Repository: [Bellman/oh-my-codex](https://github.com/Yeachan-Heo/oh-my-codex)
- Tags: how-to-guide
- Published: 2026-04-03

---

**Writing a custom skill for oh-my-codex requires creating a SKILL.md file with YAML front-matter and specific XML-style markdown sections in a dedicated directory under `./.codex/skills/<skill-name>/`.**

The **oh-my-codex** repository by Yeachan-Heo treats every reusable command as a *skill*—a self-contained markdown contract that the runtime parses and executes sequentially. When you write a custom skill using the **SKILL.md** format, you define machine-readable instructions that the engine interprets without executing arbitrary embedded code, making it safe to extend capabilities without modifying the core codebase.

## SKILL.md Architecture and File Structure

Every skill resides in its own directory, typically under `./.codex/skills/<skill-name>/` for local projects or `./skills/<skill-name>/` for global installation. The [`SKILL.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/SKILL.md) file inside this directory serves as both the manifest and execution script.

The runtime, implemented in `src/agent/`, parses this file using regular-expression markers to extract:
- **YAML front-matter** declaring `name`, `description`, and optional `argument-hint`
- **XML-style markdown sections** such as `<Purpose>`, `<Use_When>`, and `<Steps>` that drive the interactive dialog and tool execution

Before loading, the validation logic in [`src/skill/validator.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/skill/validator.ts) checks that mandatory sections exist, that YAML syntax is valid, and that declared triggers are unique. Any failure produces a `✗ Error:` prefix message identifying the specific validation fault.

## Required SKILL.md Sections

A valid SKILL.md must contain specific sections in the order expected by the parser. Each section uses XML-style tags within the markdown body.

### Front-Matter Configuration

The file must begin with YAML front-matter between triple dashes:

```yaml
---
name: hello-world
description: Print a friendly greeting; optionally persist it to a file.
argument-hint: "[name] [--output <path>]"
---

```

The `name` field determines the invocation command (`/<name>`), while `argument-hint` provides usage guidance displayed in help text.

### <Purpose> and <Use_When>

The `<Purpose>` section contains a one-sentence high-level goal describing what the skill achieves. The `<Use_When>` section defines trigger conditions—comma-separated keywords or phrases—that help the dispatcher match user intent efficiently and avoid false positives.

### <Do_Not_Use_When> and <Why_This_Exists>

Guard-rails in `<Do_Not_Use_When>` prevent misuse by specifying scenarios where the skill should refuse activation. The `<Why_This_Exists>` section provides maintenance context and design rationale, helping future contributors understand architectural decisions.

### <Execution_Policy>

This section declares high-level execution rules governing:
- **Synchronization**: Whether steps run sequentially or support parallelism
- **Model selection**: Tier specifications (e.g., `tier="LOW"`) for delegation
- **Error handling**: Validation requirements and fallback strategies
- **Path handling**: Whether to create directories automatically or validate preconditions

### <Steps>

The `<Steps>` section contains a numbered list of concrete actions. Each step can:
- Invoke sub-skills using the `$<skill>` syntax
- Call low-level tools like `omx explore`, `delegate`, or `state_write`
- Request user input via `AskUserQuestion`

Keep each step atomic—performing exactly one action or one tool call—to improve traceability and simplify the verification loop for architect and critic agents.

### <Tool_Usage> (Optional)

Document required external dependencies, binaries, or low-level tools in this optional section. This transparency allows the orchestrator to warn if dependencies are missing before execution begins, preventing runtime surprises.

## Step-by-Step: Creating a hello-world Skill

Create the directory structure:

```bash
mkdir -p ./.codex/skills/hello-world

```

Create [`./.codex/skills/hello-world/SKILL.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/./.codex/skills/hello-world/SKILL.md) with the following content:

```markdown
---
name: hello-world
description: Print a friendly greeting; optionally persist it to a file.
argument-hint: "[name] [--output <path>]"
---

<Purpose>
Provide a quick, reusable way to say hello from the command line.
</Purpose>

<Use_When>
- User types `/hello-world` or mentions "say hello".
- Helpful in tutorials or when a placeholder message is needed.
</Use_When>

<Do_Not_Use_When>
- When the user needs a complex templating engine – use `/template` instead.
</Do_Not_Use_When>

<Why_This_Exists>
A tiny example for newcomers showing the required sections and how to use arguments.
</Why_This_Exists>

<Execution_Policy>
- Run synchronously – no background jobs.
- Validate arguments before proceeding.
- If `--output` is provided, ensure the target directory exists (create it if necessary).
- All errors are reported with a `✗ Error:` prefix.
</Execution_Policy>

<Steps>

1. **Parse arguments** – split the command line on spaces.  
   - `name` = first token (default `"world"`).  
   - If the token `--output` appears, the following token is `outputPath`.

2. **Generate greeting** – `greeting = "Hello, ${name}!"`.

3. **Print greeting** – output to the console (`println(greeting)`).

4. **Optional file write** – if `outputPath` is set:  
   - Ensure the directory exists: `mkdir -p $(dirname outputPath)`.  
   - Write the greeting to the file: `echo "${greeting}" > "${outputPath}"`.  
   - Report success: `✓ Wrote greeting to ${outputPath}`.

5. **Finish** – return a success message to the runtime.

</Steps>

<Tool_Usage>
- `delegate(role="executor", tier="LOW", task="write greeting file")` – used in step 4 when `--output` is present.
- `AskUserQuestion` – not needed; arguments are supplied directly.
</Tool_Usage>

```

Invoke the skill:

```bash
/hello-world Alice --output ./greeting.txt

```

The runtime parses the YAML front-matter, validates all mandatory sections, executes the five steps sequentially, prints `Hello, Alice!`, and writes the same text to [`./greeting.txt`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/./greeting.txt) while reporting `✓ Wrote greeting to ./greeting.txt`.

## Validation and Runtime Guarantees

Before executing any skill, oh-my-codex performs mandatory checks defined in the validation layer:
- **Section completeness**: Ensures `<Purpose>`, `<Use_When>`, `<Do_Not_Use_When>`, `<Why_This_Exists>`, `<Execution_Policy>`, and `<Steps>` exist
- **YAML integrity**: Verifies front-matter is syntactically correct
- **Trigger uniqueness**: Confirms no other skill claims the same invocation triggers

If validation fails, the runtime aborts with a `✗ Error:` message indicating which section is missing or malformed, and the skill does not appear in `/skill list` output.

## Best Practices for Production Skills

When writing complex skills for the oh-my-codex ecosystem, follow these guidelines derived from the source analysis:

- **Keep steps atomic**: Each `<Step>` should perform exactly one action or tool call. This improves traceability and simplifies the verification loop for the architect/critic agents.
- **Use explicit triggers**: Define clear, comma-separated keywords in `<Use_When>` to minimize false positives from the dispatcher.
- **Limit hard-coded paths**: Prefer relative paths anchored to the skill directory to ensure portability across machines and CI pipelines.
- **Document dependencies**: List required binaries or npm packages in `<Execution_Policy>` so the orchestrator can pre-check availability.
- **Provide fallback messages**: Use the `✗ Error:` prefix for destructive actions to force user confirmation before irreversible changes.

## Reference: Built-in Skill Templates

Study these canonical implementations in the Yeachan-Heo/oh-my-codex repository to model advanced patterns:

- **[`skills/skill/SKILL.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/skills/skill/SKILL.md)**: The official template defining required sections and front-matter structure.
- **[`skills/plan/SKILL.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/skills/plan/SKILL.md)**: A complex example showing multi-step planning, consensus loops, and advanced tool usage patterns.
- **[`skills/ralph/SKILL.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/skills/ralph/SKILL.md)**: Demonstrates persistence, background execution, and verification loops for long-running tasks.
- **[`skills/worker/SKILL.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/skills/worker/SKILL.md)**: Shows how meta-skills delegate work to other agents using parallelism.
- **[`AGENTS.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/AGENTS.md)** (root): Defines the overall orchestration model, execution policies, and safety constraints that every skill must obey according to the repository's agent contract.

## Summary

- Skills are self-contained [`SKILL.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/SKILL.md) files living under `./.codex/skills/<skill-name>/` (local) or `./skills/<skill-name>/` (global).
- The format combines YAML front-matter with XML-style markdown sections (`<Purpose>`, `<Steps>`, etc.) that the engine extracts using regex markers.
- The execution engine in `src/agent/` parses these sections sequentially, invoking sub-skills (`$<skill>`) or tools (`delegate`, `state_write`) as specified in the `<Steps>` list.
- Validation logic in [`src/skill/validator.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/skill/validator.ts) ensures mandatory sections exist, YAML is valid, and triggers are unique before runtime.
- Reference [`skills/skill/SKILL.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/skills/skill/SKILL.md) for the base template and [`skills/plan/SKILL.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/skills/plan/SKILL.md) for complex real-world patterns involving consensus and delegation.

## Frequently Asked Questions

### Where should I place my custom SKILL.md file?

Create a directory under `./.codex/skills/<skill-name>/` for project-local skills or `./skills/<skill-name>/` for global installation. Place the [`SKILL.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/SKILL.md) file inside this directory. The runtime discovers skills by scanning these paths and validates them using the logic in [`src/skill/validator.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/skill/validator.ts) before making them available via the `/<skill-name>` command.

### What happens if I forget a mandatory section like <Purpose> or <Steps>?

The validation engine rejects the skill during load time and reports a `✗ Error:` message indicating which required section is missing. The skill will not appear in `/skill list` output and cannot be invoked until you add the missing section and the YAML front-matter passes syntax validation.

### Can I execute arbitrary code inside a SKILL.md file?

No. The **SKILL.md** format is pure markdown interpreted by the engine in `src/agent/`—it never executes embedded code directly. You describe actions declaratively in `<Steps>` using tool calls like `delegate` or `omx explore`, or invoke other skills using the `$<skill>` syntax. This design ensures safety and portability across different environments.

### How do I pass arguments to my custom skill?

Declare an `argument-hint` in the YAML front-matter to document the expected format. Inside `<Steps>`, describe how to parse the command line (e.g., splitting on spaces or parsing flags like `--output`). The runtime passes the raw argument string after the command name (`/<skill-name> <arguments>`), and your step logic handles tokenization and validation according to the rules defined in your `<Execution_Policy>`.