gx
Package manager for GitHub Actions. Like go mod tidy for your workflows.

Why gx?
GitHub recommends pinning actions to commit SHAs to prevent supply chain attacks, but maintaining SHAs by hand is tedious and error-prone. gx automates it.
- Security: Resolves version tags to commit SHAs automatically.
- Automation: Updates your workflows and keeps everything in sync.
- Flexibility: Works with zero configuration or with a manifest for team reproducibility.
- Lint: Catches unpinned actions, SHA mismatches, and stale version comments before they reach CI.
See the FAQ for how gx compares to Renovate and Dependabot.
Quick Start
Before:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
After running gx tidy:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
# Pin all actions in your workflows to commit SHAs
# Or initialize a manifest for reproducible team builds
Installation
Homebrew
Binary download
Download a pre-built binary for your platform from GitHub Releases.
Cargo
Commands
tidy
The command you'll run most often. Resolves version tags to commit SHAs and updates your workflow files. If gx.toml exists, also syncs the manifest and lock file.
init
Creates gx.toml and gx.lock from your current workflows for reproducible team builds.
upgrade
Checks for newer versions of pinned actions and upgrades them. Resolves new SHAs and updates workflows. Skips non-semver versions.
lint
Checks workflows for issues without modifying anything. Useful in CI to enforce pinning policies.
Rules:
unpinned(error) - action uses a tag or branch instead of a SHAsha-mismatch(error) - SHA in workflow does not match the lock filestale-comment(warn) - version comment does not match the current tagunsynced-manifest(error) - manifest is out of sync with workflows
Configuration
gx operates in two modes:
- Memory-only (no
gx.toml): Scans workflows, resolves SHAs, and updates workflow files in place. - File-backed (with
gx.toml): Maintains a manifest (.github/gx.toml) and lock file (.github/gx.lock) for reproducible builds across your team.
For details on the manifest format, hierarchical overrides, and lock file schema, see the DeepWiki documentation.
Global options
-v, --verbose- Enable verbose output--version- Print version
FAQ
Do I need a GITHUB_TOKEN?
No, but without it you are limited to 60 unauthenticated GitHub API requests per hour. For most projects gx tidy finishes well within that limit. Set GITHUB_TOKEN to avoid rate limits in CI or for large repos.
Create a token with no extra scopes required (public repo access is enough).
Do I need a gx.toml manifest?
No. gx tidy works without any configuration. The manifest is optional and exists for teams that need reproducible builds: it locks every action to a specific SHA so that everyone on the team resolves the same versions.
How do I use gx in CI?
Add gx lint as a step in your CI workflow to enforce pinning policies on every PR:
- name: Check action pins
run: gx lint
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Run gx tidy locally (or in a scheduled workflow) to keep pins up to date.
How does gx compare to Renovate and Dependabot?
These tools are complementary, not competing:
| Tool | Approach | Scope |
|---|---|---|
| Renovate / Dependabot | Bot, opens PRs on a schedule | All dependency types (npm, Docker, Actions, ...) |
| gx | CLI, rewrites in place | GitHub Actions only |
Key differences between gx and the bots:
- Initial SHA pinning: Dependabot cannot do initial SHA pinning (open feature request since 2021). gx handles this with
gx tidy. - Manifest + lock system: gx tracks every pinned SHA in a lock file, similar to
go.sum. This makes auditing and reproducibility straightforward. - Structured lint:
gx lintcan block CI on unpinned actions or SHA mismatches, giving you a policy enforcement layer. - Hierarchical overrides:
gx.tomlsupports per-workflow and per-job version overrides.
Need help?
Contributing
See docs/CONTRIBUTING.md for setup instructions and guidelines.