CI-first authorship policy tooling for keeping AI co-authors out of git history.
Gommage keeps AI assistants out of your git authorship metadata. It checks commit messages and commit authors for AI co-author trailers, generated-with badges, blocked patterns, blocked email domains, and commits authored by known bot identities. It also cleans the same attribution out of pull request titles and bodies, where agent tools leave a permanent public footer.
It is meant to fit into the workflow you already use: local checks, commit hooks, CI, GitHub Actions, shell-only environments, history cleanup, and pull request hygiene.
Use the CLI package when you want local checks, hooks, or history cleanup:
pnpm add -D @gommage/cli
Then run it through your package manager or installed binary:
gommage check
Gommage discovers .gommage.yml by walking up from the current directory. You can also pass an explicit config path with --config or the GitHub Action config-path input.
version: 1
rules:
no-ai-coauthor: true
max-authors: 1
allow-human-coauthors: false
blocked-patterns:
- "Generated with"
- "🤖"
blocked-domains:
- "bot.example.com"
allowed-patterns: []
scope:
range: "origin/main..HEAD"
Defaults are conservative about human collaborators:
allow-human-coauthors: false.max-authors is set.Check the configured range:
gommage check
Check a specific range before opening a pull request:
gommage check origin/main..HEAD
Check several ranges in one run:
gommage check "origin/main..HEAD" "origin/bartering..HEAD"
Get machine-readable output for scripts:
gommage check HEAD~10..HEAD --output json
Install Gommage as a commit-msg hook:
gommage install
The hook validates the commit message file and fails the commit if an AI trailer or blocked marker is present. Use this when you want fast local feedback before CI.
Agent tools also write a generated-with footer into pull request bodies, which is public and permanent. Check it, then strip it through the GitHub CLI:
gommage pr check --pr 106
gommage pr fix --pr 106 --dry-run
gommage pr fix --pr 106
pr check exits non-zero on a violation, so it works as a merge gate.
Cleaning must happen before the merge. GitHub keeps a merged pull request’s commits reachable at refs/pull/<number>/head permanently, so a rewrite afterwards leaves the original commit pages live. --commits does the whole scrub in one run:
gommage pr fix --pr 106 --commits --gpg-sign \
--author-name "Jane Human" --author-email jane@example.com
Restrict the repository so attribution cannot reach the default branch:
gommage protect --dry-run
gommage protect
That leaves squash as the only merge method and blanks the default squash body, so neither a rebase merge nor the repository’s commit-message setting can copy AI trailers into the merged commit.
Preview a cleanup before rewriting anything:
gommage fix --repo . --dry-run
Dry-run output shows the exact old author, new author, old message, and new message for every commit that would change. If the preview is correct, rerun without --dry-run:
gommage fix --repo .
You can restrict the rewrite and set the replacement identity explicitly:
gommage fix --repo . --range HEAD~10..HEAD --author-name "Jane Human" --author-email jane@example.com
Rewritten commits are committed by the replacement identity, the same way git rebase and git commit --amend behave. Sign them when the repository requires verified commits:
gommage fix --repo . --gpg-sign
gommage fix --repo . --gpg-sign --gpg-key 0123456789ABCDEF
History rewrites are destructive by nature. Review the dry run first, coordinate with collaborators, and push rewritten history only when everyone expects it.
Run Gommage on pull requests:
name: gommage
on:
pull_request:
jobs:
authorship:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
- uses: gommage/gommage-action@v1
with:
range: origin/${{ github.base_ref }}..HEAD
The action accepts cwd, config-path, range, and message-file. The range input takes one revision, or several separated by newlines or commas. It outputs violations, commits-checked, and config-path.
Use the GitHub App package when you want organization-wide PR checks without adding a workflow file to every repository. The package gives your app the policy evaluation and check-run output helpers; your app stays responsible for receiving webhooks, loading repository config, and creating the GitHub check run.
import { buildCheckRunOutput, evaluatePullRequestCommits } from "@gommage/github-app";
const evaluation = evaluatePullRequestCommits([
{
sha: "abc1234",
message: "feat: add policy",
authorName: "Jane Human",
authorEmail: "jane@example.com",
},
]);
const output = buildCheckRunOutput(evaluation);
Use this surface when you want one installed GitHub App to enforce the same authorship policy across many repositories, while still allowing each repository to keep its own .gommage.yml.
For minimal CI images or repositories that do not use Node, install or vendor the shell checker as gommage.sh and run it directly:
gommage.sh check origin/main..HEAD
The shell checker catches common AI co-author trailers and generated-with badges. Use the CLI when you need the full .gommage.yml policy engine.
gommage install once and let the commit hook catch accidental AI trailers.gommage check origin/main..HEAD before merging contributor branches.gommage fix --dry-run to review an exact rewrite plan before changing history.The full documentation website lives in website.
This section is for people changing Gommage itself. End users should not need these commands.
Install dependencies:
pnpm install
Use moon for repository tasks:
moon run :build
moon run :test
moon run :lint
moon run :typecheck
moon run :format-check
Run the docs site locally:
moon run website:dev
Before pushing changes, run the same verification used for review:
moon run :build :test :lint :typecheck :format-check
moon run release:status
Contributor notes:
moon commands over package scripts or direct binaries.pnpm install only for dependency installation and lockfile updates.dist, VitePress build output, and moon cache should stay out of source control.