gac's badges, author field, and project URLs all point at a different account
Intelligent LLM-powered git commit message generator that understands your code! Supports multiple languages!
At a glance
- What is it?
- A commit message generator that runs as a one-shot command through uvx, talks to more than thirty model providers, keeps local usage statistics, and scans for secrets before it commits. The package is mature; the repository's self-links are not.
- Who is it for?
- gac is worth trying if you write conventional commits and want a message that explains why rather than what, because the filtering, grouping, secret scan, and human confirmation step are all present and all optional. Three things to check before you rely on it.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 22 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 12, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The badges, the author field, and the URLs point at another account
The repository you are reading belongs to one account. Almost everything inside it that says where the project lives belongs to another.
The continuous integration badge, the code coverage badge, the contributing guide link, the author field in the package metadata, the homepage, the documentation URL, and the repository URL in that same metadata all name a different account. The badge row at the top of the readme is where you notice first, because two of the badges render from the other account's project.
So there are two identities in play. The account that owns this clone, and the account that the project's own metadata says is canonical. Neither is wrong in an obvious way: this is the shape a fork leaves behind, and it may be that one is the upstream and one is a maintained fork, or that a rename happened and only part of the metadata was updated.
What matters practically is that a bug report filed by clicking a badge lands somewhere other than where you read the code, and that the package published to the index declares an author who is not the account you cloned from.
If you are evaluating this as a dependency, the package on the index is what you get. If you want to report a problem against the source, use the repository you actually cloned.
Thirty two providers listed against a claim of thirty five
The provider section is a heading with a number and a list underneath, and the two do not agree.
The heading claims more than thirty five. Counting the bullets gives thirty three, and one of those is not a provider at all but a slot for pointing the tool at an endpoint you run yourself, in either of the two supported wire formats. So the number of named services is thirty two.
The list is broader than most of its rivals in a specific way: a substantial minority of the entries are local or self-hosted rather than hosted APIs. A desktop runtime, an open-source inference server, and a generic custom endpoint are all first-class options alongside the hosted vendors.
Three of the entries authenticate through OAuth rather than an API key, which is a different setup path: the user signs in with the same account they already have for that service instead of pasting a credential. Two more are labelled as coding plans rather than pay-as-you-go API access.
Given that setup is interactive and asks for a provider, a model, and a language on first run, the practical cost of a long provider list is setup time rather than maintenance. The number in the heading is the only thing that is wrong.
Version bumping is manual because a release tool does not support the newest Python
The package metadata advertises support for five Python versions, from 3.10 up through 3.14, and classifies the implementation for both the reference interpreter and an alternative one.
The development dependency list tells you what that costs. The automated version bump tool is present in the list and commented out, with a note that it has compatibility problems on 3.14 and that manual bumping is the workaround for now.
So the version number is not derived from a tag by a release tool. It is declared as dynamic in the metadata, which means the build backend expects it to come from somewhere other than the static table, and in practice a person is editing it.
Two other lines in that dependency list hint at the same pressure. The HTTP layer is pinned with an explicit note that one of its two packages is required for Python 3.14 compatibility, which is a workaround rather than a preference. And the dependency table has a couple of blank lines where entries were removed, which is what a trimmed list looks like when it was edited rather than regenerated.
None of this makes the tool unreliable. It does mean the release cadence is one person's typing, which is worth knowing before you build automation on top of the version.
Two hook systems and a lint target that reaches the network
Git integration is handled at two levels, and the repository carries the configuration for both.
There is a hook runner configuration at the root and a separate hooks directory, and the tool advertises that it respects hooks from other tools as well, running them before it does anything expensive. That ordering is the point: the hook is cheap and deterministic, so it runs first and can abort before a model call is ever made.
The lint target is more interesting. It runs four tools, of which two are fetched on demand through a JavaScript package runner pinned to a specific major version, and a third is another fetched tool with its own configuration file. Only the Python linter and formatter are local dependencies.
So `make lint` on a machine with no network attempts to download two tools before it can check anything. On a locked-down build host that fails, and it fails before it reports a single real finding.
The markdown linter is configured with two rule sets disabled, one for line length and one for inline HTML, which is a concession to how this particular readme is written rather than a general preference. The formatter applies to markdown, YAML, and JSON as well as to Python, so a documentation-only change can fail a lint run.
Statistics are opt-in, local, and disabled by several spellings of true
The usage statistics feature is the most carefully scoped thing in the readme, and the scoping is stated in five separate places.
It is asked about during setup rather than enabled silently. It stores everything in a single file in the home directory. What it stores is enumerated: counts, dates, project names, and model names. What it does not store is enumerated too: no commit messages, no code, no personal data. And there is no telemetry, which is stated outright.
The opt-out accepts more than one spelling. A dedicated variable set to true, or to a numeric one, or to a word for yes, or a word for on, disables it. Setting the same variable to a false spelling, or removing it entirely, leaves statistics enabled.
That last part is the one to note. There is no separate way to express no, so the only way to be certain statistics are off is to set the variable to a truthy value rather than to unset it.
What you get for opting in is a command with five subcommands: an overview with totals, streaks, and peaks, a per-model breakdown with token and latency figures, a per-project breakdown across all repositories, a recent history you can extend with a count flag, and a reset that confirms before it runs, with a variant that resets one model's numbers only.
The subcommands are worth reading as a small reporting surface rather than a statistics tool. A streak and a peak are vanity metrics; the per-model and per-project breakdowns are the ones that answer a real question, which is where your tokens are going and which repository is costing you the most.
uvx gac stats models
uvx gac stats projectsThe secret scan and the hook both run before the model call
Three filtering behaviours stack, and the ordering is the design.
The first is content filtering. The tool is described as prioritising meaningful changes while ignoring generated files, dependencies, and artefacts, which is the difference between a message about your logic and a message about a lockfile.
The second is a secret scan. Before committing, it looks for API keys, passwords, and tokens, and when it finds something potentially sensitive it stops and offers remediation options rather than committing and warning afterwards.
The third is hook integration. Hooks from the repository's own tooling and from a hook runner are respected and executed before the expensive step.
The false-positive handling on the secret scan is worth one sentence. It ignores example files, template files, and placeholder text, which are exactly the places where a key-shaped string appears without being a key.
That combination is the strongest argument for the tool. A generator that reads your diff and hands it to a model is a path by which secrets reach a provider, and scanning before the call rather than after the commit closes the obvious version of that problem.
The remaining exposure is the one no local scan can close, which is whatever the diff legitimately contains that is not a key.
Seventeen translated system prompts and no Thai, Hebrew, or Arabic file
The readme advertises output in more than twenty five languages with full support for non-Latin scripts including CJK, Cyrillic, and Thai, and the language bar at the top links sixteen readme translations.
The system prompt examples tell a different story. There are seventeen files, one base example and sixteen translations, and the set is the sixteen readme languages. There is no Arabic file, no Hebrew file, and no Thai file, despite Thai being named in the script-support claim.
So the script coverage claim and the translated-prompt coverage do not line up. A language can be a supported output target without having its own system prompt, which is a defensible design if the prompt is mostly instruction rather than prose, but the readme does not say that is what is happening.
The translation behaviour itself is a nice touch and worth knowing about. Conventional commit prefixes can stay in English while the body is translated, or everything can be translated including the prefixes. That matters because tooling on the other end of your history parses those prefixes.
The prompt examples are the artefact to watch, since they are what a contributor improving a non-English commit style would edit.
Editorial conclusion
gac is worth trying if you write conventional commits and want a message that explains why rather than what, because the filtering, grouping, secret scan, and human confirmation step are all present and all optional. Three things to check before you rely on it. Every self-link in the readme, the author field, and the package metadata point at a different account than the repository you are reading, so file issues against the one you cloned rather than the one a badge suggests. Version bumping is manual because the automatic tool does not support the Python version the classifiers advertise, which means there is no changelog generated from tags for you to trust. And the lint target fetches two of its four tools over the network on every run, so it fails on a machine that is offline even when the code is fine. Statistics are local and opt-in, and the opt-out accepts several truthy spellings worth knowing.
Frequently asked questions
What does gac do?
It generates a commit message from your staged changes using a language model and then commits. The quick start is two commands: one to configure a provider, model, and language, and one to generate and commit. You review the message and confirm with a single key before anything is written.
Which model providers does gac support?
The readme heading claims more than thirty five. The list underneath names thirty two services, including several local and self-hosted options such as a desktop runtime, an open-source inference server, and a generic custom endpoint in either wire format. Three of the entries authenticate through OAuth rather than an API key.
Does gac send my code to a model provider?
Yes, and the readme says so plainly. It mitigates the obvious exposure rather than eliminating it: it filters out generated files, dependencies, and artefacts, and it scans for API keys, passwords, and tokens before the model call, stopping to offer remediation options when it finds something.
What usage statistics does gac collect?
Counts, dates, project names, and model names, stored in a single file in your home directory. It states that commit messages, code, and personal data are not stored and that there is no telemetry. It is opt-in during setup and can be turned off with a dedicated variable set to a truthy value.
How do I choose a commit message format with gac?
Four formats are documented: a single line, a standard summary with bullet points which is the default, a verbose version covering motivation, approach, and impact, and a flag that enforces the classic fifty and seventy-two character rule. A separate flag adds a signoff line for projects that require it.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/thomwebb-gac)