Skip to content

formatter fleet: hook binary probes are blind to profile-managed PATH layers in managed/cloud sessions #2732

Description

@kyle-sexton

Root-caused in the plugin-quality audit applied in #2695 (markdown-format 0.11.17): hook processes inherit Claude Code's own process environment ("Handlers run in the current directory with Claude Code's environment" — hooks reference, fetched 2026-08-15), not the interactive shell's profile. In cloud sessions Claude Code is spawned by a supervisor without profile sourcing, so its PATH lacks the nvm layer where the SessionStart bootstrap installs tools globally — while the Bash tool (profile-initialized, sources /root/.bashrc → nvm) sees them fine. Result: command -v <tool> fails in every hook, formatting/linting silently dead for the whole session class while the environment reports the tool present. Reproduced byte-for-byte under each PATH (audit packet markdown-format/20260815T104849Z, session a86db903). Related closed precedent: #811 (node not found in scheduled-task sessions — same environment class).

#2695 fixed markdown-format specifically (accurate notice + markdownlint-cli2 as an exact repo devDependency, since its node_modules/.bin probe is filesystem-based and PATH-independent). Remaining fleet-wide work:

  1. Sweep every sibling formatter/lint hook that probes command -v (bash-format/shfmt, typos-format, biome-format, go-format, powershell-format, ruff-format, eol-normalizer, actionlint, …) for the same failure mode; give each an accurate degraded-mode notice and, where the tool has an npm/pip-installable form, a repo-local filesystem probe.
  2. markdown-format monorepo residual (recorded in its CHANGELOG): resolve_repo_markdownlint checks only the repo root's node_modules/.bin; workspace-level installs (packages/x/node_modules/.bin) are invisible. Walk from the edited file's directory up to $REPO_ROOT, keeping the per-directory symlink-containment check.
  3. Bootstrap/environment hardening: install fleet tools into a directory on the harness process PATH (or npm i -D into the repo) rather than npm i -g under nvm, so hooks and Bash agree.
  4. Optional per-plugin <tool>_binary userConfig pin (absolute path, validated -x, never shell-interpolated) for consumers who cannot do a repo-local install.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions