Inspect and run checks with chainctl
Read a pull request's Chainguard Checks results and logs from your terminal, run checks on a pushed commit without a …
For the complete documentation index, see llms.txt.
The chainctl checks commands read your pull requests’ results from your terminal, start and rerun checks, summarize your checks’ history, and validate your configuration. This page lists each command’s arguments, flags, exit codes, and JSON output. For examples of the commands in use, refer to Inspect and run checks with chainctl.
During the beta, the chainctl checks and chainctl develop commands don’t appear in chainctl --help or in the chainctl reference. You can still run them, and --help on either one shows its full help.
For example, run chainctl checks status --help. You can also type chainctl ci instead of chainctl checks. If chainctl doesn’t recognize a command or flag on this page, update chainctl.
The examples on this page use acme/app#123 for a pull request. Replace $ORGANIZATION with the name of your Chainguard organization.
| Command | What it does |
|---|---|
chainctl checks status | Shows a run and whether each of its checks passed. |
chainctl checks logs | Prints a run’s check logs, or part of one. |
chainctl checks trace | Shows the programs that each step of a check started. |
chainctl checks events | Prints the events that one attempt at a check recorded. |
chainctl checks describe | Shows where a run came from, its status, and each of its checks. |
chainctl checks list | Lists the runs you started with chainctl checks run. |
chainctl checks run | Runs a pushed commit’s checks without a pull request. |
chainctl checks rerun | Reruns a pull request’s latest run. |
chainctl checks cancel | Cancels a run you started with chainctl checks run. |
chainctl checks stats | Counts the outcomes of your organization’s newest runs. |
chainctl checks top | Ranks your organization’s checks over a window of time. |
chainctl checks trends | Shows how long checks take, hour by hour. |
chainctl checks validate | Finds problems in your configuration without running anything. |
chainctl checks explain | Prints each check as Chainguard Checks reads it. |
chainctl checks migrate | Drafts a configuration from your GitHub Actions workflows. |
chainctl checks accept-terms | Accepts the terms that Chainguard Checks is offered under. |
Every command on this page except validate, explain, migrate --dry, and accept-terms needs the owner or sandbox.user role in the Chainguard organization linked to the repository’s GitHub account. Without one of these roles, the commands fail with permission denied. To get a role, refer to Give teammates access.
If you created a Starter organization with chainctl develop init, you have the limited_owner role instead. It can start runs with chainctl checks run, which use your allowance, but can’t read any run, so don’t use chainctl checks run there. Read the results on GitHub instead, as described in The Details link or a chainctl checks command says you don’t have access.
The validate, explain, and migrate --dry commands read only your local checkout, so they don’t need a Chainguard account or network access.
The commands that need a role take --parent with the name or ID of your Chainguard organization. To use the name, you also need a role that can see the organization, such as viewer. With sandbox.user alone, pass the organization’s ID. Without --parent, chainctl uses the CHAINCTL_SANDBOX_GROUP environment variable, then the default.group value in your chainctl configuration. If neither is set, it asks you to choose an organization.
Most commands that read runs take a REF argument that names the run. During the beta, use one of the following forms:
REF | Example | What it names |
|---|---|---|
| A pull request | acme/app#123, or https://github.com/acme/app/pull/123 | The pull request’s newest run. Capitalize the owner and repository the same way GitHub does. |
| A run ID | $RUN_ID | One run. For a run after merging, use the whole ID after /runs/ in the Details link of Chainguard Checks (postsubmit). For a run you started with chainctl checks run, you can use the start of its ID. |
The chainctl checks status -o json command prints the run’s full name in its run field. Pass that name to the other commands to keep reading the same run after someone pushes to the pull request.
The commands also accept a directory, which stands for the commit checked out there, or a full commit SHA. During the beta, these never find your repositories’ runs, so the commands report that the platform created no run, even when checks ran. Without a REF, the commands use the current directory, so pass a pull request or a run ID instead. Refer to chainctl checks status reports no platform verdict.
To print JSON for a script or a coding agent, add -o json, which is short for --output json. Each command’s section describes its JSON.
On a terminal, commands that print your repository’s output remove escape sequences and other control characters from it. To keep them, add --raw to a command that takes it. When the output isn’t a terminal, such as when you pipe it to a file, the commands always print it as it is.
Unless a command’s section says otherwise, it exits with 0 when it succeeds and 1 when it fails.
Shows a run and whether each of its checks passed.
chainctl checks status REF [--watch]| Flag | Description |
|---|---|
--watch | Waits until the run finishes, and prints the checks again each time they change. |
For example, to wait for a pull request’s checks to finish:
chainctl checks status acme/app#123 --watch --parent $ORGANIZATIONThe output marks a failed advisory check as (advisory), and shows the label that runs each check that runs only on request. The command exits with one of the following codes:
| Exit code | Meaning |
|---|---|
0 | The run passed, or it’s still running and you didn’t add --watch. |
1 | The run finished and a blocking check didn’t pass, or the command failed. |
2 | Chainguard Checks created no run for the REF. |
With -o json, the command prints one object, the final one with --watch. It has the run’s run, repository, revision, pull_request, phase, and outcome, and failed, which is true when the command exits with 1. Its checks list has each check’s workflow, check, phase, and outcome, plus exit_code, advisory, and request_label when they apply. When there’s no run, the object’s status is no platform verdict.
Prints the combined standard output and standard error of a run’s checks, followed by the errors, warnings, and notices each check reported, as described in Report errors and annotations. Without --check, the command prints every check’s log, each after a line that names the check.
chainctl checks logs REF [--check CHECK [--workflow WORKFLOW]] [--follow] [--attempt N] [--raw]
chainctl checks logs REF --check CHECK (--errors | --grep RE) [-C N] [--max N] [--offset BYTES]
chainctl checks logs REF --check CHECK --tail N
chainctl checks logs REF --check CHECK --offset BYTES [--limit-bytes N]| Flag | Description |
|---|---|
--check | Prints only this check’s log. |
--workflow | Names the file of the check, when two files in the directory layout have a check with that name. |
-f, --follow | Keeps reading a running check’s output until it finishes, and waits for a check that hasn’t started. Without --check, it keeps reading until every check in the run finishes. |
--attempt | Reads this attempt of a check that ran more than once, such as 1 for the first. Needs --check. |
--errors | Shows only error lines, such as ::error lines and error-level JSON or logfmt lines. If the log has none, the command shows its last 30 lines. |
--grep | Shows only the lines that match this RE2 regular expression, reading at most 64 MiB of the log. |
-C, --context | With --errors or --grep, shows this many lines before and after each line. |
--max | With --errors or --grep, shows at most this many lines, 10 error lines or 20 matching lines by default. |
--tail | Shows the log’s last lines, up to this number or 16 KiB. |
--offset | Starts --errors or --grep at this byte of the log, or reads the log from this byte. |
--limit-bytes | With --offset, reads this many bytes, 64 KiB by default. |
--raw | Prints the log as it is, including escape sequences, even on a terminal. |
The --errors, --grep, --tail, --offset, and --limit-bytes flags read part of one check’s log, so they need --check, and you can’t combine them with --follow. Use only one of --errors, --grep, and --tail at a time. Each excerpt starts with the byte range it covers. If the command leaves lines out, it says so, and gives the --offset to continue from.
For example, to show a failed check’s error lines with three lines around each one:
chainctl checks logs acme/app#123 --check test --errors -C 3 --parent $ORGANIZATIONThe -o json flag works only with --errors, --grep, --tail, --offset, or --limit-bytes. The command then prints one JSON object per line: one with type set to excerpt for each excerpt, with its check, attempt, offset, end_offset, and text, followed by one with type set to summary. The summary says how much the command showed, whether it left anything out, and the next_offset to continue from.
Shows the programs that each step of a check started, with each program’s name, how long it ran, and how it exited. Chainguard Checks records program names, never their arguments. For a failed step, the output names the program that most likely failed it. This guess comes from the recorded programs, so it can be wrong, such as when a shell or build tool ignores a program’s exit code.
chainctl checks trace REF [--check CHECK [--workflow WORKFLOW]] [--failed]| Flag | Description |
|---|---|
--check | Shows only this check’s steps. Without it, the command shows every check that has recorded programs. |
--workflow | Names the file of the check, when two files in the directory layout have a check with that name. |
--failed | Shows only failed steps, each as the path from the step’s command to the program that most likely failed it. |
For example:
chainctl checks trace acme/app#123 --check test --failed --parent $ORGANIZATIONA trace marked INCOMPLETE lost some of its records, or chainctl cut it to fit, so parts of it might be missing. With -o json, the command prints one JSON object per line for each step, with the step’s workflow, check, step number, and its tree of programs in document.
Prints the events that one attempt at a check recorded, in order: when its setup, each of its steps, and each program that a step started began and ended, and any diagnostics attached to them.
chainctl checks events REF --check CHECK [--workflow WORKFLOW] [--attempt N]| Flag | Description |
|---|---|
--check | The check to print events for. Required. |
--workflow | Names the file of the check, when two files in the directory layout have a check with that name. |
--attempt | Reads this attempt instead of the latest one. |
For example:
chainctl checks events acme/app#123 --check test --parent $ORGANIZATIONWith -o json, the command prints the events as the API returns them.
Shows where a run came from, its status, and each of its checks.
chainctl checks describe RUN [--steps] [--events]RUN is a run ID, as described in Name a run. The command doesn’t take a pull request, so to describe a pull request’s run, pass the run field that chainctl checks status -o json prints.
| Flag | Description |
|---|---|
--steps | Adds each check’s steps. |
--events | Adds the run’s events, and how long each attempt spent queued, waiting for a free slot, booting its VM, setting up, and running its steps. |
For example:
chainctl checks describe $RUN_ID --events --parent $ORGANIZATIONWith -o json, the command prints one object with the run, its workflow_runs, and with --events, its events, as the API returns them.
Lists the runs you started with chainctl checks run, newest first. During the beta, it doesn’t list pull request runs or runs after merging.
chainctl checks list [--repo REPO] [--outcome OUTCOME] [--limit N]| Flag | Description |
|---|---|
--repo | Lists only runs of this repository, such as acme/app. |
--outcome | Lists only finished runs with this outcome: passed, failed, errored, dependency_failed, or cancelled. It searches the 500 newest runs. |
--limit | Lists at most this many runs, 20 by default. |
For example:
chainctl checks list --repo acme/app --outcome failed --parent $ORGANIZATIONWith -o json, the command prints a list with one object for each run, with its run, create_time, repository, revision, phase, and outcome.
Runs a commit’s checks in Chainguard Checks without a pull request. The commit must be pushed to GitHub, because Chainguard Checks reads its configuration from there through your organization’s link to the repository’s GitHub account. To run checks against uncommitted changes, use chainctl develop check instead, as described in Run checks in a session from your laptop.
chainctl checks run [DIR] [--check CHECK [--workflow WORKFLOW]] [--request CHECK]... [--git-remote NAME] [--base REV] [--watch]DIR is a local checkout, the current directory by default. The command runs the commit checked out there, in the github.com repository of its origin remote.
| Flag | Description |
|---|---|
--check | Runs only this check and the checks it needs, including a check that runs only on request. |
--workflow | Names the file of the check, when two files in the directory layout have a check with that name. |
--request | Runs this check if it runs only on request, as a ci/run: label does on a pull request. Repeat the flag for more checks. |
--git-remote | Uses the github.com repository of this remote instead of origin, such as upstream in a checkout of a fork. |
--base | The commit that when.changed conditions compare against. By default, it’s where the commit branched from the remote’s default branch, or the commit’s parent if the commit is on that branch. |
--watch | Waits until the run finishes, and prints the checks again each time they change. |
For example, to run the test check and wait for its result:
chainctl checks run . --check test --watch --parent $ORGANIZATIONThe run doesn’t report to GitHub, and it never counts as a pull request’s or commit’s result. It uses your organization’s Checks allowance like any other run. Because the run has no pull request, the command refuses a check whose when.expr condition reads the trigger, the pull request, or its labels.
The command prints the run’s name, followed by its checks. The run’s ID is the part of the name after /runs/. Pass the ID to chainctl checks status, cancel, or the other commands that read runs. With --watch, the command exits with 1 when a blocking check doesn’t pass. With -o json, it prints the run as the API returns it, or with --watch, the run’s final status in the same form as chainctl checks status -o json.
Reruns a pull request’s latest run after it finishes, the same way as Re-run on GitHub. Refer to Rerun checks for what reruns and how to follow the new run.
chainctl checks rerun REFDuring the beta, REF must be a pull request. The command can’t rerun runs after merging or runs you started with chainctl checks run. To run checks after merging again, push or merge a new commit to your default branch. To repeat a run you started with chainctl checks run, run that command again.
For example:
chainctl checks rerun acme/app#123 --parent $ORGANIZATIONWith -o json, the command prints the run whose checks it reruns, as the API returns it.
Cancels a run you started with chainctl checks run, stopping its checks that are queued or running. You can’t cancel a run that has finished.
chainctl checks cancel RUNRUN is the run’s ID, or the start of it. During the beta, you can’t cancel pull request runs or runs after merging with chainctl. A new push to a pull request cancels the run for the previous push.
For example:
chainctl checks cancel $RUN_ID --parent $ORGANIZATIONWith -o json, the command prints the run as the API returns it.
The stats, top, and trends commands summarize your organization’s checks across runs. For examples, refer to See check history.
The top and trends output starts with the window it read and how current its data is, because the newest attempts can take time to appear. The first time you run either command, chainctl might ask you to sign in again. Without a terminal to sign in at, such as in a script, the command fails and prints the chainctl auth login command to run first.
Counts the outcomes of your organization’s newest runs, by repository and by check.
chainctl checks stats [--limit N]| Flag | Description |
|---|---|
--limit | Counts at most this many runs, 500 by default and 2,000 at most. |
In the output, OPEN counts runs or checks that haven’t finished, and RUNNING is the part of OPEN that’s running. FAIL% is the share of failed results among the results that passed or failed, so checks that are still running, were canceled or skipped, or couldn’t finish don’t change it. CONFIGS counts the different configurations a repository’s runs used.
With -o json, the command prints one object with the number of runs it read and a repositories list. Each repository has its name, counts, configs, and a checks list with each check’s name, counts, and median_seconds. Each counts object has total, passed, failed, errored, dependency_failed, not_instantiated, cancelled, open, and running.
Ranks your organization’s checks over a window of time.
chainctl checks top [--repo REPO] [--since DURATION | --from TIME --to TIME] [--by count|runtime|failures] [--limit N]| Flag | Description |
|---|---|
--by | Ranks checks by their number of attempts (count), their total runtime (runtime), or their failure rate (failures). The default is runtime. Only a check with at least 100 attempts in the window has a failure rate. |
--repo | Ranks only checks of this repository, such as acme/app. |
--since | Reads the window that ends now and lasts this long, such as 7d or 36h. The default is 14d, and the longest is 31d. |
--from, --to | Reads the window between these RFC 3339 times, such as 2026-10-01T00:00:00Z. Use both together, for a window of up to 31 days. |
--limit | Shows at most this many checks, up to 20, which is the default. |
A check’s failure rate is the share of its attempts that failed or couldn’t finish, such as by timing out. Attempts include retries, but not attempts whose result Chainguard Checks reused from an earlier run.
With -o json, the command prints one object with the window, when the data was generated (generatedAt), the ranking (by), and a checks list. Each check has its job_ref, name, attempts, failed, errored, runtime_seconds, and failure_rate, which is null for a check with fewer than 100 attempts.
Shows the median, 95th percentile, and 99th percentile durations of checks for each hour of a window, for the 10 checks with the most total runtime in that window. Hours with no attempts don’t appear.
chainctl checks trends [--repo REPO] [--since DURATION | --from TIME --to TIME] [--check CHECK]| Flag | Description |
|---|---|
--check | Shows only this check. A check outside the 10 has no trend. |
--repo | Shows only checks of this repository, such as acme/app. |
--since | Reads the window that ends now and lasts this long, such as 7d or 36h. The default is 14d, and the longest is 31d. |
--from, --to | Reads the window between these RFC 3339 times. Use both together, for a window of up to 31 days. |
With -o json, the command prints one object with the window, generatedAt, and a trends list with one object for each check and hour. Each object has the check’s job_ref, the hour, the number of attempts it measured in samples, and the median_seconds, p95_seconds, and p99_seconds durations.
Finds problems in your configuration without running anything, the way Chainguard Checks reads it for a pull request, with the differences described in Validate your configuration offline. That section also shows the command’s output.
chainctl checks validate [PATH]PATH is a repository’s root directory, a configuration file under its .chainguard/ directory, or a standalone configuration file. For a file under .chainguard/, the command validates its repository’s whole configuration. Without PATH, the command validates the repository that the current directory is in.
For example, to validate another repository’s configuration:
chainctl checks validate ../appThe command exits with 1 when the configuration has a problem that Chainguard Checks would refuse. Warnings, such as for a key that Chainguard Checks ignores, don’t change the exit code. With -o json, the command prints one object with the repository’s root, the problems that kept it from reading the configuration in diagnostics, and a workflows list. Each workflow has its workflow name, its path, its refusals and warnings, problems with needs in graph, and ok. The object’s own ok is true when the whole configuration is valid.
Prints each check as Chainguard Checks reads it for a pull request, with its environment, trigger, steps, and resource class, without running anything.
chainctl checks explain [DIR] [--raw]DIR is the repository’s root directory. Without it, the command reads the repository that the current directory is in.
| Flag | Description |
|---|---|
--raw | Prints check names, commands, and other text from your repository as they are, including escape sequences, even on a terminal. |
If Chainguard Checks would refuse the configuration, the command prints each problem with its file and position, and exits with 1. With -o json, it prints the resolved configuration, or the problems when it’s refused.
Drafts a .chainguard/ci/migrated.yaml file from your repository’s GitHub Actions workflows that run on pull_request. Refer to Migrate from GitHub Actions to Chainguard Checks for how to review the draft.
chainctl checks migrate [PATH] --dryPATH is a local clone whose origin remote is on github.com, the current directory by default. The --dry flag drafts the file and prints it, followed by a list of what the draft carried over, flagged, and ignored, without running anything.
For example, to write the draft to its file:
mkdir -p .chainguard/ci
chainctl checks migrate --dry -o json | jq -r .document > .chainguard/ci/migrated.yamlWith -o json, the command prints one object with the repository, revision, the draft’s path, the number of jobs it drafted, the draft itself in document, and the ledger of what it carried over, flagged, and ignored.
Accepts the terms that Chainguard Checks is offered under for your organization: the Code Analysis Terms and the Master Service and License Agreement. An owner of the organization runs it once. The chainctl develop init command also asks you to accept these terms, as described in Get started with Chainguard Checks.
chainctl checks accept-terms [--parent ORGANIZATION] [--yes]| Flag | Description |
|---|---|
--parent | The organization to accept the terms for. Without it, the command uses the default.group value in your chainctl configuration, or asks you to choose. |
--yes | Accepts the terms without asking, for use without an interactive terminal. By adding it, you agree to the statement in the command’s help, which it also prints. |
For example:
chainctl checks accept-terms --parent $ORGANIZATIONRunning the command again after the organization accepts the terms changes nothing.
Last updated: 2026-10-13 15:17