Stop linting your GitHub Actions. Fix them.
Want the full pattern set, not just what `--fix` covers?
The Cut Your CI Bill cookbook ships 30 paste-ready patterns and 5 hardened workflow templates. Same author. $19, one-time, MIT-licensed templates.
Get the cookbook
Every GitHub Actions linter on the market is read-only. actionlint
catches syntax. sherif spots bad patterns. octoscan
yells about untrusted inputs. They all stop at "this workflow has problems."
You still have to open the file and type the fix yourself.
That gap is the whole reason CI workflows rot. Nobody is paid to maintain them. They drift, the bill creeps up, and the next person who touches the YAML doesn't even know what good looks like.
ci-doctor 0.2
ships --fix. It rewrites your workflows in place, in
the second between git pull and git commit. Free,
MIT, no signup, no telemetry.
What --fix does
Four issues that have a single safe answer get applied automatically:
| Rule | What it adds |
|---|---|
missing-permissions | top-level permissions: { contents: read } |
missing-concurrency | concurrency block with cancel-in-progress: true |
missing-timeout | timeout-minutes: 15 on every job missing it |
artifact-no-retention | retention-days: 7 on every actions/upload-artifact step |
Try it on a workflow you already have:
npx ci-doctor --fix --dry-run
Dry-run prints the patched YAML to stdout so you can diff it before
writing. Drop --dry-run to apply in place.
What --fix does NOT do
Anything that requires a judgment call keeps a warning so a human can decide:
- Cache ecosystem (
cache: npmvscache: pnpmvscache: pip) - depends on your repo. - Action major-version bumps (e.g.
actions/checkout@v3→v4) - changes runtime behavior. - SHA pinning - delegated to the companion CLI,
pin-actions, which queries the GitHub API to resolve refs. - Runner cost decisions (
macos-latest→ubuntu-latest) - sometimes you need the macOS runner.
These rules still fire as warnings. The principle: never apply a "fix" that could plausibly break someone's workflow.
Comments and ordering are preserved
ci-doctor uses yaml.parseDocument, not yaml.parse.
That means we mutate the document model and serialize it back, so existing
comments and key ordering survive. The new keys are appended at the end of
their parent map - YAML is unordered, so this is semantically identical and
diff-friendly.
The two-CLI workflow
The opinionated way to harden a repo's CI:
npx ci-doctor --fix
npx pin-actions
First command applies the four safe fixes above. Second pins every
uses: owner/repo@ref to a full commit SHA, so a compromised
tag can't ship malicious code through your pipeline. Both finish in under
two seconds on a normal repo.
Where the rest of the cost lives
Not every CI cost has a single safe fix. Matrix overcommit, expensive runners, redundant test jobs - those need patterns. The Cut Your CI Bill cookbook is 30 of those patterns plus 5 ready-to-paste workflows ($19, one-time). The CLI ships every rule and stays MIT.
If you want to know what each finding actually costs in dollars, the
companion CLI gha-budget
prices a workflow against the official runner rates.
Try it
# audit
npx ci-doctor
# fix the easy stuff
npx ci-doctor --fix
# pin every action to a SHA
npx pin-actions
# what does this workflow cost?
npx gha-budget