actionlint

NAME

actionlint - static checker for GitHub Actions workflow files

SYNOPSIS

actionlint [flags] [--] [files... | -]
actionlint check [flags] [--] [files... | -]

DESCRIPTION

actionlint checks GitHub Actions workflow files without executing the workflows. This is the maintained kjanat/actionlint fork, distributed as the Go module actionlint.kjanat.dev/v2.

Checks include workflow syntax, expression types and context availability, action inputs and outputs, local action metadata and composite steps, reusable workflow inputs and permissions, job dependencies, parallel steps, runner labels, event filters, schedules, and YAML anchors. Security checks report potentially unsafe expression interpolation in scripts and hard-coded credentials. Optional ShellCheck integration check scripts in run: steps.

Repository policy checks can require immutable action references, job timeouts, and particular actions. These checks are enabled explicitly in the configuration file. Cache safety policies are enabled by default; ordinary workflow checks do not require configuration.

USAGE

With no paths, actionlint and actionlint check find the current repository containing both .git and .github/workflows, then recursively check workflow YAML files in that directory. Explicit file arguments and a lone - for stdin remain supported. Passing a directory does not enable recursive input expansion; action manifests are also discovered and can be passed as explicit inputs.

$ actionlint
$ actionlint file1.yaml file2.yaml
$ actionlint check file1.yaml --output-format=json
$ actionlint check --stdin-filename .github/workflows/ci.yml -

The root and check accept options before or after filenames. -- forces subsequent arguments to be filenames. An existing regular file named like a command takes precedence on the root. The hidden --command NAME escape explicitly selects a command in that case.

actionlint --help shows common options and commands. Run actionlint check --help for all checking options, which the root invocation also accepts.

COMMANDS

fix [--apply] [--include-suggested] [FILES...]
Preview edits as JSON; apply validated edits explicitly and recheck changed sources.
lsp
Serve versioned editor buffers, diagnostics and quick fixes over stdin/stdout.
plugin search [QUERY], plugin versions PLUGIN
Discover canonical repository names and exact published tags from the registry. Use --registry to select a compatible HTTPS catalogue. --json includes host-specific compatibility evidence when listing versions.
plugin install [PLUGIN] [--version TAG|latest]
Declare a dependency in the config's root plugins list and download it without executing it. Accepts owner/repo@tag and forge-qualified names. Save its exact version, URL, publisher identity and SHA256 in the adjacent actionlint.plugins.lock.json. Commit config and lock. Without a name, install declared dependencies, preserving matching pins; migrate older lock-only projects. The default selector for new dependencies is the highest stable full semantic version; prereleases and arbitrary tags require exact selection. Admission does not prove runtime compatibility. Runner targets still require explicit selection.
plugin list, plugin update [PLUGIN], plugin remove PLUGIN, plugin sync
List declared pins offline; resolve declared versions and update pins; remove a declaration and its pin; or restore exact declared pins without catalogue access. Update accepts --version for one named plugin. Exact selectors stay exact; latest cannot downgrade unless an exact tag is explicitly selected. Failed updates preserve the old lock. Checks restore missing pinned artifacts and reuse verified cached bytes offline. Only declared plugins load automatically. Missing or mismatched pins require plugin install. Removal leaves the shared cache intact. Use --config for a custom config or outside a repository. Management rejects --no-config.
plugin inspect PATH-OR-URI
Read artifact metadata without executing a guest.
check [flags] [files...]
Check workflows with the modern option grammar. Uses the same engine and repository discovery as the root invocation.
config init
Create .github/actionlint.yaml with its YAML Language Server directive. Refuse to overwrite either supported config filename.
config path
Print the selected configuration path without parsing it, or nothing if absent.
config show [--origin]
Show effective configuration as YAML. --json returns path and config. With --origin, include sources keyed by JSON Pointer: default or config, missing/null/value state, and positions for file settings. Explicit false and empty lists remain distinguishable from defaults and null.
config validate
Validate with the same loader as analysis. This retains existing unknown-key handling; it does not substitute the stricter editor JSON Schema validator.
rules [name]
List checks under Correctness, Security, Suspicious, Policy, and External linters, alphabetically within each group, or explain one check. --json returns the alphabetical array of rule metadata.
doctor
Inspect configuration and external-tool resolution without executing tools. Directory, configuration and executable paths use file:// links when hyperlinks are enabled. Link targets support Windows drive and UNC paths and encode special characters. Missing optional tools are reported; malformed selected config returns status 3.
completion shell
Print the generated completion script for the selected shell.
version
Show version and build details. Supports --json.

FLAGS

--resolve-with EXECUTABLE
Opt in to remote dependency resolution with a literal provider executable.
--resolver-arg VALUE
Pass a literal argument to the resolver. Repeat for multiple arguments.

These options belong to the root and to check, unless noted otherwise. Root parsing retains the original single- and double-dash spellings; check uses long options and short aliases. Run --help-legacy for old spellings.

--output-format, --output, -o MODE
Select text, oneline, json, jsonl, sarif, or github. The default is text. --output is a supported alias. JSON emits a versioned analysis result with completion status, diagnostics, and configuration context. JSONL emits one diagnostic per line. GitHub annotations are emitted only when explicitly selected.
--json
Select JSON output. With help, version, config, rules or doctor, emit JSON metadata. Operational errors are JSON objects on stderr.
--json-pretty[=BOOL]
Format JSON and SARIF on a terminal with installed jq. Default: true. False keeps the original JSON. Unavailable or failing jq falls back to built-in output. Explicitly enabling this flag also selects JSON if no other output format is specified. The default value and --json-pretty=false do not select JSON. Explicit true also indents JSON in pipes and files without color codes or a jq dependency. Without an explicit pretty flag, pipes and files keep their original output. JSONL, templates and stderr records keep their existing format.
--template, --format, -f TEMPLATE
Render diagnostics with a Go template. Existing template fields and functions remain unchanged, including the JSON array returned by {{json .}}. Cannot be combined with a built-in output selector. A nonempty template takes precedence over the legacy --oneline option.
--template-file PATH
Read a Go template from a file. Cannot be combined with an inline template.
--output-file PATH
Write results to the given path. - means stdout. An existing destination prompts Overwrite? [y/N] in an interactive terminal before analysis. Enter or a negative answer keeps the file and stops the check. Replacement happens only after analysis completes, including analysis that found problems. A failure preserves a previous report. The output cannot also be a selected input.
-y, --yes
Answer yes to confirmation prompts. Required to replace an existing report when stderr is not a terminal or when - supplies workflow stdin. Confirmation never consumes workflow input. Piping yes also works in an interactive terminal.
--command NAME
Select a command explicitly when a file has the same name.
--color[=MODE]
On check, select auto, always, or never; a bare flag means always. On the root, retain the boolean syntax: -color=false does not force color on. Help uses the same controls: automatic styling follows stderr's terminal status, NO_COLOR, and TERM=dumb. With GITHUB_ACTIONS=true, help and text diagnostics also use color in workflow logs without a terminal, even with TERM=dumb. Regular files and --output-file reports stay plain in auto mode; custom templates receive no added color. Put root color flags before --help. Redirected structured output contains no terminal color codes. Optional jq formatting can color JSON and SARIF written directly to a terminal.
--no-color
Disable color. This supported legacy option wins over the root's --color boolean regardless of argument order.
--hyperlinks MODE
Select auto (default), always, or never for OSC 8 links in help and doctor. always and never override the environment. In auto, non-empty NO_HYPERLINKS disables links before non-empty FORCE_HYPERLINKS enables them; otherwise the output must be a TTY with a known capable terminal (stderr for help, stdout for doctor). Unknown terminals and multiplexers default to plain URLs. Explicit always can enable links through a multiplexer configured to pass them through. Color controls are independent. Destination URLs stay visible when links are disabled. JSON, diagnostics, templates, version output and generated completion scripts receive no added hyperlink sequences. Put root flags before --help. See https://no-hyperlinks.org/spec for the convention.
--config, --config-file PATH
Select the configuration file. This takes precedence over repository discovery. --config-file is the supported legacy name. Also available on config and doctor.
--no-config
Use defaults without loading a configuration file. Cannot be combined with a nonempty explicit config path. Also available on config and doctor.
--ignore-regex, --ignore REGEXP
Suppress findings whose messages match this Go regular expression. Repeat to add patterns. --ignore is the supported legacy name.
--plugin PATH
Load a WebAssembly component plugin that implements kjanat:actionlint/analyzer@0.1.0 or kjanat:actionlint/runner-provider@0.1.0. Repeat to load several. Each analysis runs in a fresh instance with 64 MiB of memory and 10 seconds; a trap, an exit or an exceeded limit fails that document's analysis.
--plugin-lock FILE
Explicitly load every pin from this lock, bypassing config declarations. Available on check, fix, rules, lsp and plugin management commands. Cannot accompany --plugin. Explicit --plugin sources replace automatic lock selection; --no-config disables automatic selection. Explicit --config selects its declarations and adjacent lock. On management commands, --plugin-lock places a default config beside that lock unless --config selects another file. LSP snapshots selection until restart. See the plugin commands.
--registry URL
Select an HTTPS static catalogue for plugin search, plugin versions or plugin install. Default: https://plugins.actionlint.kjanat.dev/.
--runner-target TARGET
Select the runner execution target. Defaults to github; installing a provider does not change the target. Also available on lsp.
--runner-provider NAME
Select the authoritative runner provider for the target. Ambiguous providers require an explicit selection. Also available on lsp.
--runner-snapshot FILE
Read a fixed JSON evidence envelope containing content, scope, obtained_at, freshness (fresh, stale, or missing) and complete. Maximum 8 MiB. The content is provider-specific. Restart the language server to refresh evidence. Also available on lsp.
--runner-scope SCOPE
Set the organization/repository evidence scope. Defaults to the project root. The snapshot and provider answers must match this scope. Also available on lsp.
--stdin-filename PATH
Set the path used for stdin diagnostics and project detection. The default is <stdin>. Use an existing workflow path to select its repository context.
--log-level LEVEL
Select none, info, or debug. The default is none.
--quiet, -q
Suppress progress, debug logs and summaries. Requested results and operational errors remain visible. Also available on information and config commands.
--strict
Select all stable rules, preserving explicit group/rule exceptions, bounds, scopes and rule-ID/path suppressions. Includes stable suspicious checks. Does not enable nursery rules or invent required actions. Environment default: ACTIONLINT_STRICT.
--experimental
Enable nursery rules, retaining individual exclusions. Explicit false clears nursery selections without affecting stable suspicious rules. Environment default: ACTIONLINT_EXPERIMENTAL. May be combined with --strict.
--summary
Print selected workflow and finding counts on stderr after checking. In JSON modes this is a JSON record with a summary field. Default: true. Use --summary=false or --quiet to suppress it.
--verbose, -v
Retain legacy progress logging. Prefer --log-level=info on check.
--debug
Retain legacy debug logging. On the legacy route, --verbose wins when both flags are true. An explicit --log-level selects the requested new log level.
--oneline
Retain one-line diagnostic output. Prefer --output-format=oneline.
--shellcheck[=COMMAND]
Check shell scripts with ShellCheck. A bare flag uses shellcheck on PATH. Use --shellcheck=COMMAND for a custom executable or command line. Also available on doctor. Legacy -shellcheck COMMAND remains supported on the root.
--no-shellcheck
Disable ShellCheck, overriding any selected command or environment settings.
--pyflakes COMMAND
Deprecated compatibility option. Selects Ruff's Pyflakes (F) rules when no Ruff option is supplied. An empty command or false disables Python linting. The command value is accepted for compatibility and is never executed.
--ruff[=COMMAND]
Check Python scripts with Ruff. A bare flag uses ruff on PATH. Use --ruff=COMMAND for a custom executable or command line. Ruff must already be installed. Also available on doctor. Legacy -ruff COMMAND remains supported on the root. Uses isolated, read-only checks with Ruff's default rule selection. tools.ruff configures rule selection and the Python target version.
--no-ruff
Disable Ruff, overriding any selected command or environment settings.
--allow-config-processes
Authorize native executables selected by trusted repository configuration, including inherited files and file overrides. Without this flag, selecting tools.<name>.backend.process reports an error before the executable is launched. Explicit CLI and environment tool selections authorize their own executable.

The older --ruff=false, --shellcheck=false, and empty command values remain supported. A disable flag takes precedence when both forms are supplied.

--init-config, --init
Aliases for config init, supported on the root and config command. The positional init and init-config commands invoke the same operation.
--completion, --completions SHELL
Root-only supported aliases for completion SHELL. Accept bash, fish, powershell, zsh, pwsh, shell executable paths, and auto. Cobra generates all four completion scripts. Install bash-completion for Bash and run compinit for Zsh. Regenerate saved scripts after upgrading.
--version, -V
Root-only version flag. Retains its original three-line output. Use the version command for the new presentation or version --json for metadata. Lowercase -v continues to enable verbose logging. On plugin install and plugin update, --version instead takes an exact release tag or latest as described above.
--help, -h
Show grouped help on stderr, or JSON command metadata on stdout with --json.
--help-legacy
Explain supported legacy option spellings and parsing rules without introducing deprecation warnings.

CONFIGURATION

Configuration is optional. In a detected repository, actionlint reads the first of .github/actionlint.yaml, .github/actionlint.yml, .github/actionlint.json and .github/actionlint.toml that exists. --config-file selects a different file; settings are not merged with the repository file or a user-global configuration.

The available settings are:

self-hosted-runner.labels
Additional runner-label patterns. Patterns use Go path.Match glob syntax.
config-variables
Allowed names in the vars context. Omitted or null disables this check; an empty list allows no configuration variables.
config-secrets
Allowed secret names, compared case-insensitively. Omitted or null disables this check. The built-in secrets GITHUB_TOKEN, ACTIONS_STEP_DEBUG, and ACTIONS_RUNNER_DEBUG, and secrets declared in on.workflow_call.secrets, remain allowed even with an empty list.
assume-default-permissions
Permission assumption for a local reusable workflow call when neither the calling job nor its workflow declares permissions. Defaults to restricted, which assumes read access to contents and packages. permissive assumes write access; id-token still requires an explicit grant. This setting does not change the repository's actual GitHub permissions.
paths
Map repository-relative glob patterns to configuration. Patterns use / separators and support ** and brace alternatives. Each entry's ignore list contains message regular expressions, applied in addition to --ignore.
policy.require-commit-hash
When true, require action and reusable workflow references to use 40- or 64-digit hexadecimal commit IDs, and docker:// images to use digests. Local references and expression-based references are skipped.
policy.require-job-timeout
When true, require timeout-minutes on jobs that run steps. A mapping such as { min-minutes: 5, max-minutes: 60 } sets inclusive bounds for literal timeout values. Either bound can be omitted; each must be finite and positive, and the minimum cannot exceed the maximum. Jobs calling reusable workflows are skipped; expression-based timeouts are not compared.
policy.require-permissions
When true or { scope: workflow }, require a workflow-level permissions declaration. Use { scope: job } to require one on every job, including reusable workflow calls, even when the workflow declares permissions. Empty mappings, named scopes, read-all, and write-all satisfy the check. This policy checks declaration presence; it does not infer least privilege.
policy.required-actions
List actions every workflow must use. Entries accept name and ref glob patterns, such as actions/checkout or my-org/security-scan@v2*. Only steps directly in the workflow are searched. Workflows consisting entirely of reusable workflow calls, or containing an expression-based action reference, are skipped.
policy.cache-write-untrusted
Enabled by default. Report explicit cache write grants on low-trust triggers that can access default-branch caches. Set to false to disable this check.
policy.cache-call-unrestricted
Enabled by default. Require an explicit cache access limit on reusable workflow calls under those low-trust triggers. A workflow-level declaration can supply the limit. Set to false to disable this check.
policy.cache-operation
Enabled by default. Report official cache actions disabled by the effective explicit cache mode, including restrictions inherited through nested local reusable workflow calls. Set to false to disable this check.
policy.disallow-suppressions
Prohibit inline exceptions for all cache policies with true, or select a nonempty rules list in a mapping. report selects all (default), suppression, or violation. Omission, null, or false permits inline exceptions.

The three cache policies accept line-scoped exceptions with an exact rule name and a reason:

cache-mode: write # actionlint:ignore cache-write-untrusted -- jobs use reviewed default-branch code only

Alternatively, place # actionlint:ignore-next-line RULE -- REASON immediately before the reported declaration. These directives do not suppress other rules. CLI and configured ignore patterns still apply afterwards. See the configuration document for the full trigger list, cache action modes, nested-call behavior, and suppression controls.

Other policy checks are off until enabled. For example:

self-hosted-runner: { labels: [linux.2xlarge] }
config-variables: [DEFAULT_RUNNER]
config-secrets: [DEPLOY_TOKEN]
assume-default-permissions: restricted
policy:
  require-commit-hash: true
  require-job-timeout: { min-minutes: 5, max-minutes: 60 }
  require-permissions: true
  required-actions: [actions/checkout]
paths:
  ".github/workflows/**/*.{yml,yaml}":
    ignore: ['shellcheck reported issue in this script: SC2086:.+']

The repository supplies actionlint.schema.json for editor completion and validation. See the configuration document below for the schema URL and full matching rules.

EXTERNAL LINTERS

ShellCheck checks supported shell scripts in run: steps. The executables must be available through PATH or the corresponding command flag. If a command cannot be resolved, its integration is skipped; --verbose explains why.

$ actionlint --shellcheck=
$ actionlint --shellcheck='shellcheck -e SC2086'

Command strings are parsed into an executable and arguments, not executed by a shell. Shell pipes and redirections are not supported in these flags. Your arguments precede actionlint's own arguments, so do not supply input filenames or override ShellCheck's output format.

actionlint uses JSON1 output and disables rc-file discovery with --norc by default. Set tools.shellcheck.config to inline settings, an rc-file path, or a directory containing .shellcheckrc or shellcheckrc. An rc path replaces --norc with --rcfile; relative config paths resolve from the selected actionlint configuration file's directory. Additional options can use --shellcheck arguments or SHELLCHECK_OPTS.

ShellCheck runs for recognized bash, sh, dash, and ksh interpreters or a supported dialect selected by a leading # shellcheck shell=... directive. Unresolved explicit shell expressions, unknown wrappers, and non-shell scripts are otherwise skipped. Global dialect settings and command flags alone do not select them. If no shell is configured and the runner platform is unknown, actionlint assumes Bash.

OUTPUT

Diagnostics go to standard output. Command usage, progress logs, and fatal errors go to standard error. The default diagnostic includes the file, line, column, message, rule name, and source snippet. --oneline omits the snippet; --format replaces the diagnostic presentation.

The Go template receives a sequence of errors. Each has Message, Snippet, Kind, Filepath, Line, Column, and EndColumn fields. Line and column numbers start at 1. Custom template functions include json, replace, toPascalCase, allKinds, and getVersion.

JSON:

$ actionlint --json

JSON Lines:

$ actionlint --output jsonl

Custom lines:

$ actionlint --format '{{range .}}{{.Filepath}}:{{.Line}}:{{.Column}}: {{.Message}} [{{.Kind}}]\n{{end}}'

Backslash escapes such as \n in the format string are expanded before the template is parsed.

SARIF uses the bundled template and needs no separate template file:

$ actionlint --output sarif > actionlint.sarif

The CLI's --format accepts template text. The GitHub Action's format input instead accepts names such as json and sarif. Changing output format does not change the lint exit status.

Native JSON returns a versioned analysis result shared with the GitHub Action. Each diagnostic contains rule, message, path, start, end, and an optional source-line snippet. Positions use one-based Unicode character columns and exclusive end positions; a range may end on a later line. A clean single-file check includes these fields:

{"schema_version":1,"status":"success","completed":true,"exit_code":0,"file_count":1,"diagnostics":[],"hints":[]}

The result also includes configurations with selected settings and their origins. See Analysis results for the schema, types, and compatibility rules. JSON Lines writes one diagnostic per line with schema_version: 1 on every record, or nothing for a clean check. The legacy {{json .}} template retains its array, field names, and inclusive end_column contract.

In JSON modes, incomplete checks emit the result on standard error with completed: false, an error, and a nonzero exit_code. An empty diagnostics array alone does not indicate success. Argument errors before operation selection contain only error and exit_code. Requested progress or debug logs are separate JSON Lines records with a log field on standard error. --quiet suppresses these log records. Standard output contains only the requested result. An early failure can leave standard output empty; always check the exit status.

Machine-readable metadata:

$ actionlint --help --json
$ actionlint --version --json
$ actionlint --init-config --json

JSON help describes flag names, shorthand, types, default spellings, groups, choices, repeatability, legacy aliases, and exit codes. JSON version includes name, version, installed_from, go_version, os, and goarch. JSON config creation returns {"path":"..."}. The default three-line version format remains unchanged.

SHELL COMPLETION

--completion generates native completion scripts for Bash, Fish, Zsh, and PowerShell. Cobra generates these scripts from the CLI flag definitions. Scripts complete long flags, short options, flag values, and workflow paths. Bash requires the bash-completion package; Zsh requires compinit. Load one into the current shell session:

Bash:

$ source <(actionlint --completion bash)

Fish:

$ actionlint --completion fish | source

Zsh, after initializing its completion system:

$ autoload -Uz compinit && compinit
$ source <(actionlint --completion zsh)

PowerShell:

actionlint --completion powershell | Out-String | Invoke-Expression

For persistent installation, save Bash output in a directory loaded by bash-completion, Fish output as ~/.config/fish/completions/actionlint.fish, or Zsh output as _actionlint in a directory on fpath. Load PowerShell output from your profile. Regenerate saved scripts after upgrading actionlint so they reflect the installed CLI. See the usage document for setup examples.

ENVIRONMENT

ACTIONLINT_CONFIG, ACTIONLINT_NO_CONFIG, ACTIONLINT_CONFIG_ORIGIN
Configuration selection and origin-display defaults. Explicit config flags override environment selection. config init ignores these defaults.
ACTIONLINT_STDIN_FILENAME, ACTIONLINT_IGNORE_REGEX
Stdin filename and message-filter defaults. The filter value is a JSON string array. Explicit ignore flags replace that list.

ACTIONLINT_OUTPUT_FORMAT, ACTIONLINT_JSON, ACTIONLINT_TEMPLATE, ACTIONLINT_TEMPLATE_FILE, ACTIONLINT_OUTPUT_FILE : Output defaults. Explicit format flags replace environment format selection. Templates and output files apply only to checks.

ACTIONLINT_JSON_PRETTY
Whether terminal JSON may use installed jq. Default: true. The --json-pretty=false flag disables this. Explicit --json-pretty also indents JSON in pipes and files without color codes or a jq dependency. Otherwise, pipes and files retain their original output. JSONL, templates and stderr records keep their existing format. Missing or failing jq falls back to built-in output.
ACTIONLINT_LOG_LEVEL, ACTIONLINT_QUIET, ACTIONLINT_SUMMARY
Logging and summary defaults. Explicit flags, including false values, take precedence.
ACTIONLINT_COLOR, ACTIONLINT_HYPERLINKS
Presentation defaults: auto, always or never. NO_COLOR and NO_HYPERLINKS override these defaults; explicit CLI controls take precedence over the environment.
ACTIONLINT_SHELLCHECK_BIN
Literal external-linter executable names or paths. Empty disables the tool.
ACTIONLINT_SHELLCHECK_FLAGS
Additional arguments as a JSON string array or a quoted argument list. No shell execution or variable expansion is performed.
ACTIONLINT_SHELLCHECK_ENV
Child environment overrides, as a JSON object or quoted NAME=value entries and variable names. JSON null or bare names forward inherited values; strings set values. An explicit tool command flag overrides its BIN, FLAGS and ENV settings together.

See Environment variables for precedence, defaults and examples.

PATH
Used to find ShellCheck, including the executable selected by their command flags.
NO_COLOR
Any nonempty value, including 0 or false, disables automatic color; an empty value has no effect. --color can force color; --no-color always disables it. See the NO_COLOR convention.
GITHUB_ACTIONS
The value true enables automatic color for help and text diagnostics in workflow logs. NO_COLOR and explicit color controls still apply. This does not enable hyperlinks.
NO_HYPERLINKS, FORCE_HYPERLINKS
In auto mode, a nonempty NO_HYPERLINKS disables help and doctor links. Otherwise, a nonempty FORCE_HYPERLINKS enables them even in redirected output. An empty value has no effect; 0 counts as nonempty. Explicit hyperlink modes override both variables. These controls are independent of color.
SHELL, PSModulePath
Used by --completion auto. A supported shell named by SHELL takes precedence over the PowerShell fallback indicated by a nonempty PSModulePath.
SHELLCHECK_OPTS
Additional options interpreted by the external ShellCheck process.

FILES

.github/workflows/
Workflow directory scanned when no filenames are provided.
.github/actionlint.yaml, .github/actionlint.yml, .github/actionlint.json, .github/actionlint.toml
Optional repository configuration; the first existing name in that order is read.

DOCUMENTS

Detailed documentation for this release and current installation options are available online.

Checks

https://github.com/kjanat/actionlint/blob/v2.0.0/docs/checks.md

Full list of all checks done by actionlint with example inputs, outputs, and playground links.

Installation

https://github.com/kjanat/actionlint/blob/master/docs/install.md

Installation instructions for npm, Homebrew, AUR, Scoop, aqua, mise, release archives, the download script, Docker, and Go, plus the status of WinGet and upstream-only package names.

Usage

https://github.com/kjanat/actionlint/blob/v2.0.0/docs/usage.md

CLI usage, shell completion, output templates, the GitHub Action, Docker images, and editor and CI integrations.

Configuration

https://github.com/kjanat/actionlint/blob/v2.0.0/docs/config.md

Repository configuration, runner labels, variables, secrets, and policy checks.

Go API

https://github.com/kjanat/actionlint/blob/v2.0.0/docs/api.md

How to use actionlint as Go library.

References

https://github.com/kjanat/actionlint/blob/v2.0.0/docs/reference.md

Links to resources.

USAGE ON GITHUB ACTIONS

The repository provides a GitHub Action with actionlint, and ShellCheck in a prebuilt Docker image. It reports GitHub annotations by default and fails when problems are found:

name: Lint GitHub Actions workflows
on: [push, pull_request]
permissions: { contents: read }

jobs:
  actionlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
        with: { persist-credentials: false }
      - uses: kjanat/actionlint@v1

The Docker action requires a Linux runner with a reachable Docker daemon. To run the binary directly, including on macOS, Windows with Bash, or a runner without a Docker daemon, use the download script:

- name: Check workflow files
  run: |
    bash <(curl -fsSL https://raw.githubusercontent.com/kjanat/actionlint/662318dd6bbd9c0c120e35b03168bc1be69bf428/scripts/download-actionlint.bash) latest
    ./actionlint --color
  shell: bash

The script accepts latest to resolve the newest release, or a specific version. Without a version argument, it uses the default recorded in the script. It writes the executable to the current directory and, on GitHub Actions, exposes its path as the executable step output. External linters must be available separately when using the binary.

EXIT STATUS

actionlint command exits with one of the following exit statuses.

PLAYGROUND

The WebAssembly playground runs actionlint in your browser. Workflow linting happens locally in the browser; it does not execute workflows or run the external ShellCheck programs.

https://kjanat.github.io/actionlint/

Paste a workflow into the editor to see diagnostics update as you type. Select a diagnostic to jump to its source position.

BUGS

Report problems with this fork to its issue tracker. Include the output of --version, the relevant configuration, and a minimal workflow that reproduces the problem.

https://github.com/kjanat/actionlint/issues

COPYRIGHT

actionlint is licensed under the MIT License.

Copyright (c) 2026 Kaj Kowalski
Copyright (c) 2021 rhysd

https://github.com/kjanat/actionlint/blob/HEAD/LICENSE.txt