Skip to content

Hooks and lifecycle automation

Hooks and lifecycle automation

This document explains how hooks work in the extracted Copilot CLI bundle. Hooks are one of the broadest extension points in app.js: they can run at session lifecycle boundaries, prompt submission, tool execution, permission requests, compaction, notifications, and agent/subagent stop events.

The implementation is not just “run a script.” app.js defines a hook schema, compatibility aliases, discovery/merge logic, security restrictions for HTTP hooks, hook start/end events, and output adapters that can change prompts, approvals, and tool results.

Because app.js is bundled/minified, symbol names are unstable. Line references below are searchable anchors in the extracted bundle and will shift across releases.

Source anchors

AreaAnchor strings / minified symbolsApprox. app.js lineWhat it shows
Hook schemasessionStart, sessionEnd, userPromptSubmitted, preToolUse, postToolUse, postToolUseFailure, preCompact, permissionRequest, notification238The main hook configuration object and supported hook arrays.
Command hooksbash, powershell, command, cwd, env, timeoutSec238Command hook schema and command alias normalization.
HTTP hookstype:"http", url, headers, allowedEnvVars238HTTP hook schema with credential/HTTPS validation.
Prompt hooktype:"prompt", prompt238Startup/prompt-style hooks that inject prompt content.
VS Code compatibility_vsCodeCompat, SessionStart, UserPromptSubmit, PreToolUse, Stop238, 2797Legacy/PascalCase hook names are mapped to canonical camelCase names.
Security overridesCOPILOT_HOOK_ALLOW_LOCALHOST, COPILOT_HOOK_ALLOW_HTTP_AUTH_HOOKS238, 2792Local development and HTTP auth-hook override gates.
Repo/user hook config.github/hooks/*.json, disableAllHooks, hooks7923Settings/help text describes hook config shape and repo/user scopes.
Hook execution eventshook.start, hook.end, hookInvocationId4361, 4471Sessions emit start/end events around hook invocation.
Permission hook integrationpermissionRequest, resolvedByHook, permission.completed4471Hooks can resolve authorization requests before normal prompting.
Failure guidancepostToolUseFailure, Additional guidance from postToolUseFailure hook2794Failed tools can receive hook-provided model guidance.

Runtime map

flowchart TD
Config[User config / repo settings / plugin config] --> Parse[Parse hook schema]
Parse --> Compat[Normalize VS Code compatibility aliases]
Compat --> Validate[Validate command/http/prompt hook shape]
Validate --> Security[Apply HTTP security rules]
Security --> Runtime[Effective session hooks]
Runtime --> SessionStart[sessionStart]
Runtime --> Prompt[userPromptSubmitted]
Runtime --> Tool[preToolUse / postToolUse / postToolUseFailure]
Runtime --> Permission[permissionRequest]
Runtime --> Compact[preCompact / postCompact-related handling]
Runtime --> Notify[notification]
Runtime --> End[sessionEnd / agentStop / subagentStop]
Tool --> Events[hook.start / hook.end]
Permission --> Events
Prompt --> Events

Supported hook points

The schema around line 238 supports these canonical hook names:

HookTimingMain purpose
sessionStartWhen a session startsAdd initial context or run startup automation.
sessionEndWhen a session exitsCleanup, reporting, persistence, or external notification.
userPromptSubmittedAfter user prompt submission and before final prompt processingModify prompt text or add context.
preToolUseBefore a tool runsApprove, deny, modify arguments, suppress output, or add context.
postToolUseAfter successful tool executionObserve/log results or add context.
postToolUseFailureAfter failed tool executionAdd guidance or remediation text.
errorOccurredWhen a runtime error occursNotify or collect debug context.
agentStopWhen the main agent stopsPost-turn automation.
subagentStartWhen a subagent startsAdd context or filter by agent name.
subagentStopWhen a subagent stopsCollect results or notify.
preCompactBefore conversation compactionInspect transcript/custom instructions and potentially influence compaction context.
permissionRequestWhen a permission prompt would be neededResolve or influence authorization decisions.
notificationFor system/custom notificationsForward or transform runtime notifications.

The scan found postCompact strings mostly in the compaction event path (session.compaction_complete), while canonical hook config in this bundle visibly centers on preCompact. Existing docs and compatibility layers may still mention post-compact concepts, but the directly visible config schema here is preCompact.

Hook definition types

The bundle supports multiple hook definition shapes.

Command hooks

Command hooks can specify:

FieldMeaning
bashBash command body.
powershellPowerShell command body.
commandCompatibility alias that is copied into shell-specific command fields.
cwdWorking directory override.
envExtra environment variables.
timeoutSec / timeoutExecution timeout, with timeout normalized to timeoutSec.
matcherOptional regex-like selector for hook points that support filtering.

The schema requires at least one of bash, powershell, or command.

HTTP hooks

HTTP hooks can specify:

FieldMeaning
urlEndpoint to call.
headersOptional static headers.
allowedEnvVarsEnvironment variables allowed to be sent to the hook.
timeoutSec / timeoutHTTP timeout.
matcherOptional selector for compatible hook types.

HTTP hooks are where most of the security restrictions apply.

Prompt hooks

The schema also includes a prompt hook shape:

FieldMeaning
type: "prompt"Declares prompt-style hook content.
promptText prompt to inject or return through startup prompt handling.

Prompt hooks are useful for startup/context injection without needing to execute a command or call a URL.

Discovery and merging

Hook definitions can come from multiple locations:

SourceEvidenceNotes
User/global configSettings help text around line 7923Global config hooks act as user-level hooks.
Repository settingsSettings help text around line 7923Repo settings hooks act as repo-level hooks.
.github/hooks/*.jsonSettings help says same schema as .github/hooks/*.jsonFile-based repository hook discovery.
PluginsPlugin manifest includes hooksPlugins can package hook definitions.
SDK extensionsEXTENSIONS text mentions programmatic tools and hooksRuntime extensions can provide hooks/tools when gated on.

The settings field disableAllHooks can disable repo-level and user-level hooks. The parser also preserves passthrough fields to avoid hard-failing on future hook metadata.

Compatibility aliases

The bundle maps VS Code-style hook names to canonical CLI hook names. Examples include:

Compatibility nameCanonical name
SessionStartsessionStart
SessionEndsessionEnd
UserPromptSubmituserPromptSubmitted
PreToolUsepreToolUse
PostToolUsepostToolUse
PostToolUseFailurepostToolUseFailure
ErrorOccurrederrorOccurred
StopagentStop
SubagentStopsubagentStop
PreCompactpreCompact
PermissionRequestpermissionRequest
Notificationnotification

When compatibility keys are found, the loader copies those entries into the canonical hook array and annotates each entry with _vsCodeCompat. Later adapters use that marker to translate input/output payload shapes.

Security rules for HTTP hooks

The hook system has explicit HTTPS requirements.

Hooks with allowed environment variables

If an HTTP hook uses allowedEnvVars, the URL must use HTTPS unless it targets localhost and COPILOT_HOOK_ALLOW_LOCALHOST=1 is set. The error text says this prevents credential exposure.

Authorization-affecting hooks

For preToolUse and permissionRequest, HTTP hooks affect authorization. They must use HTTPS unless:

  • COPILOT_HOOK_ALLOW_HTTP_AUTH_HOOKS=1 is set; or
  • COPILOT_HOOK_ALLOW_LOCALHOST=1 is set and the host is localhost, 127.x.x.x, or [::1].

The runtime enforces this both during schema validation and immediately before HTTP hook invocation. This double-check matters because hook definitions can be loaded from multiple sources.

Hook events

The event schema around line 4361 defines two hook lifecycle events:

EventPayload
hook.starthookInvocationId, hookType, and input payload.
hook.endMatching hookInvocationId, hookType, output payload, success flag, and optional error.

The session exposes a hook event emitter that maps hook starts/ends into normal session events. This makes hooks visible to TUI/ACP/remote clients and gives replay/telemetry code a consistent record of hook behavior.

Prompt hook outputs

userPromptSubmitted hooks can modify the submitted prompt. The output adapter visible around line 2797 handles fields such as:

Output fieldEffect
modifiedPromptReplaces or transforms the user prompt text.
additionalContextAdds model-visible context around the prompt.
suppressOutputControls whether hook output is shown.

This is one of the highest-impact hook points because it can change the prompt before the model sees it.

Tool hook outputs

preToolUse can influence tool execution. The visible adapter logic handles fields such as:

Output fieldEffect
permissionDecisionApprove/deny/decide authorization before normal prompting.
permissionDecisionReasonExplanation attached to the decision.
modifiedArgumentsRewrites tool arguments.
additionalContextAdds model-visible context around the tool call.
suppressOutputHides hook output from normal display.
handled / responseContent / handledByLets a hook handle a tool call and return response content.

postToolUseFailure can add text to a failed tool result. The bundle has explicit wording: Additional guidance from postToolUseFailure hook. That text is appended to the tool failure context passed back to the model.

Permission hooks

permissionRequest hooks can resolve authorization requests before the normal user prompt. The session code still records the lifecycle:

  1. Evaluate permission hooks.
  2. If a hook returns a decision, create a request ID.
  3. Emit permission.requested with resolvedByHook behavior.
  4. Emit permission.completed with the hook result.
  5. Return the decision to the waiting tool flow.

This keeps the event log complete even when no interactive prompt was shown.

Compaction hooks

The preCompact adapter receives context such as:

  • sessionId;
  • timestamp;
  • current working directory;
  • transcript path;
  • compaction trigger;
  • custom instructions.

This lets hooks collect or inject information before the conversation is summarized and older messages are removed. Compaction results themselves are emitted separately as session.compaction_complete.

Failure behavior

Hook failures are generally contained:

  • Hook start/end events include success/error information.
  • Permission hook failures are logged and the runtime falls back to normal permission prompting.
  • Invalid matchers can cause a specific hook entry to be skipped.
  • Unsupported hook config versions throw configuration errors.
  • disableAllHooks returns an empty hook set.

The design avoids making every hook failure fatal to the session while still surfacing useful diagnostics.

Why hooks matter architecturally

Hooks can affect:

  • model-visible prompt text;
  • tool arguments;
  • permission decisions;
  • failure guidance;
  • compaction inputs;
  • notification routing;
  • session startup/shutdown automation;
  • plugin and extension behavior.

They are therefore part of the CLI’s control plane, not just a logging mechanism.

Relationship to other documents

  • permission-system-design.md covers the permission side of preToolUse and permissionRequest.
  • prompt-sources.md covers hooks as prompt/context sources.
  • conversation-compaction.md covers compaction and pre-compaction interaction.
  • plugin-extension-architecture.md explains plugin/extension sources for hooks.
  • built-in-tool-execution-pipeline.md explains where tool hooks sit in the execution lifecycle.

Created and maintained by Yingting Huang.