How SkillSpector Handles Different Output Formats for Scan Results

SkillSpector routes scan findings through a centralized report node that dispatches to format-specific helpers based on the --format CLI flag, supporting terminal, JSON, Markdown, and SARIF outputs.

NVIDIA's SkillSpector implements a flexible reporting pipeline that converts scan findings into multiple output formats for scan results. The system uses a graph-based architecture where a single report node selects the appropriate formatter based on user input. This design allows security teams to consume vulnerability data in whatever format best fits their workflow—whether human-readable terminal output or machine-readable SARIF for CI integration.

CLI Format Parsing and State Initialization

The format selection begins in src/skillspector/cli.py, where the FormatChoice StrEnum defines the supported options: terminal, json, markdown, and sarif (lines 75‑82). The --format (or -f) argument captures the user’s selection and stores it in the graph state.

When the scan initializes, the _scan_state function creates the state dictionary and inserts the selected format under the key output_format (lines 28‑34).


# From src/skillspector/cli.py

class FormatChoice(StrEnum):
    terminal = "terminal"
    json = "json"
    markdown = "markdown"
    sarif = "sarif"

# Parsed via --format and stored in state

Report Node Dispatch Architecture

The report node in src/skillspector/nodes/report.py serves as the central dispatcher. It retrieves state["output_format"] (defaulting to "sarif" if unspecified) and branches to the appropriate formatter helper via an if/elif/else block starting at line 44 (lines 44‑90).

The dispatch logic follows this precedence:

  1. terminal → Calls _format_terminal for Rich-styled console output.
  2. json → Calls _format_json for structured JSON reports.
  3. markdown → Calls _format_markdown for human-readable documentation.
  4. fallback → Calls _build_sarif to generate SARIF 2.1.0 compliant JSON.

# From src/skillspector/nodes/report.py

output_format = state.get("output_format") or "sarif"
if output_format == "terminal":
    report_body = _format_terminal(...)
elif output_format == "json":
    report_body = _format_json(...)
elif output_format == "markdown":
    report_body = _format_markdown(...)
else:
    report_body = json.dumps(sarif_report, indent=2)

Terminal Output with Rich Formatting

The _format_terminal helper (lines 8‑23) uses the Rich library to construct colored tables and panels. This produces an interactive console view with risk scores, component lists, and styled findings optimized for terminal readability.

Structured JSON Reports

The _format_json function (lines 38‑53) assembles a Python dictionary containing scan metadata and findings, then serializes it using json.dumps(..., indent=2). This produces formatted JSON suitable for programmatic parsing by downstream tools.

Human-Readable Markdown

For documentation workflows, _format_markdown (lines 66‑76) generates markdown strings including risk tables, component tables, and per-finding sections. This allows direct inclusion of scan results into README files or security documentation.

SARIF 2.1.0 Compliance

The _build_sarif helper creates SARIF-compatible output using data classes defined in src/skillspector/sarif_models.py (report.py lines 16‑22). This format follows the OASIS SARIF standard, enabling integration with security platforms like GitHub Advanced Security and Azure DevOps.

Output Delivery and File Handling

After the report node generates the report_body, the _write_result function in src/skillspector/cli.py (lines 55‑67) handles final delivery. If the format is terminal, the Rich-rendered output prints directly to stdout. For all other formats (json, markdown, sarif), the raw string is emitted to either stdout or the file path specified by the --output option.

Practical Usage Examples

Invoke SkillSpector with different output formats using the CLI:


# Terminal output (explicit)

skillspector scan ./my-skill/ --format terminal

# JSON report to file

skillspector scan ./my-skill/ --format json --output report.json

# Markdown redirection

skillspector scan ./my-skill/ -f markdown > report.md

# SARIF output (default behavior)

skillspector scan ./my-skill/ -f sarif > report.sarif

Summary

  • SkillSpector supports four distinct output formats for scan results: terminal, JSON, Markdown, and SARIF.
  • The FormatChoice enum in src/skillspector/cli.py defines available formats and validates CLI input.
  • The report node in src/skillspector/nodes/report.py dispatches to specialized formatters based on the output_format state key.
  • SARIF serves as the default format when no explicit choice is provided.
  • Terminal output leverages Rich for styling, while other formats emit raw strings suitable for file storage or piping.

Frequently Asked Questions

What is the default output format if I don't specify one?

SARIF is the default format. According to the dispatch logic in src/skillspector/nodes/report.py, the code calls state.get("output_format") or "sarif", ensuring that missing or undefined format selections always fall back to SARIF 2.1.0 JSON output.

How does SkillSpector handle terminal output differently from file formats?

The _write_result function checks the format type before writing. For terminal, it prints the Rich-rendered output directly to stdout. For JSON, Markdown, or SARIF, it writes the raw string content, allowing these formats to be redirected to files or piped to other tools without Rich markup artifacts.

Can I export scan results to a file instead of stdout?

Yes. Use the --output (or -o) flag to specify a destination file path. The _write_result method in src/skillspector/cli.py handles file I/O for all non-terminal formats, writing the report_body string to the specified location.

Is the SARIF output compatible with standard security analysis tools?

Yes. The _build_sarif function generates SARIF 2.1.0 compliant logs using data classes from src/skillspector/sarif_models.py. This adheres to the OASIS standard, ensuring compatibility with GitHub Code Scanning, Azure DevOps, and other SARIF-consuming security platforms.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →