Skip to content

[BUG] Recursive multi-skill scan ignores a non-JSON --output file and prints to stdout instead #203

Description

@wernerkasselman-au

What I'm seeing

In recursive multi-skill mode, a non-JSON --output <file> is quietly ignored: the report goes to stdout and the file is never written. Only the --format json recursive path writes the file (the combined JSON report); every other format falls into a branch that passes None as the destination, and None means stdout.

Walking the code (commit 7bc9c0f, src/skillspector/cli.py)

In _scan_multi_skill():

  • The JSON path writes the file correctly (cli.py:410-433).
  • The non-JSON path passes None as the output (cli.py:434-437):
    elif output:
        for _skill, result in zip(skills, results, strict=True):
            if "error" not in result:
                _write_result(result, None, format)   # None, not `output`
  • And _write_result() treats output=None as "print to stdout" (cli.py:149-168, the else branch at :164-168).

So --recursive -f markdown -o report.md prints the per-skill reports to the terminal and never creates report.md.

Reproduction

skillspector scan ./skill-collection/ --recursive --format markdown --output report.md
# What I get: markdown printed to stdout, report.md not written.
# What I expected: the report written to report.md, the way single-skill mode
# honours --output for every format (cli.py:321 -> _write_result(result, output, format)).

Why it matters

It is minor, but it is silent and it is inconsistent: a user redirecting recursive output to a file gets an empty disk and an unexpected stdout dump, while the single-skill path on the same flags writes the file. The thing that makes it awkward is that the loop walks every sub-skill, so even the "intended" fix has to decide what one file should hold for N skills.

What I think the fix is

Pin down the intended contract for non-JSON recursive output and implement it, either of:

  • write the concatenated per-skill reports to output (open it once, append each skill's report_body with a separator) instead of passing None; or
  • if a single non-JSON file for N skills is not meaningful, say so explicitly (emit a message that non-JSON --output is only supported with --format json in recursive mode), rather than silently printing to stdout.

I lean towards the first, since it matches what a user typing -o report.md is asking for, but I am easy either way; let me know which contract you want and I will put it up with a test.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions