GitHub Copilot
GitHub Copilot hooks: .github/hooks/*.json for Copilot CLI and the cloud agent
How do I add hooks to GitHub Copilot CLI or the Copilot cloud agent?
Commit a JSON file to .github/hooks/ with "version": 1 and a hooks object keyed by event, such as preToolUse or sessionStart. Each entry is a command hook with bash and powershell commands and an optional timeoutSec (default 30). A preToolUse hook can deny a tool call by printing {"permissionDecision": "deny", "permissionDecisionReason": "..."}. The cloud agent reads hooks only from .github/hooks/*.json on the default branch; Copilot CLI also reads ~/.copilot/hooks/.
Compare: hooks in every AI coding agent →
GitHub Copilot settings change often
Get one email a week when a setting, flag or permission rule changes, checked against the vendor docs.
Where hooks live
- Copilot cloud agent: .github/hooks/*.json in the cloned repository. The file must be on the default branch.
- Copilot CLI, repository: .github/hooks/*.json.
- Copilot CLI, user: ~/.copilot/hooks/ (or $COPILOT_HOME/hooks/ when that is set).
- Copilot CLI, policy: /etc/github-copilot/policy.d/*.json on Linux and macOS, C:\ProgramData\GitHub\Copilot\policy.d\*.json on Windows. Policy hooks cannot be turned off with disableAllHooks.
- Plugins ship their own hooks.json.
Example: a preToolUse policy hook
.github/hooks/copilot-cli-policy.json
{
"version": 1,
"hooks": {
"preToolUse": [
{
"type": "command",
"bash": "./scripts/pre-tool-policy.sh",
"powershell": "./scripts/pre-tool-policy.ps1",
"cwd": ".github/hooks",
"timeoutSec": 15
}
]
}
}The hook allows the call by doing nothing. To deny it, print a decision object on stdout:
stdout
{"permissionDecision":"deny","permissionDecisionReason":"Privilege escalation requires manual approval."}The input arrives as JSON on stdin. toolArgs is a JSON string, not an object, so parse it a second time before reading fields like command.
Hook events
- sessionStart and sessionEnd
- userPromptSubmitted and userPromptTransformed
- preToolUse, postToolUse and postToolUseFailure
- permissionRequest
- subagentStart and subagentStop
- agentStop
- preCompact
- notification
- errorOccurred
The cloud agent how-to lists six of these: sessionStart, sessionEnd, userPromptSubmitted, preToolUse, postToolUse and errorOccurred.
Gotchas
- Files use version 1. Invalid JSON or a wrong version rejects the whole file.
- In the cloud agent a preToolUse decision of "ask" is treated as "deny", because no user is there to answer.
- The cloud agent ignores the powershell command, because it runs on Linux.
- timeoutSec defaults to 30 seconds.
Get GitHub Copilot settings changes by email
When a setting, flag or permission rule in this guide changes, it goes in the weekly AgentAtlas update, checked against the vendor docs. One email a week.
Sources
More on GitHub Copilot
More GitHub Copilot guides
- GitHub Copilot custom instructions
- Adding MCP servers to GitHub Copilot
- copilot-setup-steps.yml: set up the GitHub Copilot cloud (coding) agent environment
- GitHub Copilot CLI permissions: --allow-tool, --deny-tool, --allow-all-tools and trusted directories
- GitHub Copilot custom agents: .github/agents/*.agent.md profiles, tools and frontmatter
- GitHub Copilot code review settings: automatic PR reviews, rulesets, effort level and approvals
Other guides
Reviewed Oct 18, 2026. Settings change often; the linked vendor docs are the source of truth.