# Expected Structure of a Skill File Scanned by SkillSpector: Directory Layout and Manifest Guide

> Discover the expected structure of a SkillSpector skill file. Learn about the mandatory SKILL.md and optional implementation files for NVIDIA's SkillSpector.

- Repository: [NVIDIA Corporation/SkillSpector](https://github.com/NVIDIA/SkillSpector)
- Tags: guide
- Published: 2026-06-16

---

**SkillSpector expects a skill package directory containing a mandatory [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) file with YAML front-matter metadata, plus optional implementation files and assets.**

SkillSpector is an open-source analysis tool from NVIDIA that audits AI skills for security, permissions, and compliance. Understanding the expected structure of a skill file scanned by SkillSpector is essential for developers building compatible skill packages. The analyzer consumes a standardized directory layout centered on a manifest file that defines metadata, required capabilities, invocation triggers, and input parameters.

## Skill Package Directory Layout

A valid skill package is a directory that must contain a **[`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md)** file at its root. All other contents are optional and are discovered dynamically during the scan.

```

my-skill/
├── SKILL.md                # Required – YAML front-matter manifest

├── skill.py                # Optional – Python implementation

├── references/             # Optional – Reference files

├── scripts/                # Optional – Helper scripts

└── assets/                 # Optional – Static assets (images, etc.)

```

Only [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) is strictly required for SkillSpector to perform a scan. The **build_context** node ([`src/skillspector/nodes/build_context.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/build_context.py)) discovers and caches additional folders and files if present, populating the analysis state with component metadata and file contents.

## The SKILL.md Manifest Format

The manifest resides at the top of [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) as a YAML block delimited by triple dashes (`---`). SkillSpector parses this front-matter into a Python dictionary stored in `state["manifest"]` (defined in [`src/skillspector/state.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/state.py)).

### Required Manifest Fields

- **`name`** (`str`): Human-readable skill name.
- **`description`** (`str`): Short description of the skill's functionality.

### Optional Manifest Fields

- **`version`** (`str`): Semantic version of the skill (e.g., `"1.0.0"`).
- **`permissions`** (`list[str]` or `null`): Capability names the skill requires, such as `fs.read` or `network`. If omitted, defaults to `null`.
- **`triggers`** (`list[str]`): Phrases that invoke the skill during MCP (Model Context Protocol) analyses. Defaults to an empty list if omitted.
- **`parameters`** (`list[dict]`): Input parameter definitions, each containing:
  - `name` (`str`): Parameter identifier.
  - `type` (`str`): Expected data type (e.g., `string`, `int`).
  - `description` (`str`): Human-readable help text.
- **`example`** (`str`): Example usage string displayed in reports.
- **`tags`** (`list[str]`): Arbitrary categorization labels.

### Example SKILL.md

```markdown
---
name: text-summarizer
description: Summarize a block of text locally.
version: "1.0.0"
permissions:
  - fs.read
  - network
triggers:
  - "summarize this"
  - "give me a short version"
parameters:
  - name: text
    type: string
    description: Text to be summarized.
  - name: max_length
    type: int
    description: Maximum number of characters in the summary.
tags:
  - nlp
  - utility
---

# Text Summarizer

...skill implementation details...

```

## How SkillSpector Consumes the Manifest

The ingestion pipeline processes the skill file structure through three coordinated stages:

1. **`input_handler`** ([`src/skillspector/input_handler.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/input_handler.py)): Resolves the supplied input path, which may be a local directory, a ZIP archive, a Git URL, or a standalone [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) file.

2. **`build_context`** ([`src/skillspector/nodes/build_context.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/build_context.py)): Reads [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md), parses the YAML front-matter, normalizes `permissions` and `triggers` to lists, and stores the resulting dictionary under `state["manifest"]`. This node also populates `state["components"]` and `state["file_cache"]` with discovered assets.

3. **Analysis nodes**: The manifest fields are injected into LLM prompts, drive MCP analyses, and appear in the final SARIF or JSON reports.

If a skill directory lacks [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md), the manifest resolves to an empty dictionary (`{}`), causing most analyses to skip permission- and trigger-related checks gracefully.

## Key Source Files Defining the Structure

According to the NVIDIA/SkillSpector source code, the following files enforce the skill file contract:

- **[`src/skillspector/state.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/state.py)**: Defines the `TypedDict` for the graph state, including the `manifest` and `file_cache` fields.
- **[`src/skillspector/nodes/build_context.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/build_context.py)**: Implements the manifest parsing logic and component discovery.
- **[`src/skillspector/input_handler.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/input_handler.py)**: Handles input resolution across directory, archive, and URL formats.
- **[`docs/DEVELOPMENT.md`](https://github.com/NVIDIA/SkillSpector/blob/main/docs/DEVELOPMENT.md)**: Documents the expected layout and manifest field semantics.
- **[`tests/nodes/test_build_context.py`](https://github.com/NVIDIA/SkillSpector/blob/main/tests/nodes/test_build_context.py)**: Contains unit tests verifying manifest parsing and component discovery logic.

## Summary

- **SkillSpector requires a directory-based skill package** with a mandatory [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) file containing YAML front-matter.
- **The manifest defines** `name`, `description`, optional `permissions`, `triggers`, and `parameters` that drive security and compliance analyses.
- **The build_context node** ([`src/skillspector/nodes/build_context.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/build_context.py)) parses the manifest into `state["manifest"]`, normalizing lists and caching file contents.
- **Missing manifests** result in empty state dictionaries, allowing scans to continue but skipping permission-related checks.
- **Input flexibility** allows scanning directories, ZIP files, Git URLs, or single [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) files via [`input_handler.py`](https://github.com/NVIDIA/SkillSpector/blob/main/input_handler.py).

## Frequently Asked Questions

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

SkillSpector assigns an empty dictionary (`{}`) to `state["manifest"]` and continues execution. The scan completes, but analyses requiring metadata—such as permission audits or trigger validation—are skipped automatically.

### Can SkillSpector analyze a single file instead of a full directory?

Yes. The `input_handler` ([`src/skillspector/input_handler.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/input_handler.py)) accepts a lone [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) file, a local directory, a ZIP archive, or a Git URL. When a single file is provided, the build_context node processes it directly without requiring additional folder structure.

### What values are valid for the permissions field?

The `permissions` field accepts a list of capability strings (e.g., `fs.read`, `fs.write`, `network`, `exec`) or `null`. According to the source analysis, these strings represent capability names that the skill requests, which SkillSpector evaluates against security policies during the scan.

### How does the triggers field affect SkillSpector analysis?

The `triggers` field contains a list of invocation phrases (e.g., `"summarize this"`). These phrases are consumed during MCP (Model Context Protocol) analyses to determine how users might invoke the skill. If omitted, the field defaults to an empty list, and trigger-related checks are bypassed.