Agents write the code, people sign it. Models are disclosed in the PR body.
Coding agents add Co-authored-by: trailers to commits, putting their logos in your Contributors list. Post No Bills blocks that free advertising and requires a one-line model disclosure in the PR body instead. Credit your contributors; disclose your tools.
- Agent trailers. A
Co-authored-byline that names a coding agent. - Agent identities. A commit authored or committed by an agent's address.
- Hidden text. Invisible characters and look-alike letters.
- Model disclosure. The last line of the PR body names the job, the model and its effort, the tool and the host.
Details
- A trailer in a commit message or the PR body counts. Squash merging can carry it into the default branch.
- An agent's address, such as
noreply@anthropic.com, counts as author or committer. - Hidden text covers zero-width spaces, bidi controls, tag characters, private-use characters, and letters from another script that pass for Latin, in the title, body, commit messages, and added lines. Unusual spaces warn by default.
renovate[bot]anddependabot[bot]skip the disclosure check. Every other PR needs the line, including an empty body.
Add .github/workflows/post-no-bills.yml on your default branch:
name: Post No Bills
on:
pull_request_target:
types: [opened, synchronize, reopened, edited]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
post-no-bills:
runs-on: ubuntu-latest
steps:
- uses: stickerdaniel/post-no-bills@207fb1f8bd0b30d17bc0b43f19c811f8fd87c9a5 # v4.0.0Make post-no-bills a required check. Keep the release SHA pinned and give the job no if:: GitHub counts a skipped job as passing.
Add this to your AGENTS.md so agents get the disclosure and trailers right before CI runs:
End PR bodies with `<Job> with <model> (<effort>) in <tool> via <host>.`
Repeat `<job> with <model> (<effort>)` joined by `and` for each model that did a job.
Example: `Implemented with Claude Opus 5.5 (xhigh) and reviewed with GPT-6 Pro (max) in Claude Code via T3 Code.`
Effort is the run's reasoning setting, or `effort unknown` if nothing states it. Humans are `Human`. Ask for other unknown values.
Keep attribution in that line: before pushing, amend agent `Co-authored-by` trailers out of your commits.
Violations fail the check by default; unusual spaces warn. Severity inputs accept warn or off. model-attribution sets the required disclosure detail.
Inputs
| Input | Default | Effect |
|---|---|---|
model-attribution |
host |
off, effort, tool or host. |
co-author-trailers |
error |
error, warn or off for agent trailers in commit messages and the PR body. |
agent-identities |
error |
error, warn or off for commits authored or committed by an agent's address. |
hidden-unicode |
error |
error, warn or off for invisible and private-use characters. |
unicode-homoglyphs |
inherit |
inherit, error, warn or off for look-alike letters. inherit follows hidden-unicode. |
unicode-unusual-spaces |
inherit |
inherit, error, warn or off for unusual spaces. inherit warns unless hidden-unicode is off. |
unicode-exclude-paths |
empty | Paths whose added lines skip the hidden Unicode check. A trailing / marks a directory. |
allowed-identities |
empty | Addresses that are not agents, as email:<address> or github:<handle>. |
additional-identities |
empty | Addresses that are agents besides the built-in list, in the same form. |
additional-binary-extensions |
empty | Extensions that may be binary besides the built-in ones, lowercase without a dot. |
additional-attribution-exemptions |
empty | PR author logins exempt from the disclosure check. |
Lists take one entry per line:
with:
unicode-homoglyphs: warn
unicode-exclude-paths: |
tests/fixtures/unicode/
docs/ja.md
allowed-identities: |
github:Copilot
additional-binary-extensions: |
wasmSet inputs as literals in the workflow on the default branch, never from pull request content.
- An
email:selector matches that address, ignoring ASCII case. Agithub:selector matches the handle's noreply address, with or without its numeric ID. - An unknown input name, an invalid value, a repeated entry, or an address both lists can match fails the run.
Model attribution
host is the default: every job with its model and the model's effort, the tool and the host. effort is the minimum: every model needs an effort; write effort unknown when nothing states it. Human needs no effort. off turns the check off. A line that passes a stricter level also passes the ones below it.
| Last line of the PR body | effort |
tool |
host |
|---|---|---|---|
Implemented with Claude Opus 5.5 (xhigh). |
✓ | ✗ | ✗ |
Implemented with Claude Opus 5.5 (xhigh) in Claude Code. |
✓ | ✓ | ✗ |
Implemented with Claude Opus 5.5 (xhigh) in Claude Code via T3 Code. |
✓ | ✓ | ✓ |
Implemented with Claude Opus 5.5 (xhigh) and reviewed with GPT-6 Pro (max) in Claude Code via T3 Code. |
✓ | ✓ | ✓ |
Planned and implemented with Claude Opus 5.5 (max) in Claude Code via T3 Code. |
✓ | ✓ | ✓ |
Implemented with Claude Opus 5.5 (effort unknown) in Claude Code via T3 Code. |
✓ | ✓ | ✓ |
Implemented with Claude Opus 5.5 (xhigh) and reviewed with Human in Claude Code via T3 Code. |
✓ | ✓ | ✓ |
Implemented with Claude Opus 5.5 (xhigh) and reviewed with GPT-6 Pro in Claude Code via T3 Code. |
✗ | ✗ | ✗ |
Implemented with Claude Opus 5.5. |
✗ | ✗ | ✗ |
Verified with 35 focused tests. Static checks pass. |
✗ | ✗ | ✗ |
Implemented with Claude Opus 5.5 (xhigh) and GPT-6 Pro (max) in Claude Code. |
✗ | ✗ | ✗ |
Generated with Claude Opus 5.5 for implementation in Claude Code via T3 Code. |
✗ | ✗ | ✗ |
How it works
The workflow and the pinned action come from the default branch. The action fetches the PR and reads its commits, diff, title, and body as data, without checking out or running anything from the pull request. If a check cannot complete, the run fails.
A Linux or macOS runner needs Python 3.10+ and git 2.31+ on PATH. GitHub-hosted Ubuntu runners have both. Windows is not supported.
MIT. post_no_bills/hidden.py comes from no-ai-marks; see THIRD_PARTY_NOTICES.md.