--- title: 'Automating with Hooks' description: 'Learn how to use hooks to automate lifecycle events like formatting, linting, and governance checks during Copilot agent sessions.' authors: - GitHub Copilot Learning Hub Team lastUpdated: 2026-03-27 estimatedReadingTime: '8 minutes' tags: - hooks - automation - fundamentals relatedArticles: - ./building-custom-agents.md - ./what-are-agents-skills-instructions.md prerequisites: - Basic understanding of GitHub Copilot agents --- Hooks let you run automated scripts at key moments during a Copilot agent session — when a session starts or ends, when the user submits a prompt, or before and after the agent uses a tool. They're the glue between Copilot's AI capabilities and your team's existing tooling: linters, formatters, governance scanners, and notification systems. This article explains how hooks work, how to configure them, and practical patterns for common automation needs. ## What Are Hooks? Hooks are shell commands or scripts that run automatically in response to lifecycle events during a Copilot agent session. They execute outside the AI model, they're deterministic, repeatable, and under your full control. **Key characteristics**: - Hooks run as shell commands on the user's machine - They execute synchronously—the agent waits for them to complete - They can block actions (e.g., prevent commits that fail linting) - They're defined in JSON files stored at `.github/hooks/*.json` in your repository - They receive detailed context via JSON input, enabling context-aware automation - They can include bundled scripts for complex logic ### When to Use Hooks vs Other Customizations | Use Case | Best Tool | |----------|-----------| | Run a linter after every code change | **Hook** | | Teach Copilot your coding standards | **Instruction** | | Automate a multi-step workflow | **Skill** or **Agent** | | Scan prompts for sensitive data | **Hook** | | Format code before committing | **Hook** | | Generate tests for new code | **Skill** | Hooks are ideal for **deterministic automation** that must happen reliably—things you don't want to depend on the AI remembering to do. ## Anatomy of a Hook Each hook in this repository is a folder containing: ``` hooks/ └── my-hook/ ├── README.md # Documentation with frontmatter ├── hooks.json # Hook configuration └── scripts/ # Optional bundled scripts └── check.sh ``` > Note: Not all of these files are required for a generalised hook implementation. In your own repository, hooks are stored as JSON files in `.github/hooks/` (e.g., `.github/hooks/my-hook.json`). The folder structure above with README.md is specific to the Awesome Copilot repository for documentation purposes. ### hooks.json The configuration defines which events trigger which commands: ```json { "version": 1, "hooks": { "postToolUse": [ { "type": "command", "bash": "npx prettier --write .", "cwd": ".", "timeoutSec": 30 } ] } } ``` ## Hook Events Hooks can trigger on several lifecycle events: | Event | When It Fires | Common Use Cases | |-------|---------------|------------------| | `sessionStart` | Agent session begins or resumes | Initialize environments, log session starts, validate project state | | `sessionEnd` | Agent session completes or is terminated | Clean up temp files, generate reports, send notifications | | `userPromptSubmitted` | User submits a prompt | Log requests for auditing and compliance | | `preToolUse` | Before the agent uses any tool (e.g., `bash`, `edit`) | **Approve or deny** tool executions, block dangerous commands, enforce security policies | | `postToolUse` | After a tool completes execution | Log results, track usage, format code after edits, send failure alerts | | `agentStop` | Main agent finishes responding to a prompt | Run final linters/formatters, validate complete changes | | `subagentStart` | A subagent is spawned by the main agent | Inject additional context into the subagent's prompt, log subagent launches | | `subagentStop` | A subagent completes before returning results | Audit subagent outputs, log subagent activity | | `errorOccurred` | An error occurs during agent execution | Log errors for debugging, send notifications, track error patterns | > **Key insight**: The `preToolUse` hook is the most powerful — it can **approve or deny** individual tool executions. This enables fine-grained security policies like blocking specific shell commands or requiring approval for sensitive file operations. ### sessionStart additionalContext The `sessionStart` hook supports an `additionalContext` field in its output. When your hook script writes JSON to stdout containing an `additionalContext` key, that text is **injected directly into the conversation** at the start of the session. This lets hooks dynamically provide environment-specific context—such as the current git branch, deployment environment, or team onboarding notes—without requiring the user to paste it manually. Example hook script that surfaces context: ```bash #!/usr/bin/env bash # Output JSON with additionalContext to inject into the session cat <