Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

perf(guardrails, eol-normalizer, typos-format): about 440 ms of hooks per Edit/Write across three node-to-bash hops

Open
#6,635 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
30/100
Issue type
Refactor
Clarity
Mostly clear
Activity status
Active
Tech stack
javascript, shell

Research direction

Start with the three hooks.json files (plugins/guardrails, plugins/eol-normalizer, plugins/typos-format) and the shared hooks/exec-bash.mjs launcher that each one invokes through node. Read how exec-bash.mjs resolves the Git Bash path on Windows before changing any registration. Done means the combined PostToolUse runner runs EOL then typos in one bash process, the existing eol-normalizer and typos-format tests pass, and a CRLF file written by Write ends LF-only. Confirm the design with a maintainer first, since the issue asks to keep the PreToolUse guards synchronous.

Written by the indexing model from the issue text.

Description

needs-human needs-triage

Related: #4390 (guardrails Edit/Write process counts), #4391 and #3751 (closed formatter fan-out), #4373 (umbrella).

Problem

Each Edit/Write pays about 440 ms of hook time across three plugins, each starting its own node process that then starts bash:

  • guardrails PreToolUse (secret-pattern-detection.sh, hardcoded-path-check.sh, block-windows-drive-tmp.sh via run-guards.sh): about 220 ms, before the edit.
  • eol-normalizer PostToolUse: about 205 ms.
  • typos-format PostToolUse: about 205 ms.

The two PostToolUse hooks run in parallel with each other, so the wall-clock after an edit is about the slower of the two, but both add process load and both are node-to-bash hops.

Measured

Method: direct timing on the windows lane (melo-desk-001): canned Edit payload on a copy of a repo README in the session scratchpad, date +%s%N around node exec-bash.mjs <script>, stdin from the payload, 3 runs, latest cached versions.

hook runs (ms)
guardrails PreToolUse Edit trio (guardrails 0.48.1) 218 / 222 / 221
eol-normalizer 0.9.11 204 / 205 / 203
typos-format 0.9.12 206 / 206 / 203
bare node -e 0 52

Context: #4390 measured the guardrails Edit/Write guards at 25 to 87 processes per fire; OTEL in #4373 shows PostToolUse:Edit p50 850 ms, p95 4,249 ms (n=4,081, 7 days).

Where

  • plugins/guardrails/hooks/hooks.json:18-35 (PreToolUse, matcher Write|Edit|NotebookEdit, node hooks/exec-bash.mjs hooks/run-guards.sh secret-pattern-detection.sh hardcoded-path-check.sh block-windows-drive-tmp.sh)
  • plugins/eol-normalizer/hooks/hooks.json:17-35 (PostToolUse Write|Edit, node hooks/exec-bash.mjs --run-if-unset-or-true EOL_NORMALIZER_ENABLED hooks/eol-normalizer.sh)
  • plugins/typos-format/hooks/hooks.json:4-22 (PostToolUse Write|Edit|NotebookEdit, node hooks/exec-bash.mjs --run-if-unset-or-true TYPOS_FORMAT_ENABLED hooks/typos-format.sh)

Example command line: node ${CLAUDE_PLUGIN_ROOT}/hooks/exec-bash.mjs --run-if-unset-or-true TYPOS_FORMAT_ENABLED ${CLAUDE_PLUGIN_ROOT}/hooks/typos-format.sh

Proposed fix

One combined PostToolUse runner for the file-normalizing family (eol-normalizer, typos-format, and the other formatter plugins that match Write|Edit), registered once, running its steps in order in a single bash process (EOL first, then typos, so the second sees normalized bytes), with no node-to-bash hop: register bash with the resolved Git Bash path directly, as exec-bash.mjs resolves it today (#3686/#3708 explain why bare bash cannot be used on Windows).

Keep the secrets/path guards in PreToolUse as blocking hooks: they can deny the edit, and an async hook cannot ("response fields like decision, permissionDecision, and continue have no effect", https://code.claude.com/docs/en/hooks#run-hooks-in-the-background). Only the report-only PostToolUse rows (typos-format reports; #4677 is the earlier decision) may go "async": true. The EOL normalizer rewrites the file, so it must stay synchronous or the model's next Edit races it.

Basis: measured node start-up share (52 of about 205 ms) and bash start-up 29 ms (above); async limits at the URL above; if narrowing at https://code.claude.com/docs/en/hooks#common-fields (already used in guardrails for .md/.sh).

Expected saving

About 150 to 250 ms of CPU per Edit/Write removed (two node processes and two bash starts become one bash), and one fewer process tree for Defender-style scanners to inspect. At 581 Edit fires per day (#4390) that is 1.5 to 2.5 CPU-minutes per day; the wall-clock gain is smaller because the two rows already run in parallel.

Verify after the fix

  • Re-run the three timing commands; the combined runner should land near 100 ms.
  • /harness-ops:observability latency PostToolUse:Edit p50/p95 before and after, 7 days each.
  • Existing eol-normalizer and typos-format tests pass against the runner; a CRLF file written by Write ends LF-only, and a typo is still reported once.
Dominant language
Shell
Stars
22
Forks
2
Avg merge
5h 18m
Merged PRs (30d)
869

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from melodic-software/claude-code-plugins

All issues in melodic-software/claude-code-plugins

Similar issues

More Shell/Bash issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.