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.
What happened
The
check-docstring-substringsprek hook always outputNo forbidden patterns found in docstrings., even when violations were present. The same pattern existed incheck-comment-keywordsandcheck-banned-words.Root cause
The hooks followed a general CLI convention of printing errors to
stderrand informational messages tostdout. However, pre-commit/prek hooks operate in a captured-output context wherestdoutis the primary stream that the framework captures and displays. By sending error output tostderr, the violation details could go unseen while the success message onstdoutwas the only visible output.Additionally, the hooks printed an unnecessary success message (e.g.
No forbidden patterns found in docstrings.) tostdouton success. Pre-commit frameworks already displayPassed/Failedstatus, 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, notstderr. The pre-commit framework capturesstdoutas the primary output stream and displays it to the user. Usingstderrfor 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)— notprint(violation_details, file=sys.stderr)return 0with no output — notprint('All checks passed'); return 0Resolution
Changed all three bespoke hooks (
check-docstring-substrings.py,check-comment-keywords.py,check-banned-words.py) to print violations tostdoutinstead ofstderr, removed the unnecessary success messages, and cleaned up unusedsysimports.Follow-up
Consider updating the
usethis-prek-hook-bespoke-createskill to include this guidance so future hooks are generated correctly from the start.