Skip to content
Back to skills

Check Zsh Scripts

BSecurity

Lint and check zsh scripts with shellcheck, shfmt, zsh -n, zcompile, and scoping options. Use for "check zsh", "lint zsh", or "validate zsh".

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 2, 2026
developmentgoshellbashdocumentation

Security analysis

B88/100
  • criticalPipes output to a shell interpreter

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

Scanned October 2, 2026

npx -y skills add cboone/agent-harness-plugins --skill check-zsh-scripts --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Check Zsh Scripts?

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

Security grade badge for Check Zsh Scripts
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/cboone-check-zsh-scripts/badge)](https://www.skillsdirectory.com/skills/cboone-check-zsh-scripts)

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
---
name: check-zsh-scripts
description: >-
  Lint and check zsh scripts with shellcheck, shfmt, zsh -n, zcompile, and
  scoping options. Use for "check zsh", "lint zsh", or "validate zsh".
---

# Check Zsh Scripts

Check and evaluate zsh scripts using multiple complementary static analysis, syntax checking, and formatting tools.

## Tool Overview

| Order | Tool                          | Purpose                              | Zsh Support  | Auto-Fix |
| ----- | ----------------------------- | ------------------------------------ | ------------ | -------- |
| 1     | `zsh -n`                      | Syntax check (parse without execute) | Native       | No       |
| 2     | `zcompile`                    | Compile to wordcode                  | Native       | No       |
| 3     | `shellcheck --shell=bash`     | Static analysis                      | Limited      | No       |
| 4     | `checkbashisms`               | Identify bash-specific constructs    | Indirect     | No       |
| 5     | `shellharden --check`         | Safer syntax suggestions             | Limited      | Suggest  |
| 6     | `zsh -c 'setopt ...; source'` | Variable scope warnings              | Native       | No       |
| 7     | `shfmt -ln zsh`               | Shell formatter                      | Experimental | Yes      |

## Workflow

### 1. Identify Files to Check

Scan the project for zsh files using Glob:

- `**/*.zsh`
- `**/.zshrc`, `**/.zshenv`, `**/.zprofile`, `**/.zlogin`, `**/.zlogout`
- `**/zshrc`, `**/zshenv`, `**/zprofile`, `**/zlogin`, `**/zlogout`

For other shell scripts, use Read to check shebangs for `#!/usr/bin/env zsh` or `#!/bin/zsh`.

If the user specified particular files, use those instead of scanning.

If no zsh files are found, report this and stop.

### 2. Check Tool Availability

For each tool, verify installation:

```bash
command -v zsh
command -v shellcheck
command -v checkbashisms
command -v shellharden
command -v shfmt
```

`zcompile` is a zsh builtin and does not need a separate check.

Present a table of available vs. missing tools. For missing tools, show the install command from the tool's reference file and continue with available tools.

Minimum requirement: `zsh` must be available (pre-installed on macOS).

### 3. Run Tools

Run each available tool sequentially in the order listed below. For each tool, capture stdout, stderr, and exit code.

#### 3a. Syntax Check

```bash
zsh -n <file>
```

If this fails, report the syntax errors prominently. Syntax errors may block meaningful results from other tools, but continue running other tools anyway since they may catch different issues.

See `./references/tools/zsh-n.md`.

#### 3b. Compile Check

```bash
zsh -c 'zcompile "$1"' _ <file>
```

Then clean up:

```bash
rm -f <file>.zwc
```

See `./references/tools/zcompile.md`.

#### 3c. Static Analysis

```bash
shellcheck --shell=bash --exclude=SC1090,SC2039,SC2154,SC2168,SC2296,SC2299 <file>
```

The `--exclude` flag suppresses stable false-positive codes. Note: SC3000-series codes only fire with `--shell=sh`, not `--shell=bash`. Since this workflow uses `--shell=bash`, no SC3xxx filtering is needed. If the project ever switches to `--shell=sh`, add SC3xxx filtering at that point.

See `./references/tools/shellcheck.md` for the full list of applicable vs. false-positive SC codes.

#### 3d. Bashism Detection

```bash
checkbashisms <file>
```

Most output is informational for zsh scripts. Focus on constructs that truly differ between bash and zsh: `BASH_SOURCE`, `shopt`, `declare -n`, `readarray`/`mapfile`, `compgen`/`complete`.

See `./references/tools/checkbashisms.md`.

#### 3e. Safety Suggestions

```bash
shellharden --check <file>
```

If issues are found, show suggestions:

```bash
shellharden --suggest <file>
```

Note that some quoting suggestions are less critical in zsh (zsh does not split unquoted parameter expansions by default), but quoting remains good practice for portability.

See `./references/tools/shellharden.md`.

#### 3f. Variable Scope Warnings

```bash
zsh -c 'emulate -L zsh; setopt warn_create_global warn_nested_var; source <file>'
```

This sources the file, so review its contents for side effects first. For `.zshrc` and similar config files that intentionally set global state, many warnings are expected. Note this context when reporting.

Because this step executes code (it is not purely static analysis), generated `check-zsh.zsh` scripts and any wrapper that runs this check should support a `SKIP_SETOPT_CHECK=1` opt-out. The check runs by default during local development; CI workflows set `SKIP_SETOPT_CHECK=1` to keep lint jobs purely static. Use the guard pattern:

```zsh
if [[ "${SKIP_SETOPT_CHECK:-}" == "1" ]]; then
  print "==> setopt warnings: skipped (SKIP_SETOPT_CHECK=1)"
else
  # run the setopt check
fi
```

The `set-up-ci` zsh CI template sets `SKIP_SETOPT_CHECK: "1"` in the workflow `env`, so generated check scripts must honor this env var to interoperate with that template.

See `./references/tools/setopt-warnings.md`.

#### 3g. Shell Formatting

```bash
shfmt -ln zsh -d <file>
```

If shfmt fails to parse a zsh-specific construct, skip it gracefully for that file.

See `./references/tools/shfmt.md`.

### 4. Report Results

Display a summary table:

```text
| Tool | Status | Issues | Filtered |
|------|--------|--------|----------|
| zsh -n | Pass/Fail | N | n/a |
| zcompile | Pass/Fail | N | n/a |
| shellcheck | Pass/Issues | N | M filtered |
| checkbashisms | Pass/Info | N | M filtered |
| shellharden | Pass/Suggestions | N | M filtered |
| setopt warnings | Pass/Warnings | N | n/a |
| shfmt | Pass/Formatting | N files | n/a |
```

Then list each genuine issue with:

- File path and line number
- Tool that found it
- Error/warning code (if applicable)
- Message
- Suggested fix

### 5. Fix Issues

For formatting issues, offer to auto-fix with shfmt:

```bash
shfmt -ln zsh -w <file>
```

For other tools, present findings with manual fix guidance from the relevant reference documentation.

After applying fixes, re-run `zsh -n` to verify no new syntax errors were introduced.

### 6. Clean Up

Remove any `.zwc` files created during step 3b that were not already cleaned up:

```bash
rm -f <file>.zwc
```

## Error Handling

- **No zsh files found**: Report that no zsh files were detected in the project and stop.
- **Tool not installed**: Report the missing tool with its install command. Continue with available tools.
- **zsh -n failure**: Report syntax errors prominently. Continue running other tools.
- **zcompile failure when zsh -n passed**: Report the compilation error as a potential edge case worth investigating.
- **shellcheck excessive false positives**: If more than half the output is filtered, note this and suggest focusing on native zsh tools.
- **setopt warnings in config files**: For `.zshrc`, `.zshenv`, and similar files that set global state by design, note that `warn_create_global` warnings are expected.
- **shfmt parse error**: If shfmt cannot parse a zsh-specific construct, skip that file. The parse error is informational, not a bug in the script.
- **Source side effects**: Before running the setopt check (step 3f), review the file for commands that modify state. Skip this check for files with significant side effects if the user prefers, or set `SKIP_SETOPT_CHECK=1` to disable the step in generated check scripts.

Files in this skill

  • SKILL.md7.2 KB
  • references/tools/checkbashisms.md1.6 KB
  • references/tools/setopt-warnings.md3.1 KB
  • references/tools/shellcheck.md2.3 KB
  • references/tools/shellharden.md1.3 KB
  • references/tools/shfmt.md1.6 KB
  • references/tools/zcompile.md1.2 KB
  • references/tools/zsh-n.md818 B

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…