Skip to content

agent: pre-commit hooks must print all output to stdout, not stderr #1845

@nathanjmcdougall

Description

@nathanjmcdougall

What happened

The check-docstring-substrings prek hook always output No forbidden patterns found in docstrings., even when violations were present. The same pattern existed in check-comment-keywords and check-banned-words.

Root cause

The hooks followed a general CLI convention of printing errors to stderr and informational messages to stdout. However, pre-commit/prek hooks operate in a captured-output context where stdout is the primary stream that the framework captures and displays. By sending error output to stderr, the violation details could go unseen while the success message on stdout was the only visible output.

Additionally, the hooks printed an unnecessary success message (e.g. No forbidden patterns found in docstrings.) to stdout on success. Pre-commit frameworks already display Passed/Failed status, so a redundant success message adds noise and — combined with errors going to the wrong stream — creates the appearance that the hook always succeeds.

Generalised principle

When writing pre-commit/prek hooks, always print all output (including errors and violations) to stdout, not stderr. The pre-commit framework captures stdout as the primary output stream and displays it to the user. Using stderr for errors may cause them to be silently dropped or displayed inconsistently.

Additionally, do not print success messages from hooks. The framework already indicates pass/fail status. A success message is redundant noise that can mask the absence of expected error output.

In summary:

  • print(violation_details) — not print(violation_details, file=sys.stderr)
  • On success: return 0 with no output — not print('All checks passed'); return 0

Resolution

Changed all three bespoke hooks (check-docstring-substrings.py, check-comment-keywords.py, check-banned-words.py) to print violations to stdout instead of stderr, removed the unnecessary success messages, and cleaned up unused sys imports.

Follow-up

Consider updating the usethis-prek-hook-bespoke-create skill to include this guidance so future hooks are generated correctly from the start.

Metadata

Metadata

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