Purpose
Thin check-centric setup per the uniform setup contract (docs/PLUGIN-PHILOSOPHY.md
"Setup is explicit and repeatable" in the marketplace repository): check inspects and
reports, apply resolves. This plugin owns no consumer-project configuration. The
normalization policy is the repository's own .gitattributes, and the only tunable is the
native userConfig toggle. Every prerequisite is a system tool (Bash, jq, git), so apply
is pure guidance and writes nothing.
Action routing: no argument or check runs the check; apply runs the check first, then
points at each remediation. Both are non-interactive. Never prompt when the action is given.
check (read-only)
The hook is the single source of truth for what it requires and how it resolves things, and it
spans the entry script and the libraries it sources: ${CLAUDE_PLUGIN_ROOT}/hooks/eol-normalizer.sh
sources ${CLAUDE_PLUGIN_ROOT}/hooks/normalize-eol.sh (alongside the shared hook utilities), and
that sourced library is where the real resolution lives (the git check-attr calls, the repo-root
anchoring, and the NUL-byte binary guard), so the sourced files are in scope and the entry script
alone will not tell you what runs.
Read it first. Probe what it actually does, don't recite this file. Then run each probe via
Bash and report a PASS/FAIL/INFO table with one remediation line per FAIL. Do not modify anything.
When the plugin's toggle is disabled, every prerequisite absence downgrades from FAIL to
INFO. The hook exits through its enabled-gate before probing anything, so a deliberately
disabled plugin is not broken. Report the probes informationally and note that re-enabling
restores the FAIL semantics.
- Bash version. Check against the hook's documented floor (README Requirements),
noting any features the hook degrades without (for example telemetry's
EPOCHREALTIME,
Bash 5.0+).
jq. command -v jq. FAIL if absent: the hook then skips with a visible
once-per-session notice instead of normalizing.
git. command -v git. FAIL if absent: unlike jq, the hook emits NO visible notice
when git is missing. git check-attr and repo-root resolution silently fail and the
hook no-ops, so this probe is the only visibility. Distinguish the two non-failure cases
the hook treats differently. Git present but the path is not inside a git repository →
INFO, not applicable: nothing to normalize against, per the README. Git present
inside a repo but no eol= rule governs any path → INFO, inert by design, the opt-in
analog: resolution is entirely .gitattributes-driven.
- Consumer
.gitattributes eol= policy. Using the hook's own resolver
(git check-attr eol anchored at the repo root), confirm whether any eol=lf/eol=crlf
rule governs paths the hook would touch. check-attr answers for ANY candidate path,
tracked or not. The hook normalizes a first write to a brand-new file the same as an
edit to a tracked one, so probe representative candidate paths (or report the declared
patterns), never a tracked-files listing that would miss untracked matches. Report what
governs, or INFO that none does. Absence is the opt-out by design, so the plugin is
inert (INFO, not FAIL), matching the README's "ships no policy of its own" stance.
- Hook toggle. Report the effective
eol_normalizer_enabled value:
${user_config.eol_normalizer_enabled} (unexpanded or empty means default true).
- Hook registration. INFO: confirm the plugin is enabled for this project
(
/plugin → Installed) rather than parsing settings files.
apply (idempotent)
Run check, then for each FAIL point at the resolution. Every prerequisite here is a system
tool, so apply installs nothing and writes nothing. It only points:
- missing
jq / Bash / git: platform install instructions from the README Requirements
section; this skill never installs system packages.
- toggle off: reconfigure through Claude Code's native flow, per the marketplace's
plugin-reconfiguration convention, which owns the verified-version record
(https://github.com/melodic-software/claude-code-plugins/blob/main/docs/conventions/plugin-reconfiguration/README.md):
interactive
/plugin configure eol-normalizer@<marketplace> any time, or headless
claude plugin install eol-normalizer@<marketplace> -s <scope> --config eol_normalizer_enabled=true
(repeatable per key) — against an already-installed plugin it prints already installed and
still writes the value. Do not uninstall to reconfigure: uninstalling drops this plugin's
entire stored pluginConfigs entry, resetting every option in the README's Options reference
to its manifest default. -s defaults to user; pass the scope claude plugin list reports
for this plugin, and run from that project's directory for a project/local scope, or the
write lands at a scope that does not load. This skill never writes user settings or
pluginConfigs. Afterwards rerun check in a fresh session — the rendered
${user_config.*} is injected at skill load and each hook receives its
CLAUDE_PLUGIN_OPTION_* from an environment fixed at session start, so a same-session check
still reports the OLD value; report the observed effective value, never an unobserved change.
- no
eol= policy: this is the opt-out, not a defect. Point at the repository's own
.gitattributes as the place to declare policy; this skill never writes .gitattributes,
because that would impose a repo-wide line-ending policy the plugin has no mandate to
choose.
Re-running apply after everything passes changes nothing and reports "already configured".
What this skill does NOT do
- Normalize any file. Editing a file exercises the hook end-to-end.
- Write the plugin cache, Claude Code user settings, or
pluginConfigs. Nor .gitattributes.
- Install any tool, during either
check or apply. All prerequisites are system tools
resolved with guidance only.
1---2name: setup-433description: Verify the eol-normalizer hook's runtime prerequisites and configuration for this repository. Use when: 'set up eol-normalizer', 'configure eol-normalizer', 'is eol-normalizer working', line endings silently aren't normalizing, or the hook reported a missing prerequisite. Actions: check (read-only verification, default) | apply (resolve what check found). Re-runnable and safe.4---56## Purpose78Thin check-centric setup per the uniform setup contract (`docs/PLUGIN-PHILOSOPHY.md`9"Setup is explicit and repeatable" in the marketplace repository): `check` inspects and10reports, `apply` resolves. This plugin owns no consumer-project configuration. The11normalization policy is the repository's own `.gitattributes`, and the only tunable is the12native `userConfig` toggle. Every prerequisite is a system tool (Bash, jq, git), so `apply`13is pure guidance and writes nothing.1415Action routing: no argument or `check` runs the check; `apply` runs the check first, then16points at each remediation. Both are non-interactive. Never prompt when the action is given.1718## `check` (read-only)1920The hook is the single source of truth for what it requires and how it resolves things, and it21spans the entry script and the libraries it sources: `${CLAUDE_PLUGIN_ROOT}/hooks/eol-normalizer.sh`22sources `${CLAUDE_PLUGIN_ROOT}/hooks/normalize-eol.sh` (alongside the shared hook utilities), and23that sourced library is where the real resolution lives (the `git check-attr` calls, the repo-root24anchoring, and the NUL-byte binary guard), so the sourced files are in scope and the entry script25alone will not tell you what runs.2627**Read it first.** Probe what it actually does, don't recite this file. Then run each probe via28Bash and report a PASS/FAIL/INFO table with one remediation line per FAIL. Do not modify anything.2930When the plugin's toggle is disabled, every prerequisite absence downgrades from FAIL to31INFO. The hook exits through its enabled-gate before probing anything, so a deliberately32disabled plugin is not broken. Report the probes informationally and note that re-enabling33restores the FAIL semantics.34351. **Bash version.** Check against the hook's documented floor (README Requirements),36 noting any features the hook degrades without (for example telemetry's `EPOCHREALTIME`,37 Bash 5.0+).382. **`jq`.** `command -v jq`. FAIL if absent: the hook then skips with a visible39 once-per-session notice instead of normalizing.403. **`git`.** `command -v git`. FAIL if absent: unlike jq, the hook emits NO visible notice41 when git is missing. `git check-attr` and repo-root resolution silently fail and the42 hook no-ops, so this probe is the only visibility. Distinguish the two non-failure cases43 the hook treats differently. Git present but the path is not inside a git repository →44 INFO, not applicable: nothing to normalize against, per the README. Git present45 inside a repo but no `eol=` rule governs any path → INFO, inert by design, the opt-in46 analog: resolution is entirely `.gitattributes`-driven.474. **Consumer `.gitattributes` `eol=` policy.** Using the hook's own resolver48 (`git check-attr eol` anchored at the repo root), confirm whether any `eol=lf`/`eol=crlf`49 rule governs paths the hook would touch. `check-attr` answers for ANY candidate path,50 tracked or not. The hook normalizes a first write to a brand-new file the same as an51 edit to a tracked one, so probe representative candidate paths (or report the declared52 patterns), never a tracked-files listing that would miss untracked matches. Report what53 governs, or INFO that none does. Absence is the opt-out by design, so the plugin is54 inert (INFO, not FAIL), matching the README's "ships no policy of its own" stance.555. **Hook toggle.** Report the effective `eol_normalizer_enabled` value:56 `${user_config.eol_normalizer_enabled}` (unexpanded or empty means default `true`).576. **Hook registration.** INFO: confirm the plugin is enabled for this project58 (`/plugin` → Installed) rather than parsing settings files.5960## `apply` (idempotent)6162Run `check`, then for each FAIL point at the resolution. Every prerequisite here is a system63tool, so `apply` installs nothing and writes nothing. It only points:6465- missing `jq` / Bash / git: platform install instructions from the README Requirements66 section; this skill never installs system packages.67- toggle off: reconfigure through Claude Code's native flow, per the marketplace's68 plugin-reconfiguration convention, which owns the verified-version record69 (<https://github.com/melodic-software/claude-code-plugins/blob/main/docs/conventions/plugin-reconfiguration/README.md>):70 interactive `/plugin configure eol-normalizer@<marketplace>` any time, or headless71 `claude plugin install eol-normalizer@<marketplace> -s <scope> --config eol_normalizer_enabled=true`72 (repeatable per key) — against an already-installed plugin it prints `already installed` **and73 still writes the value**. Do **not** uninstall to reconfigure: uninstalling drops this plugin's74 entire stored `pluginConfigs` entry, resetting every option in the README's Options reference75 to its manifest default. `-s` defaults to `user`; pass the scope `claude plugin list` reports76 for this plugin, and run from that project's directory for a `project`/`local` scope, or the77 write lands at a scope that does not load. This skill never writes user settings or78 `pluginConfigs`. Afterwards rerun `check` in a **fresh session** — the rendered79 `${user_config.*}` is injected at skill load and each hook receives its80 `CLAUDE_PLUGIN_OPTION_*` from an environment fixed at session start, so a same-session `check`81 still reports the OLD value; report the observed effective value, never an unobserved change.82- no `eol=` policy: this is the opt-out, not a defect. Point at the repository's own83 `.gitattributes` as the place to declare policy; this skill never writes `.gitattributes`,84 because that would impose a repo-wide line-ending policy the plugin has no mandate to85 choose.8687Re-running `apply` after everything passes changes nothing and reports "already configured".8889## What this skill does NOT do9091- Normalize any file. Editing a file exercises the hook end-to-end.92- Write the plugin cache, Claude Code user settings, or `pluginConfigs`. Nor `.gitattributes`.93- Install any tool, during either `check` or `apply`. All prerequisites are system tools94 resolved with guidance only.