fix(hooks): use absolute path for teamai binary in hook commands#177
Merged
jeff-r2026 merged 3 commits intoJul 10, 2026
Merged
Conversation
GUI-launched AI tools (CodeBuddy/WorkBuddy) may spawn hook subprocesses without a complete PATH, causing `teamai hook-dispatch` to fail silently. Resolve the absolute path of the teamai binary at init/pull time via process.argv[0] (node binary dir, where npm places the teamai symlink) and embed it in the hook command. Falls back to bare `teamai` when resolution fails. Also fix hook identification regexes (isTeamaiHookCommand, extractTeamaiSubcommand) to match absolute paths so reconcile correctly detects and replaces existing teamai hooks. --story=1032029153857553 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t PATH WorkBuddy uses a bundled Node and its hook subprocesses lack the user's PATH, causing `teamai: command not found`. Instead of embedding absolute paths in every hook command, write a thin wrapper script at `~/.teamai/bin/teamai` (using WorkBuddy's bundled Node + the real entry script), and prepend `~/.teamai/bin` to PATH in WorkBuddy hook commands. This keeps all `teamai xxx` subcommands working (not just hook-dispatch) and preserves the `teamai hook-dispatch ...` command format so existing reconcile identification logic continues to match. Also widen `isTeamaiHookCommand` regex to match WorkBuddy's PATH-prefixed command format (`PATH="..." teamai hook-dispatch ...`). Other tools (Claude Code, CodeBuddy, Cursor) are unchanged. --story=1032029153857553 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The WorkBuddy PATH wrapper was only written by injectHooksToAllTools, but init/pull/hooks-inject go through reconcileHooksToAllTools, which never created it — so GUI-launched hooks still failed to resolve `teamai`. CodeBuddy has the same limited-PATH problem but was left on bare `teamai`. - reconcileHooksToAllTools now writes the wrapper when workbuddy/codebuddy are active (P0: init path was a no-op before) - builtinHookDefs routes both workbuddy and codebuddy through the wrapper PATH-prepend command; wrapper node resolution now also probes CodeBuddy's bundled node (~/.codebuddy-server*/bin/stable-*/node) - wrapper command uses the `$HOME` shell literal so golden fixtures stay byte-stable across machines - fix bundled-node version pick to compare numerically, not lexically - update codebuddy golden fixture, add workbuddy fixture + wrapper tests Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5c0fe32 to
2e1d306
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
teamaibinary at init/pull time and embed it in hook commandsteamaiand absolute pathsRoot Cause
Hook commands are written as
bash -lc "teamai hook-dispatch ..."which relies onteamaibeing in PATH. GUI-launched IDE processes (CodeBuddy, WorkBuddy) may not inherit the user's full login shell PATH, causing the hook to fail silently — no report, no sync, no debug.log update.Fix
resolveTeamaiBinPath()(new): looks forteamaiinpath.dirname(process.argv[0])— this is the node binary directory where npm global install places theteamaisymlink. Falls back to bareteamaiif not found.getDispatchCommand(): accepts optionalbinPathparameter, defaults to'teamai'for backward compatibility.builtinHookDefs(): callsresolveTeamaiBinPath()and passes the result togetDispatchCommand().Hook identification regexes:
isTeamaiHookCommandandextractTeamaiSubcommandupdated from/"teamai\s/to/(?:^|\/|")teamai\s/so reconcile correctly detects hooks with absolute paths (prevents duplicate injection).Compatibility
teamai init --forceorteamai pullwill automatically upgrade hook commands to use absolute paths via the normal reconcile flowprocess.argv[0]is set to/nonexistentin beforeEach soresolveTeamaiBinPathfalls back to'teamai', keeping fixtures stableresolveTeamaiBinPathfalls back to bareteamai(same behavior as before)Test plan
npx tsc --noEmitpassesnpx vitest run— no new failures (golden + hooks tests all pass)teamai init --http <url> --agent codebuddy --force, verify~/.codebuddy/settings.jsoncontains absolute path like/Users/xxx/.nvm/.../bin/teamai hook-dispatch ...teamai)🤖 Generated with Claude Code