Skip to content

fix(axi-sdk-js): use absolute path for hooks when CLI installed via a Node version manager - #110

Open
sholsinger wants to merge 1 commit into
kunchenguid:mainfrom
sholsinger:fix/version-manager-hook-command
Open

fix(axi-sdk-js): use absolute path for hooks when CLI installed via a Node version manager#110
sholsinger wants to merge 1 commit into
kunchenguid:mainfrom
sholsinger:fix/version-manager-hook-command

Conversation

@sholsinger

Copy link
Copy Markdown

Problem

<tool> setup hooks (e.g. jira-axi setup hooks, confluence-axi setup hooks) registers a Claude Code SessionStart hook that fails on every session start with:

Failed with non-blocking status code: /bin/sh: jira-axi: command not found

...even though jira-axi works fine in the user's terminal.

Root cause

resolvePortableHookCommand prefers the bare binary name (jira-axi) whenever that name resolves on process.env.PATH at install time. When the CLI is installed through a Node version manager (nvm, nvs, fnm, asdf, Volta, nodenv), the manager's active bin directory is only added to PATH by interactive shell startup files (~/.zshrc, ~/.bashrc, fnm/asdf shell hooks).

Claude Code runs SessionStart hooks under a non-interactive shell (/bin/sh -c "<command>") that never sources those files, so the version-manager bin dir is absent from PATH and the bare name is command not found. The install-time PATH ≠ the hook-execution-time PATH.

Fix

Skip version-manager-managed directories when choosing the hook command. When the bare name only resolves via such a directory, the resolver falls back to the absolute exec path it already computes — which does not depend on an interactively-augmented PATH. If the binary is also reachable from a stable system dir (e.g. /usr/local/bin), the short portable name is still used.

Detected via path segment match: .nvm, .nvs, .fnm, fnm_multishells, .asdf, .volta, .nodenv.

Tests

  • resolvePortableHookCommand returns the absolute path when the binary only resolves via an nvm dir (regression for the reported bug).
  • A stable PATH dir still wins over a version-manager dir for the same binary.
  • Truth table for the new exported isVersionManagerPathEntry helper.

tsc build, vitest (125/125), prettier --check, and eslint on the changed files all pass.

Known limitation (out of scope)

If Node itself is reachable only via a version manager (no system node on the non-interactive PATH), the absolute-script command's #!/usr/bin/env node shebang would still fail to find node. A fully robust fix would anchor the command on process.execPath, but that reintroduces version-pinning trade-offs, so it's left as a follow-up.

🤖 Generated with Claude Code

… Node version manager

resolvePortableHookCommand preferred the bare binary name whenever it
resolved on PATH at install time. But Node version managers (nvm, nvs,
fnm, asdf, Volta, nodenv) add their bin directory to PATH only from
interactive shell startup files. Agent SessionStart hooks run under a
non-interactive shell (`/bin/sh -c`) that never sources those files, so
the bare name is "command not found" when the hook fires.

Skip version-manager bin directories when choosing the command so the
resolver falls back to the absolute exec path, which does not depend on
an interactively-augmented PATH.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant