github-agent is a Python command-line steward for GitHub repositories and their wikis: it scores the README, CHANGELOG and community contracts, lints documents, links, anchors and tables, scans for leaked secrets, renders the banner and social preview, and keeps the wiki in the repository — one command per job.
Read this in: English · Deutsch · 中文 · हिन्दी · Español · Русский
The animation is produced by tools/make_demo.py from the real output of three commands; it
cannot show anything the tool did not print.
Installation · Usage · Why this exists · How it compares · Docs site · Wiki · AGENTS.md · Packaging · Changelog · Issues · Security · Русская версия
A repository rarely fails on code; it fails on documentation. The README has no installation
section, the changelog has no dates, the wiki is three pages without navigation, the banner is
a broken image, the description is one word. git push succeeds, so the defect lives for years.
This pack puts a verifiable contract on each of those places and reduces the work to one command. It does not write marketing copy and does not invent numbers: it checks what a human wrote and refuses to publish what is broken.
Documentation status. Every number in this README was measured on 2026-11-01 against version 1.3.0 with the commands named in the table. Long guides live in the Wiki and
docs/; the protocol for agents isAGENTS.md, the packaging and migration notes aredocs/PACKAGING.mdandMIGRATION.md.
For agents. Start with
AGENTS.md: where the pack lives, how to prove the installation is intact, and the single command that replaces each multi-file investigation.
- Why this exists
- Installation
- Usage
- What the pack does
- How it compares
- In numbers
- Checks that run
- Images
- Import into another agent
- Wiki as documentation
- Languages of the documentation
- How it is built
- Limitations
- Development
- Contributing
- License
GitHub renders whatever you commit. It does not tell you that the installation section is
missing, that the changelog has no dates, that the wiki has no navigation, that the banner is a
broken image or that the description is one word. git push succeeds either way, and the defect
survives for years because nobody is looking at the repository as a product.
Three ideas decide how the pack behaves:
- A check you cannot run is not a check. Every rule is one command with an exit code:
0clean,1findings at error level,2usage or environment problem. A rule that examined zero objects reportscoverage.skipped— a green check over an empty set is a defect. - A false
PASSis worse than a falseFAIL. The tool would rather stop a correct pull request than wave a broken one through. Where that costs a real repository time, the rule is narrowed until both answers are right — see Field notes. - Numbers over adjectives. The README, the changelog and the metadata are checked against what the repository can prove. Nothing here writes marketing copy.
Python 3.11 or newer is required; CI runs the suite on 3.11 and 3.13. There are no runtime
dependencies. Four install paths exist, and they are not interchangeable: the package managers
install the CLI, while the clone is what ghagent install --profile ... --write needs because
the wheel ships only the CLI.
uv tool install github-agent-cli # uv, isolated tool environment
pipx install github-agent-cli # pipx, isolated virtual environment
pip install github-agent-cli # pip into the active environment
brew install paulmann/homebrew-github-agent-cli/github-agent-cli # macOS and Linux
scoop bucket add github-agent-cli https://github.com/paulmann/scoop-github-agent-cli
scoop install github-agent-cli # Windows
ghagent --versionPublished on PyPI.
github-agent-cli1.3.0 has been available since 2026-11-01: https://pypi.org/project/github-agent-cli/. The wheel ships the CLI only; the pack (skills, tests, reference, wiki sources) comes from the clone below.
The console script is ghagent; the distribution name is github-agent.
assets render always writes the SVG. PNG output needs Pillow, which is an optional extra:
pip install "github-agent-cli[png]"
uv tool install --with pillow github-agent-cliWithout Pillow the command says why no PNG exists instead of pretending a social preview is ready.
The clone is the second install path and the only one that carries tests/, skills/,
reference/, wiki/ and the templates, so it is also the one that install, verify-install,
snippet and uninstall need. An editable install adds the ghagent command to the checkout:
git clone https://github.com/paulmann/github-agent.git
cd github-agent
pip install -e .
python tools/ghagent.py selftestThe repository ships a Dockerfile; build it locally and mount the repository under test at
/repo, which is the image working directory:
docker build -t ghagent .
docker run --rm -v "$PWD:/repo" ghagent audit .On Windows PowerShell the same mount is -v "${PWD}:/repo". The entry point is ghagent, so
the first argument after the image name is the command. No registry image is published as part
of 1.3.0 and CI does not build the container: the tag is a local convention. See
examples/docker.md.
The composite action installs the pack from its own checkout, so it does not depend on a PyPI release and works as soon as the tag exists:
- uses: actions/checkout@v7
- uses: paulmann/github-agent@v1.3.0 # pin the release tag
with:
command: audit .
min-score: "80"| Input | Default | Purpose |
|---|---|---|
command |
audit . --min-score 80 |
any ghagent command, without the program name |
min-score |
80 |
score threshold, applied only when command starts with audit and passes no flag |
working-directory |
. |
repository directory the command runs in, relative to $GITHUB_WORKSPACE |
python-version |
3.13 |
interpreter installed by actions/setup-python |
github-token |
${{ github.token }} |
exported as GITHUB_TOKEN for metadata commands |
For a non-audit command the action runs exactly the given argument string, for example
command: doc --root .. There are no outputs: the step exit code is the result (0 clean,
1 findings, 2 usage or environment problem). A complete workflow, including a second job
that runs doc and a Docker alternative, is in examples/ci-usage.md.
The repository is also a pre-commit hook source; the hooks are ghagent-doc,
ghagent-audit, ghagent-privacy and ghagent-changelog:
repos:
- repo: https://github.com/paulmann/github-agent
rev: v1.3.0 # placeholder: pin the release tag you decide to trust
hooks:
- id: ghagent-doc
- id: ghagent-audit
- id: ghagent-privacy
- id: ghagent-changelogInstall the hooks into the consuming repository with pre-commit install. The full consumer
file is examples/pre-commit-config.yaml; the hook
definitions are in .pre-commit-hooks.yaml. The hooks need a released
tag, because pre-commit builds the tool from the tagged tree.
After any install, one command answers whether the CLI is the released build:
ghagent --version # prints the version, for example github-agent 1.3.0
ghagent audit . # 0 clean, 1 findings at error level, 2 usage or environment problemIn a clone the full self-test suite runs; the wheel ships the CLI only, so ghagent selftest
there exits 2 with a message that points at the clone rather than reporting a false PASS:
git clone https://github.com/paulmann/github-agent.git
cd github-agent
python tools/ghagent.py selftest # 194/194 checks passedghagent audit . # score repository hygiene, exit 1 on errors
ghagent doc --root . # markdown, links, anchors, tables, table of contents
ghagent privacy --root . # tokens, private keys, machine paths, personal addresses
ghagent assets render --write # banner and social preview from the repository metadata
ghagent assets check # format, dimensions, alt text, referenced files
ghagent wiki build # rewrite links for the wiki namespace
ghagent wiki verify # every internal link resolves
ghagent changelog check # Keep a Changelog and SemVer
ghagent changelog release 1.3.0 --write
ghagent meta suggest # description and topicsEvery check command accepts --json; findings print as file:line with a rule id, so a caller
does not need to parse prose. selftest runs the suite, and report writes the combined markdown
file, so neither needs the machine format.
| Exit code | Meaning |
|---|---|
0 |
no findings at error level |
1 |
findings at error level, each printed with file:line |
2 |
usage or environment problem: wrong path, missing file, missing gh or token |
Example audit output, from a deliberately failing repository and not from this tree:
[ERROR] repo.contributing CONTRIBUTING.md is absent hint: add CONTRIBUTING.md
[WARN ] readme.badges only 1 badge(s) hint: 3-8 badges: CI, release, license, runtime
[ERROR] changelog.date-missing version 1.1.0 has no ISO date CHANGELOG.md:14
score: 72.5% (22 scored, 1 skipped)
| Job | One command |
|---|---|
| Score a repository | ghagent audit . |
| Lint documents, links and anchors | ghagent doc --root . |
| Find secrets and machine paths | ghagent privacy --root . |
| Render the banner and social preview | ghagent assets render --write |
| Build, verify and publish the wiki | ghagent wiki build, verify, publish --push |
| Release a version | ghagent changelog release 1.3.0 --write |
| Fix description and topics | ghagent meta apply --repo owner/name --write |
| Install the skill into another agent | ghagent install --profile harness --write |
The CLI has 13 commands; the table names the ones used every day. The rest (report,
snippet, verify-install, uninstall, selftest, assets suggest, changelog suggest,
changelog notes, meta suggest, wiki init, wiki publish) carry their flags in
ghagent --help; the recurring jobs are mapped in AGENTS.md.
The pack does not replace the tools below and does not compete with them on their ground: it orchestrates the documentation surface of a repository and calls the same ideas from one place, with one exit code.
| Tool | Strong at | Where this pack differs |
|---|---|---|
markdownlint |
markdown style, one rule id per finding | ghagent doc adds links, anchors, TOC, tables, privacy and the CHANGELOG contract; it also checks documents that are not markdown |
vale / textlint |
prose style with a dictionary you maintain | the pack checks structure a machine can prove and does not judge wording; only the README summary is checked for superlatives |
action-gh-release |
creating a release from a tag | changelog notes <version> produces the body from the CHANGELOG, and changelog check refuses a release without a dated section |
pre-commit hooks |
running linters before a commit | the pack ships hooks for its own commands; the hooks are the delivery, not the check |
release-please |
version bumps from conventional commits | the CHANGELOG stays hand-written and machine-verified; changelog suggest drafts entries but a human writes them |
| GitHub community health files | a checklist in the UI | audit scores the same files from the tree and from the remote, so a missing SECURITY.md is a number, not a badge nobody opens |
Measured in this tree on 2026-11-01 against version 1.3.0:
| Surface | Value | Measurement source |
|---|---|---|
| Self-tests | 194 | python tests/run_tests.py |
| CLI commands | 13 | ghagent --help |
| Library modules | 11 | tools/ghalib/*.py |
| Document rules examined on this tree | 17 | ghagent doc --json, field rules_examined |
| Runtime dependencies | 0 | pyproject.toml, dependencies = [] |
| Platform traps recorded | 15 | the traps table in docs/RULES.md |
| Python lines | 4412 | wc -l tools/ghagent.py tools/ghalib/*.py |
| Group | Rules |
|---|---|
| Text | UTF-8 without BOM, LF instead of CRLF, final newline, no tab indentation |
| Structure | one H1, no skipped heading levels, closed code fences, language on every fence |
| Tables | the cell count of every row matches the header and the separator |
| Links | the relative file exists, the anchor exists (including Cyrillic) |
| Table of contents | every entry resolves, no H2 is forgotten |
| Markup | the five alert types, alt text on images, no images over http:// |
| Privacy | tokens, private keys, absolute machine paths, personal addresses |
| Images | banner referenced, preview is PNG/JPG/GIF, under 1 MB, at least 640×320 |
| Wiki | manifest and files agree, Home/_Sidebar/_Footer present, no .md links, no relative images |
| CHANGELOG | SemVer and ISO date per version, newest first, known types, no empty version, comparison links |
| Agents file | the canonical root AGENTS.md stays a map: above 120 lines is a warning and detail belongs in docs/ |
| Metadata | description under 200 characters without a wasted prefix, 8–20 lowercase-hyphenated topics |
A rule that examined zero objects is not passed: it is reported as coverage.skipped, and an
empty tree is doc.no-text-files.
The banner at the top of this file is generated by the pack itself:
ghagent assets render --title "github-agent" \
--tagline "Repository and wiki steward for AI agents: one command per job." \
--command "ghagent audit ." --chips "python,github,wiki,lint" --writeassets/social-preview.png— 1280×640, under 1 MB, ready for Settings → Social preview.assets/social-preview.svg— vector twin for the README, no dependency needed.assets checkverifies format, byte size, dimensions, alt text and that every referenced file exists. The repository copy is not the social preview automatically: that upload is a manual step, and the check prints the reminder.
| Agent | Skill root | What to do |
|---|---|---|
| AutoClaw2 | %USERPROFILE%\.pi\agent\skills |
install --profile autoclaw --write, then paste the snippet block into its AGENTS.md |
| HARNESS | %USERPROFILE%\.dsh\skills |
install --profile harness --write, same block |
| SagaAI | any directory | install --target <dir> --write and the block from snippet --target <dir> |
The snippet block names the pack path, the verification command and one rule: one job, one
command. After import the agent must run verify-install and get 0; anything else means the
installed copy is not the tested one. Import is the workflow that needs the clone rather than the
wheel, because the wheel ships only the CLI. Details: docs/IMPORT.md.
The wiki is maintained from the repository: pages live in wiki/, order is set by
wiki/wiki.json. wiki build rewrites links for the wiki namespace — internal links lose
.md, links into the repository tree become absolute, and a relative image is an error because
the wiki repository cannot see the project tree.
Built and verified with the pack's own commands. Publication needs one action in the GitHub
interface: <repo>.wiki.git does not exist until a first page is saved, and git push cannot
create it — wiki publish then returns wiki.remote-missing with that step. The full workflow
is in docs/WIKI.md.
English files are canonical; Russian translations carry the .ru.md suffix, the convention
GitHub itself uses (README.ru.md, AGENTS.ru.md, wiki/01-Why.ru.md).
Translations are updated in the same commit as the original. A translation that silently lags is
a documentation defect, and the wiki carries both sets: English pages as canonical, Russian as
*.ru.md pages in their own navigation group.
flowchart LR
R["Repository<br/>README, CHANGELOG, docs"] --> A["audit"]
R --> D["doc"]
R --> I["assets"]
W["wiki/ + wiki.json"] --> B["wiki build"]
B --> V["wiki verify"]
V --> P["wiki publish --push"]
A --> O["report, --json"]
D --> O
I --> O
| Component | Responsibility |
|---|---|
tools/ghagent.py |
argument parsing, exit codes, report assembly |
tools/ghalib/mdcheck.py |
markdown, links, anchors, privacy |
tools/ghalib/audit.py |
required files, README and changelog contracts, score |
tools/ghalib/assets.py |
banner and social preview: render, check, suggest |
tools/ghalib/wiki.py |
manifest, link rewriting, sidebar and footer, publication |
tools/ghalib/changelog.py |
Keep a Changelog 2.0.0, release, draft from commits |
tools/ghalib/meta.py |
description, topics, homepage |
tools/ghalib/install.py |
skill installation, sha256 manifest, drift, removal |
tools/ghalib/report.py |
findings, severities, markdown and --json output |
tools/ghalib/config.py, tools/ghalib/util.py |
.ghagent.json, paths, text I/O, anchors |
tests/run_tests.py |
194 self-tests with fixtures and decoys |
Anchors follow GitHub's rules: lowercase, punctuation dropped, spaces to hyphens, a repeated
heading gets -1. The rule was verified against a live table of contents: an em dash in a
heading produces a double hyphen. Architecture notes: docs/ARCHITECTURE.md.
audit --repoandmetaneedghorGITHUB_TOKEN. Without them the command returns an error instead of an empty success.- External links are not fetched: relative paths, anchors and structure are checked. A network crawl is a separate decision, not a side effect of a linter.
- Wiki pages are barely discoverable through search engines: per GitHub documentation, only wikis with 500+ stars and public editing disabled are indexed. Use GitHub Pages for discovery.
changelog suggestis a draft. It does not know what matters to a user.- PNG rendering needs Pillow. Without it the SVG is produced and the check says why no PNG exists, instead of pretending a social preview is ready.
python tools/ghagent.py selftest
python tests/run_tests.py
python tools/ghagent.py doc --root .
python tools/ghagent.py audit .
python tools/ghagent.py assets checkA new rule arrives with a fixture that fails without it and a decoy that must stay quiet. A rule without a fixture is removed: a check that cannot be proven is worse than no check. Packaging and the wheel layout are described in docs/PACKAGING.md; the 1.1.0 → 1.2.0 changes are in MIGRATION.md.
Before a pull request: python tests/run_tests.py and python tools/ghagent.py doc --root .
must be green. One change, one reason. Rules: CONTRIBUTING.md, security
policy: SECURITY.md.
MIT.

