# How Multi-Skill Directories Are Detected and Scanned Independently in SkillSpector

> Learn how SkillSpector detects and scans multi-skill directories independently. Discover the process within the NVIDIA SkillSpector codebase for efficient skill analysis.

- Repository: [NVIDIA Corporation/SkillSpector](https://github.com/NVIDIA/SkillSpector)
- Tags: deep-dive
- Published: 2026-07-07

---

**SkillSpector detects multi-skill directories by verifying the absence of a root [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) file alongside the presence of two or more subdirectories each containing their own [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md), then scans each skill independently using the `detect_skills` function and `_scan_multi_skill` helper in the NVIDIA/SkillSpector codebase.**

SkillSpector, NVIDIA’s open-source skill analysis tool, provides specialized handling for repositories that contain multiple independent skills rather than a single monolithic skill definition. Understanding how the tool differentiates between single-skill and multi-skill hierarchies is essential for CI/CD pipelines and bulk analysis workflows.

## Detection Logic in [`multi_skill.py`](https://github.com/NVIDIA/SkillSpector/blob/main/multi_skill.py)

The detection mechanism resides in [`src/skillspector/multi_skill.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/multi_skill.py), where the public API determines whether a directory represents a collection of independent skills.

### The `detect_skills` Function

The entry point for multi-skill detection is the `detect_skills` function, which accepts a `Path` object and returns a `MultiSkillDetectionResult`. According to the source implementation, this function walks the immediate children of the supplied directory, skipping non-directories and hidden folders, and constructs a list of `SkillDirectory` objects containing the path, name, and relative_path for each candidate skill.

### Detection Rules and Criteria

The specific detection algorithm (lines 54-57) applies two Boolean rules:

1. **The top-level directory must not contain a [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) (or [`skill.md`](https://github.com/NVIDIA/SkillSpector/blob/main/skill.md)) file.** If a root skill definition exists, the directory is treated as a single skill regardless of nested structures.
2. **At least two immediate subdirectories must each contain their own [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) (or [`skill.md`](https://github.com/NVIDIA/SkillSpector/blob/main/skill.md)) file.** Only when multiple sub-skills are identified does the detection return a positive result.

The `MultiSkillDetectionResult` object returned includes three critical fields: `is_multi_skill` (Boolean), `skills` (list of `SkillDirectory` objects), and `has_root_skill` (Boolean flag indicating whether a root-level skill file was found).

## Independent Scanning in [`cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/cli.py)

Once detection completes, the CLI layer in [`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py) orchestrates the independent scanning of each discovered skill.

### The `_scan_multi_skill` Helper

When invoking `skillspector scan <path> --recursive`, the CLI logic (lines 76-84) first calls `detect_skills`. If `detection.is_multi_skill` evaluates to `True`, the code delegates to the private helper `_scan_multi_skill` (lines 355-430) rather than executing a standard single-skill scan.

The `_scan_multi_skill` function iterates over every `SkillDirectory` in the detection result and performs the following operations for each entry:

- Prints a progress header identifying the current skill being analyzed
- Initializes a fresh scan state (`_scan_state`) pointing at the specific sub-skill’s folder
- Invokes the graph engine via `graph.invoke` to execute the full analysis pipeline on that skill alone
- Extracts the risk score, severity level, and finding count from the results

### Aggregating Results and Exit Codes

After processing all sub-skills, the CLI aggregates the individual results into a combined output format. If the output format is JSON, the tool generates a merged report containing each skill’s name, path, risk score, severity, and finding count. For human-readable output, the CLI concatenates the individual reports into a unified summary table.

The exit behavior mirrors single-skill scanning: if any individual skill’s risk score exceeds the global `RISK_THRESHOLD`, the CLI exits with a non-zero status code, ensuring that CI/CD systems can detect security or quality issues across the entire multi-skill repository.

## Programmatic Usage Example

You can leverage the detection API directly without invoking the CLI:

```python
from pathlib import Path
from skillspector.multi_skill import detect_skills

# Analyze a directory that potentially contains multiple skills

root = Path("/path/to/skill-collection")
result = detect_skills(root)

if result.is_multi_skill:
    print(f"Found {len(result.skills)} independent skills:")
    for skill in result.skills:
        print(f" - {skill.name} ({skill.relative_path})")
else:
    if result.has_root_skill:
        print("Single-skill directory detected.")
    else:
        print("No valid skill structure found.")

```

When running via the CLI with the `--recursive` flag on the same directory, SkillSpector automatically invokes the same detection logic and executes `_scan_multi_skill` to process each skill independently.

## Summary

- **Detection requires two conditions**: No [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) at the root, and at least two subdirectories containing their own [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) files.
- **Core detection function**: `detect_skills` in [`src/skillspector/multi_skill.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/multi_skill.py) returns structured metadata about each discovered skill.
- **Independent scanning**: The `_scan_multi_skill` helper in [`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py) (lines 355-430) instantiates fresh scan states and invokes the graph engine separately for each skill.
- **Unified reporting**: Results are aggregated into either JSON or human-readable formats while preserving individual risk scores and severities.
- **Consistent exit codes**: The CLI maintains standard exit behavior across single and multi-skill scans, failing if any skill exceeds the risk threshold.

## Frequently Asked Questions

### What defines a multi-skill directory in SkillSpector?

A multi-skill directory is defined as a folder that lacks a root-level [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) file but contains at least two immediate subdirectories, each housing its own [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) (or [`skill.md`](https://github.com/NVIDIA/SkillSpector/blob/main/skill.md)) file. This structure indicates that the repository contains multiple independent skills rather than a single composite skill.

### How does SkillSpector handle a root SKILL.md versus nested skill directories?

If a root [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) exists at the top level of the scanned directory, SkillSpector treats the entire directory as a single skill regardless of any nested [`SKILL.md`](https://github.com/NVIDIA/SkillSpector/blob/main/SKILL.md) files found in subdirectories. The `has_root_skill` flag in the `MultiSkillDetectionResult` object tracks this condition explicitly.

### Can I scan multi-skill directories programmatically without using the CLI?

Yes. Import the `detect_skills` function from `skillspector.multi_skill` to identify skill boundaries programmatically. While the independent scanning logic (`_scan_multi_skill`) is internal to the CLI module, you can replicate its behavior by iterating over the `skills` list in the detection result and invoking the analysis engine separately for each `SkillDirectory` path.

### How are results aggregated when scanning multiple skills independently?

When scanning multi-skill directories, SkillSpector collects individual results from each sub-skill analysis and merges them into a single output. For JSON output, this produces a unified report containing arrays of findings per skill. For console output, the CLI prints concatenated reports with clear headers identifying each skill, followed by a summary table showing risk scores and severities across all discovered skills.