@zhuxixi/pi-commit-lint
Conventional Commits lint for pi: blocks non-conforming `git commit -m` commands in the bash tool and returns a corrective hint to the model
Package details
Install @zhuxixi/pi-commit-lint from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@zhuxixi/pi-commit-lint- Package
@zhuxixi/pi-commit-lint- Version
0.3.0- Published
- Nov 7, 2026
- Downloads
- 264/mo · 11/wk
- Author
- zhuxixi
- License
- MIT
- Types
- extension
- Size
- 20.1 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-commit-lint
Conventional Commits lint for pi:
blocks non-conforming git commit -m ... commands run through the bash
tool and returns a corrective hint to the model. A port of the Claude Code
PreToolUse hook (~/.claude/scripts/commit_lint.py).
🚫 commit message 不符合 Conventional Commits,已阻止提交。
当前 subject: "update stuff"
要求格式: type(scope)?: 描述
合法 type: feat / fix / docs / style / refactor / perf / test / build / ci / chore / revert / merge
示例:
feat(scan): 新增整页 OCR
fix(qa): 修复离散采样越界
docs: 更新设计文档 (#5)
请改成规范格式后重新提交。
Table of Contents
Features
- Blocks non-conforming commits: a
git commit -m ...whose subject does not match Conventional Commits is blocked at the tool call; the block reason is the corrective hint, sent back to the model so it can retry with a valid message. - Segment-scoped message lookup: the command is first stripped of text a
shell never executes (heredoc bodies,
#comments), then split into command segments (&&||;&|newline). Only thegit commitsegment is asked for its message, sopython3 -m unittest … && git commit -m "fix: x"andgit commit -F msg.txt && git stash push -m "wip"are judged on the real message. A commit with no message option (-F,--file,--amend) passes through. - Only
-mcommits are intercepted: editor/heredoc commits (no-m/-am/--message) pass through untouched. - Zero dependencies beyond pi: the validation logic is a pure
function in
lib/commit-lint.ts, unit-tested without a test framework.
Requirements
- pi ≥ 0.84 (uses the
tool_callevent). No other dependencies.
Installation
From npm (recommended)
pi install npm:@zhuxixi/pi-commit-lint
Then run /reload in pi (no restart needed).
To update later:
pi update --extensions
To remove:
pi remove npm:@zhuxixi/pi-commit-lint
From source
Clone the repository into a subdirectory of pi's global extensions dir:
git clone https://github.com/zhuxixi/pi-commit-lint.git ~/.pi/agent/extensions/pi-commit-lint
How It Works
- On the
tool_callevent, non-bashcalls are ignored. - Text a shell never executes is blanked first: heredoc bodies
(
<<EOF,<<-EOF, quoted delimiters) and#comments, so a commit command quoted inside documentation prose is not judged as one. - The remaining string is split into command segments on unquoted
separators:
&&,||,;,&,|, newline. Quotes protect their contents, so-m "a && b"stays one segment. - Every segment starting with
git commitis inspected on its own. The first-m/-am/-qm/--message/--message=/-mfoovalue in that segment is the subject (multiple-mkeep the first). A segment with no message option is skipped —-F/--filemessage files are not read. - The subject is checked against
^(TYPES)(\([\w./-]+\))?!?: .+withTYPES = "feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert|merge". - Non-conforming subjects are blocked with
{ block: true, reason }, wherereasonis a Chinese corrective hint.
No configuration, no commands, no state files — it just works.
Development
./test/run-all.sh # bundles test/*.test.ts with esbuild and runs them
Tests are dependency-free: lib/commit-lint.ts is pure and covered by
positive/negative cases (subject conformance, -m extraction, git-commit
detection without false positives).
After editing, run /reload inside pi to hot-reload the extension.
Troubleshooting
- Commits aren't blocked: check that the extension is listed in
pi config; after install you must/reload(or restart) pi for the extension to load. - A commit was blocked unexpectedly: read the hint's first lines.
来源:names this extension (it is not a repo git hook), and检测到的命令片段 (n/m)shows exactly which segment was judged — check that the message in that segment really is the one you meant to commit. - Editor/heredoc commits: these are intentionally not intercepted.
Limitations
-F/--filemessage files are not read or validated; such commits pass through. The file may not exist yet when the tool call is intercepted.git -C <dir> commit, environment-prefixed invocations (VAR=x git commit) and subshell forms ((git commit …)) are not recognised — they pass through unvalidated.- This is a minimal shell scanner, not a shell parser: command substitution
(
$(…), backticks) and process substitution are treated as opaque text. Anything the scanner cannot classify fails open (the command is allowed). - A subject built at runtime —
-m "$(cat msg.txt)",-m `cat msg.txt`,-m "$MSG"— is not judged; the commit passes through, since the real text is unknowable when the command is intercepted. - Redirections (
2>&1,&>file) do not split a command segment, sogit commit 2>&1 -m "…"is judged as one commit. - The check runs on the
tool_callevent, before the command executes; it is not a git hook. A blocked command never runs, so side effects earlier in the same chain do not happen either.