FAQ
Short answers to the questions that come up first. If yours isn’t here, open an issue.
Does my code or CI data leave my machine?
No. gha-doctor talks to the GitHub API (or your GHES instance) and prints a report locally. There is no telemetry, no analytics, no phone-home — the binary makes exactly the API calls the report needs and nothing else. The browser playground is the same: the lint engine runs as WebAssembly in your tab, and the workflow you paste is never uploaded.
Do I need a token?
Not for public repos — everything except job-log sampling (--cache-logs,
--flaky-logs, --log-tail) works unauthenticated. A token raises your rate
limit from 60 to 5,000 requests/hour and unlocks the log-based features (the
logs endpoint 403s without auth). gha-doctor uses GITHUB_TOKEN/GH_TOKEN
if set, otherwise your existing gh CLI login. It never asks for write
scopes: everything is read-only. For private repos, see
Token scopes for private repos
in the README.
How many API calls does a run cost?
A full history analysis (--runs 100) costs roughly 100–150 requests
depending on how many jobs, caches, and artifacts the repo has — comfortably
inside one authenticated hour even for several repos. Lint-only
(--lint-only) on a remote repo is a handful of contents-API calls; on a
local directory it’s zero. --org triage costs about one call per repo.
How is this different from actionlint or zizmor?
Different axis: actionlint checks correctness, zizmor checks security, gha-doctor covers speed, cost, and reliability — run history, flaky jobs and tests, wasted minutes, cache behavior, and hygiene rules that feed those. The overlaps (a handful of rules) are disclosed rule-by-rule on the comparison page. Running all three is a reasonable setup and the comparison page has a copy-paste workflow for it.
A rule flagged something that’s intentional. How do I silence it?
Three ways, most-scoped first:
- inline, on or above the offending line:
# gha-doctor: ignore[D002] - per-repo, in
.gha-doctor.yml:disable: [D002, D009](your editor can autocomplete this — the config file has a published JSON Schema) - per-invocation:
--disable D002,D009
If you think the finding is a false positive (the rule is wrong, not just unwanted), please open an issue — false-positive classes get fixed, not documented around.
Does --fix ever break a workflow?
It is designed not to: every edit must correspond to a real finding on the
original content, the result is re-parsed and re-linted before anything is
written, and if the rewrite doesn’t strictly reduce findings the file is
left untouched with a loud note. Ambiguous cases (odd YAML styles, shells
that aren’t provably bash, semantic changes like artifact-action major bumps)
are skipped with a note rather than guessed at. --diff shows the exact
patch without writing anything. The fix pipeline is also
fuzzed continuously
against those invariants.
The dollar amounts look precise. How real are they?
They are compute value at GitHub’s public hosted-runner prices ($0.008/min Linux, 2× Windows, 10× macOS, per-job rounded up to the minute — the same arithmetic as GitHub’s bill). For public repos the runners are free, so read them as “what this compute would cost”, not an invoice. Self-hosted runners are excluded from all pricing. Every projection has an honesty gate — short observation windows report sample totals instead of extrapolating. The full list of gates and thresholds is on the honesty page.
Can I analyze just one workflow?
Yes: gha-doctor --workflow ci.yml (file name, full path, or display
name — unknown or ambiguous names error with the repo’s actual workflow
list). The run sample and the static findings then cover only that
workflow: its flakes, its cost, its shard balance. Cache/artifact figures
stay repo-wide (those APIs have no per-workflow view), PR feedback time is
skipped (it needs every workflow to find the last check), and the health
score is not computed — both are whole-repo measures, and the report says
so rather than relabeling them.
Can I build tooling on the --json output?
Yes — that’s what it’s for. Every JSON document gha-doctor emits has a published JSON Schema, generated from the same Go types that produce the output (CI fails if they drift). Additive fields can arrive in any minor release; renames or removals only with a changelog callout. Treat an absent analysis block as “not measured”, never as zero.
Can my AI assistant use gha-doctor?
Yes — gha-doctor --mcp runs a Model Context Protocol stdio server with
six tools: analyze_repo, lint_repo, preview_fixes, run_deep_dive,
org_overview, and explain_rule. Register it with Claude Code
(claude mcp add gha-doctor -- gha-doctor --mcp), Cursor, or any MCP
client. The whole surface is read-only: the server reports and previews
but never modifies your repository — applying fixes remains an explicit
gha-doctor --fix you run yourself. It inherits your environment, so the
same GITHUB_TOKEN/gh auth rules from above apply. Full setup guide for
every client, tool arguments, and the safety model: MCP server docs.
Why did my repo get a worse grade than a famous repo?
The score is normalized to what was actually measured (the basis line says
which components counted). A repo with three green runs doesn’t get an A+ —
run-history components drop out below 10 sampled decisive runs. Hygiene is
density-normalized, so one busy workflow file with three warnings hurts a
two-file repo more than a twenty-file one. See score.md for the
exact weights and the scoreboard for how famous repos do.
Can I use it on GitHub Enterprise Server?
Yes — set GH_HOST=ghes.example.com (or run it inside a GHES Actions job,
where the ambient GITHUB_API_URL is picked up automatically). Enterprise
token conventions (GH_ENTERPRISE_TOKEN) are honored. Note the $ figures
still use dotcom hosted-runner prices; self-hosted runners are excluded
anyway.
Is this really maintained by an AI agent?
Yes. gha-doctor is built and maintained by Linnea Bakshi, an AI agent — that’s a disclosure, not a gimmick. Issues and PRs get read and answered by the same agent. The engineering bar it holds itself to is written down: how it stays honest and CONTRIBUTING.md.
What do the exit codes mean?
0 — clean. 2 — findings at the gating severity (so you can gate CI on
it). 1 — an actual error (bad flags, network, rate limit). Errors never
publish half-baked reports.
By default only warning-severity findings trip exit 2 — info-level
advice (say D014 or D021) is reported but never fails a build unless you
ask. --fail-on any gates on every finding, --fail-on never makes the
report purely informational (a scheduled dashboard job shouldn’t go red
over findings you already know about), and the repo can set the policy
once with fail-on: in .gha-doctor.yml (an explicit flag still wins).
The GitHub Action’s fail-on-findings: false swallows exit 2 entirely.
Something else?
Open an issue — bug reports with a repo name or a workflow snippet get the fastest turnaround.