MCPcopy Create free account
hub / github.com/AnukarOP/claude-code-leaked / execCommandHook

Function execCommandHook

source code/utils/hooks.ts:749–1337  ·  view source on GitHub ↗

* Execute a command-based hook using bash or PowerShell. * * Shell resolution: hook.shell → 'bash'. PowerShell hooks spawn pwsh * with -NoProfile -NonInteractive -Command and skip bash-specific prep * (POSIX path conversion, .sh auto-prepend, CLAUDE_CODE_SHELL_PREFIX). * See docs/design/ps-shel

(
  hook: HookCommand & { type: 'command' },
  hookEvent: HookEvent | 'StatusLine' | 'FileSuggestion',
  hookName: string,
  jsonInput: string,
  signal: AbortSignal,
  hookId: string,
  hookIndex?: number,
  pluginRoot?: string,
  pluginId?: string,
  skillRoot?: string,
  forceSyncExecution?: boolean,
  requestPrompt?: (request: PromptRequest) => Promise<PromptResponse>,
)

Source from the content-addressed store, hash-verified

747 * See docs/design/ps-shell-selection.md §5.1.
748 */
749async function execCommandHook(
750 hook: HookCommand & { type: 'command' },
751 hookEvent: HookEvent | 'StatusLine' | 'FileSuggestion',
752 hookName: string,
753 jsonInput: string,
754 signal: AbortSignal,
755 hookId: string,
756 hookIndex?: number,
757 pluginRoot?: string,
758 pluginId?: string,
759 skillRoot?: string,
760 forceSyncExecution?: boolean,
761 requestPrompt?: (request: PromptRequest) => Promise<PromptResponse>,
762): Promise<{
763 stdout: string
764 stderr: string
765 output: string
766 status: number
767 aborted?: boolean
768 backgrounded?: boolean
769}> {
770 // Gated to once-per-session events to keep diag_log volume bounded.
771 // started/completed live inside the try/finally so setup-path throws
772 // don't orphan a started marker — that'd be indistinguishable from a hang.
773 const shouldEmitDiag =
774 hookEvent === 'SessionStart' ||
775 hookEvent === 'Setup' ||
776 hookEvent === 'SessionEnd'
777 const diagStartMs = Date.now()
778 let diagExitCode: number | undefined
779 let diagAborted = false
780
781 const isWindows = getPlatform() === 'windows'
782
783 // --
784 // Per-hook shell selection (phase 1 of docs/design/ps-shell-selection.md).
785 // Resolution order: hook.shell → DEFAULT_HOOK_SHELL. The defaultShell
786 // fallback (settings.defaultShell) is phase 2 — not wired yet.
787 //
788 // The bash path is the historical default and stays unchanged. The
789 // PowerShell path deliberately skips the Windows-specific bash
790 // accommodations (cygpath conversion, .sh auto-prepend, POSIX-quoted
791 // SHELL_PREFIX).
792 const shellType = hook.shell ?? DEFAULT_HOOK_SHELL
793
794 const isPowerShell = shellType === 'powershell'
795
796 // --
797 // Windows bash path: hooks run via Git Bash (Cygwin), NOT cmd.exe.
798 //
799 // This means every path we put into env vars or substitute into the command
800 // string MUST be a POSIX path (/c/Users/foo), not a Windows path
801 // (C:\Users\foo or C:/Users/foo). Git Bash cannot resolve Windows paths.
802 //
803 // windowsPathToPosixPath() is pure-JS regex conversion (no cygpath shell-out):
804 // C:\Users\foo -> /c/Users/foo, UNC preserved, slashes flipped. Memoized
805 // (LRU-500) so repeated calls are cheap.
806 //

Callers 4

executeHooksFunction · 0.85
executeHooksOutsideREPLFunction · 0.85
executeStatusLineCommandFunction · 0.85

Calls 15

getPlatformFunction · 0.85
getProjectRootFunction · 0.85
pathExistsFunction · 0.85
getPluginDataDirFunction · 0.85
formatShellPrefixCommandFunction · 0.85
subprocessEnvFunction · 0.85
getHookEnvFilePathFunction · 0.85
getCwdFunction · 0.85
getOriginalCwdFunction · 0.85
logForDebuggingFunction · 0.85
getCachedPowerShellPathFunction · 0.85

Tested by

no test coverage detected