GitHub Account Maintainer is a local command-line tool for inspecting the GitHub repositories your account can access. It is being built to compare those repositories with an explicit policy and report what is correct, missing, unsupported, or inaccessible.
The current version is deliberately read-only. It can verify GitHub identities, inventory and classify repositories, redact private repository identities, bind classifications to layered policy, audit metadata, community files, repository settings, and security features, aggregate an account audit, and retain sanitized local finding history. It cannot change GitHub.
- Current status
- What the tool does
- What the tool does not do
- Safety and privacy
- Prerequisites
- Quick start for Windows
- Create a GitHub token
- Store the token securely
- Create the configuration
- Verify authentication
- Inventory repositories
- Audit repositories
- Review audit history
- Run the Release 0.1 pilot
- Command reference
- Repository check foundation
- Classification and policy binding
- Configuration guide
- Policy resolution
- Reports and exit codes
- Troubleshooting
- Development
- Project documents
- Release roadmap
The package version is 0.1.0.dev0. Release 0.1 is still under development.
| Capability | Status | Notes |
|---|---|---|
| Create local configuration | Implemented | Uses strict validation and refuses accidental overwrite. |
| Verify authenticated identity | Implemented | Calls the read-only GET /user endpoint. |
| Inventory accessible repositories | Implemented | Calls paginated GET /user/repos requests. |
| Redact private repository identities | Implemented | Enabled by the default minimal report detail. |
| Classify repositories and bind policy | Implemented | The account audit records confidence and binds repository-class, project-type, and repository policy. |
| Resolve layered policy | Implemented | The account audit resolves and hashes policy separately for each in-scope repository. |
| Audit repository policy | Implemented | The public audit command runs 26 deterministic metadata, community, settings, and security checks per in-scope repository. |
| Track audit history | Implemented | A versioned local SQLite database tracks new, persistent, resolved, and regressed findings without storing repository names or report evidence. |
| Apply GitHub changes | Not implemented | No GitHub mutation endpoint exists. |
| Full Release 0.1 audit | Pilot passed | Two expanded 26-check read-only runs matched across 73 repositories with zero writes on 2026-08-10. |
This status matters. A successful inventory does not mean the account passed a full security or compliance audit.
The implemented code can:
- Create a local YAML configuration with safe defaults.
- Load credentials from Windows Credential Manager through Python
keyring. - Load a credential from an explicitly named environment variable when requested.
- Confirm that the token belongs to the configured GitHub login.
- Inventory repositories visible within the configured affiliation and visibility scope.
- Follow GitHub pagination until no next page remains.
- Deduplicate repositories by GitHub repository ID.
- Record repository visibility, archive state, fork state, and effective permissions.
- Mark successful, partial, and failed coverage explicitly.
- Redact private and internal repository names and URLs by default.
- Produce JSON or Markdown output.
- Resolve policy in a deterministic order.
- Record where every resolved policy value came from.
- Create a canonical SHA-256 hash for the effective policy.
- Validate active, expired, pending, and permanent policy exceptions.
- Classify visibility, activity, repository kind, ownership, project type, repository class, and maintenance tier from validated evidence.
- Record per-dimension confidence and privacy-safe evidence, plus terminal classification coverage and a stable classification hash.
- Bind the classified repository class and project type to the existing policy hierarchy before repository checks run.
- Evaluate repository description, homepage, topic count, primary language, visibility, and archive state.
- Detect eight common community files through GitHub's community-profile and contents metadata endpoints without cloning or reading file content.
- Audit default-branch protection, active rules, required reviews, required status checks, Actions policy, and default workflow token permissions.
- Audit Dependabot alerts and security updates, secret scanning, push protection, code scanning, and private vulnerability reporting.
- Distinguish supported, inaccessible, not-applicable, unverified, unsupported, and unavailable-by-plan settings evidence without treating missing evidence as compliance.
- Distinguish compliant, noncompliant, observed, unknown, and inaccessible outcomes with a terminal coverage state for every check.
- Produce privacy-safe repository findings with stable check IDs, exact current and desired states, evidence, severity, and remediation class.
- Run the complete account audit from one CLI command and continue across repository-specific failures.
- Apply include and exclude patterns before requesting repository audit endpoints.
- Aggregate schema-versioned JSON or Markdown bindings, results, findings, severity counts, accepted permissions, and coverage.
- Record sanitized audit runs and finding transitions in a versioned local SQLite database.
- Report recent audit history as count-only JSON or Markdown without exposing account or repository names.
- Exit with code
0,1, or2based on complete coverage and the configured finding threshold.
The current version does not:
- Change repository settings.
- Create, edit, close, approve, or merge pull requests.
- Create or delete repositories, branches, tags, releases, issues, or files.
- Enable or disable GitHub security features.
- Dismiss security alerts.
- Clone repository content during inventory.
- Infer flagship or exempt maintenance tiers without explicit future override rules.
- Schedule unattended runs.
- Create backups.
- Use browser automation.
The configuration contains sections for planned features. The presence of a setting does not mean that feature is active.
The project uses these boundaries:
- The GitHub API client exposes only GET operations.
- Requests are serial rather than concurrent.
- The API version is pinned to
2026-03-10. - Pagination and redirects must remain on the configured GitHub API origin.
- The automatic-write allowlist is empty.
- Automatic merge and destructive operations are prohibited by the schema.
- Policy layers cannot override hard safety invariants.
- Expired, pending, unmatched, or invalid exceptions cannot suppress checks.
- Unknown configuration and policy fields are rejected.
- Tokens are resolved at runtime and are not placed in reports.
- Backend credential errors are reduced to safe error classes.
- Private and internal repository names and URLs are redacted in
minimaldetail mode. - Repository checks report presence and counts. They do not store descriptions, homepage URLs, topic names, language names, file paths, or file content.
- Classification evidence treats raw topics and language names as ephemeral input. Serialized evidence and binding reports exclude those values and the internal repository API name.
- Audit history stores a key hashed from GitHub host and account login, numeric repository IDs, stable check metadata, transition counts, timestamps, and one-way state hashes. It does not store account names, repository names, credentials, URLs, evidence, or raw current and desired values.
- SQLite migrations are numbered, transactional, and forward-only. A local backup is created before a nonempty database is upgraded.
- Default configuration, state, cache, report, log, browser, and backup-metadata paths are outside the cloned repository.
Treat a personal access token like a password. Never paste it into config.yaml, a command history entry, an issue, a pull request, a report, or a committed file.
For the Windows instructions below, you need:
- Windows 11 with PowerShell.
- A GitHub account.
- Git installed and available as
git. - Internet access to GitHub and Python package sources.
uv, which manages Python 3.12 and the project dependencies.
You do not need to create a Python virtual environment manually. uv sync creates and manages .venv for this repository.
If this command prints a version, Git is already installed:
git --versionIf it is missing, install Git for Windows, reopen PowerShell, and run the version command again.
The simplest Windows package-manager installation is:
winget install --id astral-sh.uv -eClose and reopen PowerShell, then verify the installation:
uv --versionThe official uv installation guide lists the standalone PowerShell installer and other supported methods.
These commands clone the repository, install the locked dependencies, and show the CLI help.
git clone https://github.com/mickpletcher/github-account-maintainer.git
Set-Location .\github-account-maintainer
uv sync --locked --dev
uv run github-account-maintainer --version
uv run github-account-maintainer --helpWhat each command does:
git clonedownloads the source repository.Set-Locationenters the repository folder.uv sync --locked --devcreates.venvand installs the exact locked application and development dependencies.uv runexecutes a command inside the managed project environment.
Expected version output:
0.1.0.dev0
If uv sync --locked --dev would require a lockfile change, it stops instead. This protects reproducibility.
The implemented commands use discovery and audit credential references. Use fine-grained personal access tokens with the smallest practical access. A single read-only token may be stored under both references, or you may create separate tokens.
GitHub's current token steps are documented in Managing your personal access tokens.
- Sign in to GitHub.
- Open your profile menu and select Settings.
- Open Developer settings.
- Open Personal access tokens, then Fine-grained tokens.
- Select Generate new token.
- Give the token a clear name such as
github-account-maintainer-discovery. - Set an expiration date.
- Select the personal account or organization that owns the repositories you want to inventory.
- Select all repositories or only the repositories that should be visible to this tool.
- Grant repository Metadata read access for discovery. For the complete
audit, also grant repository Contents, Administration, and Code scanning alerts read access. - Do not grant write permissions for the current release.
- Generate the token and copy it once.
The implemented GET /user call does not require an additional fine-grained permission. Inventory requires repository Metadata: read access. The complete audit requires Contents: read for community-file metadata, Administration: read for branch protection, Actions, Dependabot, and code-scanning setup, and Code scanning alerts: read to detect advanced or external code-scanning analyses. No write permission is required. See GitHub's official endpoint documentation for repository inventory, branch protection, Actions permissions, and code scanning.
Important token limitations:
- A fine-grained token is limited to its selected resource owner and repository access.
- An organization may require an administrator to approve the token.
- A pending or unapproved organization token may not return the expected repositories.
- A token cannot grant access that your GitHub account does not already have.
- Use a short practical expiration and rotate the token when it expires.
The default configuration expects this credential reference:
keyring:github-account-maintainer/discovery
The part before the slash is the keyring service. The part after the slash is the keyring account.
From the repository directory, run:
uv run keyring set github-account-maintainer discoveryThe command prompts for a password. Paste the GitHub token at that prompt. The token is stored by the active system keyring backend, which is normally Windows Credential Manager on Windows. It is not written to the project configuration.
To run the full audit, also store a token under the audit account:
uv run keyring set github-account-maintainer auditThat token needs Metadata, Contents, Administration, and Code scanning alerts read access. If one least-privilege token has all four read permissions, you may paste the same token into both prompts.
You can inspect keyring diagnostics without printing the token:
uv run keyring diagnoseDo not use keyring get in a shared terminal, recording, or log. That command can print the stored secret.
For an isolated development session, you can use an environment variable instead of keyring.
First change the configuration reference:
credentials:
discovery: env:GITHUB_TOKENThen set the variable only in the current PowerShell process. The masked prompt requires PowerShell 7.1 or later:
$env:GITHUB_TOKEN = Read-Host "GitHub token" -MaskInputOn older Windows PowerShell versions, use the recommended keyring method so the token is not displayed while you type it. Microsoft documents -MaskInput in the Read-Host reference.
Run the command in the same PowerShell window. Remove the variable when finished:
Remove-Item Env:GITHUB_TOKENDo not place the token in a .ps1 file, profile, repository .env file, or committed configuration.
Replace YOUR_GITHUB_LOGIN with the login shown in your GitHub profile URL.
uv run github-account-maintainer init --login YOUR_GITHUB_LOGINOn Windows, the default file is normally:
%LOCALAPPDATA%\GitHubAccountMaintainer\config\config.yaml
To display the expected path in PowerShell:
Join-Path $env:LOCALAPPDATA "GitHubAccountMaintainer\config\config.yaml"To create the file somewhere else:
uv run github-account-maintainer init `
--login YOUR_GITHUB_LOGIN `
--output C:\LocalData\GitHubAccountMaintainer\config.yamlThe command creates parent directories when required. It does not overwrite an existing file unless --overwrite is explicitly supplied.
uv run github-account-maintainer init `
--login YOUR_GITHUB_LOGIN `
--output C:\LocalData\GitHubAccountMaintainer\config.yaml `
--overwriteUse --overwrite carefully. It atomically replaces the selected configuration.
Run the identity preflight before inventory:
uv run github-account-maintainer auth checkFor readable Markdown output:
uv run github-account-maintainer auth check --format markdownFor a nondefault configuration path:
uv run github-account-maintainer auth check `
--config C:\LocalData\GitHubAccountMaintainer\config.yaml `
--format markdownA successful report includes:
- The configured GitHub login.
- The login returned by GitHub.
- The authenticated numeric user ID.
- The credential source reference, not the credential value.
- OAuth scopes when GitHub reports them.
- Accepted permissions when GitHub reports them.
- Remaining rate-limit information when available.
- The check timestamp.
The command fails if the authenticated login does not match account.login. This prevents accidentally auditing with the wrong account's token.
After authentication succeeds, run:
uv run github-account-maintainer inventory --format markdownJSON is the default:
uv run github-account-maintainer inventoryTo save a local JSON report:
uv run github-account-maintainer inventory --format json |
Set-Content -Path .\inventory.json -Encoding utf8Treat saved reports as local data. Do not commit them unless you have reviewed their contents and intentionally accepted the disclosure risk.
The inventory report contains:
- Tool and report schema versions.
- The configured account display.
- The credential source reference.
- Declared affiliations.
- Start and completion timestamps.
- Complete or partial status.
- Pages read.
- Duplicate count.
- Accepted GitHub permissions when reported.
- Repository records.
- Terminal coverage records.
In the default minimal mode, a private repository may appear as:
nonpublic-repository:123456789
Its URL is omitted. Public repository names and URLs are not redacted.
After both credentials are stored, run the complete read-only audit:
uv run github-account-maintainer audit --format markdown
$LASTEXITCODEThe command performs this sequence:
- Verifies the discovery credential and inventories every repository in declared affiliation and visibility scope.
- Verifies the separate audit credential against the configured GitHub login.
- Applies
repositories.include_patternsandrepositories.exclude_patterns. - Reads repository metadata and language totals for deterministic classification.
- Resolves and hashes the effective policy for that repository.
- Runs six metadata, eight community-file, six repository-settings, and six security-feature checks.
- Continues to the next repository if one repository is inaccessible or returns invalid evidence.
- Aggregates policy bindings, results, findings, permissions, and terminal coverage.
- Evaluates findings against
audit.failure_threshold. - Records a sanitized local run and its finding transitions when history is enabled.
JSON is the default and is intended for local automation:
uv run github-account-maintainer audit --format json |
Set-Content -Path .\account-audit.json -Encoding utf8
$auditExitCode = $LASTEXITCODETreat saved audit reports as private local data. Minimal mode redacts private and internal names, but reports still contain public repository names, numeric repository IDs, policy decisions, findings, and operational coverage.
Exit code 0 means complete coverage with no finding at or above the configured threshold. Code 1 means complete coverage with a threshold finding. Code 2 means coverage is partial, even if findings were also produced. Code 3 means the configuration or command input is invalid.
By default, complete and partial audit results are recorded in:
%LOCALAPPDATA%\GitHubAccountMaintainer\state\audit-history.sqlite3
This database is local application state. It is not inside the cloned repository and is not pushed to GitHub. To skip history for one audit, add --no-history. To disable automatic history for all audits using a configuration, set history.enabled to false.
Show the 20 most recent stored runs as readable Markdown:
uv run github-account-maintainer history --format markdownJSON is the default. Use --limit to return between 1 and 100 recent runs:
uv run github-account-maintainer history --limit 50The history report contains run timestamps, complete or partial status, repository and finding counts, a one-way run ID, and these transition counts:
new: The finding identity has not been seen before.persistent: The finding was active in local history and appeared again.resolved: A complete audit conclusively evaluates the same repository and check without the previously active finding.regressed: A resolved finding appeared again.
A partial audit never resolves an absent finding. A complete audit also preserves findings for repositories or checks that are excluded, absent from inventory, inaccessible, unsupported, unavailable by plan, unverified, failed, or skipped by policy. Missing evidence is not proof that a problem was fixed. The history command returns only sanitized counts and run metadata. It does not return finding evidence, current or desired values, repository names, credential references, URLs, or local file paths.
Runs must match the configured account and be recorded in chronological order. Re-recording the same semantic audit is idempotent and does not duplicate events. The tool rejects a database created by a newer schema. When an older nonempty database needs an upgrade, the tool checks database integrity, creates a timestamped backup under the local state directory, and applies each numbered migration in its own transaction.
If enabled history recording fails, audit still writes its complete JSON or Markdown report to stdout. It writes a sanitized history error to stderr and exits with code 2 so automation cannot mistake missing requested history for full success.
The Release 0.1 pilot verifies the locked build and then runs the live audit twice. It emits only counts and pass/fail state. Detailed audit reports stay in memory and are not written to disk.
Use a private minimal-detail configuration with at least one repository in scope:
.\scripts\Invoke-Release01Pilot.ps1 `
-Config "$env:LOCALAPPDATA\GitHubAccountMaintainer\config\config.yaml" `
-Repeat 2The pilot intentionally rejects:
report_detail: full;- fewer than two or more than five repeated audits;
- a non-serial GitHub request mode;
- automatic write operations;
- automatic merge or destructive operations;
- zero in-scope repositories;
- partial inventory, classification, or check coverage;
- missing JSON or Markdown report contract sections;
- different semantic results between the repeated runs.
Findings do not fail the pilot. Findings describe repository compliance. The pilot verifies that the audit itself is complete, deterministic, private by default, and read-only.
The latest 2026-08-10 pilot passed two matching runs across 73 repositories. Each run produced 1,898 check results, 2,045 coverage records, and 604 findings. The summary contained counts only, enforced minimal detail and GET-only requests, and recorded zero automatic writes.
See RELEASE-0.1-PILOT.md for prerequisites, Windows and Linux commands, safe output fields, exit behavior, and the evidence manifest.
uv run github-account-maintainer [OPTIONS] COMMAND| Option | Purpose |
|---|---|
--version |
Print the package version. |
--help |
Show the top-level help. |
--install-completion |
Install shell completion for the current shell. |
--show-completion |
Print shell-completion instructions. |
uv run github-account-maintainer init --login LOGIN [--output PATH] [--overwrite]| Option | Required | Purpose |
|---|---|---|
--login |
Yes | GitHub login placed in the configuration. |
--output |
No | Explicit configuration path. The platform default is used when omitted. |
--overwrite |
No | Atomically replace an existing configuration. |
uv run github-account-maintainer auth check [--config PATH] [--format json|markdown]This command resolves the discovery credential, calls GET /user, and verifies the returned identity.
uv run github-account-maintainer inventory [--config PATH] [--format json|markdown]This command verifies identity and then reads every page returned by GET /user/repos within the declared affiliation and visibility scope.
uv run github-account-maintainer audit [--config PATH] [--format json|markdown] [--no-history]This command inventories repositories with the discovery credential, verifies the separate audit credential, applies repository scope patterns, classifies each in-scope repository, binds its effective policy, runs 26 checks, aggregates the result, and records sanitized history unless configuration or --no-history disables it. It uses only GET requests and does not change GitHub.
For a readable report:
uv run github-account-maintainer audit --format markdown
$LASTEXITCODEThe command continues when one repository is inaccessible or malformed. The final report marks every affected check with terminal coverage and exits with code 2 so partial evidence cannot look complete.
uv run github-account-maintainer history [--config PATH] [--format json|markdown] [--limit 1..100]This command reads sanitized run and transition counts for the configured account. It does not contact GitHub. If no history database exists, it returns an empty report without creating one.
FUT-002 provides the read-only repository check layer used by the account-level audit command.
The layer performs 26 stable checks:
- Metadata:
metadata.description,metadata.homepage,metadata.topics,metadata.primary_language,metadata.visibility, andmetadata.archive_state. - Community files:
community.readme,community.license,community.security,community.contributing,community.code_of_conduct,community.support,community.issue_template, andcommunity.pull_request_template. - Repository settings:
settings.branch_protection,settings.rulesets,settings.required_reviews,settings.required_status_checks,settings.actions_permissions, andsettings.actions_workflow_permissions. - Security features:
security.dependabot_alerts,security.dependabot_security_updates,security.secret_scanning,security.push_protection,security.code_scanning, andsecurity.private_vulnerability_reporting.
Each result records:
outcome:compliant,noncompliant,observed,unknown, orinaccessible.coverage_state: the terminal coverage vocabulary, includingaudited,supported,unsupported,unavailable_by_plan,inherited,inaccessible,not_applicable,unverified,skipped_by_policy,not_requested, andfailed.- Sanitized current and desired state.
- Count-only or presence-only evidence.
Required values that are confirmed missing produce findings. Optional values are observed without producing false violations. Repository or community-profile authorization and not-found responses are treated as inaccessible. A missing directory listing is treated as an absent directory only after repository access succeeds. Malformed or operational failures are unknown and failed. An active policy exception marks its check skipped_by_policy and does not produce a finding.
Settings and security checks fail closed. Supported evidence can produce a compliant or noncompliant result. A confirmed disabled feature is supported evidence and may produce a finding. Inaccessible or unverified evidence makes the account audit partial, records unknown values instead of false negatives, and does not produce a false finding. A feature that does not apply to the repository visibility, archive state, or branch state uses not_applicable. A feature that GitHub does not provide for the active plan uses unavailable_by_plan. Private repositories without the required GitHub plan use unavailable_by_plan for unavailable branch controls, secret scanning, push protection, and code scanning. Archived repositories use not_applicable for code scanning.
The implementation uses only these GET requests:
GET /userto verify the audit credential identity.GET /repos/{owner}/{repository}for metadata.GET /repos/{owner}/{repository}/community/profilefor GitHub-recognized community files on non-forks.GET /repos/{owner}/{repository}/contents, plus.githubanddocsdirectory listings, for file-presence metadata.GET /repos/{owner}/{repository}/rules/branches/{branch}and the default-branch protection endpoint for branch policy.- Repository Actions policy and default workflow permission GET endpoints.
- Dependabot alert and automated security-fix status GET endpoints. HTTP 204 means enabled and HTTP 404 means disabled for these status-only checks; the tool does not try to parse an empty 204 response body.
- Repository security-and-analysis metadata, code-scanning setup or count-only analysis presence, and private vulnerability reporting status.
It does not clone repositories or request file bodies. Inherited community files are reported with inherited coverage when GitHub identifies a source outside the audited repository.
FUT-014 provides the deterministic layer between inventory and repository checks. FUT-003 now orchestrates it across every in-scope inventoried repository.
The classifier evaluates seven dimensions:
| Dimension | Possible results |
|---|---|
| Visibility | public, private, or internal |
| Activity | active, dormant, abandoned_candidate, archived, or unknown |
| Repository kind | source, fork, template, mirror, or empty |
| Ownership | personal_account, organization, or unknown |
| Project type | python, powershell, nodejs, mcp_server, documentation, configuration, web_application, infrastructure, mixed, or unknown |
| Repository class | application, library, cli, service, desktop_application, github_pages, infrastructure, documentation, configuration, empty, or unknown |
| Maintenance tier | active, standard, experimental, or legacy from current evidence. flagship and exempt are reserved for explicit future override rules. |
Direct GitHub facts such as visibility, archive state, fork state, owner type, template state, mirror state, repository size, Pages state, and push time receive the strongest confidence. Project type and repository class use a fixed allowlist of known topic and language families. Unknown inputs never become new policy selectors. Multiple recognized language families that each represent at least 20 percent are classified as mixed.
Activity uses fixed Release 0.1 thresholds:
active: pushed within 180 days.dormant: last push was 181 through 730 days ago.abandoned_candidate: last push was more than 730 days ago.archived: GitHub reports the repository as archived.unknown: no push timestamp was available.
The raw GitHub repository and language responses are validated before classification. Repository ID, visibility, archive state, and fork state must match inventory. A mismatch fails closed. The classification hash must match its canonical decisions, and policy binding requires the classification timestamp to equal the policy evaluation timestamp.
Binding feeds the canonical repository class and project type into policy resolution in the existing order. Repository-specific policy still has higher precedence. The privacy-safe binding record contains the redacted display name, classification decisions and confidence, classification hash, policy hash, and applied policy-source types. It does not contain the internal owner/repository selector, raw topics, raw language names, or policy source keys.
The configuration is strict YAML. Indentation matters. Unknown fields, invalid values, and unsafe combinations are rejected with exit code 3.
| Section | Current use |
|---|---|
account |
Controls identity, GitHub host, visibility, and repository affiliations used by authentication and inventory. |
github_api |
Pins the API version and serial request mode. |
credentials |
Stores credential references. It must never contain literal secrets. |
local_data |
Defines local directories, report detail, and retention values. |
safety |
Enforces non-overridable write and approval boundaries. |
audit |
Sets the finding severity that makes a complete audit exit with code 1. |
history |
Enables or disables automatic sanitized SQLite history recording for audit. |
repositories |
Supplies account-wide repository policy defaults. Include and exclude patterns are applied by audit. |
pins |
Validated policy for the planned profile-pin feature. Not active yet. |
readme |
Validated policy for planned README checks and remediation. Not active yet. |
metadata |
Active desired-state policy for the repository metadata check layer. |
community |
Active required or optional policy for eight common community files. |
social_preview |
Validated policy for planned social-preview work. Not active yet. |
security |
Active read-only policy toggles for repository settings and security-feature checks. |
backup |
Reserved and forced disabled in the current schema. |
notifications |
Validated notification policy. Notifications are not active yet. |
policy |
Stores repository-class, project-type, repository-specific, and exception overrides. |
The default account block is:
account:
login: YOUR_GITHUB_LOGIN
github_host: github.com
include_private: true
include_owned: true
include_administered: false
affiliations:
- ownerRules:
loginmust match the token's authenticated GitHub login, ignoring case.github_hostis a hostname only. Do not includehttps://or a path.include_private: falserequests only public repositories.include_ownedmust agree with whetherownerappears inaffiliations.include_administeredmust be true whencollaboratorororganization_memberis selected.- Valid affiliations are
owner,collaborator, andorganization_member.
Example that includes repositories administered through collaboration or organization membership:
account:
login: YOUR_GITHUB_LOGIN
github_host: github.com
include_private: true
include_owned: true
include_administered: true
affiliations:
- owner
- collaborator
- organization_memberThe token must still be allowed to access those repositories. Configuration does not grant GitHub permissions.
Supported forms are:
keyring:SERVICE/ACCOUNT
env:VARIABLE_NAME
Examples:
credentials:
discovery: keyring:github-account-maintainer/discovery
audit: keyring:github-account-maintainer/audit
remediation: disabled
classic_token: disabled
browser_profile: disabledThe auth check and inventory commands use only credentials.discovery. The audit command uses discovery for inventory and credentials.audit for repository evidence. It verifies both identities and never falls back to the discovery or remediation credential for checks.
Store the audit token after storing the discovery token:
uv run keyring set github-account-maintainer auditThe audit token needs repository Metadata, Contents, Administration, and Code scanning alerts read access for every repository in scope. You may store the same least-privilege token under both keyring accounts, but separate credentials make the access boundary explicit.
The default threshold is low:
audit:
failure_threshold: low
repositories:
include_patterns:
- "*"
exclude_patterns: []Valid thresholds are informational, low, medium, high, and critical. Matching is case-insensitive and uses shell-style wildcard patterns against owner/repository. An excluded repository remains in inventory coverage but its classification and checks are marked not_requested.
History is enabled by default:
history:
enabled: trueSet enabled: false to prevent future audit commands from writing local history. This does not delete existing history. The history command can still read an existing database. Retention is not automatic in the current release because pruning requires its own explicit plan.
The default configuration enables every implemented read-only settings and security check:
security:
audit_branch_protection: true
audit_rulesets: true
audit_required_reviews: true
audit_required_status_checks: true
audit_actions_permissions: true
audit_actions_workflow_permissions: true
audit_dependabot: true
audit_secret_scanning: true
audit_push_protection: true
audit_code_scanning: true
audit_private_vulnerability_reporting: true
security_alert_dismissal: prohibitedSetting an audit toggle to false marks that check skipped_by_policy. It does not change GitHub. The security_alert_dismissal value is fixed at prohibited.
local_data:
report_detail: minimalValid values are:
minimal: Redacts private and internal repository names and removes their URLs.full: Includes private and internal repository names and URLs.
Use full only for private local reports with controlled storage. It increases disclosure risk.
The engine resolves policy in this order. A later matching layer overrides an earlier layer.
- Built-in safe defaults.
- Account-wide settings from the top-level configuration sections.
- A matching repository-class policy.
- A matching language or project-type policy.
- A matching repository-specific policy.
- Matching active exceptions.
Hard safety invariants are outside this hierarchy. A policy patch cannot enable automatic merging, destructive operations, write operations, secret collection, or the other prohibited behaviors.
Example:
policy:
repository_classes:
application:
metadata:
minimum_topics: 2
community:
security: required
security:
audit_code_scanning: true
project_types:
python:
readme:
validate_links: true
repositories:
owner/repository:
readme:
preserve_manual_sections: true
exceptions:
- exception_id: EXC-001
target_selector: owner/repository
check_ids:
- metadata.description
reason: Temporary migration window
creator: github-login
created_at: 2026-08-10T00:00:00Z
expires_at: 2026-09-10T00:00:00ZException requirements:
exception_idis stable and unique, ignoring case.target_selectoridentifies matching repositories and may use shell-style wildcard matching.check_idsis a nonempty list of stable lowercase identifiers.reasonandcreatorcannot be empty.- Timestamps must use RFC 3339 UTC.
- A non-permanent exception requires
expires_ataftercreated_at. - A permanent exception sets
permanent: trueand must not haveexpires_at. - A pending exception does not apply before
created_at. - An expired exception no longer suppresses checks.
Resolution produces:
- The final effective policy settings.
- Active exception records.
- Expired and pending exception IDs.
- The sorted set of suppressed check IDs.
- A trace containing each value, source layer, and source key.
- A canonical SHA-256 policy hash.
Equivalent policy inputs produce the same resolved result and hash. The audit command resolves and records one binding for each successfully classified in-scope repository.
The classification layer supplies repository_class and project_type automatically during account-wide CLI execution.
The built-in metadata policy requires a description, at least one topic, and a primary language. Homepage is optional. The built-in community policy requires README, LICENSE, and SECURITY files. CONTRIBUTING, CODE_OF_CONDUCT, SUPPORT, issue templates, and pull request templates are optional unless a matching policy layer makes them required.
auth check, inventory, audit, and history support:
json: Machine-readable output. This is the default.markdown: Human-readable output.
The account audit report includes sanitized repository displays, classification and policy hashes, all check results, finding counts by severity, exact current and desired states, remediation details, accepted GitHub permissions, and terminal coverage. Internal selectors for private repositories are used only in memory and are not serialized in minimal mode.
Classification and policy binding also have schema-versioned JSON and Markdown renderers. They include confidence and hashes without exposing raw private classification inputs.
| Code | Meaning | Typical action |
|---|---|---|
0 |
The command completed, coverage is complete, and no audit finding reached the configured threshold. | Review the report. |
1 |
The audit completed and at least one finding reached the configured threshold. | Review and prioritize findings. |
2 |
The run was incomplete or failed operationally. Partial status takes precedence over findings. | Check authentication, authorization, rate limits, network access, and coverage details. |
3 |
The command, configuration, policy, plan, or approval is invalid. | Correct the input before retrying. |
A partial inventory or audit always exits with code 2, even if it returns repository records or findings. Do not treat partial output as complete coverage.
To inspect the last exit code in PowerShell:
$LASTEXITCODEClose and reopen PowerShell after installing uv. Then run:
uv --versionIf it still fails, use the official uv installation guide to verify the installation and PATH.
init protects existing files. Either use the existing file, select a different --output path, or explicitly use --overwrite after reviewing the target.
Common causes are:
- Incorrect YAML indentation.
- An unknown field.
- A literal token in a credential field.
- A URL instead of a hostname in
github_host. include_ownedorinclude_administereddisagreeing withaffiliations.- An exception without a valid expiration or
permanent: true. - A non-UTC exception timestamp.
Compare the edited file with a fresh configuration created at a separate path.
Store it again with the exact service and account expected by the configuration:
uv run keyring set github-account-maintainer discoveryThen confirm that the YAML reference is exactly:
keyring:github-account-maintainer/discovery
Use uv run keyring diagnose if the keyring backend is unavailable.
The stored token belongs to a different GitHub user than account.login.
- Confirm the intended GitHub login.
- Replace the keyring entry with a token created by that account, or correct
account.login. - Run
auth checkagain.
Do not disable the identity check.
The token is missing, invalid, expired, or revoked. Create or store a valid replacement token and retry.
The token or account lacks access, an organization approval is pending, or GitHub denied the request. Review the token's resource owner, repository selection, metadata permission, expiration, and organization policy.
Wait until the reported reset or retry period. Repeated immediate retries can prolong the problem. The tool fails closed and marks the inventory partial.
Check all of these:
- The token's resource owner.
- The token's selected repositories.
- Repository Metadata: read permission.
- Organization approval status.
include_private.affiliations.- The matching
include_ownedandinclude_administeredflags. - Whether your GitHub account itself has access.
Fine-grained tokens have owner and repository boundaries. One token may not cover repositories owned by unrelated organizations.
The report is partial. Inspect its final inventory.repositories coverage record and detail value. Earlier pages may be present, but declared coverage was not completed.
| Path | Purpose |
|---|---|
src/github_account_maintainer/ |
Application package. |
tests/ |
Unit tests and sanitized fixtures. |
.github/workflows/ |
Pinned GitHub Actions validation. |
prompts/ |
Approved project specification. |
assessment.md |
Current capability, safety, limitation, and verification overview. |
changelog.md |
Complete repository change log. |
future-upgrades.md |
Prioritized backlog with stable FUT IDs. |
completed-upgrades.md |
Verified implemented upgrades. |
uv sync --locked --devuv run ruff check .
uv run ruff format --check .
uv run pyright
uv run pytest
uv lock --checkThe current baseline is 81 tests with 95.76 percent total coverage. The configured minimum is 90 percent.
Pull requests and pushes to main run equivalent validation. CodeQL scans Python and GitHub Actions sources.
Every repository change must:
- Update
changelog.mdunderUnreleased. - Review and update
assessment.md. - Keep the README accurate when commands, behavior, status, safety, or setup changes.
- Preserve the read-only and fail-closed boundaries unless a later approved release explicitly changes them.
When a tracked upgrade is implemented:
- Remove it from
future-upgrades.md. - Add it to
completed-upgrades.mdwith its original ID and verification evidence. - Add at least one new, distinct future idea in the same pull request.
- Confirm that no item appears in both ledgers and no ID is assigned twice.
- Project specification: Approved scope, architecture, safety model, command surface, and release gates.
- Assessment: Current implemented behavior, risks, limitations, verification, and next priorities.
- Changelog: Every repository change.
- Future upgrades: Three-tier prioritized backlog.
- Completed upgrades: Implemented upgrades with evidence.
- Release 0.1 pilot: Locked validation and count-only repeated live-audit procedure.
- Release 0.1 gate manifest: Machine-readable mapping of all ten gate criteria to evidence.
- Security policy: Supported versions and vulnerability-reporting instructions.
- License: MIT license terms.
The expanded Release 0.1 private pilot passed on 2026-08-10. It completed two matching GET-only audits across 73 repositories, with 1,898 check results, 2,045 coverage records, 604 findings, and zero writes per run. Before tagging the release:
- Rerun the count-only pilot after any further material audit change with a private minimal-detail configuration and valid read-only credentials.
- Retain only the count-only result and CI links as release evidence. Do not commit private audit output.
Release 0.1 remains read-only. No remediation path is enabled.