Conventional commit automation for the pi coding agent.
Creates commits as you work. The extension is opt-in — enable it per-project with a config file.
- Commits automatically when a pi-goal completes (
on_goaltrigger, opt-in). Other modes available. - Splits diffs into separate commits via a subagent (e.g. feature and tests in one commit, docs in another).
- Commit messages generated by a subagent using your model.
- Pick the model with
/commit-modelor thesubagent_modelconfig key. - Detects and commits in any git repositories the agent touched.
commit_changestool that agents can call to checkpoint work.- Exclusion patterns for files matching glob patterns (
*.log,build/, etc.). - Slash commands:
/commit,/commit-config,/commit-model.
pi install npm:pi-committerThis installs the package globally. Pi auto-loads it on startup.
git clone https://github.com/tmonk/pi-committer.git
cd pi-committer && npm install
# Load it in a session
pi -e ./index.tsln -s ~/projects/pi-committer ~/.pi/agent/extensions/pi-committerCreate .pi-committer.toml (or .pi-committer.json) in your project root. The extension walks up directories to find it.
[committer]
enabled = false # off by default; set to true to enable
trigger_mode = "on_goal" # on_goal | agent_sensible | after_tool | manual
detailed_body = true
min_changes = 1
staged_commits = true
exclude_patterns = ["*.log", "node_modules/"]
# When true and trigger_mode is "on_goal", the commit_changes tool will skip
# when pi-goal has an active goal and defer to the automatic commit-after-audit
# flow. Defaults to false — commit_changes always proceeds immediately unless
# you explicitly opt in to deferral.
# defer_to_goal_audit = false
# Minimum number of changed files before the subagent is called for grouping.
# Small change sets below this threshold use a single commit with a
# subagent-generated message (unless also below subagent_message_min_files).
# Default: 15 (determined empirically — see benchmark results).
# subagent_grouping_min_files = 15
# Minimum number of changed files before the subagent is called for the
# commit message. Below this threshold, the deterministic fallback is used
# directly (no LLM call at all). Default: 3 — 1-2 file changes are simple
# enough for deterministic.
# subagent_message_min_files = 3
# Optional: override the model used by the commit-message subagent
# subagent_model = "openai/gpt-4o-mini"
# Threshold for async (background subprocess) commits. When the number of changed
# files >= this value, /commit and commit_changes fork the commit pipeline into a
# detached subprocess so the conversation continues immediately. The widget shows
# progress and Esc cancels. Default: 10. Set to 0 to disable async (always sync).
# async_threshold = 10
# Optional: extend conventional commit types / restrict scopes
# custom_types = ["api", "wip"]
# allowed_scopes = ["api", "cli", "core"]| Mode | Behaviour |
|---|---|
on_goal |
Commits when a goal transitions to complete |
agent_sensible |
Commits after every agent turn |
after_tool |
Commits after each tool call |
manual (default) |
Never auto-commits; use /commit or commit_changes only |
First, enable auto-commit in your project config:
# .pi-committer.toml
[committer]
enabled = trueWith enabled = true and trigger_mode = "on_goal" (default), the extension hooks into pi-goal's lifecycle. When a goal managed by pi-goal transitions to complete status, pi-committer automatically stages and commits the changes:
/goals "Add user authentication" ← start a goal via /goals
> agent implements auth logic ← work happens
> pi-goal marks the goal complete ← pi-committer auto-commits
The commit is triggered by the goal state transition — no manual /commit needed.
/commit
Or ask the agent to "save my progress" and it will call the commit_changes tool.
/commit-model
Opens an interactive selector. Defaults to your current agent model.
/commit-config
When staged_commits = true (default), the subagent receives the diff and organizes changes into commit groups. Editing a source file, adding tests, and updating docs might produce:
feat(api): add user authentication endpoint
test(api): add authentication tests
docs: update API documentation
The subagent decides the grouping from the diff content, not from file extensions.
If the agent edits files in multiple git repositories during a session, commit_changes finds and commits in all of them. Detection works via session tool-call history — repos where the agent created or modified files using write or edit tools are detected and added on top of the primary working directory.
When the subagent is unavailable (e.g., SDK load failure) or returns no result, pi-committer generates a deterministic commit message using string analysis — no LLM calls needed:
- Smart scope: Uses the longest common ancestor directory across all changed files. If files span unrelated directories, scope is omitted entirely.
- Specific description: Extracts meaningful keywords from file names (strips extensions, skips boilerplate like
__init__andconftest, convertssnake_caseto readable words). Never says "update N modules". - Structured body: Includes the description summary line followed by a file list with change stats.
Every subagent fallback decision point logs a DIAG: diagnostic message to help identify root causes.
Extension events (turn_end, tool_result, goal_event)
│
▼
commitAllRepos(dir, ctx)
│
├─ findDirtyRepos(ctx) discover all dirty repos
│
└─ tryCommit(repo, ...) for each dirty repo
│
├─ stageAll / unstageExcluded
│
├─ generateStagedCommitGroups subagent decides grouping
│ └─ createAgentSession no tools, diff inline
│ └─ prompt: "Organize changes into logical commits"
│
├─ generateCommitMessageViaSubagent single-commit fallback
│
└─ git commit for each group
The subagent uses createAgentSession from @earendil-works/pi-coding-agent, the same pattern as pi-goal's runGoalCompletionAuditor. No pi-subagents dependency required.
- pi coding agent 0.71+
- Node.js 18+
- Git
smol-toml(installed vianpm install)
git clone <this-repo>
cd pi-committer
npm install
npm test # unit tests
npm run test:e2e # end-to-end testsMIT