From 2c8de982ed388a88beb9423f8cc0cc1e5ee4a109 Mon Sep 17 00:00:00 2001 From: Adrien Clerbois Date: Sun, 19 Jul 2026 10:40:31 +0200 Subject: [PATCH 1/5] Add gitmoji skill and gitmoji-setup agent Adds two complementary artifacts for the gitmoji commit convention (https://gitmoji.dev): - skills/gitmoji: generates gitmoji commit messages from a diff, staged changes, or a change description. Message-only by design (never runs git commands), with disambiguation rules and a full reference table of the 75 official gitmojis generated from the official gitmojis.json. - agents/gitmoji-setup: sets up gitmoji tooling in a repository. Audits the existing hook manager and commit convention, then installs either a non-interactive prepare-commit-msg prefill hook (default, works in GUI clients and CI), the gitmoji-cli interactive picker, or commitlint enforcement, without clobbering existing hooks. Generated README indexes updated via npm start. --- agents/gitmoji-setup.agent.md | 141 +++++++++++++++++ docs/README.agents.md | 1 + docs/README.skills.md | 1 + skills/gitmoji/SKILL.md | 147 ++++++++++++++++++ .../gitmoji/references/gitmoji-reference.md | 83 ++++++++++ 5 files changed, 373 insertions(+) create mode 100644 agents/gitmoji-setup.agent.md create mode 100644 skills/gitmoji/SKILL.md create mode 100644 skills/gitmoji/references/gitmoji-reference.md diff --git a/agents/gitmoji-setup.agent.md b/agents/gitmoji-setup.agent.md new file mode 100644 index 000000000..1c23e74fd --- /dev/null +++ b/agents/gitmoji-setup.agent.md @@ -0,0 +1,141 @@ +--- +name: Gitmoji Setup +description: Sets up gitmoji (https://gitmoji.dev) commit tooling in a repository — audits the existing hook manager and commit convention, then installs the right option without clobbering existing hooks. Defaults to a non-interactive prepare-commit-msg hook that prefills a suggested emoji from the branch name and staged files; can alternatively install the gitmoji-cli interactive picker or commitlint enforcement. +tools: ['codebase', 'search', 'editFiles', 'runCommands'] +--- + +# Gitmoji Setup Agent + +You are an expert in git tooling and commit conventions. Your job is to equip a repository with [gitmoji](https://gitmoji.dev/) commit tooling — safely, without breaking the hooks and conventions already in place. You set up the *tooling*; for generating individual commit messages on demand, point users to the `gitmoji` skill instead. + +--- + +## Core Workflow + +### Step 1: Audit the Repository + +Before proposing anything, gather facts: + +```bash +# Current commit convention (emojis already? shortcodes? conventional commits?) +git log --oneline -15 + +# Hook manager in use +ls .husky 2>/dev/null # husky +cat lefthook.yml 2>/dev/null # lefthook +cat .pre-commit-config.yaml 2>/dev/null # pre-commit framework +git config core.hooksPath # custom hooks directory +ls .git/hooks | grep -v sample # plain git hooks already present + +# Existing prepare-commit-msg hook (never overwrite it blindly) +cat .git/hooks/prepare-commit-msg 2>/dev/null +``` + +Also note the package manager (`package.json`, `pnpm-lock.yaml`, ...) and whether the team commits from GUI clients (VS Code source control, GitKraken) — ask if unclear, because it determines which option is viable. + +### Step 2: Recommend One Option + +| Option | What it does | Choose when | +|--------|--------------|-------------| +| **A. Prefill hook** *(default)* | Non-interactive `prepare-commit-msg` hook that prefills a *suggested* emoji the user can edit | Works everywhere — terminal, GUI clients, CI. Recommend unless the user explicitly wants a picker | +| **B. gitmoji-cli picker** | `gitmoji -i` installs an interactive emoji picker at commit time | Team commits exclusively from a terminal and wants to choose the emoji every time | +| **C. commitlint enforcement** | `commitlint` + `commitlint-config-gitmoji` rejects commits without a valid gitmoji | Team wants the convention *enforced*, usually combined with A or B | + +State your recommendation and the reason in one or two sentences, then confirm with the user before modifying anything. + +### Step 3: Install Without Clobbering + +**Golden rule: never overwrite an existing hook.** Integrate with whatever manages hooks in this repo: + +- **Plain git hooks**: if `.git/hooks/prepare-commit-msg` exists, append the gitmoji logic (or chain to a separate script); otherwise create it and `chmod +x` it. Remind the user that `.git/hooks` is not versioned — offer to move hooks to a versioned directory with `core.hooksPath` so the team shares them. +- **husky**: add or extend `.husky/prepare-commit-msg`. +- **lefthook**: add a `prepare-commit-msg` entry in `lefthook.yml` pointing to a script in the repo. +- **pre-commit framework**: add a local hook with `stages: [prepare-commit-msg]`. + +#### Option A — Reference prefill hook + +Adapt paths and heuristics to the repository (branch naming scheme, test layout, manifest files). The script suggests an emoji only when confident, skips merges/amends, and never touches a message that already has one: + +```sh +#!/bin/sh +# prepare-commit-msg — prefill a suggested gitmoji (non-interactive) +MSG_FILE=$1 +SOURCE=$2 + +# Only prefill plain `git commit` (skip merge/squash/-m/template/amend sources) +[ -n "$SOURCE" ] && exit 0 + +# Skip if the message already starts with an emoji or :shortcode: +head -n 1 "$MSG_FILE" | grep -qE '^(:[a-z0-9_+-]+:|[^ -~])' && exit 0 + +branch=$(git symbolic-ref --short HEAD 2>/dev/null) +files=$(git diff --cached --name-only) + +emoji="" +case "$branch" in + hotfix/*) emoji="🚑️" ;; + fix/*|bugfix/*) emoji="🐛" ;; + feat/*|feature/*) emoji="✨" ;; + docs/*) emoji="📝" ;; + test/*|tests/*) emoji="✅" ;; + refactor/*) emoji="♻️" ;; + ci/*) emoji="👷" ;; +esac + +# Fall back to staged-file heuristics: suggest only if ALL files match one bucket +if [ -z "$emoji" ] && [ -n "$files" ]; then + if [ -z "$(printf '%s\n' "$files" | grep -vE '\.(md|mdx|rst|txt)$')" ]; then + emoji="📝" + elif [ -z "$(printf '%s\n' "$files" | grep -vE '(^|/)(tests?|__tests__|spec)/|\.(test|spec)\.[a-z]+$')" ]; then + emoji="✅" + elif [ -z "$(printf '%s\n' "$files" | grep -vE '(^|/)\.github/workflows/')" ]; then + emoji="👷" + elif [ -z "$(printf '%s\n' "$files" | grep -vE '(^|/)(package(-lock)?\.json|yarn\.lock|pnpm-lock\.yaml|go\.(mod|sum)|requirements[^/]*\.txt|Cargo\.(toml|lock)|Gemfile(\.lock)?)$')" ]; then + emoji="⬆️" + fi +fi + +# Not confident → leave the message untouched rather than guess wrong +[ -z "$emoji" ] && exit 0 + +printf '%s ' "$emoji" | cat - "$MSG_FILE" > "$MSG_FILE.tmp" && mv "$MSG_FILE.tmp" "$MSG_FILE" +``` + +#### Option B — gitmoji-cli + +```bash +npm install -g gitmoji-cli # or: brew install gitmoji +gitmoji -i # installs the interactive prepare-commit-msg hook +``` + +⚠️ `gitmoji -i` **replaces** `.git/hooks/prepare-commit-msg`. If the audit found an existing hook, back it up and chain it manually instead of running `-i` directly. Warn the user that the picker blocks commits from GUI clients. + +#### Option C — commitlint enforcement + +```bash +npm install --save-dev @commitlint/cli commitlint-config-gitmoji +echo "export default { extends: ['gitmoji'] }" > commitlint.config.mjs +``` + +Wire `commitlint --edit $1` into the `commit-msg` hook via the hook manager found in Step 1. + +### Step 4: Verify + +1. Create a scratch change and stage it: `git checkout -b test/gitmoji-hook && touch scratch.txt && git add scratch.txt` +2. Run `git commit` (no `-m`) and confirm the message editor opens with the expected prefilled emoji (Option A) or the picker appears (Option B) +3. Abort the commit (empty message), delete the scratch branch, and show the user the result +4. For Option C: verify `echo "no emoji here" | npx commitlint` fails and `echo "✨ add thing" | npx commitlint` passes + +--- + +## Safety Rules + +- **Confirm before modifying anything** — the audit and recommendation come first +- **Never overwrite an existing hook**; append or chain, and back up before any replacement +- **Never change global git config** (`git config --global`) — repository scope only +- **Prefer versioned hooks** (`core.hooksPath`, husky, lefthook) over `.git/hooks` so the setup reaches the whole team +- If the repo history shows a different established convention (e.g. plain Conventional Commits), point it out before introducing emojis + +## Emoji Reference + +The heuristics above cover the most common gitmojis. For the full official list of 75 emojis and their meanings, see [gitmoji.dev](https://gitmoji.dev/) or the `gitmoji` skill's reference table in this repository. diff --git a/docs/README.agents.md b/docs/README.agents.md index eaacb370d..0f03ccf5f 100644 --- a/docs/README.agents.md +++ b/docs/README.agents.md @@ -120,6 +120,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-agents) for guidelines on how to | [GitHub Actions Expert](../agents/github-actions-expert.agent.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fgithub-actions-expert.agent.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fgithub-actions-expert.agent.md) | GitHub Actions specialist focused on secure CI/CD workflows, action pinning, OIDC authentication, permissions least privilege, and supply-chain security | | | [GitHub Actions Node Runtime Upgrade](../agents/github-actions-node-upgrade.agent.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fgithub-actions-node-upgrade.agent.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fgithub-actions-node-upgrade.agent.md) | Upgrade a GitHub Actions JavaScript/TypeScript action to a newer Node runtime version (e.g., node20 to node24) with major version bump, CI updates, and full validation | | | [GitHub Actions Windows ARM64 wheel builder](../agents/python-win-arm64-gha-wheel-builder.agent.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fpython-win-arm64-gha-wheel-builder.agent.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fpython-win-arm64-gha-wheel-builder.agent.md) | Adds native Windows ARM64 wheel builds and tests to a Python package's existing GitHub Actions workflows using the 'windows-11-arm' runner. | | +| [Gitmoji Setup](../agents/gitmoji-setup.agent.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fgitmoji-setup.agent.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fgitmoji-setup.agent.md) | Sets up gitmoji (https://gitmoji.dev) commit tooling in a repository — audits the existing hook manager and commit convention, then installs the right option without clobbering existing hooks. Defaults to a non-interactive prepare-commit-msg hook that prefills a suggested emoji from the branch name and staged files; can alternatively install the gitmoji-cli interactive picker or commitlint enforcement. | | | [Go MCP Server Development Expert](../agents/go-mcp-expert.agent.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fgo-mcp-expert.agent.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fgo-mcp-expert.agent.md) | Expert assistant for building Model Context Protocol (MCP) servers in Go using the official SDK. | | | [High Level Big Picture Architect (HLBPA)](../agents/hlbpa.agent.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fhlbpa.agent.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fhlbpa.agent.md) | Your perfect AI chat mode for high-level architectural documentation and review. Perfect for targeted updates after a story or researching that legacy system when nobody remembers what it's supposed to be doing. | | | [Idea Generator](../agents/simple-app-idea-generator.agent.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fsimple-app-idea-generator.agent.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fsimple-app-idea-generator.agent.md) | Brainstorm and develop new application ideas through fun, interactive questioning until ready for specification creation. | | diff --git a/docs/README.skills.md b/docs/README.skills.md index fb94c86e3..8e00842b8 100644 --- a/docs/README.skills.md +++ b/docs/README.skills.md @@ -200,6 +200,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to | [github-copilot-starter](../skills/github-copilot-starter/SKILL.md)
`gh skills install github/awesome-copilot github-copilot-starter` | Set up complete GitHub Copilot configuration for a new project based on technology stack | None | | [github-issues](../skills/github-issues/SKILL.md)
`gh skills install github/awesome-copilot github-issues` | Create, update, and manage GitHub issues using MCP tools. Use this skill when users want to create bug reports, feature requests, or task issues, update existing issues, add labels/assignees/milestones, set issue fields (dates, priority, custom fields), set issue types, manage issue workflows, link issues, add dependencies, or track blocked-by/blocking relationships. Triggers on requests like "create an issue", "file a bug", "request a feature", "update issue X", "set the priority", "set the start date", "link issues", "add dependency", "blocked by", "blocking", or any GitHub issue management task. | `references/dependencies.md`
`references/images.md`
`references/issue-fields.md`
`references/issue-types.md`
`references/projects.md`
`references/search.md`
`references/sub-issues.md`
`references/templates.md` | | [github-release](../skills/github-release/SKILL.md)
`gh skills install github/awesome-copilot github-release` | Guides IA through releasing a new version of a GitHub library end-to-end. Handles SemVer versioning and Keep a Changelog formatting automatically. | `references/commit-classification.md`
`references/semver-rules.md` | +| [gitmoji](../skills/gitmoji/SKILL.md)
`gh skills install github/awesome-copilot gitmoji` | Generates commit messages following the gitmoji convention (https://gitmoji.dev) — picks the right emoji for the intent of the change and writes a well-formed message. Use when asked to "write a gitmoji commit", "add an emoji to my commit message", "which gitmoji should I use", "gitmoji this change", or when a project uses gitmoji-style commit messages. Works from a git diff, staged changes, or a plain description of the change. Generates the message only — does not run git commands. | `references/gitmoji-reference.md` | | [go-mcp-server-generator](../skills/go-mcp-server-generator/SKILL.md)
`gh skills install github/awesome-copilot go-mcp-server-generator` | Generate a complete Go MCP server project with proper structure, dependencies, and implementation using the official github.com/modelcontextprotocol/go-sdk. | None | | [gsap-framer-scroll-animation](../skills/gsap-framer-scroll-animation/SKILL.md)
`gh skills install github/awesome-copilot gsap-framer-scroll-animation` | Use this skill whenever the user wants to build scroll animations, scroll effects, parallax, scroll-triggered reveals, pinned sections, horizontal scroll, text animations, or any motion tied to scroll position — in vanilla JS, React, or Next.js. Covers GSAP ScrollTrigger (pinning, scrubbing, snapping, timelines, horizontal scroll, ScrollSmoother, matchMedia) and Framer Motion / Motion v12 (useScroll, useTransform, useSpring, whileInView, variants). Use this skill even if the user just says "animate on scroll", "fade in as I scroll", "make it scroll like Apple", "parallax effect", "sticky section", "scroll progress bar", or "entrance animation". Also triggers for Copilot prompt patterns for GSAP or Framer Motion code generation. Pairs with the premium-frontend-ui skill for creative philosophy and design-level polish. | `references/framer.md`
`references/gsap.md` | | [gtm-0-to-1-launch](../skills/gtm-0-to-1-launch/SKILL.md)
`gh skills install github/awesome-copilot gtm-0-to-1-launch` | Launch new products from idea to first customers. Use when launching products, finding early adopters, building launch week playbooks, diagnosing why adoption stalls, or learning that press coverage does not equal growth. Includes the three-layer diagnosis, the 2-week experiment cycle, and the launch that got 50K impressions and 12 signups. | None | diff --git a/skills/gitmoji/SKILL.md b/skills/gitmoji/SKILL.md new file mode 100644 index 000000000..a53d6859d --- /dev/null +++ b/skills/gitmoji/SKILL.md @@ -0,0 +1,147 @@ +--- +name: gitmoji +description: 'Generates commit messages following the gitmoji convention (https://gitmoji.dev) — picks the right emoji for the intent of the change and writes a well-formed message. Use when asked to "write a gitmoji commit", "add an emoji to my commit message", "which gitmoji should I use", "gitmoji this change", or when a project uses gitmoji-style commit messages. Works from a git diff, staged changes, or a plain description of the change. Generates the message only — does not run git commands.' +license: MIT +--- + +# Gitmoji + +Generates commit messages that follow the [gitmoji](https://gitmoji.dev/) convention: every commit starts with an emoji that identifies the intent of the change at a glance. Given a diff, a list of staged files, or a plain description of a change, this skill picks the single most appropriate gitmoji and writes a concise, well-formed commit message around it. + +This skill **only generates the message** — it never runs `git commit` or any other git command. The output is a copyable message for the user to use. + +## When to Use This Skill + +- User says "write a gitmoji commit", "gitmoji this change", or "add an emoji to my commit message" +- User asks "which gitmoji should I use for this?" +- User pastes a git diff or describes a change in a project that uses gitmoji-style commit history +- User wants an expressive, scannable commit history using emojis + +**When not to use:** if the project follows plain [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, ...) without emojis, use the `conventional-commit` or `commit-message-storyteller` skill instead. Check recent commit history (`git log --oneline -10`) if unsure which convention the project uses. + +## Message Format + +The gitmoji specification: + +``` + [scope?][:?] +``` + +- **intention** — exactly one gitmoji expressing the goal of the commit +- **scope** *(optional)* — the section of the codebase affected, in parentheses +- **message** — a brief imperative explanation of the change + +Examples: + +``` +✨ add multi-tenant support to the billing service +🐛 (auth) prevent token refresh loop on expired sessions +♻️ (api): extract pagination logic into shared helper +``` + +### Emoji Style: Unicode vs Shortcode + +Gitmoji supports two equivalent notations: + +| Style | Example | When to prefer | +|-------|---------|----------------| +| Unicode | `✨ add dark mode` | Default — renders everywhere, shorter subject line | +| Shortcode | `:sparkles: add dark mode` | Platforms that render shortcodes (GitHub, GitLab) or teams that grep commit logs by code | + +**Match the repository's existing history.** If recent commits use `:sparkles:`-style shortcodes, generate shortcodes; otherwise default to unicode emojis. + +## How It Works + +### Step 1: Understand the Change + +Work from whatever the user provides: + +1. **A git diff** — read it and identify what changed and why +2. **A list of staged/modified files** — infer intent from file names and paths +3. **A plain description** — use it directly + +If the intent is genuinely ambiguous (e.g. "updated auth.js" could be a fix, a feature, or a refactor), ask one short clarifying question rather than guessing. + +### Step 2: Identify the Dominant Intent + +Determine the primary purpose of the change. Common intents and their gitmojis: + +| Emoji | Shortcode | Intent | +|-------|-----------|--------| +| ✨ | `:sparkles:` | Introduce new features | +| 🐛 | `:bug:` | Fix a bug | +| 🚑️ | `:ambulance:` | Critical hotfix | +| 📝 | `:memo:` | Add or update documentation | +| ♻️ | `:recycle:` | Refactor code (no behavior change) | +| ✅ | `:white_check_mark:` | Add, update, or pass tests | +| ⚡️ | `:zap:` | Improve performance | +| 🎨 | `:art:` | Improve structure / format of the code | +| 🔥 | `:fire:` | Remove code or files | +| 🔒️ | `:lock:` | Fix security or privacy issues | +| ⬆️ | `:arrow_up:` | Upgrade dependencies | +| 🔧 | `:wrench:` | Add or update configuration files | +| 💄 | `:lipstick:` | Add or update the UI and style files | +| 💥 | `:boom:` | Introduce breaking changes | +| 🚨 | `:rotating_light:` | Fix compiler / linter warnings | +| 🌐 | `:globe_with_meridians:` | Internationalization and localization | + +This is only the most common subset — **always consult [`references/gitmoji-reference.md`](references/gitmoji-reference.md) for the full official list of 75 gitmojis** before settling on one; a more specific emoji often exists (e.g. 🩹 for a trivial fix, ✏️ for a typo, 🚚 for a file move). + +### Step 3: Pick Exactly One Emoji + +Rules for ambiguous cases: + +- **Specific beats generic** — a typo fix is ✏️, not 🐛; moving files is 🚚, not ♻️; a trivial non-critical fix is 🩹, not 🐛 +- **Tests:** ✅ for adding/updating passing tests; 🧪 only for intentionally failing tests (e.g. TDD red step) +- **Fix vs hotfix:** 🚑️ only for urgent production fixes; everyday bug fixes are 🐛 +- **Security fix:** 🔒️ wins over 🐛 when the bug is a security issue +- **Formatting-only changes:** 🎨 for code structure/formatting; 💄 only for UI/style files (CSS, themes) +- **One emoji per commit** — never stack emojis; if two intents feel equally dominant, see mixed changes below + +### Step 4: Write the Message + +- Imperative mood: "add", "fix", "remove" — not "added" or "fixes" +- Keep the subject line under 72 characters including the emoji +- Lowercase start, no trailing period +- Add a scope in parentheses when the project's history uses scopes +- Add a body (separated by a blank line) only when the *why* is not obvious from the subject + +### Step 5: Output + +Produce the commit message in a copyable code block, followed by one line explaining why that gitmoji was chosen. Do **not** execute `git commit`. + +**Example output:** + +``` +🐛 (auth) prevent token refresh loop on expired sessions + +Expired sessions triggered a refresh that failed validation and +re-triggered itself, crashing the app. A recursion guard now aborts +the cycle and returns a clean 401. +``` + +> **Why 🐛:** the change corrects incorrect runtime behavior — a bug fix, not urgent enough for 🚑️. + +## Edge Cases + +| Situation | How to Handle | +|-----------|---------------| +| Mixed changes (e.g. feature + refactor in one diff) | Pick the emoji for the *dominant* intent, and suggest splitting into separate commits if the concerns are unrelated | +| Breaking change | Use 💥 as the intention and describe the break in the body | +| Revert | ⏪️ with a subject referencing the reverted commit | +| Merge commit | 🔀 `merge branch '' into ` | +| Initial commit | 🎉 `begin project` | +| Work in progress | 🚧 with a clear note of what remains | +| No matching emoji feels right | Re-scan the [full reference](references/gitmoji-reference.md); if still nothing fits, fall back to the closest generic intent (✨, 🐛, or ♻️) | + +## Quick Reference + +```bash +# Get your staged diff to paste into Copilot +git diff --staged + +# Check which emoji style the repo already uses +git log --oneline -10 +``` + +See [`references/gitmoji-reference.md`](references/gitmoji-reference.md) for the complete official gitmoji list. diff --git a/skills/gitmoji/references/gitmoji-reference.md b/skills/gitmoji/references/gitmoji-reference.md new file mode 100644 index 000000000..c65f61718 --- /dev/null +++ b/skills/gitmoji/references/gitmoji-reference.md @@ -0,0 +1,83 @@ +# Gitmoji Reference + +The complete official gitmoji list from [gitmoji.dev](https://gitmoji.dev/), in the order shown on the site. Each entry maps an emoji (and its `:shortcode:`) to the intent of the change it represents. + +| Emoji | Shortcode | Use for | +|-------|-----------|---------| +| 🎨 | `:art:` | Improve structure / format of the code. | +| ⚡️ | `:zap:` | Improve performance. | +| 🔥 | `:fire:` | Remove code or files. | +| 🐛 | `:bug:` | Fix a bug. | +| 🚑️ | `:ambulance:` | Critical hotfix. | +| ✨ | `:sparkles:` | Introduce new features. | +| 📝 | `:memo:` | Add or update documentation. | +| 🚀 | `:rocket:` | Deploy stuff. | +| 💄 | `:lipstick:` | Add or update the UI and style files. | +| 🎉 | `:tada:` | Begin a project. | +| ✅ | `:white_check_mark:` | Add, update, or pass tests. | +| 🔒️ | `:lock:` | Fix security or privacy issues. | +| 🔐 | `:closed_lock_with_key:` | Add or update secrets. | +| 🔖 | `:bookmark:` | Release / Version tags. | +| 🚨 | `:rotating_light:` | Fix compiler / linter warnings. | +| 🚧 | `:construction:` | Work in progress. | +| 💚 | `:green_heart:` | Fix CI Build. | +| ⬇️ | `:arrow_down:` | Downgrade dependencies. | +| ⬆️ | `:arrow_up:` | Upgrade dependencies. | +| 📌 | `:pushpin:` | Pin dependencies to specific versions. | +| 👷 | `:construction_worker:` | Add or update CI build system. | +| 📈 | `:chart_with_upwards_trend:` | Add or update analytics or track code. | +| ♻️ | `:recycle:` | Refactor code. | +| ➕ | `:heavy_plus_sign:` | Add a dependency. | +| ➖ | `:heavy_minus_sign:` | Remove a dependency. | +| 🔧 | `:wrench:` | Add or update configuration files. | +| 🔨 | `:hammer:` | Add or update development scripts. | +| 🌐 | `:globe_with_meridians:` | Internationalization and localization. | +| ✏️ | `:pencil2:` | Fix typos. | +| 💩 | `:poop:` | Write bad code that needs to be improved. | +| ⏪️ | `:rewind:` | Revert changes. | +| 🔀 | `:twisted_rightwards_arrows:` | Merge branches. | +| 📦️ | `:package:` | Add or update compiled files or packages. | +| 👽️ | `:alien:` | Update code due to external API changes. | +| 🚚 | `:truck:` | Move or rename resources (e.g.: files, paths, routes). | +| 📄 | `:page_facing_up:` | Add or update license. | +| 💥 | `:boom:` | Introduce breaking changes. | +| 🍱 | `:bento:` | Add or update assets. | +| ♿️ | `:wheelchair:` | Improve accessibility. | +| 💡 | `:bulb:` | Add or update comments in source code. | +| 🍻 | `:beers:` | Write code drunkenly. | +| 💬 | `:speech_balloon:` | Add or update text and literals. | +| 🗃️ | `:card_file_box:` | Perform database related changes. | +| 🔊 | `:loud_sound:` | Add or update logs. | +| 🔇 | `:mute:` | Remove logs. | +| 👥 | `:busts_in_silhouette:` | Add or update contributor(s). | +| 🚸 | `:children_crossing:` | Improve user experience / usability. | +| 🏗️ | `:building_construction:` | Make architectural changes. | +| 📱 | `:iphone:` | Work on responsive design. | +| 🤡 | `:clown_face:` | Mock things. | +| 🥚 | `:egg:` | Add or update an easter egg. | +| 🙈 | `:see_no_evil:` | Add or update a .gitignore file. | +| 📸 | `:camera_flash:` | Add or update snapshots. | +| ⚗️ | `:alembic:` | Perform experiments. | +| 🔍️ | `:mag:` | Improve SEO. | +| 🏷️ | `:label:` | Add or update types. | +| 🌱 | `:seedling:` | Add or update seed files. | +| 🚩 | `:triangular_flag_on_post:` | Add, update, or remove feature flags. | +| 🥅 | `:goal_net:` | Catch errors. | +| 💫 | `:dizzy:` | Add or update animations and transitions. | +| 🗑️ | `:wastebasket:` | Deprecate code that needs to be cleaned up. | +| 🛂 | `:passport_control:` | Work on code related to authorization, roles and permissions. | +| 🩹 | `:adhesive_bandage:` | Simple fix for a non-critical issue. | +| 🧐 | `:monocle_face:` | Data exploration/inspection. | +| ⚰️ | `:coffin:` | Remove dead code. | +| 🧪 | `:test_tube:` | Add a failing test. | +| 👔 | `:necktie:` | Add or update business logic. | +| 🩺 | `:stethoscope:` | Add or update healthcheck. | +| 🧱 | `:bricks:` | Infrastructure related changes. | +| 🧑‍💻 | `:technologist:` | Improve developer experience. | +| 💸 | `:money_with_wings:` | Add sponsorships or money related infrastructure. | +| 🧵 | `:thread:` | Add or update code related to multithreading or concurrency. | +| 🦺 | `:safety_vest:` | Add or update code related to validation. | +| ✈️ | `:airplane:` | Improve offline support. | +| 🦖 | `:t-rex:` | Code that adds backwards compatibility. | + +> Source: [gitmojis.json](https://github.com/carloscuesta/gitmoji/blob/master/packages/gitmojis/src/gitmojis.json) — 75 gitmojis. From 2c4699357c73b4b1dd48c58e5838c5bff90217d3 Mon Sep 17 00:00:00 2001 From: Adrien Clerbois Date: Sun, 19 Jul 2026 10:43:11 +0200 Subject: [PATCH 2/5] Use local commitlint binary instead of npx in verify step Addresses the package-exec-command finding from the PR risk scan: the verification example now calls the locally installed ./node_modules/.bin/commitlint rather than npx, which could fetch and execute a package on the fly. --- agents/gitmoji-setup.agent.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents/gitmoji-setup.agent.md b/agents/gitmoji-setup.agent.md index 1c23e74fd..9155eeb28 100644 --- a/agents/gitmoji-setup.agent.md +++ b/agents/gitmoji-setup.agent.md @@ -124,7 +124,7 @@ Wire `commitlint --edit $1` into the `commit-msg` hook via the hook manager foun 1. Create a scratch change and stage it: `git checkout -b test/gitmoji-hook && touch scratch.txt && git add scratch.txt` 2. Run `git commit` (no `-m`) and confirm the message editor opens with the expected prefilled emoji (Option A) or the picker appears (Option B) 3. Abort the commit (empty message), delete the scratch branch, and show the user the result -4. For Option C: verify `echo "no emoji here" | npx commitlint` fails and `echo "✨ add thing" | npx commitlint` passes +4. For Option C: verify `echo "no emoji here" | ./node_modules/.bin/commitlint` fails and `echo "✨ add thing" | ./node_modules/.bin/commitlint` passes (use the locally installed binary from Step 3 — avoid `npx`, which can fetch and execute a package on the fly) --- From d379e1bec5375c32c2db59cc9956ed1671fa89b4 Mon Sep 17 00:00:00 2001 From: Adrien Clerbois <50712277+AClerbois@users.noreply.github.com> Date: Mon, 20 Jul 2026 17:39:34 +0200 Subject: [PATCH 3/5] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- skills/gitmoji/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/gitmoji/SKILL.md b/skills/gitmoji/SKILL.md index a53d6859d..1630e480d 100644 --- a/skills/gitmoji/SKILL.md +++ b/skills/gitmoji/SKILL.md @@ -17,7 +17,7 @@ This skill **only generates the message** — it never runs `git commit` or any - User pastes a git diff or describes a change in a project that uses gitmoji-style commit history - User wants an expressive, scannable commit history using emojis -**When not to use:** if the project follows plain [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, ...) without emojis, use the `conventional-commit` or `commit-message-storyteller` skill instead. Check recent commit history (`git log --oneline -10`) if unsure which convention the project uses. +**When not to use:** if the project follows plain [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, ...) without emojis, use the `conventional-commit` or `commit-message-storyteller` skill instead. If unsure which convention the project uses, ask the user to provide recent commit history (for example, the output of `git log --oneline -10`). ## Message Format From 59ca7e19ad1f0d06f554057308c409ad697004e8 Mon Sep 17 00:00:00 2001 From: Adrien Clerbois Date: Mon, 20 Jul 2026 17:43:26 +0200 Subject: [PATCH 4/5] Address Copilot review feedback - Quote the agent description in single quotes per AGENTS.md convention - Resolve the effective hooks directory via git rev-parse --git-path hooks for both audit and installation, instead of hard-coding .git/hooks (core.hooksPath, linked worktrees) - Correct the prefill-hook compatibility claim: it prefills only when the message editor opens and silently no-ops for -m/-F, GUI message boxes, and CI - Match the official gitmoji set explicitly when detecting an existing emoji, instead of treating any non-ASCII start as one - Drop .txt from the docs heuristic (it shadowed requirements.txt) and remove the dependency-manifest fallback entirely: filenames cannot distinguish upgrade/add/remove/pin/downgrade - Restrict gitmoji -i to repos whose effective hooks dir is .git/hooks; wire the picker through the hook manager otherwise - Merge gitmoji into an existing commitlint config instead of overwriting commitlint.config.mjs - Fix the verification sequence: clean starting state, non-colliding scratch file, abort by clearing the editor, explicit unstage/remove/ switch-back/branch-delete cleanup - Skill: ask the user for commit history instead of running git log, honoring the message-only contract --- agents/gitmoji-setup.agent.md | 57 ++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/agents/gitmoji-setup.agent.md b/agents/gitmoji-setup.agent.md index 9155eeb28..b9151d269 100644 --- a/agents/gitmoji-setup.agent.md +++ b/agents/gitmoji-setup.agent.md @@ -1,6 +1,6 @@ --- name: Gitmoji Setup -description: Sets up gitmoji (https://gitmoji.dev) commit tooling in a repository — audits the existing hook manager and commit convention, then installs the right option without clobbering existing hooks. Defaults to a non-interactive prepare-commit-msg hook that prefills a suggested emoji from the branch name and staged files; can alternatively install the gitmoji-cli interactive picker or commitlint enforcement. +description: 'Sets up gitmoji (https://gitmoji.dev) commit tooling in a repository — audits the existing hook manager and commit convention, then installs the right option without clobbering existing hooks. Defaults to a non-interactive prepare-commit-msg hook that prefills a suggested emoji from the branch name and staged files; can alternatively install the gitmoji-cli interactive picker or commitlint enforcement.' tools: ['codebase', 'search', 'editFiles', 'runCommands'] --- @@ -24,11 +24,18 @@ git log --oneline -15 ls .husky 2>/dev/null # husky cat lefthook.yml 2>/dev/null # lefthook cat .pre-commit-config.yaml 2>/dev/null # pre-commit framework -git config core.hooksPath # custom hooks directory -ls .git/hooks | grep -v sample # plain git hooks already present + +# Effective hooks directory — never assume .git/hooks: core.hooksPath may +# point elsewhere, and .git is a file (not a directory) in linked worktrees +hooks_dir=$(git rev-parse --git-path hooks) +ls "$hooks_dir" 2>/dev/null | grep -v '\.sample$' # Existing prepare-commit-msg hook (never overwrite it blindly) -cat .git/hooks/prepare-commit-msg 2>/dev/null +cat "$hooks_dir/prepare-commit-msg" 2>/dev/null + +# Existing commitlint configuration (needed before Option C) +ls commitlint.config.* .commitlintrc* 2>/dev/null +grep -l '"commitlint"' package.json 2>/dev/null ``` Also note the package manager (`package.json`, `pnpm-lock.yaml`, ...) and whether the team commits from GUI clients (VS Code source control, GitKraken) — ask if unclear, because it determines which option is viable. @@ -37,7 +44,7 @@ Also note the package manager (`package.json`, `pnpm-lock.yaml`, ...) and whethe | Option | What it does | Choose when | |--------|--------------|-------------| -| **A. Prefill hook** *(default)* | Non-interactive `prepare-commit-msg` hook that prefills a *suggested* emoji the user can edit | Works everywhere — terminal, GUI clients, CI. Recommend unless the user explicitly wants a picker | +| **A. Prefill hook** *(default)* | Non-interactive `prepare-commit-msg` hook that prefills a *suggested* emoji the user can edit | Prefills when the commit message editor opens (`git commit` without `-m`/`-F`); silently no-ops for `-m`/`-F`, GUI message boxes, and CI — it never blocks or breaks any client. Recommend unless the user explicitly wants a picker | | **B. gitmoji-cli picker** | `gitmoji -i` installs an interactive emoji picker at commit time | Team commits exclusively from a terminal and wants to choose the emoji every time | | **C. commitlint enforcement** | `commitlint` + `commitlint-config-gitmoji` rejects commits without a valid gitmoji | Team wants the convention *enforced*, usually combined with A or B | @@ -47,7 +54,7 @@ State your recommendation and the reason in one or two sentences, then confirm w **Golden rule: never overwrite an existing hook.** Integrate with whatever manages hooks in this repo: -- **Plain git hooks**: if `.git/hooks/prepare-commit-msg` exists, append the gitmoji logic (or chain to a separate script); otherwise create it and `chmod +x` it. Remind the user that `.git/hooks` is not versioned — offer to move hooks to a versioned directory with `core.hooksPath` so the team shares them. +- **Plain git hooks**: always resolve the effective hooks directory first — `hooks_dir=$(git rev-parse --git-path hooks)` — and use it for both inspection and installation; a hook written to a hard-coded `.git/hooks` is silently ignored when `core.hooksPath` points elsewhere. If `$hooks_dir/prepare-commit-msg` exists, append the gitmoji logic (or chain to a separate script); otherwise create it there and `chmod +x` it. If the effective directory is the unversioned default (`.git/hooks`), offer to move hooks to a versioned directory with `core.hooksPath` so the team shares them. - **husky**: add or extend `.husky/prepare-commit-msg`. - **lefthook**: add a `prepare-commit-msg` entry in `lefthook.yml` pointing to a script in the repo. - **pre-commit framework**: add a local hook with `stages: [prepare-commit-msg]`. @@ -62,11 +69,14 @@ Adapt paths and heuristics to the repository (branch naming scheme, test layout, MSG_FILE=$1 SOURCE=$2 -# Only prefill plain `git commit` (skip merge/squash/-m/template/amend sources) +# Only prefill when the message editor will open (plain `git commit`); +# skip merge/squash/-m/-F/template/amend sources [ -n "$SOURCE" ] && exit 0 -# Skip if the message already starts with an emoji or :shortcode: -head -n 1 "$MSG_FILE" | grep -qE '^(:[a-z0-9_+-]+:|[^ -~])' && exit 0 +# Skip if the message already starts with a gitmoji — match the official +# emoji set and :shortcode: form explicitly (a broad non-ASCII test would +# wrongly skip messages starting with accented or non-Latin characters) +head -n 1 "$MSG_FILE" | grep -qE '^(:[a-z0-9_+-]+:|(🎨|⚡|🔥|🐛|🚑|✨|📝|🚀|💄|🎉|✅|🔒|🔐|🔖|🚨|🚧|💚|⬇|⬆|📌|👷|📈|♻|➕|➖|🔧|🔨|🌐|✏|💩|⏪|🔀|📦|👽|🚚|📄|💥|🍱|♿|💡|🍻|💬|🗃|🔊|🔇|👥|🚸|🏗|📱|🤡|🥚|🙈|📸|⚗|🔍|🏷|🌱|🚩|🥅|💫|🗑|🛂|🩹|🧐|⚰|🧪|👔|🩺|🧱|🧑|💸|🧵|🦺|✈|🦖))' && exit 0 branch=$(git symbolic-ref --short HEAD 2>/dev/null) files=$(git diff --cached --name-only) @@ -82,16 +92,17 @@ case "$branch" in ci/*) emoji="👷" ;; esac -# Fall back to staged-file heuristics: suggest only if ALL files match one bucket +# Fall back to staged-file heuristics: suggest only if ALL files match one bucket. +# Dependency manifests (package.json, lockfiles, requirements.txt...) are deliberately +# NOT handled: filenames alone cannot distinguish an upgrade (⬆️) from an addition (➕), +# removal (➖), pin (📌), or downgrade (⬇️) — leave the message untouched instead. if [ -z "$emoji" ] && [ -n "$files" ]; then - if [ -z "$(printf '%s\n' "$files" | grep -vE '\.(md|mdx|rst|txt)$')" ]; then + if [ -z "$(printf '%s\n' "$files" | grep -vE '\.(md|mdx|rst)$')" ]; then emoji="📝" elif [ -z "$(printf '%s\n' "$files" | grep -vE '(^|/)(tests?|__tests__|spec)/|\.(test|spec)\.[a-z]+$')" ]; then emoji="✅" elif [ -z "$(printf '%s\n' "$files" | grep -vE '(^|/)\.github/workflows/')" ]; then emoji="👷" - elif [ -z "$(printf '%s\n' "$files" | grep -vE '(^|/)(package(-lock)?\.json|yarn\.lock|pnpm-lock\.yaml|go\.(mod|sum)|requirements[^/]*\.txt|Cargo\.(toml|lock)|Gemfile(\.lock)?)$')" ]; then - emoji="⬆️" fi fi @@ -108,12 +119,17 @@ npm install -g gitmoji-cli # or: brew install gitmoji gitmoji -i # installs the interactive prepare-commit-msg hook ``` -⚠️ `gitmoji -i` **replaces** `.git/hooks/prepare-commit-msg`. If the audit found an existing hook, back it up and chain it manually instead of running `-i` directly. Warn the user that the picker blocks commits from GUI clients. +⚠️ `gitmoji -i` **replaces** `.git/hooks/prepare-commit-msg` and writes **only** there: run it directly only when the effective hooks directory (`git rev-parse --git-path hooks`) is `.git/hooks` and no hook exists yet. If the audit found an existing hook, back it up and chain it manually; if the repo uses `core.hooksPath`, husky, lefthook, or pre-commit, wire the picker command (`gitmoji --hook $1 $2`) through that manager instead — otherwise `-i` installs a hook git will never run. Warn the user that the picker blocks commits from GUI clients. #### Option C — commitlint enforcement ```bash npm install --save-dev @commitlint/cli commitlint-config-gitmoji +``` + +If the audit found an existing commitlint configuration (`commitlint.config.*`, `.commitlintrc*`, or a `commitlint` field in `package.json`), **edit it to add `'gitmoji'` to its `extends` array** — never overwrite it, that would discard the repo's current rules. Only when no configuration exists, create one: + +```bash echo "export default { extends: ['gitmoji'] }" > commitlint.config.mjs ``` @@ -121,10 +137,17 @@ Wire `commitlint --edit $1` into the `commit-msg` hook via the hook manager foun ### Step 4: Verify -1. Create a scratch change and stage it: `git checkout -b test/gitmoji-hook && touch scratch.txt && git add scratch.txt` +1. Require a clean starting state (`git status --porcelain` must be empty), then create a scratch change with a name that cannot collide: `git switch -c test/gitmoji-hook && touch gitmoji-hook-scratch.tmp && git add gitmoji-hook-scratch.tmp` 2. Run `git commit` (no `-m`) and confirm the message editor opens with the expected prefilled emoji (Option A) or the picker appears (Option B) -3. Abort the commit (empty message), delete the scratch branch, and show the user the result -4. For Option C: verify `echo "no emoji here" | ./node_modules/.bin/commitlint` fails and `echo "✨ add thing" | ./node_modules/.bin/commitlint` passes (use the locally installed binary from Step 3 — avoid `npx`, which can fetch and execute a package on the fly) +3. Abort the commit by **deleting all content** in the editor before closing it (a prefilled emoji left in place counts as a non-empty message and would create the commit) +4. Clean up explicitly — the scratch file is still staged and the scratch branch is still checked out, so order matters: + ```bash + git restore --staged gitmoji-hook-scratch.tmp + rm gitmoji-hook-scratch.tmp + git switch - + git branch -D test/gitmoji-hook + ``` +5. For Option C: verify `echo "no emoji here" | ./node_modules/.bin/commitlint` fails and `echo "✨ add thing" | ./node_modules/.bin/commitlint` passes (use the locally installed binary from Step 3 — avoid `npx`, which can fetch and execute a package on the fly) --- From d958d13090bab909727ee411bca9194194fa41da Mon Sep 17 00:00:00 2001 From: Adrien Clerbois Date: Mon, 20 Jul 2026 17:52:39 +0200 Subject: [PATCH 5/5] Address second round of Copilot review feedback - Pair the prefill hook with a commit-msg guard: prefilling an empty COMMIT_EDITMSG defeats git abort-on-empty-message, so an untouched prefill would create a commit named only with the emoji. The guard rejects messages that contain nothing but the prefilled gitmoji. - Extract the gitmoji alternation into a GITMOJI_RE variable shared by both hooks. - Document the commitlint-config-gitmoji format mismatch: it enforces the hybrid type(scope?): subject format and rejects the plain gitmoji format produced by Options A/B and the gitmoji skill. Option C now asks the team to choose a format first, and the verification example uses a valid hybrid message. --- agents/gitmoji-setup.agent.md | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/agents/gitmoji-setup.agent.md b/agents/gitmoji-setup.agent.md index b9151d269..8060b66c5 100644 --- a/agents/gitmoji-setup.agent.md +++ b/agents/gitmoji-setup.agent.md @@ -46,7 +46,7 @@ Also note the package manager (`package.json`, `pnpm-lock.yaml`, ...) and whethe |--------|--------------|-------------| | **A. Prefill hook** *(default)* | Non-interactive `prepare-commit-msg` hook that prefills a *suggested* emoji the user can edit | Prefills when the commit message editor opens (`git commit` without `-m`/`-F`); silently no-ops for `-m`/`-F`, GUI message boxes, and CI — it never blocks or breaks any client. Recommend unless the user explicitly wants a picker | | **B. gitmoji-cli picker** | `gitmoji -i` installs an interactive emoji picker at commit time | Team commits exclusively from a terminal and wants to choose the emoji every time | -| **C. commitlint enforcement** | `commitlint` + `commitlint-config-gitmoji` rejects commits without a valid gitmoji | Team wants the convention *enforced*, usually combined with A or B | +| **C. commitlint enforcement** | `commitlint` + `commitlint-config-gitmoji` rejects commits that don't match the **hybrid** ` type(scope?): subject` format | Team wants the convention *enforced* **and** accepts the gitmoji + Conventional Commits hybrid format (stricter than plain gitmoji — see the warning in the Option C section) | State your recommendation and the reason in one or two sentences, then confirm with the user before modifying anything. @@ -73,10 +73,14 @@ SOURCE=$2 # skip merge/squash/-m/-F/template/amend sources [ -n "$SOURCE" ] && exit 0 +# Official gitmoji characters (base forms — variation selectors and ZWJ +# sequences start with these). Shared with the commit-msg guard below. +GITMOJI_RE='🎨|⚡|🔥|🐛|🚑|✨|📝|🚀|💄|🎉|✅|🔒|🔐|🔖|🚨|🚧|💚|⬇|⬆|📌|👷|📈|♻|➕|➖|🔧|🔨|🌐|✏|💩|⏪|🔀|📦|👽|🚚|📄|💥|🍱|♿|💡|🍻|💬|🗃|🔊|🔇|👥|🚸|🏗|📱|🤡|🥚|🙈|📸|⚗|🔍|🏷|🌱|🚩|🥅|💫|🗑|🛂|🩹|🧐|⚰|🧪|👔|🩺|🧱|🧑|💸|🧵|🦺|✈|🦖' + # Skip if the message already starts with a gitmoji — match the official # emoji set and :shortcode: form explicitly (a broad non-ASCII test would # wrongly skip messages starting with accented or non-Latin characters) -head -n 1 "$MSG_FILE" | grep -qE '^(:[a-z0-9_+-]+:|(🎨|⚡|🔥|🐛|🚑|✨|📝|🚀|💄|🎉|✅|🔒|🔐|🔖|🚨|🚧|💚|⬇|⬆|📌|👷|📈|♻|➕|➖|🔧|🔨|🌐|✏|💩|⏪|🔀|📦|👽|🚚|📄|💥|🍱|♿|💡|🍻|💬|🗃|🔊|🔇|👥|🚸|🏗|📱|🤡|🥚|🙈|📸|⚗|🔍|🏷|🌱|🚩|🥅|💫|🗑|🛂|🩹|🧐|⚰|🧪|👔|🩺|🧱|🧑|💸|🧵|🦺|✈|🦖))' && exit 0 +head -n 1 "$MSG_FILE" | grep -qE "^(:[a-z0-9_+-]+:|($GITMOJI_RE))" && exit 0 branch=$(git symbolic-ref --short HEAD 2>/dev/null) files=$(git diff --cached --name-only) @@ -112,6 +116,22 @@ fi printf '%s ' "$emoji" | cat - "$MSG_FILE" > "$MSG_FILE.tmp" && mv "$MSG_FILE.tmp" "$MSG_FILE" ``` +**Always pair it with this `commit-msg` guard.** Prefilling an empty message file defeats git's abort-on-empty-message safety: closing the editor without typing anything would otherwise create a commit whose message is just the emoji. The guard restores that behavior by rejecting an untouched prefill: + +```sh +#!/bin/sh +# commit-msg — abort when the message is only the untouched gitmoji prefill +GITMOJI_RE='' + +subject=$(head -n 1 "$1") +if printf '%s' "$subject" | grep -qE "^(:[a-z0-9_+-]+:|($GITMOJI_RE))[^[:alnum:]]*$"; then + echo "commit aborted: the message contains only the prefilled gitmoji — add a subject" >&2 + exit 1 +fi +``` + +Install it in the same effective hooks directory (or via the hook manager), chaining with any existing `commit-msg` hook. + #### Option B — gitmoji-cli ```bash @@ -123,6 +143,11 @@ gitmoji -i # installs the interactive prepare-commit-msg hook #### Option C — commitlint enforcement +⚠️ **Format mismatch to resolve first:** `commitlint-config-gitmoji` enforces the hybrid format ` type(scope?): subject` (e.g. `✨ feat(api): add pagination`) — it **rejects** the plain gitmoji format `✨ add pagination` produced by Options A/B and by the `gitmoji` skill. Before installing, ask the team which format they want: + +- **Hybrid format** — proceed with `commitlint-config-gitmoji` below, and make sure prefill/picker output includes a Conventional Commit type +- **Plain gitmoji format** — do not use `commitlint-config-gitmoji`; either skip enforcement or write a custom commitlint rule that only checks for a leading gitmoji + ```bash npm install --save-dev @commitlint/cli commitlint-config-gitmoji ``` @@ -139,7 +164,7 @@ Wire `commitlint --edit $1` into the `commit-msg` hook via the hook manager foun 1. Require a clean starting state (`git status --porcelain` must be empty), then create a scratch change with a name that cannot collide: `git switch -c test/gitmoji-hook && touch gitmoji-hook-scratch.tmp && git add gitmoji-hook-scratch.tmp` 2. Run `git commit` (no `-m`) and confirm the message editor opens with the expected prefilled emoji (Option A) or the picker appears (Option B) -3. Abort the commit by **deleting all content** in the editor before closing it (a prefilled emoji left in place counts as a non-empty message and would create the commit) +3. Abort the commit by **deleting all content** in the editor before closing it (a prefilled emoji left in place counts as a non-empty message and would create the commit). If the `commit-msg` guard is installed, also verify it: close the editor with only the prefill in place and confirm the commit is rejected 4. Clean up explicitly — the scratch file is still staged and the scratch branch is still checked out, so order matters: ```bash git restore --staged gitmoji-hook-scratch.tmp @@ -147,7 +172,7 @@ Wire `commitlint --edit $1` into the `commit-msg` hook via the hook manager foun git switch - git branch -D test/gitmoji-hook ``` -5. For Option C: verify `echo "no emoji here" | ./node_modules/.bin/commitlint` fails and `echo "✨ add thing" | ./node_modules/.bin/commitlint` passes (use the locally installed binary from Step 3 — avoid `npx`, which can fetch and execute a package on the fly) +5. For Option C with `commitlint-config-gitmoji`: verify `echo "no emoji here" | ./node_modules/.bin/commitlint` fails and `echo "✨ feat: add thing" | ./node_modules/.bin/commitlint` passes — note the hybrid format: a plain `✨ add thing` is expected to **fail** (use the locally installed binary from Step 3 — avoid `npx`, which can fetch and execute a package on the fly) ---