npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@chaoxu1997/gentle-committer

v0.3.2

Published

Commit automation for the pi coding agent with review/bypass commit modes and work-unit commit discipline (independent project, originally derived from pi-committer)

Readme

gentle-committer

gentle-committer is an independent commit-automation extension for the pi coding agent, originally derived from pi-committer v0.12.8 and adapted for the gentle-pi ecosystem. All credit for the original commit automation goes to the pi-committer contributors; this project is MIT under the same terms.

Commit automation for the pi coding agent with a commit_mode switch: commit directly (bypass) or route each commit through gentle-ai's review gate (review) — plus optional work-unit commit discipline injected into the commit-message prompts.

| Mode | What happens | When to use | | --- | --- | --- | | bypass (default) | stage → generate message → git commit (byte-identical to pi-committer) | everyday work; developing gentle-committer itself | | review | stage + generate message → write a message file → hand off a git commit -F directive so gentle-ai's gate reviews the commit before it lands | features/changes you want reviewed before they land |

Override per-commit without touching config: commit_changes({mode: "review"}) for a big feature, commit_changes({mode: "bypass"}) for a quick fix.

pi install npm:@chaoxu1997/gentle-committer

What's different from pi-committer

| Area | pi-committer | gentle-committer | | --- | --- | --- | | Commit path | always execSync direct | bypass (direct) or review (gentle-ai gate) | | Per-commit mode | — | commit_changes({mode}) override | | Commit-message prompt | fixed | + optional work-unit rules (prompt_rules_path) | | gentle-ai coupling | — | none — review fires via the existing bash gate | | Everything else | — | unchanged (staged commits, subagent, multi-repo, async, widget) |

Quick start

  1. Install (above) — pi auto-loads it on startup.

  2. Enable + pick a mode in .pi-committer.toml:

    [committer]
    enabled     = true
    commit_mode = "bypass"   # or "review"
  3. Commit: ask the agent to commit, run /commit, or (with trigger_mode = "on_goal") let it auto-commit when a pi-goal completes.

Commit modes

bypass (default) — direct commit

Stage → subagent generates a conventional message → git commit. Byte-identical to upstream pi-committer. No gate.

review — commit through gentle-ai's gate

Stage + generate the message, but do not commit. Instead:

commit_changes({mode:"review"})
  → stages files, generates message
  → writes .git/gentle_committer_pending_msg
  → returns a directive (pending: true, NO commit):
      "Run: git commit -F .git/gentle_committer_pending_msg
       gentle-ai's gate will review the commit before it lands.
       Do NOT modify the staging area (git add/reset/restore)."
  → the model runs `git commit -F <file>`
  → gentle-ai's bash gate intercepts `git commit` → review → receipt → gate
  → the commit lands ONLY if the review passes

Why indirect? An extension cannot call the gentle_review tool in-process (its execute closure is private; ExtensionAPI exposes no invokeTool). So gentle-committer prepares the commit and lets the model's git commit trip gentle-ai's existing gate. Zero coupling — gentle-ai can upgrade without affecting gentle-committer.

Review-mode guardrails:

  • [ ] Async worker is disabled (review is synchronous; one message file).
  • [ ] Grouped/staged commits collapse to a single commit (one message, one directive).
  • [ ] Automatic triggers (turn_end / tool_result / goal_event) are suppressed — call commit_changes explicitly so the directive reaches the model.
  • [ ] If commit_mode = "review" but gentle-ai isn't loaded, it warns and falls back to bypass.

Per-call mode override

Don't want to flip a global config? Pass mode to commit_changes:

| You say | Model calls | Result | | --- | --- | --- | | "just commit this" | commit_changes({mode:"bypass"}) | direct commit | | "review then commit" | commit_changes({mode:"review"}) | directive → gate | | (nothing) | commit_changes() | uses commit_mode config (default bypass) |

SDD vs review-mode — SDD reviews the design/spec (planning); review-mode gates the commit diff (publish). They compose: SDD plan + implement → commit_changes({mode:"review"}).

Configuration

Create .pi-committer.toml (or .pi-committer.json) in your project root. The extension walks up directories to find it.

[committer]
enabled           = true
commit_mode       = "bypass"            # bypass | review            (gentle-committer)
prompt_rules_path = "commit-rules/work-unit-commits.md"               # (gentle-committer, optional)
trigger_mode      = "on_goal"           # on_goal | agent_sensible | after_tool | manual
staged_commits    = true
min_changes       = 1
exclude_patterns  = ["*.log", "node_modules/"]

# subagent_model             = "openai/gpt-4o-mini"
# subagent_grouping_min_files = 15   # ≥N files → subagent splits into groups
# subagent_message_min_files  = 3    # <N files → deterministic message (no LLM)
# async_threshold            = 10    # ≥N files → background subprocess; 0 = always sync
# custom_types               = ["api", "wip"]
# allowed_scopes             = ["api", "cli", "core"]
# defer_to_goal_audit        = false
# detailed_body              = true

| Key | Default | Purpose | | --- | --- | --- | | enabled | false | master switch | | commit_mode | "bypass" | direct commit vs gentle-ai gate | | prompt_rules_path | unset | markdown appended to the commit-message prompts | | trigger_mode | "on_goal" | when to auto-commit | | staged_commits | true | subagent splits the diff into logical commits | | async_threshold | 10 | ≥ N files → fork into a background subprocess | | subagent_model | agent model | model used to generate messages | | exclude_patterns | [] | glob patterns to skip |

Trigger modes

| Mode | Behaviour | | --- | --- | | on_goal (default) | commits when a pi-goal transitions to complete | | agent_sensible | commits after every agent turn | | after_tool | commits after each tool call | | manual | never auto-commits; /commit or commit_changes only |

Work-unit commit rules (prompt_rules_path)

Point prompt_rules_path at a markdown file (this repo ships commit-rules/work-unit-commits.md). Its content is appended to the grouping and single-message prompts — commit-by-work-unit, tests-with-code, scope-equals-work-unit, one-purpose-per-commit. When unset or unreadable, prompts are byte-identical to upstream pi-committer (bypass mode is unaffected).

Features

  • commit_mode switch — direct commit (bypass) or gentle-ai-gated commit (review).
  • Per-call mode override on commit_changes — pick the path per commit.
  • Commits automatically when a pi-goal completes (on_goal trigger, opt-in).
  • Splits diffs into separate commits via a subagent (feature + tests in one commit, docs in another).
  • Commit messages generated by a subagent using your model — pick it with /commit-model or subagent_model.
  • Detects and commits in any git repositories the agent touched.
  • commit_changes tool that agents can call to checkpoint work.
  • Exclusion patterns for files matching globs (*.log, build/, etc.).
  • Slash commands: /commit, /commit-config, /commit-model.

Usage

Enable auto-commit, then drive it by goal, command, or tool:

# .pi-committer.toml
[committer]
enabled = true

Auto-commit on goal completion

With trigger_mode = "on_goal" (default), the extension hooks into pi-goal's lifecycle and commits when a goal transitions to complete:

/goals "Add user authentication"   ← start a goal
> agent implements auth logic       ← work happens
> pi-goal marks the goal complete   ← gentle-committer auto-commits

Manual commit

/commit

Or ask the agent to "save my progress" — it calls commit_changes (pass {mode:"review"} if you want it gated).

Choose the commit-message model

/commit-model

Opens an interactive selector. Defaults to your current agent model.

Reload config

/commit-config

Staged commits

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. (In review mode this is forced to a single commit — one message file, one directive.)

Multi-repo

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 are detected on top of the primary working directory.

Deterministic commit message fallback

When the subagent is unavailable or returns nothing, gentle-committer generates a deterministic message using string analysis — no LLM call:

  • Smart scope — longest common ancestor directory across changed files; omitted if files span unrelated directories.
  • Specific description — meaningful keywords from file names (strips extensions, skips __init__/conftest, converts snake_case to words). Never "update N modules".
  • Contamination guard — isValidDiffContent / isValidDiffStat / isValidCommitMessage reject non-diff output so unrelated shell output can't leak into a message.

Every fallback decision logs a DIAG: diagnostic to help identify root causes.

Architecture

Extension events (turn_end, tool_result, goal_event)  +  commit_changes tool
            │
            ▼
      commitAllRepos(dir, ctx)
            │
            ├─ findDirtyRepos(ctx)          discover all dirty repos
            │
            └─ tryCommit(repo, ...)          for each dirty repo
                   │
                   ├─ stageAll / unstageExcluded / filterGitignored
                   │
                   ├─ resolveEffectiveCommitMode(pi, override?)   bypass | review (+R9 fallback)
                   │
                   ├─ buildGroupingPrompt / buildSingleMessagePrompt   (prompt-builders.ts)
                   │      └─ + loadCommitRules(prompt_rules_path)        append work-unit rules
                   │
                   ├─ generateStagedCommitGroups / generateCommitMessageViaSubagent
                   │      └─ createAgentSession    no tools, diff inline
                   │
                   └─ performCommit(mode, …)        (commit-emission.ts)
                          ├─ bypass → execSync("git commit -F -")   (byte-identical)
                          └─ review → write .git/gentle_committer_pending_msg + handoff directive

The commit-emission shim (commit-emission.ts) and prompt builders (prompt-builders.ts) are shared by both the main process and the async worker, with no circular imports (commit-emission uses only node builtins; prompt-builders takes a type-only CommitterConfig). The subagent uses createAgentSession from @earendil-works/pi-coding-agent — no pi-subagents dependency required.

Requirements

Install from source

git clone https://github.com/ChaoXu1997/gentle-committer.git
cd gentle-committer && npm install

# try it in a session without installing
pi -e ./index.ts

Development

cd gentle-committer
npm install

npm test            # unit + worker-edge tests
npm run test:all    # full suite
npm run test:e2e    # end-to-end (PI_COMMITTER_E2E=1)

Tests run via tsx (this node build's --experimental-strip-types is unreliable); the worker fork resolves tsx/jiti loaders automatically.

License

MIT