Skip to content
Back to skills

Setup

ASecurity

Verify the actionlint-check hook's runtime prerequisites and configuration for this repository. Use when: 'set up actionlint', 'configure actionlint', 'is actionlint working', workflow lint silently isn't happening, or the hook reported a missing prerequisite. Actions: check (read-only verification, default) | apply (resolve what check found). Re-runnable and safe.

  • 13 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added February 9, 2026
toolsgoshellbashnodegit

Works with

  • claude code
  • cli

Security analysis

A100/100

Pro scans all 11 files and shows the line behind each finding

Scanned October 4, 2026

npx -y skills add melodic-software/claude-code-plugins --skill setup --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Setup?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Setup
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/melodic-software-setup/badge)](https://www.skillsdirectory.com/skills/melodic-software-setup)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
description: "Verify the actionlint-check hook's runtime prerequisites and configuration for this repository. Use when: 'set up actionlint', 'configure actionlint', 'is actionlint working', workflow lint silently isn't happening, or the hook reported a missing prerequisite. Actions: check (read-only verification, default) | apply (resolve what check found). Re-runnable and safe."
argument-hint: "[check|apply]"
user-invocable: true
disable-model-invocation: true
shell: bash
---

## Pre-computed context

`check`'s tool probes ran at load time. Read these rows instead of re-issuing them; each shows the
tool's path when present, or `absent` when missing:

- `node`: !`{ command -v node 2>/dev/null || echo "absent"; }`
- `jq`: !`{ command -v jq 2>/dev/null || echo "absent"; }`
- `actionlint`: !`{ command -v actionlint 2>/dev/null || echo "absent"; }`

A row reading `[shell command execution disabled by policy]` carries no result: run that tool's
`command -v` probe via Bash instead.

## Purpose

Thin check-centric setup per the uniform setup contract (`docs/plugin-philosophy.md`
"Setup is explicit and repeatable" in the marketplace repository): `check` inspects and
reports, `apply` resolves. This plugin owns no consumer-project configuration. actionlint
auto-discovers its own optional config from the repository, and the tunables are the native
`userConfig` options (`actionlint_enabled`, `actionlint_lint_gitignored` and
`stdin_read_timeout`). Every
prerequisite is a `PATH` binary the plugin never bundles, and the plugin never installs
system packages, so `apply` is guidance-only with **no write path**. It never modifies the
repository, user settings, or the plugin cache.

Action routing: no argument or `check` runs the check; `apply` runs the check first, then
offers remediation guidance. Both are non-interactive. Never prompt when the action is given.

## `check` (read-only)

The hook script (`${CLAUDE_PLUGIN_ROOT}/hooks/actionlint-check.sh`) is the single source of
truth for what it requires and how it resolves things.

**Read it first.** Probe what it actually does, don't recite this file. Then read the
pre-computed tool rows, run the remaining probes via Bash, and report a PASS/FAIL/INFO
table with one remediation line per FAIL. Do not modify anything.

When the plugin's toggle is disabled, every prerequisite absence except `node` downgrades from
FAIL to INFO. The hook exits through its enabled-gate before probing anything, so a deliberately
disabled plugin is not broken. Report those probes informationally and note that re-enabling
restores the FAIL semantics. A missing `node` stays FAIL: the launcher runs before the enabled-gate.

1. **Bash version.** Check against the hook's documented floor (README Requirements),
   noting any features the hook degrades without (for example telemetry's `EPOCHREALTIME`,
   a Bash 5.0+ builtin).
1a. **`node`.** The pre-computed `node` row. FAIL if absent, even when the toggle is off: every hook row launches through
   `node hooks/exec-bash.mjs`, so the hook does not launch and lint does not run. The hook cannot
   report this itself; the transcript shows a hook error notice. Probed here through Bash, which
   works without the launcher.
2. **`jq`.** The pre-computed `jq` row. FAIL if absent: the hook then skips with a visible
   notice, once per session and agent and renewed every eighth skip, instead of linting.
3. **`actionlint`.** The pre-computed `actionlint` row. FAIL if absent: the hook skips workflow lint
   with a visible notice, once per session (all agents share it) and renewed every eighth
   skip (it ships no binary of its own).
4. **actionlint config.** INFO: actionlint auto-discovers an optional
   `.github/actionlint.yaml` from the repository when present. It is not required. actionlint
   runs with its built-in defaults without one. Report whether one exists for the reader's
   awareness; its absence is not a FAIL.
5. **Hook toggle.** Report the effective `actionlint_enabled` value:
   `${user_config.actionlint_enabled}` (unexpanded or empty means default `true`; any value
   other than `true` disables the hook).
5a. **Path scope, gitignored workflow files.** INFO: report the effective
   `${user_config.actionlint_lint_gitignored}` value (unexpanded or empty means default
   `false`; only `true` lints gitignored workflow files). A tracked file that matches an
   ignore pattern is always in scope. Consult it when a workflow edit produced no lint.
5b. **Stdin read timeout.** INFO: report the effective `stdin_read_timeout` value:
   `${user_config.stdin_read_timeout}` (unexpanded or empty means default `2` seconds,
   minimum `1`). It is an IDLE bound. Any byte arriving resets it, so it fires only once
   the pipe has gone silent for that long, at which point this hook fails open. A value
   `read -t` will not accept, or `0`, falls back to the default.
6. **Hook registration.** INFO: confirm the plugin is enabled for this project
   (`/plugin` → Installed) rather than parsing settings files.

## `apply` (idempotent)

Run `check`, then for each FAIL point at the resolution. This skill installs nothing:

- missing `actionlint`: platform install guidance from the README Requirements section
  (the [actionlint install guide](https://github.com/rhysd/actionlint/blob/main/docs/install.md)).
- missing `node` / `jq` / Bash: platform install instructions from the README Requirements section.
- toggle off: reconfigure through Claude Code's native flow, per the marketplace's
  plugin-reconfiguration convention
  (<https://github.com/melodic-software/claude-code-plugins/blob/main/docs/conventions/plugin-reconfiguration/README.md>,
  which owns the verified-version record): interactive
  `/plugin configure actionlint@<marketplace>` any time, or headless
  `claude plugin install actionlint@<marketplace> -s <scope> --config actionlint_enabled=true`
  (repeatable per key). Against an already-installed plugin it prints `already installed`
  **and still writes the value**. Do **not** uninstall to reconfigure: that drops this plugin's
  entire stored `pluginConfigs` entry, resetting every option in the README's Options reference
  to its manifest default. Pass the scope `claude plugin list` reports for this plugin, and for a
  `project` or `local` scope run from that project's directory, so the rerun matches the existing
  install record; from the home directory pass `user`. A rejected value prints a warning yet
  exits 0, so read the output. This skill never writes user settings or `pluginConfigs`.
  Afterwards rerun `check` in a **fresh session**. The rendered
  `${user_config.*}` is injected at skill load and each hook receives its
  `CLAUDE_PLUGIN_OPTION_*` from an environment fixed at session start, so a same-session
  `check` still reports the OLD value; report the observed effective value, never an
  unobserved change.

After pointing at a remediation, re-run the relevant `check` probe live via Bash (a pre-computed row
predates the remediation, so never re-read it) and report its actual result. Never claim resolved on
the reader's report that they installed something.

Re-running `apply` after everything passes changes nothing and reports "already configured".

## Gotchas

- **A userConfig knob is reachable natively only if the manifest declares it.** Per current
  docs, `claude plugin install --config <key=value>` sets options "declared in the plugin's
  manifest". An undeclared key silently cannot be set through native config surfaces (a raw
  settings `env` block still works). That is why `stdin_read_timeout` is declared in this
  plugin's manifest even though the shared hook lib supplies its default; hook plugins reusing
  the shared lib should declare it too.
- **`--config`'s post-install behavior is undocumented, so the guidance above rests on
  observation.** The official docs describe `--config` only as a `claude plugin install` flag
  and say nothing about an already-installed plugin. The verified-version record lives only in
  the plugin-reconfiguration convention cited in `apply` above. It names which CLI release the
  still-writes claim was observed on, and which conditions it covered.
- **`-shellcheck=` / `-pyflakes=` are deliberate, and the deadlock claim is a local
  observation.** The hook disables actionlint's external run-block linters primarily for
  edit-time latency; the additional "ShellCheck deadlocks on large blocks under the Windows
  subprocess IPC path in actionlint 1.7.x" rationale is the hook author's own reproduction.
  No matching upstream rhysd/actionlint issue as of 2026-07-23; recheck when a rhysd/actionlint
  issue or release note reports ShellCheck hanging or deadlocking under the Windows subprocess
  path, which would replace the local reproduction with an upstream-confirmed cause and a fixed
  version to pin against. The latency rationale alone justifies the flags for an advisory
  edit-time hook; deep run-block linting belongs in a commit hook or CI.

## What this skill does NOT do

- Run the linter. Editing any `.github/workflows/*.yml` or `*.yaml` file exercises the hook
  end-to-end.
- Write the plugin cache, Claude Code user settings, or `pluginConfigs`. Nor the repository.
  Every prerequisite is a `PATH` binary or the native toggle, so remediation is guidance only.
- Download or execute tools during `check` beyond the read-only `command -v` presence probes.

Files in this skill

  • SKILL.md11.9 KB
  • references/alias-definitions.sh3.5 KB
  • references/bashrc-claude.sh10.5 KB
  • references/configuration-details.md8.5 KB
  • references/git-bash-history-troubleshooting.md10.2 KB
  • references/install-linux.md1.6 KB
  • references/install-macos.md2 KB
  • references/install-windows.md6.4 KB
  • references/install-wsl.md7.7 KB
  • references/testing-evaluations.md8.2 KB
  • scripts/bash-aliases.sh10 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…