# How the CLI-Anything Skill Generator Parses and Formats YAML Frontmatter for Agent Skill Discovery

> Discover how CLI-Anything's skill generator parses and formats YAML frontmatter for agent skill discovery. Learn to create discoverable SKILL.md files for seamless agent interaction.

- Repository: [✨Data Intelligence Lab@HKU✨/CLI-Anything](https://github.com/HKUDS/CLI-Anything)
- Tags: how-to-guide
- Published: 2026-05-18

---

**The [`skill_generator.py`](https://github.com/HKUDS/CLI-Anything/blob/main/skill_generator.py) script in HKUDS/CLI-Anything extracts CLI metadata and manually assembles a YAML frontmatter block using folded block scalars (`>-`), creating a discoverable [`SKILL.md`](https://github.com/HKUDS/CLI-Anything/blob/main/SKILL.md) file that agents parse to identify available skills by their `name` and `description` fields.**

The HKUDS/CLI-Anything repository provides a framework for wrapping command-line interfaces into agent-compatible skills. At the heart of this system lies the skill generator, which transforms source code metadata into structured YAML frontmatter embedded in Markdown files, enabling automated discovery by AI agents scanning the repository.

## Extracting CLI Metadata from Source Code

The skill generation process begins with deep inspection of the harness directory. The **`extract_cli_metadata`** function walks the project structure, extracting critical information needed for the frontmatter.

### Directory Walking and AST Parsing

At lines 72-80 of [`zotero/agent-harness/skill_generator.py`](https://github.com/HKUDS/CLI-Anything/blob/main/zotero/agent-harness/skill_generator.py), the generator:

- Reads the **README** for introductory descriptions
- Pulls **version strings** from [`setup.py`](https://github.com/HKUDS/CLI-Anything/blob/main/setup.py)
- Discovers **command groups and commands** by parsing CLI source files using Python's `ast` module

The command extraction logic at lines 13-47 specifically hunts for `@cli.group` and `@cli.command` decorators within files like [`zotero/agent-harness/cli_anything/zotero/zotero_cli.py`](https://github.com/HKUDS/CLI-Anything/blob/main/zotero/agent-harness/cli_anything/zotero/zotero_cli.py), building a complete map of the CLI's capabilities before formatting begins.

## Constructing the YAML Frontmatter Block

Once metadata is collected, the generator formats it into a strict YAML structure that precedes the Markdown body content.

### Manual Assembly with Folded Block Scalars

The **`generate_skill_md_simple`** function (lines 94-99) manually constructs the frontmatter using literal string concatenation:

```python
---
name: >-
  {skill_name}
description: >-
  {skill_description}
---

```

The **`>-`** indicator is a YAML folded block scalar that strips newlines while preserving the content as a single logical line. This allows the source code to indent values for readability while ensuring agents receive compact, single-line strings for the `name` and `description` fields.

### Required Frontmatter Fields

Every generated [`SKILL.md`](https://github.com/HKUDS/CLI-Anything/blob/main/SKILL.md) contains exactly two metadata keys:

- **`name`**: A unique identifier (e.g., `cli-anything-zotero`) that serves as the skill's canonical reference
- **`description`**: A brief, searchable summary of the CLI harness functionality

## Template-Based Rendering with Jinja2 Fallback

While manual string assembly serves as the default, the generator supports sophisticated templating when available.

The **`generate_skill_md`** function (lines 44-50) attempts to load `zotero/agent-harness/templates/SKILL.md.template` and render the same frontmatter variables through Jinja2. If Jinja2 is not installed, the code gracefully falls back to `generate_skill_md_simple` (lines 45-48), ensuring the skill file is always produced regardless of optional dependencies.

## Normalizing Markdown Output

After rendering, the **`_normalize_generated_markdown`** function (lines 37-41) performs final cleanup:

- Removes stray blank lines that could confuse YAML parsers
- Ensures the file terminates with a single newline character
- Guarantees the document conforms to strict Markdown/YAML hybrid formatting

This normalization step prevents parsing errors when agents read the file boundaries between the YAML frontmatter and the Markdown content body.

## How Agents Discover Skills via Frontmatter

Agent frameworks implementing the CLI-Anything protocol scan repositories for Markdown files matching a specific header pattern. The discovery mechanism looks for files where the first three lines match:

```text
---
name: ...
description: ...
---

```

Once identified, YAML parsers extract the `name` and `description` keys to register the skill for **agent-native discovery**. This convention allows any compatible agent to automatically inventory available CLI tools by parsing standardized metadata rather than executing arbitrary code.

## Generating Skill Files

### Command-Line Execution

Generate a skill file directly from the repository root:

```bash
python -m zotero.agent-harness.skill_generator /path/to/zotero/agent-harness \
    -o ./skills/cli-anything-zotero/SKILL.md

```

The command outputs the path to the newly written [`SKILL.md`](https://github.com/HKUDS/CLI-Anything/blob/main/SKILL.md) containing the properly formatted frontmatter.

### Programmatic API Usage

Import the generator functions directly in Python:

```python
from zotero.agent_harness.skill_generator import generate_skill_file

skill_path = generate_skill_file(
    harness_path="zotero/agent-harness",
    output_path="skills/cli-anything-zotero/SKILL.md"
)

print(f"Skill file written to {skill_path}")

```

### Verifying the YAML Structure

Inspect the generated frontmatter to confirm proper formatting:

```python
from pathlib import Path

content = Path("skills/cli-anything-zotero/SKILL.md").read_text()
print(content.split("\n")[:5])

# Output:

# ['---',

#  'name: >-',

#  '  cli-anything-zotero',

#  'description: >-',

#  '  CLI harness for Zotero.']

```

## Summary

- The **`extract_cli_metadata`** function in [`skill_generator.py`](https://github.com/HKUDS/CLI-Anything/blob/main/skill_generator.py) uses AST parsing to extract CLI commands and metadata from harness source code.
- **`generate_skill_md_simple`** manually assembles YAML frontmatter using the folded block scalar syntax (`>-`) to ensure single-line values with readable indentation.
- The frontmatter requires exactly two fields: **`name`** for unique identification and **`description`** for searchable summaries.
- A **Jinja2 template fallback** at lines 44-50 provides extensibility while maintaining a hardcoded string fallback for environments without Jinja2.
- **`_normalize_generated_markdown`** ensures the output file ends with a newline and contains no stray blank lines, preserving YAML validity.
- Agent discovery relies on parsing the specific `---\nname: ...\ndescription: ...\n---` pattern found at the start of [`SKILL.md`](https://github.com/HKUDS/CLI-Anything/blob/main/SKILL.md) files throughout the repository.

## Frequently Asked Questions

### What YAML syntax does the skill generator use for multi-line strings?

The generator uses the **folded block scalar** indicator `>-` (lines 94-99). This YAML syntax strips literal newlines from the source while treating the indented content as a single logical line, allowing the Python code to format values across multiple lines for readability without breaking the YAML structure.

### How does the skill generator handle missing Jinja2 dependencies?

If Jinja2 is not installed, the **`generate_skill_md`** function (lines 44-50) catches the import failure and falls back to **`generate_skill_md_simple`**, which constructs the frontmatter using basic string formatting. This ensures skill files are always generated regardless of optional templating libraries.

### Where does the skill generator source the version information?

The **`extract_cli_metadata`** function extracts version strings by reading [`setup.py`](https://github.com/HKUDS/CLI-Anything/blob/main/setup.py) in the harness directory (lines 72-80), alongside documentation from the README and command structures parsed from CLI source files using the `ast` module.

### What file pattern do agents use to discover CLI-Anything skills?

Agent frameworks scan for Markdown files containing a YAML frontmatter block where line 1 is `---`, line 2 starts with `name:`, line 3 starts with `description:`, and line 4 is `---`. This four-line header pattern allows automated parsers to identify [`SKILL.md`](https://github.com/HKUDS/CLI-Anything/blob/main/SKILL.md) files and extract the metadata needed to register CLI harnesses for agent-native discovery.