MCPcopy Create free account
hub / github.com/Noumena-Network/code / executeHooksOutsideREPL

Function executeHooksOutsideREPL

src/utils/hooks.ts:3007–3385  ·  view source on GitHub ↗

* Execute hooks outside of the REPL (e.g. notifications, session end) * * Unlike executeHooks() which yields messages that are exposed to the model as * system messages, this function only logs errors via logForDebugging (visible * with --debug). Callers that need to surface errors to users shou

({
  getAppState,
  hookInput,
  matchQuery,
  signal,
  timeoutMs = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
}: {
  getAppState?: () => AppState
  hookInput: HookInput
  matchQuery?: string
  signal?: AbortSignal
  timeoutMs: number
})

Source from the content-addressed store, hash-verified

3005 * @returns Array of HookOutsideReplResult objects containing command, succeeded, and output
3006 */
3007async function executeHooksOutsideREPL({
3008 getAppState,
3009 hookInput,
3010 matchQuery,
3011 signal,
3012 timeoutMs = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3013}: {
3014 getAppState?: () => AppState
3015 hookInput: HookInput
3016 matchQuery?: string
3017 signal?: AbortSignal
3018 timeoutMs: number
3019}): Promise<HookOutsideReplResult[]> {
3020 if (isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE)) {
3021 return []
3022 }
3023
3024 const hookEvent = hookInput.hook_event_name
3025 const hookName = matchQuery ? `${hookEvent}:${matchQuery}` : hookEvent
3026 if (shouldDisableAllHooksIncludingManaged()) {
3027 logForDebugging(
3028 `Skipping hooks for ${hookName} due to 'disableAllHooks' managed setting`,
3029 )
3030 return []
3031 }
3032
3033 // SECURITY: ALL hooks require workspace trust in interactive mode
3034 // This centralized check prevents RCE vulnerabilities for all current and future hooks
3035 if (shouldSkipHookDueToTrust()) {
3036 logForDebugging(
3037 `Skipping ${hookName} hook execution - workspace trust not accepted`,
3038 )
3039 return []
3040 }
3041
3042 const appState = getAppState ? getAppState() : undefined
3043 // Use main session ID for outside-REPL hooks
3044 const sessionId = getSessionId()
3045 const matchingHooks = await getMatchingHooks(
3046 appState,
3047 sessionId,
3048 hookEvent,
3049 hookInput,
3050 )
3051 if (matchingHooks.length === 0) {
3052 return []
3053 }
3054
3055 if (signal?.aborted) {
3056 return []
3057 }
3058
3059 const userHooks = matchingHooks.filter(h => !isInternalHook(h))
3060 if (userHooks.length > 0) {
3061 const pluginHookCounts = getPluginHookCounts(userHooks)
3062 const hookTypeCounts = getHookTypeCounts(userHooks)
3063 logEvent(`ncode_run_hook`, {
3064 hookName:

Callers 12

executeNotificationHooksFunction · 0.85
executeStopFailureHooksFunction · 0.85
executePreCompactHooksFunction · 0.85
executePostCompactHooksFunction · 0.85
executeSessionEndHooksFunction · 0.85
executeConfigChangeHooksFunction · 0.85
executeEnvHooksFunction · 0.85
executeElicitationHooksFunction · 0.85

Calls 15

isEnvTruthyFunction · 0.90
randomUUIDFunction · 0.90
shouldSkipHookDueToTrustFunction · 0.85
getSessionIdFunction · 0.85
getMatchingHooksFunction · 0.85
isInternalHookFunction · 0.85
getPluginHookCountsFunction · 0.85
getHookTypeCountsFunction · 0.85
jsonStringifyFunction · 0.85
isAsyncHookJSONOutputFunction · 0.85

Tested by

no test coverage detected