For the complete documentation index, see llms.txt.

Get started with Chainguard Checks

Sign up for Chainguard Checks, add checks to one of your GitHub repositories, and see them run on a pull request.
  8 min read

Get a first check passing with the quick start, or learn each part in the step-by-step guide.

Quick start

  1. Install chainctl

    To install chainctl with Homebrew, run the following command:

    brew install chainguard-dev/tap/chainctl

    Or, to install it with curl on macOS or Linux, run the following commands:

    curl -fL -o chainctl "https://dl.enforce.dev/chainctl/latest/chainctl_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/aarch64/arm64/')"
    sudo install -o $UID -g $(id -g) -m 0755 chainctl /usr/local/bin/

    If you already have chainctl, you need 0.2.386 or later. Update it with sudo chainctl update, or with brew upgrade chainctl if you installed it with Homebrew.

  2. Sign up

    In the root of a local clone of a GitHub repository that you can push to, run the following command:

    chainctl develop init

    The command creates your Chainguard organization, if you don’t have one, and turns on Chainguard Checks. When it asks which GitHub account to link, choose the one that owns your repository: press Enter for your own user, or enter the organization’s name. If the Chainguard App isn’t installed on that account, the command offers to open its installation page. Give the App access to your repository. If you installed it earlier and GitHub shows that it’s asking for more permissions, accept them. To sign in with an email address and password, first run chainctl config set default.social-login email.

  3. Add a first check

    Create a branch and a .chainguard/ci.yaml file with one check:

    git checkout -b add-chainguard-checks
    mkdir -p .chainguard
    cat > .chainguard/ci.yaml <<'EOF'
    version: 1
    environment: {}
    checks:
      hello:
        cmd: ls -la
    EOF

    The check lists the files in its working directory and needs no packages or network access, so it passes on any repository.

  4. Open a pull request

    Commit the file and push the branch:

    git add .chainguard/ci.yaml
    git commit -m "Add Chainguard Checks"
    git push -u origin add-chainguard-checks

    Then open a pull request, from the link that git push prints or on github.com.

  5. Read the result

    On the pull request’s Checks tab, wait for Chainguard Checks (presubmit) to appear and pass, which usually takes less than a minute. It’s the only check that Chainguard Checks adds for this file, because a check that passes without reporting anything gets no GitHub check of its own. Select it to see the run’s summary: its title reads All 1 check(s) passed, and its table lists hello as passed. If no check appears, refer to A pull request gets no checks.

To replace the first check with your own, refer to Replace the first check with your own. To move checks from your GitHub Actions workflows, refer to Migrate from GitHub Actions.

Note: Chainguard Checks is in beta. Available to organizations that turn it on with chainctl develop init, which comes with a free monthly compute allowance, or that arrange access with their Chainguard account team.

Step-by-step guide

The following steps add the same first check as the quick start and explain each part. If you followed the quick start, skip to Step 4.

Step 1: Sign up

Sign up as described in Set up Chainguard Checks and Chainguard Workspaces. You install or update chainctl, install the Chainguard App on the account that owns your repository, and run chainctl develop init, which turns on Chainguard Checks and Chainguard Workspaces together. You also need a local clone of a repository on github.com that you can push to.

Step 2: Add a configuration file to your repository

In your local clone, create a branch for the change. Replace $REPO_DIR with the path to your local clone:

cd $REPO_DIR
git checkout -b add-chainguard-checks

Next, create a .chainguard/ci.yaml configuration file that defines one check:

mkdir -p .chainguard
cat > .chainguard/ci.yaml <<'EOF'
version: 1
environment: {}
checks:
  hello:
    cmd: ls -la
EOF

This file defines one environment and one check, named hello. Every file that has checks needs an environment key, and environment: {} is the smallest one: a bare root filesystem with no packages added. Each check runs in a fresh VM with no network access unless it asks for some, and hello doesn’t need any. It runs ls -la, which lists the files in its working directory, so it passes on any repository. A string cmd runs without a shell, so it can’t use pipes, redirects, or variables. To run a command through a shell, write it as a list, such as cmd: [sh, -c, "ls -la | head"]. Refer to the configuration reference for every option.

To find mistakes in the file before you push it, run chainctl checks validate with the repository’s directory:

chainctl checks validate .

The command reads the file the same way Chainguard Checks does, without running anything. For this file, it prints workflow ci (.chainguard/ci.yaml) followed by ok: the document lowers. For a file with problems, it prints each problem with its line number.

Step 3: Open a pull request

Commit the file and push the branch:

git add .chainguard/ci.yaml
git commit -m "Add Chainguard Checks"
git push -u origin add-chainguard-checks

Then open a pull request, from the link that git push prints or on github.com. If you use the GitHub CLI, gh pr create --fill also opens one.

Chainguard Checks reads the configuration file from the pull request itself, so the pull request that adds .chainguard/ci.yaml runs its checks.

Step 4: Review the results

Open the pull request on GitHub and scroll to its checks. Within about a minute, you’ll see the following:

  • Chainguard Checks (presubmit), the summary check for the whole run. It’s pending while checks run, then passes only if every blocking check passed.
  • presubmit / ci / hello, for a check that doesn’t pass or that reports errors, warnings, notices, or a summary. A check that passes without reporting anything appears only in the summary check’s output.

To read a check’s output, select the check. On GitHub, its output shows each step’s outcome, exit code, and duration, followed by the end of its log and any errors it reported. The Details link opens the check’s full log on a run page that Chainguard hosts. To open the run page, you need a role in your Chainguard organization, as described in The Details link or a chainctl checks command says you don’t have access. If you created your organization with chainctl develop init, you don’t have that role, so read the output on GitHub.

If no checks appear, refer to Troubleshoot Chainguard Checks.

Step 5: Require checks before merging

To block merging until checks pass, add Chainguard Checks (presubmit) as a required status check in your branch protection rule or ruleset for the default branch. GitHub lists the check there only after it has run in the repository within the past week. For where to find these settings on GitHub, refer to GitHub’s Managing a branch protection rule or Creating rulesets for a repository.

Require only the summary check, not the per-check results. A check that passes without reporting anything, or that a condition skips, never reports a result of its own, so GitHub would wait for it indefinitely. The summary check accounts for skipped checks.

Replace the first check with your own

Once the first check passes, replace it with the checks your repository needs. For example, if your repository is a Go module, with a go.mod file at its root, the following .chainguard/ci.yaml file runs go vet and go test as two checks:

.chainguard/ci.yaml
version: 1
environment:
  packages: [go]
checks:
  vet:
    cmd: go vet ./...
    network:
      egress: [proxy.golang.org, sum.golang.org]
  test:
    cmd: go test ./...
    network:
      egress: [proxy.golang.org, sum.golang.org]

This file tells Chainguard Checks to install the go package in each check’s VM, then run go vet in one check and go test in another. Both checks list the Go module proxy and checksum database under network.egress to download the modules your code depends on. In a repository that isn’t a Go module, both commands fail, so use your own packages and commands instead.

Run chainctl checks validate . again, then commit and push the change. Chainguard Checks runs the new checks on the pull request when it’s updated.

Give teammates access

Your teammates don’t need a Chainguard account to get checks on their pull requests or to read the results on GitHub. A teammate needs a role in your Chainguard organization only to open the run page, to use chainctl checks commands such as status and rerun, or to run checks in a Workspaces session. To give them one, refer to Give teammates access.

Next steps

Last updated: 2026-11-04 17:00