-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Hooks #685
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Hooks #685
Changes from all commits
acb5ad4
99a48a4
20806d3
4ddc77b
6210128
f62a764
a23d39a
e80e20b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # 🪝 Hooks | ||
|
|
||
| Hooks enable automated workflows triggered by specific events during GitHub Copilot coding agent sessions, such as session start, session end, user prompts, and tool usage. | ||
| ### How to Use Hooks | ||
|
|
||
| **What's Included:** | ||
| - Each hook is a folder containing a `README.md` file and a `hooks.json` configuration | ||
| - Hooks may include helper scripts, utilities, or other bundled assets | ||
| - Hooks follow the [GitHub Copilot hooks specification](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/use-hooks) | ||
|
|
||
| **To Install:** | ||
| - Copy the hook folder to your repository's `.github/hooks/` directory | ||
| - Ensure any bundled scripts are executable (`chmod +x script.sh`) | ||
| - Commit the hook to your repository's default branch | ||
|
|
||
| **To Activate/Use:** | ||
| - Hooks automatically execute during Copilot coding agent sessions | ||
| - Configure hook events in the `hooks.json` file | ||
| - Available events: `sessionStart`, `sessionEnd`, `userPromptSubmitted`, `preToolUse`, `postToolUse`, `errorOccurred` | ||
|
|
||
| **When to Use:** | ||
| - Automate session logging and audit trails | ||
| - Auto-commit changes at session end | ||
| - Track usage analytics | ||
| - Integrate with external tools and services | ||
| - Custom session workflows | ||
|
|
||
| | Name | Description | Events | Bundled Assets | | ||
| | ---- | ----------- | ------ | -------------- | | ||
| | [Session Auto-Commit](../hooks/session-auto-commit/README.md) | Automatically commits and pushes changes when a Copilot coding agent session ends | sessionEnd | `auto-commit.sh`<br />`hooks.json` | | ||
| | [Session Logger](../hooks/session-logger/README.md) | Logs all Copilot coding agent session activity for audit and analysis | sessionStart, sessionEnd, userPromptSubmitted | `hooks.json`<br />`log-prompt.sh`<br />`log-session-end.sh`<br />`log-session-start.sh` | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,11 @@ import fs from "fs"; | |
| import path from "path"; | ||
| import readline from "readline"; | ||
| import { COLLECTIONS_DIR, ROOT_FOLDER } from "./constants.mjs"; | ||
| import { parseCollectionYaml, parseFrontmatter } from "./yaml-parser.mjs"; | ||
| import { | ||
| parseCollectionYaml, | ||
| parseFrontmatter, | ||
| parseHookMetadata, | ||
| } from "./yaml-parser.mjs"; | ||
|
|
||
| const PLUGINS_DIR = path.join(ROOT_FOLDER, "plugins"); | ||
|
|
||
|
|
@@ -158,6 +162,12 @@ function getDisplayName(filePath, kind) { | |
| return basename.replace(".agent.md", ""); | ||
| } else if (kind === "instruction") { | ||
| return basename.replace(".instructions.md", ""); | ||
| } else if (kind === "hook") { | ||
aaronpowell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // For folder-based hooks like hooks/<hook>/README.md, use the folder name. | ||
| if (basename.toLowerCase() === "readme.md") { | ||
| return path.basename(path.dirname(filePath)); | ||
| } | ||
| return basename.replace(".hook.md", ""); | ||
| } else if (kind === "skill") { | ||
| return path.basename(filePath); | ||
| } | ||
|
|
@@ -221,6 +231,27 @@ function generateReadme(collection, items) { | |
| lines.push(""); | ||
| } | ||
|
|
||
| // Hooks | ||
| const hooks = items.filter((item) => item.kind === "hook"); | ||
| if (hooks.length > 0) { | ||
| lines.push("### Hooks"); | ||
| lines.push(""); | ||
| lines.push("| Hook | Description | Event |"); | ||
| lines.push("|------|-------------|-------|"); | ||
| for (const item of hooks) { | ||
| const name = getDisplayName(item.path, "hook"); | ||
| const description = | ||
| item.frontmatter?.description || item.frontmatter?.name || name; | ||
| // Extract events from hooks.json rather than frontmatter | ||
| const hookFolderPath = path.join(ROOT_FOLDER, path.dirname(item.path)); | ||
| const hookMeta = parseHookMetadata(hookFolderPath); | ||
| const event = | ||
| hookMeta?.hooks?.length > 0 ? hookMeta.hooks.join(", ") : "N/A"; | ||
| lines.push(`| \`${name}\` | ${description} | ${event} |`); | ||
| } | ||
| lines.push(""); | ||
|
Comment on lines
234
to
252
|
||
| } | ||
|
|
||
| // Skills | ||
| const skills = items.filter((item) => item.kind === "skill"); | ||
| if (skills.length > 0) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doc still describes hooks as
.hook.mdfiles (repository structure and frontmatter rules), but the implementation in this PR treats hooks as folders containingREADME.md+hooks.json. Please update the.hook.mdreferences to match the folder-based hook format to avoid confusing contributors.