360 Secure SkillHub
360 安全技能中心

conventional-commits

读取当前分支和 Git diff,提取工单号、判断 API/CLIENT/CONSOLE/DB 项目标签,并按 Conventional Commits 规范生成提交信息;信息不足时省略对应前缀或提示拆分提交。

dennisrongo
dennisrongo
热度 27.66
最近更新 2026-08-17 04:49:32
分类:开发依赖:代码执行应用场景:工作流 / 模板 / 摘要总结

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add dennisrongo/conventional-commits
Metadata
name
conventional-commits
description
Write git commit messages following the Conventional Commits specification, with an automatic ticket number pulled from the current branch and a project tag (API / CLIENT / CONSOLE / DB) when the project type can be detected from the diff. Use this skill whenever the user asks to write a commit message, asks for help committing changes, runs `git commit`, or mentions writing changelog entries — even if they don't explicitly say "conventional commits".

Conventional Commits

Write commit messages that follow the Conventional Commits spec, prefixed with the ticket number (from the current branch) and the project tag (API / CLIENT / CONSOLE / DB) when those can be determined.

Format

[#<ticket>] [(<PROJECT>)] <type>[(<scope>)][!]: <description>

[optional body]

[optional footer(s)]

Bracketed segments are included only when they apply (see Branch & project context). A fully-tagged example:

#12345 (CLIENT) fix: prevent modal z-index regression on settings page

Types

  • feat — a new feature (correlates with MINOR in semver)
  • fix — a bug fix (correlates with PATCH in semver)
  • docs — documentation only changes
  • style — formatting, missing semicolons, etc; no code change
  • refactor — code change that neither fixes a bug nor adds a feature
  • perf — a code change that improves performance
  • test — adding or correcting tests
  • build — changes to the build system or external dependencies
  • ci — changes to CI configuration files and scripts
  • chore — other changes that don't modify src or test files
  • revert — reverts a previous commit

Branch & project context

Before composing the message, gather two pieces of context from the repo.

Ticket number (from current branch)

  1. Run git rev-parse --abbrev-ref HEAD to get the current branch name.
  2. Take the last /-separated segment of the branch (so feature/12345-fix_this_bug becomes 12345-fix_this_bug).
  3. If that segment starts with one or more digits followed by -, _, or end-of-string, those leading digits are the ticket number.
  4. If no leading numeric ID is found, omit #<ticket> from the message entirely — do not invent one, do not guess one from conversation context, do not reuse a stale number mentioned earlier in the session, and do not prompt the user for it. The branch name is the only source of truth for the ticket.

Examples:

Branch Extracted ticket
feature/12345-fix_this_bug 12345
12345-fix_this_bug 12345
bugfix/9-typo 9
main, release/v2, feature/redesign (none — omit #)

Project tag

Pick ONE of API, CLIENT, CONSOLE, or DB based on what was actually changed in the diff:

  • API — backend services, REST / GraphQL endpoints, server-side handlers. Signals: paths like api/, server/, backend/, services/api/, apps/api/; server framework code (Express, NestJS, FastAPI, Django, Rails, Spring); OpenAPI specs.
  • CLIENT — user-facing frontend. Signals: paths like client/, web/, frontend/, apps/web/, apps/client/, ui/; .tsx / .jsx / .vue / .svelte; React / Vue / Angular / Svelte component files; user-facing CSS / Tailwind / design assets.
  • CONSOLE — .NET console applications (CLIs, worker services, background tools). Signals: .csproj files with <OutputType>Exe</OutputType> or Sdk="Microsoft.NET.Sdk" (and NOT Microsoft.NET.Sdk.Web); Program.cs without ASP.NET / web-host bootstrap; Microsoft.Extensions.Hosting worker or BackgroundService usage; CLI libraries like System.CommandLine, Spectre.Console, CommandLineParser, McMaster.Extensions.CommandLineUtils; project names ending in .Console, .Cli, .Worker, or .Tool; paths like console/, apps/console/, tools/, cli/.
  • DB — database schema, migrations, seeds, ORM models. Signals: paths like db/, migrations/, prisma/, schema.prisma, SQL files, alembic/, knex/, model-only changes.

How to decide:

  1. Run git diff --cached --name-only (fall back to git diff --name-only if nothing is staged).
  2. Match the changed paths against the signals above. If all changed files cluster under one bucket, use that tag.
  3. If the diff genuinely spans multiple buckets, pick the dominant one (most files or largest change) and mention the secondary in the body.
  4. If none of the four buckets fit the repo (e.g., a library, a docs-only repo, a meta-tooling project), omit (PROJECT) — same fallback rule as the missing ticket.
  5. If two buckets are plausibly equal and you can't break the tie from the diff, ask the user which one applies. Do not guess silently.

Rules

  1. Description must be lowercase, present tense ("add" not "added"), and under 72 characters. The #12345 (CLIENT) prefix counts toward the 72-char header budget — keep the description tight.
  2. No period at the end of the description.
  3. Breaking changes get a ! after the type / scope (e.g., #12345 (API) feat!: drop support for Node 16) and a BREAKING CHANGE: footer.
  4. Inner type(scope) is optional and usually redundant once (PROJECT) is present. Only use it when it adds real specificity beyond the project tag (e.g., #12345 (API) fix(auth): ... when "auth" narrows further than "API").
  5. Body explains the why, not the what. Wrap at 72 chars.
  6. The description states what changed at the level a reader scanning a changelog needs; the why goes in the body. A description that only restates the type ("fix bug") carries no information — rewrite it.
    • ❌ fix: fix bug in login
    • ✅ fix: reject expired refresh tokens instead of issuing new access tokens
  7. The type must match the diff, not the user's phrasing. The user saying "quick fix" while the staged diff adds a new endpoint means feat, not fix. Determine the type from git diff --staged output you actually read this session — never from the conversation summary or the user's wording alone.
  8. If the staged diff contains two unrelated changes (e.g., an auth bug fix plus a new export page), say so and suggest splitting into two commits — do not paper over it with a vague umbrella description like chore: various updates.

Workflow

When the user asks for a commit message:

  1. Get the current branch with git rev-parse --abbrev-ref HEAD and extract the ticket number per the rules above.
  2. Inspect the staged diff: git diff --cached (or git diff if nothing is staged).
  3. From the changed file paths, determine the project tag — or decide to omit it.
  4. Categorize the change into one of the types — based on the diff you just read, not on how the user described the work.
  5. Write a concise description.
  6. If the change is non-trivial, add a body explaining the rationale.
  7. Flag breaking changes explicitly.
  8. Assemble the header as [#<ticket>] [(<PROJECT>)] <type>: <description>, including only the segments that apply.

Examples

#12345 (CLIENT) fix: prevent modal z-index regression on settings page

#12345 (API) feat(auth): add OAuth2 PKCE flow for mobile clients

#987 (DB) chore: add index on users.created_at for analytics query

#42 (CONSOLE) feat: add bulk-export action to billing dashboard

(API) refactor: extract token validator into shared middleware
# ^ branch had no ticket — `#` omitted

#7 fix: correct off-by-one in pagination cursor
# ^ repo doesn't fit API / CLIENT / CONSOLE / DB — `(PROJECT)` omitted

fix: prevent race condition in cache invalidation

The previous implementation could double-invalidate when two requests
arrived within the lock window. Use a single atomic CAS.

Fixes #482
# ^ no ticket in branch, no project bucket fits — both prefixes omitted

#1024 (API) refactor!: rename `user.email` column to `user.email_address`

BREAKING CHANGE: clients reading `user.email` must update to `user.email_address`.

Anti-patterns to avoid

  • ❌ update stuff (no type, vague)
  • ❌ Fix: Bug in login page. (capitalized, trailing period)
  • ❌ feat: added the ability to export CSV files (past tense)
  • ❌ #12345 (CLIENT) feat: added export. (past tense + trailing period)
  • ❌ Inventing a ticket number when the branch doesn't have one — or guessing one from conversation context
  • ❌ fix: quick fix per request when the staged diff adds a new endpoint (type from the user's phrasing, not the diff — should be feat)
  • ❌ chore: various updates covering two unrelated changes — flag the split instead
  • ❌ Forcing a (PROJECT) tag when the diff doesn't actually map to API / CLIENT / CONSOLE / DB
  • ✅ #12345 (CLIENT) feat: add CSV export