ClaudeMods
☰
ZH-TW
● 0 人在線上 · 瀏覽 0 次
贊助提交作品
GitHub 儲存庫 · 發布者 KilimcininKorOglu

git-commit

一個 Claude Code 外掛,提供 git 提交技能,並讓每個 Bash git 指令都經過檢查:阻擋未使用技能的提交、盲目 git add、AI 簽名尾註、機密、被忽略路徑,以及未要求的推送或分支變更。

KilimcininKorOglu@KilimcininKorOglu

KilimcininKorOglu/claude-code-mods/tree/main/plugins/git-commit

已翻譯

關於這個 mod

提供提交技能(git-commit:commit),並讓所有 Bash git 指令遵守它。技能開啟時會附加儲存庫狀態區塊(分支、已暫存/未暫存/未追蹤/衝突檔案、最近的主旨、憑證名稱警告),讓模型不必先執行 git status 或 git log。

硬性規則(預設的 deny 模式會在 git 執行前停止指令):本輪沒有由此代理開啟技能時不得提交;沒有相符技能選項時不得使用 --no-verify、--amend、-a;不得使用 --allow-empty、--interactive、-p;路徑規格和 glob 不得越過本次變更的檔案;不得對被忽略路徑使用 git add -f;不得提交包含被忽略檔案或憑證名稱檔案的內容;提交訊息不得帶 AI 簽名尾註,也不得為空、超過 72 個字元或以句號結尾;在 conventional repo 中不得使用不合規範的主旨;不得使用跳過掛鉤的環境變數或設定;除非最近一則提示要求,否則不得推送或切換分支。

軟性規則只提示、從不停止:超過 100 個變更行、觸及超過一個區域、主旨以 -ed/-ing 開頭、與最近主旨大小寫不一致、git add 暫存了未追蹤檔案,或訊息/索引狀態無法讀取。

指令:/git-commit on|off、/git-commit mode deny|note。安裝:

claude plugin marketplace add KilimcininKorOglu/claude-code-mods
claude plugin install git-commit@kilimcininkoroglu-mods

已在 Claude Code 2.1.284 上用 claude plugin validate 驗證。達到 L2:執行 git、cp、rm;讀取 Bash 指令文字、最近提示、技能參數和透過 git 讀取的儲存庫;任何內容都不會離開機器。限制包括透過 sh -c、腳本、git 別名、git commit-tree 或 MCP git 工具執行的提交、由 shell 建立的訊息,以及其他形式的機密。

安裝

請先查看作者 README,確認 marketplace 與外掛名稱;指令可能隨儲存庫結構而變動。

claude plugin marketplace add KilimcininKorOglu/claude-code-mods
claude plugin install git-commit
原文 / README

git-commit

A commit skill tells the model how to commit: explicit paths, no AI signature, no push nobody asked for. The model reads the skill, and then it sometimes runs git commit straight from Bash without it. This mod ships the commit skill and holds every Bash git command to it. A commit the skill did not open, a blanket git add, a signature trailer, a secret, an ignored path, or a push or branch change nobody asked for is stopped before git runs. The model reads which rule the command broke and runs it again the right way.

What it does

  1. The mod ships the skill as git-commit:commit (skills/commit/SKILL.md). The model opens it with the Skill tool, or you type /git-commit:commit, with the options you gave: --all, --staged, --modified, --no-verify, --amend, --push.

  2. When the skill opens, the mod appends a Current repository state (git-commit) block to its text: the branch, the staged, unstaged, untracked and conflicted files (40 of each at most), the options the skill was opened with, the style of the last 20 subjects, the last 10 subjects, and a warning for each staged file whose name holds credentials or that an ignore file names. The model starts from that block instead of running git status and git log first.

  3. The skill counts as open for the agent loop that opened it, until that loop's turn ends. The main loop and each subagent are separate: a subagent that commits opens the skill itself. A new turn opens it again.

  4. Each Bash command that names git is read before it runs. The mod splits the command at &&, ||, ;, |, &, parentheses and new lines, skips env, command, exec, time, nohup and variable assignments in front of git, and follows a cd and git -C. It reads the arguments of add, rm, commit, push, merge, config, rebase, switch, branch and checkout the way git's own option parser reads them (-am, -mtext, --message=text, --), and a heredoc as the message it holds. Every other git call runs unread.

  5. To measure what a commit records, the mod copies the index to a temporary file and replays the command's own git add and git rm --cached calls into that copy through GIT_INDEX_FILE. A commit -a stages the tracked changes into the copy; a commit with a pathspec starts from a fresh index that holds HEAD. The real index is never written, and the temporary files are deleted after the measure.

  6. A rule is either hard or soft. In deny mode, the default, a command that breaks a hard rule stops before it runs, and the model reads:

    git-commit: stopped before it ran, because it breaks the git-commit:commit skill:
    - A git commit runs only after the git-commit:commit skill was opened in this turn, by this agent. Call the Skill tool with skill "git-commit:commit" and, as args, the options the user gave (such as --push or --amend), follow its steps, then run the commit again.
    There is no way around this gate.
    

    In note mode the command runs, and the model reads the broken rules after its result. A soft rule never stops a command: in both modes its note comes after the result.

  7. You read one line per rule: in the sidebar stream while it is open (red for a hard rule, yellow for a soft one, under git command stopped or git command noted), else one transcript line such as git-commit: stopped: skill not opened.

  8. While the mod is on, the engine's commit attribution text is empty, so the model is not told to add a Co-Authored-By trailer.

In the live check on Claude Code 2.1.284 the gate stopped a git commit run without the skill, a git add ., a git add -f of a file .gitignore names, a commit with a Co-Authored-By: Claude line, and a git push the prompt did not ask for. After the model opened git-commit:commit, it read the state block and the same commit ran. In note mode git add . ran, and the model read the broken rule and the three new files it staged.

Rules

Hard rules (deny mode stops the command):

| Command | Stopped when | |---|---| | git commit | the skill was not opened in this turn by this agent | | git commit | --no-verify or -n without the skill's --no-verify; --amend without --amend; -a without --all or --modified | | git commit | --allow-empty, --allow-empty-message, --interactive, -p | | git commit, git add | a pathspec that reaches past this change's files: ., .., *, a glob, a : pathspec, a directory (a submodule is a file here); the skill's --all allows them | | git add | -A without --all; -u without --all or --modified; -i, -p, -e, --pathspec-from-file | | git add -f | a path that an ignore file names | | git commit | the commit holds a path that an ignore file names: the project's .gitignore files, .git/info/exclude and the global excludes file, as git check-ignore -v reports them, with the file and the line | | git commit | the commit holds a file whose name holds credentials (.env and .env.* except the example files, *.pem, *.key, *.p12, *.pfx, *.keystore, *.jks, id_rsa and the other id_* keys, credentials.json, .netrc, .pgpass), or adds a line that looks like a private key, an AWS, Google, GitHub, Slack, Stripe, npm, Hugging Face or sk- key, a JSON Web Token, or a quoted value of 16 or more characters with letters and digits after api_key, secret, token or password; the note names the file, the line and the kind, never the value | | git commit | the message carries an AI signature: a Co-authored-by: line that names an AI tool, a Generated with or Created by line that names one, [email protected], or 🤖. A Co-authored-by: line for a person passes | | git commit | the subject is empty, longer than 72 characters, or ends with a period | | git commit | the repository writes conventional subjects (more than half of the last 20, from at least 3), and the subject is not type(scope): subject, or its type is not in the skill's list | | git commit, git push, git merge | -c core.hooksPath=...; HUSKY=0, HUSKY_SKIP_HOOKS, SKIP or LEFTHOOK=0 without the skill's --no-verify | | git push | your last prompt does not say push and the skill was not opened with --push; --no-verify without the skill's --no-verify. A --dry-run passes | | git switch, git branch <name>, git branch -d/-m/-c, git checkout -b/-B/--orphan/--detach, git checkout <name> | your last prompt does not say branch, checkout or switch. A git checkout with --, with two or more operands, or with one operand that is an existing path restores files and passes | | git config | it writes a setting; --get, --list and the other reads pass | | git rebase | -i |

Soft rules (a note in both modes):

  • The commit changes more than 100 lines.
  • The commit touches more than one area, where an area is the first two path segments (plugins/a and plugins/b).
  • The subject's first word ends in -ed or -ing (added, adding).
  • The subject's case after type(scope): differs from the case of the recent subjects.
  • git add stages untracked files; the note names them.
  • The mod could not read the message (the shell builds it at run time, it comes from another commit, or git opens an editor), or could not measure what the commit holds (after a cd -, a cd ~ or a cd to a path with $, or when git could not replay the command's staging).

A git commit --dry-run, --short, --porcelain, --long or --help records nothing and is not read.

Command

/git-commit                   on or off, and the mode
/git-commit on | off          on by default; off also gives the engine its commit attribution text back
/git-commit mode deny         a command that breaks a hard rule stops; the default
/git-commit mode note         every command runs, and the model reads the broken rules after it

Install

claude plugin marketplace add KilimcininKorOglu/claude-code-mods
claude plugin install git-commit@kilimcininkoroglu-mods

Function hooks are early access. Claude Code 2.1.288 and later load them by default, so there is nothing to switch on.

After installing

  1. Restart Claude Code.
  2. Type /git-commit:commit to commit through the skill. /commit does not open a plugin skill.
  3. If you keep a commit skill of your own (~/.claude/skills/commit), remove it. The mod counts only git-commit:commit as the skill, so a commit after your own skill is stopped, and the model reads two skills that say the same thing.
  4. If your CLAUDE.md tells the model to commit through a skill, name it git-commit:commit there.

What it can reach

Validated with claude plugin validate on Claude Code 2.1.284:

❯ ./register.ts hooks: session.start, command.run{command=git-commit}, turn.start, prompt.submit, tool.call{tool=Skill}, skill.prompt{skill=git-commit:commit}, attribution.text{kind=commit}, tool.call{tool=Bash}, turn.complete
❯ ./register.ts calls: $.command.register, $.fs.exists (via directoryFindings, judgeCheckout, scratchIndex), $.fs.read (via messageCheck), $.fs.stat (via directoryFindings), $.process.run (via dropTemps, git, scratchIndex), $.session.cwd (via judge, repoBlock), $.sidebar.set (via toPerson), $.store.get (via readSettings), $.store.set (via runCommand, setMode), $.ui.log (via dropTemps, toPerson)

Reach L2, it runs git, cp and rm.

1. Reads:    the Bash command text of each call that names git; your prompts, of which it keeps the last one in memory; the Skill tool's arguments; a -F message file; the repository through git
2. Runs:     git with LC_ALL=C: rev-parse, status, log -20, diff --cached, check-ignore, ls-files, and read-tree, add and rm --cached into a temporary index through GIT_INDEX_FILE; cp to copy the index; rm -f to delete the temporary index files
3. Sends:    a deny text or a note to the model, a repository state block after the skill's text, one sidebar entry or transcript line to you, and an empty commit attribution text to the engine; nothing leaves the machine
4. Persists: in $.store, the on/off setting and the mode; for the length of one command, temporary index files beside .git/index
5. Hostile input: the command text is parsed, never run by a shell; the command's own git add arguments are replayed as argv into a temporary index; a secret is named by file, line and kind, never by its value

Limits

  • The gate reads the Bash command text. A commit through sh -c, a script, a make target, a git alias, git commit-tree or an MCP git tool is not read.
  • The push and branch checks search your last prompt for a word. push etme ("do not push") reads as a request for a push.
  • A message that the shell builds when the command runs ($VAR, backticks, a $(...) other than cat <<'EOF') is not checked; the model reads a note instead.
  • The style rules follow the last 20 subjects. Where fewer than 3 exist or fewer than half are conventional, only the length, period and signature rules apply.
  • The secret check matches file names and added lines with regular expressions. A key of another shape is not seen.
  • The mood check reads the ending of the first word, not its grammar.
  • A git merge is checked only for skipped hooks.
  • The deny mode has no bypass. When a hard rule cannot be met, you turn the gate off with /git-commit mode note.

Development

make install     # eslint, typescript-eslint, typescript
make lint        # complexity limit 10, the build fails above it
make typecheck   # needs .claude/types/ from /plugin-types
make validate
make test        # claude plugin test

更多類似作品